| Index: sandbox/win/src/ipc_unittest.cc
|
| diff --git a/sandbox/win/src/ipc_unittest.cc b/sandbox/win/src/ipc_unittest.cc
|
| deleted file mode 100644
|
| index c41720da36a3237703058601cddb3ce348fa62de..0000000000000000000000000000000000000000
|
| --- a/sandbox/win/src/ipc_unittest.cc
|
| +++ /dev/null
|
| @@ -1,632 +0,0 @@
|
| -// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include <stddef.h>
|
| -#include <stdint.h>
|
| -
|
| -#include "sandbox/win/src/crosscall_client.h"
|
| -#include "sandbox/win/src/crosscall_server.h"
|
| -#include "sandbox/win/src/sharedmem_ipc_client.h"
|
| -#include "sandbox/win/src/sharedmem_ipc_server.h"
|
| -#include "testing/gtest/include/gtest/gtest.h"
|
| -
|
| -namespace sandbox {
|
| -
|
| -// Helper function to make the fake shared memory with some
|
| -// basic elements initialized.
|
| -IPCControl* MakeChannels(size_t channel_size, size_t total_shared_size,
|
| - size_t* base_start) {
|
| - // Allocate memory
|
| - char* mem = new char[total_shared_size];
|
| - memset(mem, 0, total_shared_size);
|
| - // Calculate how many channels we can fit in the shared memory.
|
| - total_shared_size -= offsetof(IPCControl, channels);
|
| - size_t channel_count =
|
| - total_shared_size / (sizeof(ChannelControl) + channel_size);
|
| - // Calculate the start of the first channel.
|
| - *base_start = (sizeof(ChannelControl)* channel_count) +
|
| - offsetof(IPCControl, channels);
|
| - // Setup client structure.
|
| - IPCControl* client_control = reinterpret_cast<IPCControl*>(mem);
|
| - client_control->channels_count = channel_count;
|
| - return client_control;
|
| -}
|
| -
|
| -enum TestFixMode {
|
| - FIX_NO_EVENTS,
|
| - FIX_PONG_READY,
|
| - FIX_PONG_NOT_READY
|
| -};
|
| -
|
| -void FixChannels(IPCControl* client_control, size_t base_start,
|
| - size_t channel_size, TestFixMode mode) {
|
| - for (size_t ix = 0; ix != client_control->channels_count; ++ix) {
|
| - ChannelControl& channel = client_control->channels[ix];
|
| - channel.channel_base = base_start;
|
| - channel.state = kFreeChannel;
|
| - if (mode != FIX_NO_EVENTS) {
|
| - BOOL signaled = (FIX_PONG_READY == mode)? TRUE : FALSE;
|
| - channel.ping_event = ::CreateEventW(NULL, FALSE, FALSE, NULL);
|
| - channel.pong_event = ::CreateEventW(NULL, FALSE, signaled, NULL);
|
| - }
|
| - base_start += channel_size;
|
| - }
|
| -}
|
| -
|
| -void CloseChannelEvents(IPCControl* client_control) {
|
| - for (size_t ix = 0; ix != client_control->channels_count; ++ix) {
|
| - ChannelControl& channel = client_control->channels[ix];
|
| - ::CloseHandle(channel.ping_event);
|
| - ::CloseHandle(channel.pong_event);
|
| - }
|
| -}
|
| -
|
| -TEST(IPCTest, ChannelMaker) {
|
| - // Test that our testing rig is computing offsets properly. We should have
|
| - // 5 channnels and the offset to the first channel is 108 bytes in 32 bits
|
| - // and 216 in 64 bits.
|
| - size_t channel_start = 0;
|
| - IPCControl* client_control = MakeChannels(12 * 64, 4096, &channel_start);
|
| - ASSERT_TRUE(NULL != client_control);
|
| - EXPECT_EQ(5u, client_control->channels_count);
|
| -#if defined(_WIN64)
|
| - EXPECT_EQ(216u, channel_start);
|
| -#else
|
| - EXPECT_EQ(108u, channel_start);
|
| -#endif
|
| - delete[] reinterpret_cast<char*>(client_control);
|
| -}
|
| -
|
| -TEST(IPCTest, ClientLockUnlock) {
|
| - // Make 7 channels of kIPCChannelSize (1kb) each. Test that we lock and
|
| - // unlock channels properly.
|
| - size_t base_start = 0;
|
| - IPCControl* client_control =
|
| - MakeChannels(kIPCChannelSize, 4096 * 2, &base_start);
|
| - FixChannels(client_control, base_start, kIPCChannelSize, FIX_NO_EVENTS);
|
| -
|
| - char* mem = reinterpret_cast<char*>(client_control);
|
| - SharedMemIPCClient client(mem);
|
| -
|
| - // Test that we lock the first 3 channels in sequence.
|
| - void* buff0 = client.GetBuffer();
|
| - EXPECT_TRUE(mem + client_control->channels[0].channel_base == buff0);
|
| - EXPECT_EQ(kBusyChannel, client_control->channels[0].state);
|
| - EXPECT_EQ(kFreeChannel, client_control->channels[1].state);
|
| - EXPECT_EQ(kFreeChannel, client_control->channels[2].state);
|
| - EXPECT_EQ(kFreeChannel, client_control->channels[3].state);
|
| - EXPECT_EQ(kFreeChannel, client_control->channels[4].state);
|
| - EXPECT_EQ(kFreeChannel, client_control->channels[5].state);
|
| -
|
| - void* buff1 = client.GetBuffer();
|
| - EXPECT_TRUE(mem + client_control->channels[1].channel_base == buff1);
|
| - EXPECT_EQ(kBusyChannel, client_control->channels[0].state);
|
| - EXPECT_EQ(kBusyChannel, client_control->channels[1].state);
|
| - EXPECT_EQ(kFreeChannel, client_control->channels[2].state);
|
| - EXPECT_EQ(kFreeChannel, client_control->channels[3].state);
|
| - EXPECT_EQ(kFreeChannel, client_control->channels[4].state);
|
| - EXPECT_EQ(kFreeChannel, client_control->channels[5].state);
|
| -
|
| - void* buff2 = client.GetBuffer();
|
| - EXPECT_TRUE(mem + client_control->channels[2].channel_base == buff2);
|
| - EXPECT_EQ(kBusyChannel, client_control->channels[0].state);
|
| - EXPECT_EQ(kBusyChannel, client_control->channels[1].state);
|
| - EXPECT_EQ(kBusyChannel, client_control->channels[2].state);
|
| - EXPECT_EQ(kFreeChannel, client_control->channels[3].state);
|
| - EXPECT_EQ(kFreeChannel, client_control->channels[4].state);
|
| - EXPECT_EQ(kFreeChannel, client_control->channels[5].state);
|
| -
|
| - // Test that we unlock and re-lock the right channel.
|
| - client.FreeBuffer(buff1);
|
| - EXPECT_EQ(kBusyChannel, client_control->channels[0].state);
|
| - EXPECT_EQ(kFreeChannel, client_control->channels[1].state);
|
| - EXPECT_EQ(kBusyChannel, client_control->channels[2].state);
|
| - EXPECT_EQ(kFreeChannel, client_control->channels[3].state);
|
| - EXPECT_EQ(kFreeChannel, client_control->channels[4].state);
|
| - EXPECT_EQ(kFreeChannel, client_control->channels[5].state);
|
| -
|
| - void* buff2b = client.GetBuffer();
|
| - EXPECT_TRUE(mem + client_control->channels[1].channel_base == buff2b);
|
| - EXPECT_EQ(kBusyChannel, client_control->channels[0].state);
|
| - EXPECT_EQ(kBusyChannel, client_control->channels[1].state);
|
| - EXPECT_EQ(kBusyChannel, client_control->channels[2].state);
|
| - EXPECT_EQ(kFreeChannel, client_control->channels[3].state);
|
| - EXPECT_EQ(kFreeChannel, client_control->channels[4].state);
|
| - EXPECT_EQ(kFreeChannel, client_control->channels[5].state);
|
| -
|
| - client.FreeBuffer(buff0);
|
| - EXPECT_EQ(kFreeChannel, client_control->channels[0].state);
|
| - EXPECT_EQ(kBusyChannel, client_control->channels[1].state);
|
| - EXPECT_EQ(kBusyChannel, client_control->channels[2].state);
|
| - EXPECT_EQ(kFreeChannel, client_control->channels[3].state);
|
| - EXPECT_EQ(kFreeChannel, client_control->channels[4].state);
|
| - EXPECT_EQ(kFreeChannel, client_control->channels[5].state);
|
| -
|
| - delete[] reinterpret_cast<char*>(client_control);
|
| -}
|
| -
|
| -TEST(IPCTest, CrossCallStrPacking) {
|
| - // This test tries the CrossCall object with null and non-null string
|
| - // combination of parameters, integer types and verifies that the unpacker
|
| - // can read them properly.
|
| - size_t base_start = 0;
|
| - IPCControl* client_control =
|
| - MakeChannels(kIPCChannelSize, 4096 * 4, &base_start);
|
| - client_control->server_alive = HANDLE(1);
|
| - FixChannels(client_control, base_start, kIPCChannelSize, FIX_PONG_READY);
|
| -
|
| - char* mem = reinterpret_cast<char*>(client_control);
|
| - SharedMemIPCClient client(mem);
|
| -
|
| - CrossCallReturn answer;
|
| - uint32_t tag1 = 666;
|
| - const wchar_t *text = L"98765 - 43210";
|
| - base::string16 copied_text;
|
| - CrossCallParamsEx* actual_params;
|
| -
|
| - CrossCall(client, tag1, text, &answer);
|
| - actual_params = reinterpret_cast<CrossCallParamsEx*>(client.GetBuffer());
|
| - EXPECT_EQ(1u, actual_params->GetParamsCount());
|
| - EXPECT_EQ(tag1, actual_params->GetTag());
|
| - EXPECT_TRUE(actual_params->GetParameterStr(0, &copied_text));
|
| - EXPECT_STREQ(text, copied_text.c_str());
|
| -
|
| - // Check with an empty string.
|
| - uint32_t tag2 = 777;
|
| - const wchar_t* null_text = NULL;
|
| - CrossCall(client, tag2, null_text, &answer);
|
| - actual_params = reinterpret_cast<CrossCallParamsEx*>(client.GetBuffer());
|
| - EXPECT_EQ(1u, actual_params->GetParamsCount());
|
| - EXPECT_EQ(tag2, actual_params->GetTag());
|
| - uint32_t param_size = 1;
|
| - ArgType type = INVALID_TYPE;
|
| - void* param_addr = actual_params->GetRawParameter(0, ¶m_size, &type);
|
| - EXPECT_TRUE(NULL != param_addr);
|
| - EXPECT_EQ(0u, param_size);
|
| - EXPECT_EQ(WCHAR_TYPE, type);
|
| - EXPECT_TRUE(actual_params->GetParameterStr(0, &copied_text));
|
| -
|
| - uint32_t tag3 = 888;
|
| - param_size = 1;
|
| - copied_text.clear();
|
| -
|
| - // Check with an empty string and a non-empty string.
|
| - CrossCall(client, tag3, null_text, text, &answer);
|
| - actual_params = reinterpret_cast<CrossCallParamsEx*>(client.GetBuffer());
|
| - EXPECT_EQ(2u, actual_params->GetParamsCount());
|
| - EXPECT_EQ(tag3, actual_params->GetTag());
|
| - type = INVALID_TYPE;
|
| - param_addr = actual_params->GetRawParameter(0, ¶m_size, &type);
|
| - EXPECT_TRUE(NULL != param_addr);
|
| - EXPECT_EQ(0u, param_size);
|
| - EXPECT_EQ(WCHAR_TYPE, type);
|
| - EXPECT_TRUE(actual_params->GetParameterStr(0, &copied_text));
|
| - EXPECT_TRUE(actual_params->GetParameterStr(1, &copied_text));
|
| - EXPECT_STREQ(text, copied_text.c_str());
|
| -
|
| - param_size = 1;
|
| - base::string16 copied_text_p0, copied_text_p2;
|
| -
|
| - const wchar_t *text2 = L"AeFG";
|
| - CrossCall(client, tag1, text2, null_text, text, &answer);
|
| - actual_params = reinterpret_cast<CrossCallParamsEx*>(client.GetBuffer());
|
| - EXPECT_EQ(3u, actual_params->GetParamsCount());
|
| - EXPECT_EQ(tag1, actual_params->GetTag());
|
| - EXPECT_TRUE(actual_params->GetParameterStr(0, &copied_text_p0));
|
| - EXPECT_STREQ(text2, copied_text_p0.c_str());
|
| - EXPECT_TRUE(actual_params->GetParameterStr(2, &copied_text_p2));
|
| - EXPECT_STREQ(text, copied_text_p2.c_str());
|
| - type = INVALID_TYPE;
|
| - param_addr = actual_params->GetRawParameter(1, ¶m_size, &type);
|
| - EXPECT_TRUE(NULL != param_addr);
|
| - EXPECT_EQ(0u, param_size);
|
| - EXPECT_EQ(WCHAR_TYPE, type);
|
| -
|
| - CloseChannelEvents(client_control);
|
| - delete[] reinterpret_cast<char*>(client_control);
|
| -}
|
| -
|
| -TEST(IPCTest, CrossCallIntPacking) {
|
| - // Check handling for regular 32 bit integers used in Windows.
|
| - size_t base_start = 0;
|
| - IPCControl* client_control =
|
| - MakeChannels(kIPCChannelSize, 4096 * 4, &base_start);
|
| - client_control->server_alive = HANDLE(1);
|
| - FixChannels(client_control, base_start, kIPCChannelSize, FIX_PONG_READY);
|
| -
|
| - uint32_t tag1 = 999;
|
| - uint32_t tag2 = 111;
|
| - const wchar_t *text = L"godzilla";
|
| - CrossCallParamsEx* actual_params;
|
| -
|
| - char* mem = reinterpret_cast<char*>(client_control);
|
| - SharedMemIPCClient client(mem);
|
| -
|
| - CrossCallReturn answer;
|
| - DWORD dw = 0xE6578;
|
| - CrossCall(client, tag2, dw, &answer);
|
| - actual_params = reinterpret_cast<CrossCallParamsEx*>(client.GetBuffer());
|
| - EXPECT_EQ(1u, actual_params->GetParamsCount());
|
| - EXPECT_EQ(tag2, actual_params->GetTag());
|
| - ArgType type = INVALID_TYPE;
|
| - uint32_t param_size = 1;
|
| - void* param_addr = actual_params->GetRawParameter(0, ¶m_size, &type);
|
| - ASSERT_EQ(sizeof(dw), param_size);
|
| - EXPECT_EQ(UINT32_TYPE, type);
|
| - ASSERT_TRUE(NULL != param_addr);
|
| - EXPECT_EQ(0, memcmp(&dw, param_addr, param_size));
|
| -
|
| - // Check handling for windows HANDLES.
|
| - HANDLE h = HANDLE(0x70000500);
|
| - CrossCall(client, tag1, text, h, &answer);
|
| - actual_params = reinterpret_cast<CrossCallParamsEx*>(client.GetBuffer());
|
| - EXPECT_EQ(2u, actual_params->GetParamsCount());
|
| - EXPECT_EQ(tag1, actual_params->GetTag());
|
| - type = INVALID_TYPE;
|
| - param_addr = actual_params->GetRawParameter(1, ¶m_size, &type);
|
| - ASSERT_EQ(sizeof(h), param_size);
|
| - EXPECT_EQ(VOIDPTR_TYPE, type);
|
| - ASSERT_TRUE(NULL != param_addr);
|
| - EXPECT_EQ(0, memcmp(&h, param_addr, param_size));
|
| -
|
| - // Check combination of 32 and 64 bits.
|
| - CrossCall(client, tag2, h, dw, h, &answer);
|
| - actual_params = reinterpret_cast<CrossCallParamsEx*>(client.GetBuffer());
|
| - EXPECT_EQ(3u, actual_params->GetParamsCount());
|
| - EXPECT_EQ(tag2, actual_params->GetTag());
|
| - type = INVALID_TYPE;
|
| - param_addr = actual_params->GetRawParameter(0, ¶m_size, &type);
|
| - ASSERT_EQ(sizeof(h), param_size);
|
| - EXPECT_EQ(VOIDPTR_TYPE, type);
|
| - ASSERT_TRUE(NULL != param_addr);
|
| - EXPECT_EQ(0, memcmp(&h, param_addr, param_size));
|
| - type = INVALID_TYPE;
|
| - param_addr = actual_params->GetRawParameter(1, ¶m_size, &type);
|
| - ASSERT_EQ(sizeof(dw), param_size);
|
| - EXPECT_EQ(UINT32_TYPE, type);
|
| - ASSERT_TRUE(NULL != param_addr);
|
| - EXPECT_EQ(0, memcmp(&dw, param_addr, param_size));
|
| - type = INVALID_TYPE;
|
| - param_addr = actual_params->GetRawParameter(2, ¶m_size, &type);
|
| - ASSERT_EQ(sizeof(h), param_size);
|
| - EXPECT_EQ(VOIDPTR_TYPE, type);
|
| - ASSERT_TRUE(NULL != param_addr);
|
| - EXPECT_EQ(0, memcmp(&h, param_addr, param_size));
|
| -
|
| - CloseChannelEvents(client_control);
|
| - delete[] reinterpret_cast<char*>(client_control);
|
| -}
|
| -
|
| -TEST(IPCTest, CrossCallValidation) {
|
| - // First a sanity test with a well formed parameter object.
|
| - unsigned long value = 124816;
|
| - const uint32_t kTag = 33;
|
| - const uint32_t kBufferSize = 256;
|
| - ActualCallParams<1, kBufferSize> params_1(kTag);
|
| - params_1.CopyParamIn(0, &value, sizeof(value), false, UINT32_TYPE);
|
| - void* buffer = const_cast<void*>(params_1.GetBuffer());
|
| -
|
| - uint32_t out_size = 0;
|
| - CrossCallParamsEx* ccp = 0;
|
| - ccp = CrossCallParamsEx::CreateFromBuffer(buffer, params_1.GetSize(),
|
| - &out_size);
|
| - ASSERT_TRUE(NULL != ccp);
|
| - EXPECT_TRUE(ccp->GetBuffer() != buffer);
|
| - EXPECT_EQ(kTag, ccp->GetTag());
|
| - EXPECT_EQ(1u, ccp->GetParamsCount());
|
| - delete[] (reinterpret_cast<char*>(ccp));
|
| -
|
| - // Test that we handle integer overflow on the number of params
|
| - // correctly. We use a test-only ctor for ActualCallParams that
|
| - // allows to create malformed cross-call buffers.
|
| - const int32_t kPtrDiffSz = sizeof(ptrdiff_t);
|
| - for (int32_t ix = -1; ix != 3; ++ix) {
|
| - uint32_t fake_num_params = (UINT32_MAX / kPtrDiffSz) + ix;
|
| - ActualCallParams<1, kBufferSize> params_2(kTag, fake_num_params);
|
| - params_2.CopyParamIn(0, &value, sizeof(value), false, UINT32_TYPE);
|
| - buffer = const_cast<void*>(params_2.GetBuffer());
|
| -
|
| - EXPECT_TRUE(NULL != buffer);
|
| - ccp = CrossCallParamsEx::CreateFromBuffer(buffer, params_1.GetSize(),
|
| - &out_size);
|
| - // If the buffer is malformed the return is NULL.
|
| - EXPECT_TRUE(NULL == ccp);
|
| - }
|
| -
|
| - ActualCallParams<1, kBufferSize> params_3(kTag, 1);
|
| - params_3.CopyParamIn(0, &value, sizeof(value), false, UINT32_TYPE);
|
| - buffer = const_cast<void*>(params_3.GetBuffer());
|
| - EXPECT_TRUE(NULL != buffer);
|
| -
|
| - uint32_t correct_size = params_3.OverrideSize(1);
|
| - ccp = CrossCallParamsEx::CreateFromBuffer(buffer, kBufferSize, &out_size);
|
| - EXPECT_TRUE(NULL == ccp);
|
| -
|
| - // The correct_size is 8 bytes aligned.
|
| - params_3.OverrideSize(correct_size - 7);
|
| - ccp = CrossCallParamsEx::CreateFromBuffer(buffer, kBufferSize, &out_size);
|
| - EXPECT_TRUE(NULL == ccp);
|
| -
|
| - params_3.OverrideSize(correct_size);
|
| - ccp = CrossCallParamsEx::CreateFromBuffer(buffer, kBufferSize, &out_size);
|
| - EXPECT_TRUE(NULL != ccp);
|
| -
|
| - // Make sure that two parameters work as expected.
|
| - ActualCallParams<2, kBufferSize> params_4(kTag, 2);
|
| - params_4.CopyParamIn(0, &value, sizeof(value), false, UINT32_TYPE);
|
| - params_4.CopyParamIn(1, buffer, sizeof(buffer), false, VOIDPTR_TYPE);
|
| - buffer = const_cast<void*>(params_4.GetBuffer());
|
| - EXPECT_TRUE(NULL != buffer);
|
| -
|
| - ccp = CrossCallParamsEx::CreateFromBuffer(buffer, kBufferSize, &out_size);
|
| - EXPECT_TRUE(NULL != ccp);
|
| -
|
| -#if defined(_WIN64)
|
| - correct_size = params_4.OverrideSize(1);
|
| - params_4.OverrideSize(correct_size - 1);
|
| - ccp = CrossCallParamsEx::CreateFromBuffer(buffer, kBufferSize, &out_size);
|
| - EXPECT_TRUE(NULL == ccp);
|
| -#endif
|
| -}
|
| -
|
| -// This structure is passed to the mock server threads to simulate
|
| -// the server side IPC so it has the required kernel objects.
|
| -struct ServerEvents {
|
| - HANDLE ping;
|
| - HANDLE pong;
|
| - volatile LONG* state;
|
| - HANDLE mutex;
|
| -};
|
| -
|
| -// This is the server thread that quicky answers an IPC and exits.
|
| -DWORD WINAPI QuickResponseServer(PVOID param) {
|
| - ServerEvents* events = reinterpret_cast<ServerEvents*>(param);
|
| - DWORD wait_result = 0;
|
| - wait_result = ::WaitForSingleObject(events->ping, INFINITE);
|
| - ::InterlockedExchange(events->state, kAckChannel);
|
| - ::SetEvent(events->pong);
|
| - return wait_result;
|
| -}
|
| -
|
| -class CrossCallParamsMock : public CrossCallParams {
|
| - public:
|
| - CrossCallParamsMock(uint32_t tag, uint32_t params_count)
|
| - : CrossCallParams(tag, params_count) {}
|
| -};
|
| -
|
| -void FakeOkAnswerInChannel(void* channel) {
|
| - CrossCallReturn* answer = reinterpret_cast<CrossCallReturn*>(channel);
|
| - answer->call_outcome = SBOX_ALL_OK;
|
| -}
|
| -
|
| -// Create two threads that will quickly answer IPCs; the first one
|
| -// using channel 1 (channel 0 is busy) and one using channel 0. No time-out
|
| -// should occur.
|
| -TEST(IPCTest, ClientFastServer) {
|
| - const size_t channel_size = kIPCChannelSize;
|
| - size_t base_start = 0;
|
| - IPCControl* client_control =
|
| - MakeChannels(channel_size, 4096 * 2, &base_start);
|
| - FixChannels(client_control, base_start, kIPCChannelSize, FIX_PONG_NOT_READY);
|
| - client_control->server_alive = ::CreateMutex(NULL, FALSE, NULL);
|
| -
|
| - char* mem = reinterpret_cast<char*>(client_control);
|
| - SharedMemIPCClient client(mem);
|
| -
|
| - ServerEvents events = {0};
|
| - events.ping = client_control->channels[1].ping_event;
|
| - events.pong = client_control->channels[1].pong_event;
|
| - events.state = &client_control->channels[1].state;
|
| -
|
| - HANDLE t1 = ::CreateThread(NULL, 0, QuickResponseServer, &events, 0, NULL);
|
| - ASSERT_TRUE(NULL != t1);
|
| - ::CloseHandle(t1);
|
| -
|
| - void* buff0 = client.GetBuffer();
|
| - EXPECT_TRUE(mem + client_control->channels[0].channel_base == buff0);
|
| - EXPECT_EQ(kBusyChannel, client_control->channels[0].state);
|
| - EXPECT_EQ(kFreeChannel, client_control->channels[1].state);
|
| - EXPECT_EQ(kFreeChannel, client_control->channels[2].state);
|
| -
|
| - void* buff1 = client.GetBuffer();
|
| - EXPECT_TRUE(mem + client_control->channels[1].channel_base == buff1);
|
| - EXPECT_EQ(kBusyChannel, client_control->channels[0].state);
|
| - EXPECT_EQ(kBusyChannel, client_control->channels[1].state);
|
| - EXPECT_EQ(kFreeChannel, client_control->channels[2].state);
|
| -
|
| - EXPECT_EQ(0u, client_control->channels[1].ipc_tag);
|
| -
|
| - uint32_t tag = 7654;
|
| - CrossCallReturn answer;
|
| - CrossCallParamsMock* params1 = new(buff1) CrossCallParamsMock(tag, 1);
|
| - FakeOkAnswerInChannel(buff1);
|
| -
|
| - ResultCode result = client.DoCall(params1, &answer);
|
| - if (SBOX_ERROR_CHANNEL_ERROR != result)
|
| - client.FreeBuffer(buff1);
|
| -
|
| - EXPECT_TRUE(SBOX_ALL_OK == result);
|
| - EXPECT_EQ(tag, client_control->channels[1].ipc_tag);
|
| - EXPECT_EQ(kBusyChannel, client_control->channels[0].state);
|
| - EXPECT_EQ(kFreeChannel, client_control->channels[1].state);
|
| - EXPECT_EQ(kFreeChannel, client_control->channels[2].state);
|
| -
|
| - HANDLE t2 = ::CreateThread(NULL, 0, QuickResponseServer, &events, 0, NULL);
|
| - ASSERT_TRUE(NULL != t2);
|
| - ::CloseHandle(t2);
|
| -
|
| - client.FreeBuffer(buff0);
|
| - events.ping = client_control->channels[0].ping_event;
|
| - events.pong = client_control->channels[0].pong_event;
|
| - events.state = &client_control->channels[0].state;
|
| -
|
| - tag = 4567;
|
| - CrossCallParamsMock* params2 = new(buff0) CrossCallParamsMock(tag, 1);
|
| - FakeOkAnswerInChannel(buff0);
|
| -
|
| - result = client.DoCall(params2, &answer);
|
| - if (SBOX_ERROR_CHANNEL_ERROR != result)
|
| - client.FreeBuffer(buff0);
|
| -
|
| - EXPECT_TRUE(SBOX_ALL_OK == result);
|
| - EXPECT_EQ(tag, client_control->channels[0].ipc_tag);
|
| - EXPECT_EQ(kFreeChannel, client_control->channels[0].state);
|
| - EXPECT_EQ(kFreeChannel, client_control->channels[1].state);
|
| - EXPECT_EQ(kFreeChannel, client_control->channels[2].state);
|
| -
|
| - CloseChannelEvents(client_control);
|
| - ::CloseHandle(client_control->server_alive);
|
| -
|
| - delete[] reinterpret_cast<char*>(client_control);
|
| -}
|
| -
|
| -// This is the server thread that very slowly answers an IPC and exits. Note
|
| -// that the pong event needs to be signaled twice.
|
| -DWORD WINAPI SlowResponseServer(PVOID param) {
|
| - ServerEvents* events = reinterpret_cast<ServerEvents*>(param);
|
| - DWORD wait_result = 0;
|
| - wait_result = ::WaitForSingleObject(events->ping, INFINITE);
|
| - ::Sleep(kIPCWaitTimeOut1 + kIPCWaitTimeOut2 + 200);
|
| - ::InterlockedExchange(events->state, kAckChannel);
|
| - ::SetEvent(events->pong);
|
| - return wait_result;
|
| -}
|
| -
|
| -// This thread's job is to keep the mutex locked.
|
| -DWORD WINAPI MainServerThread(PVOID param) {
|
| - ServerEvents* events = reinterpret_cast<ServerEvents*>(param);
|
| - DWORD wait_result = 0;
|
| - wait_result = ::WaitForSingleObject(events->mutex, INFINITE);
|
| - Sleep(kIPCWaitTimeOut1 * 20);
|
| - return wait_result;
|
| -}
|
| -
|
| -// Creates a server thread that answers the IPC so slow that is guaranteed to
|
| -// trigger the time-out code path in the client. A second thread is created
|
| -// to hold locked the server_alive mutex: this signals the client that the
|
| -// server is not dead and it retries the wait.
|
| -TEST(IPCTest, ClientSlowServer) {
|
| - size_t base_start = 0;
|
| - IPCControl* client_control =
|
| - MakeChannels(kIPCChannelSize, 4096*2, &base_start);
|
| - FixChannels(client_control, base_start, kIPCChannelSize, FIX_PONG_NOT_READY);
|
| - client_control->server_alive = ::CreateMutex(NULL, FALSE, NULL);
|
| -
|
| - char* mem = reinterpret_cast<char*>(client_control);
|
| - SharedMemIPCClient client(mem);
|
| -
|
| - ServerEvents events = {0};
|
| - events.ping = client_control->channels[0].ping_event;
|
| - events.pong = client_control->channels[0].pong_event;
|
| - events.state = &client_control->channels[0].state;
|
| -
|
| - HANDLE t1 = ::CreateThread(NULL, 0, SlowResponseServer, &events, 0, NULL);
|
| - ASSERT_TRUE(NULL != t1);
|
| - ::CloseHandle(t1);
|
| -
|
| - ServerEvents events2 = {0};
|
| - events2.pong = events.pong;
|
| - events2.mutex = client_control->server_alive;
|
| -
|
| - HANDLE t2 = ::CreateThread(NULL, 0, MainServerThread, &events2, 0, NULL);
|
| - ASSERT_TRUE(NULL != t2);
|
| - ::CloseHandle(t2);
|
| -
|
| - ::Sleep(1);
|
| -
|
| - void* buff0 = client.GetBuffer();
|
| - uint32_t tag = 4321;
|
| - CrossCallReturn answer;
|
| - CrossCallParamsMock* params1 = new(buff0) CrossCallParamsMock(tag, 1);
|
| - FakeOkAnswerInChannel(buff0);
|
| -
|
| - ResultCode result = client.DoCall(params1, &answer);
|
| - if (SBOX_ERROR_CHANNEL_ERROR != result)
|
| - client.FreeBuffer(buff0);
|
| -
|
| - EXPECT_TRUE(SBOX_ALL_OK == result);
|
| - EXPECT_EQ(tag, client_control->channels[0].ipc_tag);
|
| - EXPECT_EQ(kFreeChannel, client_control->channels[0].state);
|
| -
|
| - CloseChannelEvents(client_control);
|
| - ::CloseHandle(client_control->server_alive);
|
| - delete[] reinterpret_cast<char*>(client_control);
|
| -}
|
| -
|
| -// This test-only IPC dispatcher has two handlers with the same signature
|
| -// but only CallOneHandler should be used.
|
| -class UnitTestIPCDispatcher : public Dispatcher {
|
| - public:
|
| - enum {
|
| - CALL_ONE_TAG = 78,
|
| - CALL_TWO_TAG = 87
|
| - };
|
| -
|
| - UnitTestIPCDispatcher();
|
| - ~UnitTestIPCDispatcher() override{};
|
| -
|
| - bool SetupService(InterceptionManager* manager, int service) override {
|
| - return true;
|
| - }
|
| -
|
| - private:
|
| - bool CallOneHandler(IPCInfo* ipc, HANDLE p1, uint32_t p2) {
|
| - ipc->return_info.extended[0].handle = p1;
|
| - ipc->return_info.extended[1].unsigned_int = p2;
|
| - return true;
|
| - }
|
| -
|
| - bool CallTwoHandler(IPCInfo* ipc, HANDLE p1, uint32_t p2) { return true; }
|
| -};
|
| -
|
| -UnitTestIPCDispatcher::UnitTestIPCDispatcher() {
|
| - static const IPCCall call_one = {{CALL_ONE_TAG, {VOIDPTR_TYPE, UINT32_TYPE}},
|
| - reinterpret_cast<CallbackGeneric>(
|
| - &UnitTestIPCDispatcher::CallOneHandler)};
|
| - static const IPCCall call_two = {{CALL_TWO_TAG, {VOIDPTR_TYPE, UINT32_TYPE}},
|
| - reinterpret_cast<CallbackGeneric>(
|
| - &UnitTestIPCDispatcher::CallTwoHandler)};
|
| - ipc_calls_.push_back(call_one);
|
| - ipc_calls_.push_back(call_two);
|
| -}
|
| -
|
| -// This test does most of the shared memory IPC client-server roundtrip
|
| -// and tests the packing, unpacking and call dispatching.
|
| -TEST(IPCTest, SharedMemServerTests) {
|
| - size_t base_start = 0;
|
| - IPCControl* client_control =
|
| - MakeChannels(kIPCChannelSize, 4096, &base_start);
|
| - client_control->server_alive = HANDLE(1);
|
| - FixChannels(client_control, base_start, kIPCChannelSize, FIX_PONG_READY);
|
| -
|
| - char* mem = reinterpret_cast<char*>(client_control);
|
| - SharedMemIPCClient client(mem);
|
| -
|
| - CrossCallReturn answer;
|
| - HANDLE bar = HANDLE(191919);
|
| - DWORD foo = 6767676;
|
| - CrossCall(client, UnitTestIPCDispatcher::CALL_ONE_TAG, bar, foo, &answer);
|
| - void* buff = client.GetBuffer();
|
| - ASSERT_TRUE(NULL != buff);
|
| -
|
| - UnitTestIPCDispatcher dispatcher;
|
| - // Since we are directly calling InvokeCallback, most of this structure
|
| - // can be set to NULL.
|
| - sandbox::SharedMemIPCServer::ServerControl srv_control = {};
|
| - srv_control.channel_size = kIPCChannelSize;
|
| - srv_control.shared_base = reinterpret_cast<char*>(client_control);
|
| - srv_control.dispatcher = &dispatcher;
|
| -
|
| - sandbox::CrossCallReturn call_return = {0};
|
| - EXPECT_TRUE(SharedMemIPCServer::InvokeCallback(&srv_control, buff,
|
| - &call_return));
|
| - EXPECT_EQ(SBOX_ALL_OK, call_return.call_outcome);
|
| - EXPECT_TRUE(bar == call_return.extended[0].handle);
|
| - EXPECT_EQ(foo, call_return.extended[1].unsigned_int);
|
| -
|
| - CloseChannelEvents(client_control);
|
| - delete[] reinterpret_cast<char*>(client_control);
|
| -}
|
| -
|
| -} // namespace sandbox
|
|
|