- add sources.
[platform/framework/web/crosswalk.git] / src / sandbox / win / src / ipc_unittest.cc
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/basictypes.h"
6 #include "sandbox/win/src/crosscall_client.h"
7 #include "sandbox/win/src/crosscall_server.h"
8 #include "sandbox/win/src/sharedmem_ipc_client.h"
9 #include "sandbox/win/src/sharedmem_ipc_server.h"
10 #include "testing/gtest/include/gtest/gtest.h"
11
12 namespace sandbox {
13
14 // Helper function to make the fake shared memory with some
15 // basic elements initialized.
16 IPCControl* MakeChannels(size_t channel_size, size_t total_shared_size,
17                          size_t* base_start) {
18   // Allocate memory
19   char* mem = new char[total_shared_size];
20   memset(mem, 0, total_shared_size);
21   // Calculate how many channels we can fit in the shared memory.
22   total_shared_size -= offsetof(IPCControl, channels);
23   size_t channel_count =
24     total_shared_size / (sizeof(ChannelControl) + channel_size);
25   // Calculate the start of the first channel.
26   *base_start = (sizeof(ChannelControl)* channel_count) +
27     offsetof(IPCControl, channels);
28   // Setup client structure.
29   IPCControl* client_control = reinterpret_cast<IPCControl*>(mem);
30   client_control->channels_count = channel_count;
31   return client_control;
32 }
33
34 enum TestFixMode {
35   FIX_NO_EVENTS,
36   FIX_PONG_READY,
37   FIX_PONG_NOT_READY
38 };
39
40 void FixChannels(IPCControl* client_control, size_t base_start,
41                  size_t channel_size, TestFixMode mode) {
42   for (size_t ix = 0; ix != client_control->channels_count; ++ix) {
43     ChannelControl& channel = client_control->channels[ix];
44     channel.channel_base = base_start;
45     channel.state = kFreeChannel;
46     if (mode != FIX_NO_EVENTS) {
47       BOOL signaled = (FIX_PONG_READY == mode)? TRUE : FALSE;
48       channel.ping_event = ::CreateEventW(NULL, FALSE, FALSE, NULL);
49       channel.pong_event = ::CreateEventW(NULL, FALSE, signaled, NULL);
50     }
51     base_start += channel_size;
52   }
53 }
54
55 void CloseChannelEvents(IPCControl* client_control) {
56   for (size_t ix = 0; ix != client_control->channels_count; ++ix) {
57     ChannelControl& channel = client_control->channels[ix];
58     ::CloseHandle(channel.ping_event);
59     ::CloseHandle(channel.pong_event);
60   }
61 }
62
63 TEST(IPCTest, ChannelMaker) {
64   // Test that our testing rig is computing offsets properly. We should have
65   // 5 channnels and the offset to the first channel is 108 bytes in 32 bits
66   // and 216 in 64 bits.
67   size_t channel_start = 0;
68   IPCControl* client_control = MakeChannels(12 * 64, 4096, &channel_start);
69   ASSERT_TRUE(NULL != client_control);
70   EXPECT_EQ(5, client_control->channels_count);
71 #if defined(_WIN64)
72   EXPECT_EQ(216, channel_start);
73 #else
74   EXPECT_EQ(108, channel_start);
75 #endif
76   delete[] reinterpret_cast<char*>(client_control);
77 }
78
79 TEST(IPCTest, ClientLockUnlock) {
80   // Make 7 channels of kIPCChannelSize (1kb) each. Test that we lock and
81   // unlock channels properly.
82   size_t base_start = 0;
83   IPCControl* client_control =
84       MakeChannels(kIPCChannelSize, 4096 * 2, &base_start);
85   FixChannels(client_control, base_start, kIPCChannelSize, FIX_NO_EVENTS);
86
87   char* mem = reinterpret_cast<char*>(client_control);
88   SharedMemIPCClient client(mem);
89
90   // Test that we lock the first 3 channels in sequence.
91   void* buff0 = client.GetBuffer();
92   EXPECT_TRUE(mem + client_control->channels[0].channel_base == buff0);
93   EXPECT_EQ(kBusyChannel, client_control->channels[0].state);
94   EXPECT_EQ(kFreeChannel, client_control->channels[1].state);
95   EXPECT_EQ(kFreeChannel, client_control->channels[2].state);
96   EXPECT_EQ(kFreeChannel, client_control->channels[3].state);
97   EXPECT_EQ(kFreeChannel, client_control->channels[4].state);
98   EXPECT_EQ(kFreeChannel, client_control->channels[5].state);
99
100   void* buff1 = client.GetBuffer();
101   EXPECT_TRUE(mem + client_control->channels[1].channel_base == buff1);
102   EXPECT_EQ(kBusyChannel, client_control->channels[0].state);
103   EXPECT_EQ(kBusyChannel, client_control->channels[1].state);
104   EXPECT_EQ(kFreeChannel, client_control->channels[2].state);
105   EXPECT_EQ(kFreeChannel, client_control->channels[3].state);
106   EXPECT_EQ(kFreeChannel, client_control->channels[4].state);
107   EXPECT_EQ(kFreeChannel, client_control->channels[5].state);
108
109   void* buff2 = client.GetBuffer();
110   EXPECT_TRUE(mem + client_control->channels[2].channel_base == buff2);
111   EXPECT_EQ(kBusyChannel, client_control->channels[0].state);
112   EXPECT_EQ(kBusyChannel, client_control->channels[1].state);
113   EXPECT_EQ(kBusyChannel, client_control->channels[2].state);
114   EXPECT_EQ(kFreeChannel, client_control->channels[3].state);
115   EXPECT_EQ(kFreeChannel, client_control->channels[4].state);
116   EXPECT_EQ(kFreeChannel, client_control->channels[5].state);
117
118   // Test that we unlock and re-lock the right channel.
119   client.FreeBuffer(buff1);
120   EXPECT_EQ(kBusyChannel, client_control->channels[0].state);
121   EXPECT_EQ(kFreeChannel, client_control->channels[1].state);
122   EXPECT_EQ(kBusyChannel, client_control->channels[2].state);
123   EXPECT_EQ(kFreeChannel, client_control->channels[3].state);
124   EXPECT_EQ(kFreeChannel, client_control->channels[4].state);
125   EXPECT_EQ(kFreeChannel, client_control->channels[5].state);
126
127   void* buff2b = client.GetBuffer();
128   EXPECT_TRUE(mem + client_control->channels[1].channel_base == buff2b);
129   EXPECT_EQ(kBusyChannel, client_control->channels[0].state);
130   EXPECT_EQ(kBusyChannel, client_control->channels[1].state);
131   EXPECT_EQ(kBusyChannel, client_control->channels[2].state);
132   EXPECT_EQ(kFreeChannel, client_control->channels[3].state);
133   EXPECT_EQ(kFreeChannel, client_control->channels[4].state);
134   EXPECT_EQ(kFreeChannel, client_control->channels[5].state);
135
136   client.FreeBuffer(buff0);
137   EXPECT_EQ(kFreeChannel, client_control->channels[0].state);
138   EXPECT_EQ(kBusyChannel, client_control->channels[1].state);
139   EXPECT_EQ(kBusyChannel, client_control->channels[2].state);
140   EXPECT_EQ(kFreeChannel, client_control->channels[3].state);
141   EXPECT_EQ(kFreeChannel, client_control->channels[4].state);
142   EXPECT_EQ(kFreeChannel, client_control->channels[5].state);
143
144   delete[] reinterpret_cast<char*>(client_control);
145 }
146
147 TEST(IPCTest, CrossCallStrPacking) {
148   // This test tries the CrossCall object with null and non-null string
149   // combination of parameters, integer types and verifies that the unpacker
150   // can read them properly.
151   size_t base_start = 0;
152   IPCControl* client_control =
153       MakeChannels(kIPCChannelSize, 4096 * 4, &base_start);
154   client_control->server_alive = HANDLE(1);
155   FixChannels(client_control, base_start, kIPCChannelSize, FIX_PONG_READY);
156
157   char* mem = reinterpret_cast<char*>(client_control);
158   SharedMemIPCClient client(mem);
159
160   CrossCallReturn answer;
161   uint32 tag1 = 666;
162   const wchar_t text[] = L"98765 - 43210";
163   std::wstring copied_text;
164   CrossCallParamsEx* actual_params;
165
166   CrossCall(client, tag1, text, &answer);
167   actual_params = reinterpret_cast<CrossCallParamsEx*>(client.GetBuffer());
168   EXPECT_EQ(1, actual_params->GetParamsCount());
169   EXPECT_EQ(tag1, actual_params->GetTag());
170   EXPECT_TRUE(actual_params->GetParameterStr(0, &copied_text));
171   EXPECT_STREQ(text, copied_text.c_str());
172
173   // Check with an empty string.
174   uint32 tag2 = 777;
175   const wchar_t* null_text = NULL;
176   CrossCall(client, tag2, null_text, &answer);
177   actual_params = reinterpret_cast<CrossCallParamsEx*>(client.GetBuffer());
178   EXPECT_EQ(1, actual_params->GetParamsCount());
179   EXPECT_EQ(tag2, actual_params->GetTag());
180   uint32 param_size = 1;
181   ArgType type = INVALID_TYPE;
182   void* param_addr = actual_params->GetRawParameter(0, &param_size, &type);
183   EXPECT_TRUE(NULL != param_addr);
184   EXPECT_EQ(0, param_size);
185   EXPECT_EQ(WCHAR_TYPE, type);
186   EXPECT_TRUE(actual_params->GetParameterStr(0, &copied_text));
187
188   uint32 tag3 = 888;
189   param_size = 1;
190   copied_text.clear();
191
192   // Check with an empty string and a non-empty string.
193   CrossCall(client, tag3, null_text, text, &answer);
194   actual_params = reinterpret_cast<CrossCallParamsEx*>(client.GetBuffer());
195   EXPECT_EQ(2, actual_params->GetParamsCount());
196   EXPECT_EQ(tag3, actual_params->GetTag());
197   type = INVALID_TYPE;
198   param_addr = actual_params->GetRawParameter(0, &param_size, &type);
199   EXPECT_TRUE(NULL != param_addr);
200   EXPECT_EQ(0, param_size);
201   EXPECT_EQ(WCHAR_TYPE, type);
202   EXPECT_TRUE(actual_params->GetParameterStr(0, &copied_text));
203   EXPECT_TRUE(actual_params->GetParameterStr(1, &copied_text));
204   EXPECT_STREQ(text, copied_text.c_str());
205
206   param_size = 1;
207   std::wstring copied_text_p0, copied_text_p2;
208
209   const wchar_t text2[] = L"AeFG";
210   CrossCall(client, tag1, text2, null_text, text, &answer);
211   actual_params = reinterpret_cast<CrossCallParamsEx*>(client.GetBuffer());
212   EXPECT_EQ(3, actual_params->GetParamsCount());
213   EXPECT_EQ(tag1, actual_params->GetTag());
214   EXPECT_TRUE(actual_params->GetParameterStr(0, &copied_text_p0));
215   EXPECT_STREQ(text2, copied_text_p0.c_str());
216   EXPECT_TRUE(actual_params->GetParameterStr(2, &copied_text_p2));
217   EXPECT_STREQ(text, copied_text_p2.c_str());
218   type = INVALID_TYPE;
219   param_addr = actual_params->GetRawParameter(1, &param_size, &type);
220   EXPECT_TRUE(NULL != param_addr);
221   EXPECT_EQ(0, param_size);
222   EXPECT_EQ(WCHAR_TYPE, type);
223
224   CloseChannelEvents(client_control);
225   delete[] reinterpret_cast<char*>(client_control);
226 }
227
228 TEST(IPCTest, CrossCallIntPacking) {
229   // Check handling for regular 32 bit integers used in Windows.
230   size_t base_start = 0;
231   IPCControl* client_control =
232       MakeChannels(kIPCChannelSize, 4096 * 4, &base_start);
233   client_control->server_alive = HANDLE(1);
234   FixChannels(client_control, base_start, kIPCChannelSize, FIX_PONG_READY);
235
236   uint32 tag1 = 999;
237   uint32 tag2 = 111;
238   const wchar_t text[] = L"godzilla";
239   CrossCallParamsEx* actual_params;
240
241   char* mem = reinterpret_cast<char*>(client_control);
242   SharedMemIPCClient client(mem);
243
244   CrossCallReturn answer;
245   DWORD dw = 0xE6578;
246   CrossCall(client, tag2, dw, &answer);
247   actual_params = reinterpret_cast<CrossCallParamsEx*>(client.GetBuffer());
248   EXPECT_EQ(1, actual_params->GetParamsCount());
249   EXPECT_EQ(tag2, actual_params->GetTag());
250   ArgType type = INVALID_TYPE;
251   uint32 param_size = 1;
252   void* param_addr = actual_params->GetRawParameter(0, &param_size, &type);
253   ASSERT_EQ(sizeof(dw), param_size);
254   EXPECT_EQ(ULONG_TYPE, type);
255   ASSERT_TRUE(NULL != param_addr);
256   EXPECT_EQ(0, memcmp(&dw, param_addr, param_size));
257
258   // Check handling for windows HANDLES.
259   HANDLE h = HANDLE(0x70000500);
260   CrossCall(client, tag1, text, h, &answer);
261   actual_params = reinterpret_cast<CrossCallParamsEx*>(client.GetBuffer());
262   EXPECT_EQ(2, actual_params->GetParamsCount());
263   EXPECT_EQ(tag1, actual_params->GetTag());
264   type = INVALID_TYPE;
265   param_addr = actual_params->GetRawParameter(1, &param_size, &type);
266   ASSERT_EQ(sizeof(h), param_size);
267   EXPECT_EQ(VOIDPTR_TYPE, type);
268   ASSERT_TRUE(NULL != param_addr);
269   EXPECT_EQ(0, memcmp(&h, param_addr, param_size));
270
271   // Check combination of 32 and 64 bits.
272   CrossCall(client, tag2, h, dw, h, &answer);
273   actual_params = reinterpret_cast<CrossCallParamsEx*>(client.GetBuffer());
274   EXPECT_EQ(3, actual_params->GetParamsCount());
275   EXPECT_EQ(tag2, actual_params->GetTag());
276   type = INVALID_TYPE;
277   param_addr = actual_params->GetRawParameter(0, &param_size, &type);
278   ASSERT_EQ(sizeof(h), param_size);
279   EXPECT_EQ(VOIDPTR_TYPE, type);
280   ASSERT_TRUE(NULL != param_addr);
281   EXPECT_EQ(0, memcmp(&h, param_addr, param_size));
282   type = INVALID_TYPE;
283   param_addr = actual_params->GetRawParameter(1, &param_size, &type);
284   ASSERT_EQ(sizeof(dw), param_size);
285   EXPECT_EQ(ULONG_TYPE, type);
286   ASSERT_TRUE(NULL != param_addr);
287   EXPECT_EQ(0, memcmp(&dw, param_addr, param_size));
288   type = INVALID_TYPE;
289   param_addr = actual_params->GetRawParameter(2, &param_size, &type);
290   ASSERT_EQ(sizeof(h), param_size);
291   EXPECT_EQ(VOIDPTR_TYPE, type);
292   ASSERT_TRUE(NULL != param_addr);
293   EXPECT_EQ(0, memcmp(&h, param_addr, param_size));
294
295   CloseChannelEvents(client_control);
296   delete[] reinterpret_cast<char*>(client_control);
297 }
298
299 TEST(IPCTest, CrossCallValidation) {
300   // First a sanity test with a well formed parameter object.
301   unsigned long value = 124816;
302   const uint32 kTag = 33;
303   const uint32 kBufferSize = 256;
304   ActualCallParams<1, kBufferSize> params_1(kTag);
305   params_1.CopyParamIn(0, &value, sizeof(value), false, ULONG_TYPE);
306   void* buffer = const_cast<void*>(params_1.GetBuffer());
307
308   uint32 out_size = 0;
309   CrossCallParamsEx* ccp = 0;
310   ccp = CrossCallParamsEx::CreateFromBuffer(buffer, params_1.GetSize(),
311                                             &out_size);
312   ASSERT_TRUE(NULL != ccp);
313   EXPECT_TRUE(ccp->GetBuffer() != buffer);
314   EXPECT_EQ(kTag, ccp->GetTag());
315   EXPECT_EQ(1, ccp->GetParamsCount());
316   delete[] (reinterpret_cast<char*>(ccp));
317
318 #if defined(NDEBUG)
319   // Test hat we handle integer overflow on the number of params
320   // correctly. We use a test-only ctor for ActualCallParams that
321   // allows to create malformed cross-call buffers.
322   const int32 kPtrDiffSz = sizeof(ptrdiff_t);
323   for (int32 ix = -1; ix != 3; ++ix) {
324     uint32 fake_num_params = (kuint32max / kPtrDiffSz) + ix;
325     ActualCallParams<1, kBufferSize> params_2(kTag, fake_num_params);
326     params_2.CopyParamIn(0, &value, sizeof(value), false, ULONG_TYPE);
327     buffer = const_cast<void*>(params_2.GetBuffer());
328
329     EXPECT_TRUE(NULL != buffer);
330     ccp = CrossCallParamsEx::CreateFromBuffer(buffer, params_1.GetSize(),
331                                               &out_size);
332     // If the buffer is malformed the return is NULL.
333     EXPECT_TRUE(NULL == ccp);
334   }
335 #endif  // defined(NDEBUG)
336
337   ActualCallParams<1, kBufferSize> params_3(kTag, 1);
338   params_3.CopyParamIn(0, &value, sizeof(value), false, ULONG_TYPE);
339   buffer = const_cast<void*>(params_3.GetBuffer());
340   EXPECT_TRUE(NULL != buffer);
341
342   uint32 correct_size = params_3.OverrideSize(1);
343   ccp = CrossCallParamsEx::CreateFromBuffer(buffer, kBufferSize, &out_size);
344   EXPECT_TRUE(NULL == ccp);
345
346   // The correct_size is 8 bytes aligned.
347   params_3.OverrideSize(correct_size - 7);
348   ccp = CrossCallParamsEx::CreateFromBuffer(buffer, kBufferSize, &out_size);
349   EXPECT_TRUE(NULL == ccp);
350
351   params_3.OverrideSize(correct_size);
352   ccp = CrossCallParamsEx::CreateFromBuffer(buffer, kBufferSize, &out_size);
353   EXPECT_TRUE(NULL != ccp);
354
355   // Make sure that two parameters work as expected.
356   ActualCallParams<2, kBufferSize> params_4(kTag, 2);
357   params_4.CopyParamIn(0, &value, sizeof(value), false, ULONG_TYPE);
358   params_4.CopyParamIn(1, buffer, sizeof(buffer), false, VOIDPTR_TYPE);
359   buffer = const_cast<void*>(params_4.GetBuffer());
360   EXPECT_TRUE(NULL != buffer);
361
362   ccp = CrossCallParamsEx::CreateFromBuffer(buffer, kBufferSize, &out_size);
363   EXPECT_TRUE(NULL != ccp);
364
365 #if defined(_WIN64)
366   correct_size = params_4.OverrideSize(1);
367   params_4.OverrideSize(correct_size - 1);
368   ccp = CrossCallParamsEx::CreateFromBuffer(buffer, kBufferSize, &out_size);
369   EXPECT_TRUE(NULL == ccp);
370 #endif
371 }
372
373 // This structure is passed to the mock server threads to simulate
374 // the server side IPC so it has the required kernel objects.
375 struct ServerEvents {
376   HANDLE ping;
377   HANDLE pong;
378   volatile LONG* state;
379   HANDLE mutex;
380 };
381
382 // This is the server thread that quicky answers an IPC and exits.
383 DWORD WINAPI QuickResponseServer(PVOID param) {
384   ServerEvents* events = reinterpret_cast<ServerEvents*>(param);
385   DWORD wait_result = 0;
386   wait_result = ::WaitForSingleObject(events->ping, INFINITE);
387   ::InterlockedExchange(events->state, kAckChannel);
388   ::SetEvent(events->pong);
389   return wait_result;
390 }
391
392 class CrossCallParamsMock : public CrossCallParams {
393  public:
394   CrossCallParamsMock(uint32 tag, uint32 params_count)
395       :  CrossCallParams(tag, params_count) {
396   }
397  private:
398   void* params[4];
399 };
400
401 void FakeOkAnswerInChannel(void* channel) {
402   CrossCallReturn* answer = reinterpret_cast<CrossCallReturn*>(channel);
403   answer->call_outcome = SBOX_ALL_OK;
404 }
405
406 // Create two threads that will quickly answer IPCs; the first one
407 // using channel 1 (channel 0 is busy) and one using channel 0. No time-out
408 // should occur.
409 TEST(IPCTest, ClientFastServer) {
410   const size_t channel_size = kIPCChannelSize;
411   size_t base_start = 0;
412   IPCControl* client_control =
413       MakeChannels(channel_size, 4096 * 2, &base_start);
414   FixChannels(client_control, base_start, kIPCChannelSize, FIX_PONG_NOT_READY);
415   client_control->server_alive = ::CreateMutex(NULL, FALSE, NULL);
416
417   char* mem = reinterpret_cast<char*>(client_control);
418   SharedMemIPCClient client(mem);
419
420   ServerEvents events = {0};
421   events.ping = client_control->channels[1].ping_event;
422   events.pong = client_control->channels[1].pong_event;
423   events.state = &client_control->channels[1].state;
424
425   HANDLE t1 = ::CreateThread(NULL, 0, QuickResponseServer, &events, 0, NULL);
426   ASSERT_TRUE(NULL != t1);
427   ::CloseHandle(t1);
428
429   void* buff0 = client.GetBuffer();
430   EXPECT_TRUE(mem + client_control->channels[0].channel_base == buff0);
431   EXPECT_EQ(kBusyChannel, client_control->channels[0].state);
432   EXPECT_EQ(kFreeChannel, client_control->channels[1].state);
433   EXPECT_EQ(kFreeChannel, client_control->channels[2].state);
434
435   void* buff1 = client.GetBuffer();
436   EXPECT_TRUE(mem + client_control->channels[1].channel_base == buff1);
437   EXPECT_EQ(kBusyChannel, client_control->channels[0].state);
438   EXPECT_EQ(kBusyChannel, client_control->channels[1].state);
439   EXPECT_EQ(kFreeChannel, client_control->channels[2].state);
440
441   EXPECT_EQ(0, client_control->channels[1].ipc_tag);
442
443   uint32 tag = 7654;
444   CrossCallReturn answer;
445   CrossCallParamsMock* params1 = new(buff1) CrossCallParamsMock(tag, 1);
446   FakeOkAnswerInChannel(buff1);
447
448   ResultCode result = client.DoCall(params1, &answer);
449   if (SBOX_ERROR_CHANNEL_ERROR != result)
450     client.FreeBuffer(buff1);
451
452   EXPECT_TRUE(SBOX_ALL_OK == result);
453   EXPECT_EQ(tag, client_control->channels[1].ipc_tag);
454   EXPECT_EQ(kBusyChannel, client_control->channels[0].state);
455   EXPECT_EQ(kFreeChannel, client_control->channels[1].state);
456   EXPECT_EQ(kFreeChannel, client_control->channels[2].state);
457
458   HANDLE t2 = ::CreateThread(NULL, 0, QuickResponseServer, &events, 0, NULL);
459   ASSERT_TRUE(NULL != t2);
460   ::CloseHandle(t2);
461
462   client.FreeBuffer(buff0);
463   events.ping = client_control->channels[0].ping_event;
464   events.pong = client_control->channels[0].pong_event;
465   events.state = &client_control->channels[0].state;
466
467   tag = 4567;
468   CrossCallParamsMock* params2 = new(buff0) CrossCallParamsMock(tag, 1);
469   FakeOkAnswerInChannel(buff0);
470
471   result = client.DoCall(params2, &answer);
472   if (SBOX_ERROR_CHANNEL_ERROR != result)
473     client.FreeBuffer(buff0);
474
475   EXPECT_TRUE(SBOX_ALL_OK == result);
476   EXPECT_EQ(tag, client_control->channels[0].ipc_tag);
477   EXPECT_EQ(kFreeChannel, client_control->channels[0].state);
478   EXPECT_EQ(kFreeChannel, client_control->channels[1].state);
479   EXPECT_EQ(kFreeChannel, client_control->channels[2].state);
480
481   CloseChannelEvents(client_control);
482   ::CloseHandle(client_control->server_alive);
483
484   delete[] reinterpret_cast<char*>(client_control);
485 }
486
487 // This is the server thread that very slowly answers an IPC and exits. Note
488 // that the pong event needs to be signaled twice.
489 DWORD WINAPI SlowResponseServer(PVOID param) {
490   ServerEvents* events = reinterpret_cast<ServerEvents*>(param);
491   DWORD wait_result = 0;
492   wait_result = ::WaitForSingleObject(events->ping, INFINITE);
493   ::Sleep(kIPCWaitTimeOut1 + kIPCWaitTimeOut2 + 200);
494   ::InterlockedExchange(events->state, kAckChannel);
495   ::SetEvent(events->pong);
496   return wait_result;
497 }
498
499 // This thread's job is to keep the mutex locked.
500 DWORD WINAPI MainServerThread(PVOID param) {
501   ServerEvents* events = reinterpret_cast<ServerEvents*>(param);
502   DWORD wait_result = 0;
503   wait_result = ::WaitForSingleObject(events->mutex, INFINITE);
504   Sleep(kIPCWaitTimeOut1 * 20);
505   return wait_result;
506 }
507
508 // Creates a server thread that answers the IPC so slow that is guaranteed to
509 // trigger the time-out code path in the client. A second thread is created
510 // to hold locked the server_alive mutex: this signals the client that the
511 // server is not dead and it retries the wait.
512 TEST(IPCTest, ClientSlowServer) {
513   size_t base_start = 0;
514   IPCControl* client_control =
515       MakeChannels(kIPCChannelSize, 4096*2, &base_start);
516   FixChannels(client_control, base_start, kIPCChannelSize, FIX_PONG_NOT_READY);
517   client_control->server_alive = ::CreateMutex(NULL, FALSE, NULL);
518
519   char* mem = reinterpret_cast<char*>(client_control);
520   SharedMemIPCClient client(mem);
521
522   ServerEvents events = {0};
523   events.ping = client_control->channels[0].ping_event;
524   events.pong = client_control->channels[0].pong_event;
525   events.state = &client_control->channels[0].state;
526
527   HANDLE t1 = ::CreateThread(NULL, 0, SlowResponseServer, &events, 0, NULL);
528   ASSERT_TRUE(NULL != t1);
529   ::CloseHandle(t1);
530
531   ServerEvents events2 = {0};
532   events2.pong = events.pong;
533   events2.mutex = client_control->server_alive;
534
535   HANDLE t2 = ::CreateThread(NULL, 0, MainServerThread, &events2, 0, NULL);
536   ASSERT_TRUE(NULL != t2);
537   ::CloseHandle(t2);
538
539   ::Sleep(1);
540
541   void* buff0 = client.GetBuffer();
542   uint32 tag = 4321;
543   CrossCallReturn answer;
544   CrossCallParamsMock* params1 = new(buff0) CrossCallParamsMock(tag, 1);
545   FakeOkAnswerInChannel(buff0);
546
547   ResultCode result = client.DoCall(params1, &answer);
548   if (SBOX_ERROR_CHANNEL_ERROR != result)
549     client.FreeBuffer(buff0);
550
551   EXPECT_TRUE(SBOX_ALL_OK == result);
552   EXPECT_EQ(tag, client_control->channels[0].ipc_tag);
553   EXPECT_EQ(kFreeChannel, client_control->channels[0].state);
554
555   CloseChannelEvents(client_control);
556   ::CloseHandle(client_control->server_alive);
557   delete[] reinterpret_cast<char*>(client_control);
558 }
559
560 // This test-only IPC dispatcher has two handlers with the same signature
561 // but only CallOneHandler should be used.
562 class UnitTestIPCDispatcher : public Dispatcher {
563  public:
564   enum {
565     CALL_ONE_TAG = 78,
566     CALL_TWO_TAG = 87
567   };
568
569   UnitTestIPCDispatcher();
570   ~UnitTestIPCDispatcher() {};
571
572   virtual bool SetupService(InterceptionManager* manager, int service) {
573     return true;
574   }
575
576  private:
577   bool CallOneHandler(IPCInfo* ipc, HANDLE p1, DWORD p2) {
578     ipc->return_info.extended[0].handle = p1;
579     ipc->return_info.extended[1].unsigned_int = p2;
580     return true;
581   }
582
583   bool CallTwoHandler(IPCInfo* ipc, HANDLE p1, DWORD p2) {
584     return true;
585   }
586 };
587
588 UnitTestIPCDispatcher::UnitTestIPCDispatcher() {
589   static const IPCCall call_one = {
590     {CALL_ONE_TAG, VOIDPTR_TYPE, ULONG_TYPE},
591     reinterpret_cast<CallbackGeneric>(
592         &UnitTestIPCDispatcher::CallOneHandler)
593   };
594   static const IPCCall call_two = {
595     {CALL_TWO_TAG, VOIDPTR_TYPE, ULONG_TYPE},
596     reinterpret_cast<CallbackGeneric>(
597         &UnitTestIPCDispatcher::CallTwoHandler)
598   };
599   ipc_calls_.push_back(call_one);
600   ipc_calls_.push_back(call_two);
601 }
602
603 // This test does most of the shared memory IPC client-server roundtrip
604 // and tests the packing, unpacking and call dispatching.
605 TEST(IPCTest, SharedMemServerTests) {
606   size_t base_start = 0;
607   IPCControl* client_control =
608       MakeChannels(kIPCChannelSize, 4096, &base_start);
609   client_control->server_alive = HANDLE(1);
610   FixChannels(client_control, base_start, kIPCChannelSize, FIX_PONG_READY);
611
612   char* mem = reinterpret_cast<char*>(client_control);
613   SharedMemIPCClient client(mem);
614
615   CrossCallReturn answer;
616   HANDLE bar = HANDLE(191919);
617   DWORD foo = 6767676;
618   CrossCall(client, UnitTestIPCDispatcher::CALL_ONE_TAG, bar, foo, &answer);
619   void* buff = client.GetBuffer();
620   ASSERT_TRUE(NULL != buff);
621
622   UnitTestIPCDispatcher dispatcher;
623   // Since we are directly calling InvokeCallback, most of this structure
624   // can be set to NULL.
625   sandbox::SharedMemIPCServer::ServerControl srv_control = {
626       NULL, NULL, kIPCChannelSize, NULL,
627       reinterpret_cast<char*>(client_control),
628       NULL, &dispatcher, {0} };
629
630   sandbox::CrossCallReturn call_return = {0};
631   EXPECT_TRUE(SharedMemIPCServer::InvokeCallback(&srv_control, buff,
632                                                  &call_return));
633   EXPECT_EQ(SBOX_ALL_OK, call_return.call_outcome);
634   EXPECT_TRUE(bar == call_return.extended[0].handle);
635   EXPECT_EQ(foo, call_return.extended[1].unsigned_int);
636
637   CloseChannelEvents(client_control);
638   delete[] reinterpret_cast<char*>(client_control);
639 }
640
641 }  // namespace sandbox