1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be 3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file. 4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/basictypes.h" 6731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "base/mac/scoped_nsautorelease_pool.h" 7ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/scoped_ptr.h" 8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/shared_memory.h" 93345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/test/multiprocess_test.h" 103f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/threading/platform_thread.h" 11513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "base/time.h" 12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "testing/gtest/include/gtest/gtest.h" 133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "testing/multiprocess_func_list.h" 14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const int kNumThreads = 5; 16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const int kNumTasks = 5; 17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace base { 19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace { 21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Each thread will open the shared memory. Each thread will take a different 4 23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// byte int pointer, and keep changing it, with some small pauses in between. 24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Verify that each thread's value in the shared memory is always correct. 25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass MultipleThreadMain : public PlatformThread::Delegate { 26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public: 27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott explicit MultipleThreadMain(int16 id) : id_(id) {} 28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ~MultipleThreadMain() {} 29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott static void CleanUp() { 31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SharedMemory memory; 32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memory.Delete(s_test_name_); 33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // PlatformThread::Delegate interface. 36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void ThreadMain() { 37731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick mac::ScopedNSAutoreleasePool pool; // noop if not OSX 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const uint32 kDataSize = 1024; 39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SharedMemory memory; 40513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch bool rv = memory.CreateNamed(s_test_name_, true, kDataSize); 41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EXPECT_TRUE(rv); 42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rv = memory.Map(kDataSize); 43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EXPECT_TRUE(rv); 44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int *ptr = static_cast<int*>(memory.memory()) + id_; 45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EXPECT_EQ(*ptr, 0); 46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (int idx = 0; idx < 100; idx++) { 48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *ptr = idx; 49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PlatformThread::Sleep(1); // Short wait. 50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EXPECT_EQ(*ptr, idx); 51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memory.Close(); 54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private: 57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int16 id_; 58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick static const char* const s_test_name_; 60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DISALLOW_COPY_AND_ASSIGN(MultipleThreadMain); 62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst char* const MultipleThreadMain::s_test_name_ = 653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick "SharedMemoryOpenThreadTest"; 66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// TODO(port): 68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// This test requires the ability to pass file descriptors between processes. 69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// We haven't done that yet in Chrome for POSIX. 70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(OS_WIN) 71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Each thread will open the shared memory. Each thread will take the memory, 72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// and keep changing it while trying to lock it, with some small pauses in 73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// between. Verify that each thread's value in the shared memory is always 74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// correct. 75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass MultipleLockThread : public PlatformThread::Delegate { 76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public: 77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott explicit MultipleLockThread(int id) : id_(id) {} 78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ~MultipleLockThread() {} 79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // PlatformThread::Delegate interface. 81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void ThreadMain() { 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const uint32 kDataSize = sizeof(int); 83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SharedMemoryHandle handle = NULL; 84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott { 85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SharedMemory memory1; 86513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch EXPECT_TRUE(memory1.CreateNamed("SharedMemoryMultipleLockThreadTest", 87513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch true, kDataSize)); 88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EXPECT_TRUE(memory1.ShareToProcess(GetCurrentProcess(), &handle)); 89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // TODO(paulg): Implement this once we have a posix version of 90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // SharedMemory::ShareToProcess. 91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EXPECT_TRUE(true); 92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SharedMemory memory2(handle, false); 95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EXPECT_TRUE(memory2.Map(kDataSize)); 96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott volatile int* const ptr = static_cast<int*>(memory2.memory()); 97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (int idx = 0; idx < 20; idx++) { 99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memory2.Lock(); 100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int i = (id_ << 16) + idx; 101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *ptr = i; 102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PlatformThread::Sleep(1); // Short wait. 103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EXPECT_EQ(*ptr, i); 104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memory2.Unlock(); 105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memory2.Close(); 108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private: 111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int id_; 112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DISALLOW_COPY_AND_ASSIGN(MultipleLockThread); 114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif 116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} // namespace 118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST(SharedMemoryTest, OpenClose) { 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const uint32 kDataSize = 1024; 1213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick std::string test_name = "SharedMemoryOpenCloseTest"; 122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Open two handles to a memory segment, confirm that they are mapped 124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // separately yet point to the same space. 125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SharedMemory memory1; 126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool rv = memory1.Delete(test_name); 127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EXPECT_TRUE(rv); 128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rv = memory1.Delete(test_name); 129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EXPECT_TRUE(rv); 130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rv = memory1.Open(test_name, false); 131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EXPECT_FALSE(rv); 132513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch rv = memory1.CreateNamed(test_name, false, kDataSize); 133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EXPECT_TRUE(rv); 134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rv = memory1.Map(kDataSize); 135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EXPECT_TRUE(rv); 136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SharedMemory memory2; 137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rv = memory2.Open(test_name, false); 138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EXPECT_TRUE(rv); 139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rv = memory2.Map(kDataSize); 140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EXPECT_TRUE(rv); 141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EXPECT_NE(memory1.memory(), memory2.memory()); // Compare the pointers. 142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Make sure we don't segfault. (it actually happened!) 144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ASSERT_NE(memory1.memory(), static_cast<void*>(NULL)); 145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ASSERT_NE(memory2.memory(), static_cast<void*>(NULL)); 146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Write data to the first memory segment, verify contents of second. 148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memset(memory1.memory(), '1', kDataSize); 149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EXPECT_EQ(memcmp(memory1.memory(), memory2.memory(), kDataSize), 0); 150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Close the first memory segment, and verify the second has the right data. 152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memory1.Close(); 153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott char *start_ptr = static_cast<char *>(memory2.memory()); 154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott char *end_ptr = start_ptr + kDataSize; 155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (char* ptr = start_ptr; ptr < end_ptr; ptr++) 156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EXPECT_EQ(*ptr, '1'); 157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Close the second memory segment. 159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memory2.Close(); 160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rv = memory1.Delete(test_name); 162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EXPECT_TRUE(rv); 163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rv = memory2.Delete(test_name); 164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EXPECT_TRUE(rv); 165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 167513209b27ff55e2841eac0e4120199c23acce758Ben MurdochTEST(SharedMemoryTest, OpenExclusive) { 168513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const uint32 kDataSize = 1024; 169513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const uint32 kDataSize2 = 2048; 170513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch std::ostringstream test_name_stream; 171513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch test_name_stream << "SharedMemoryOpenExclusiveTest." 172513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch << Time::Now().ToDoubleT(); 173513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch std::string test_name = test_name_stream.str(); 174513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 175513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Open two handles to a memory segment and check that open_existing works 176513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // as expected. 177513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch SharedMemory memory1; 178513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch bool rv = memory1.CreateNamed(test_name, false, kDataSize); 179513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch EXPECT_TRUE(rv); 180513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 181513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Memory1 knows it's size because it created it. 182513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch EXPECT_EQ(memory1.created_size(), kDataSize); 183513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 184513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch rv = memory1.Map(kDataSize); 185513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch EXPECT_TRUE(rv); 186513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 187513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch memset(memory1.memory(), 'G', kDataSize); 188513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 189513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch SharedMemory memory2; 190513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Should not be able to create if openExisting is false. 191513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch rv = memory2.CreateNamed(test_name, false, kDataSize2); 192513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch EXPECT_FALSE(rv); 193513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 194513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Should be able to create with openExisting true. 195513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch rv = memory2.CreateNamed(test_name, true, kDataSize2); 196513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch EXPECT_TRUE(rv); 197513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 198513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Memory2 shouldn't know the size because we didn't create it. 199513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch EXPECT_EQ(memory2.created_size(), 0U); 200513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 201513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // We should be able to map the original size. 202513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch rv = memory2.Map(kDataSize); 203513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch EXPECT_TRUE(rv); 204513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 205513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Verify that opening memory2 didn't truncate or delete memory 1. 206513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch char *start_ptr = static_cast<char *>(memory2.memory()); 207513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch char *end_ptr = start_ptr + kDataSize; 208513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch for (char* ptr = start_ptr; ptr < end_ptr; ptr++) { 209513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch EXPECT_EQ(*ptr, 'G'); 210513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 211513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 212513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch memory1.Close(); 213513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch memory2.Close(); 214513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 215513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch rv = memory1.Delete(test_name); 216513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch EXPECT_TRUE(rv); 217513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 218513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 219c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Create a set of N threads to each open a shared memory segment and write to 220c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// it. Verify that they are always reading/writing consistent data. 221c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST(SharedMemoryTest, MultipleThreads) { 222c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott MultipleThreadMain::CleanUp(); 223c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // On POSIX we have a problem when 2 threads try to create the shmem 224c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // (a file) at exactly the same time, since create both creates the 225c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // file and zerofills it. We solve the problem for this unit test 226c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // (make it not flaky) by starting with 1 thread, then 227c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // intentionally don't clean up its shmem before running with 228c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // kNumThreads. 229c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 230c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int threadcounts[] = { 1, kNumThreads }; 231c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (size_t i = 0; i < sizeof(threadcounts) / sizeof(threadcounts); i++) { 232c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int numthreads = threadcounts[i]; 233c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott scoped_array<PlatformThreadHandle> thread_handles; 234c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott scoped_array<MultipleThreadMain*> thread_delegates; 235c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 236c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott thread_handles.reset(new PlatformThreadHandle[numthreads]); 237c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott thread_delegates.reset(new MultipleThreadMain*[numthreads]); 238c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 239c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Spawn the threads. 240c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (int16 index = 0; index < numthreads; index++) { 241c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PlatformThreadHandle pth; 242c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott thread_delegates[index] = new MultipleThreadMain(index); 243c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EXPECT_TRUE(PlatformThread::Create(0, thread_delegates[index], &pth)); 244c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott thread_handles[index] = pth; 245c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 246c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 247c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Wait for the threads to finish. 248c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (int index = 0; index < numthreads; index++) { 249c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PlatformThread::Join(thread_handles[index]); 250c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott delete thread_delegates[index]; 251c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 252c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 253c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott MultipleThreadMain::CleanUp(); 254c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 255c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 256c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// TODO(port): this test requires the MultipleLockThread class 257c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// (defined above), which requires the ability to pass file 258c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// descriptors between processes. We haven't done that yet in Chrome 259c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// for POSIX. 260c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(OS_WIN) 261c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Create a set of threads to each open a shared memory segment and write to it 262c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// with the lock held. Verify that they are always reading/writing consistent 263c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// data. 264c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST(SharedMemoryTest, Lock) { 265c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PlatformThreadHandle thread_handles[kNumThreads]; 266c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott MultipleLockThread* thread_delegates[kNumThreads]; 267c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 268c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Spawn the threads. 269c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (int index = 0; index < kNumThreads; ++index) { 270c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PlatformThreadHandle pth; 271c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott thread_delegates[index] = new MultipleLockThread(index); 272c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EXPECT_TRUE(PlatformThread::Create(0, thread_delegates[index], &pth)); 273c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott thread_handles[index] = pth; 274c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 275c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 276c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Wait for the threads to finish. 277c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (int index = 0; index < kNumThreads; ++index) { 278c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PlatformThread::Join(thread_handles[index]); 279c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott delete thread_delegates[index]; 280c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 281c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 282c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif 283c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 284c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Allocate private (unique) shared memory with an empty string for a 285c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// name. Make sure several of them don't point to the same thing as 286c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// we might expect if the names are equal. 287c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST(SharedMemoryTest, AnonymousPrivate) { 288c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int i, j; 289c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int count = 4; 290c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool rv; 291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const uint32 kDataSize = 8192; 292c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 293c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott scoped_array<SharedMemory> memories(new SharedMemory[count]); 294c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott scoped_array<int*> pointers(new int*[count]); 295c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ASSERT_TRUE(memories.get()); 296c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ASSERT_TRUE(pointers.get()); 297c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 298c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (i = 0; i < count; i++) { 299513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch rv = memories[i].CreateAndMapAnonymous(kDataSize); 300c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EXPECT_TRUE(rv); 301c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int *ptr = static_cast<int*>(memories[i].memory()); 302c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EXPECT_TRUE(ptr); 303c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott pointers[i] = ptr; 304c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 305c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 306c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (i = 0; i < count; i++) { 307c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // zero out the first int in each except for i; for that one, make it 100. 308c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (j = 0; j < count; j++) { 309c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (i == j) 310c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott pointers[j][0] = 100; 311c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else 312c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott pointers[j][0] = 0; 313c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 314c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // make sure there is no bleeding of the 100 into the other pointers 315c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (j = 0; j < count; j++) { 316c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (i == j) 317c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EXPECT_EQ(100, pointers[j][0]); 318c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else 319c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EXPECT_EQ(0, pointers[j][0]); 320c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 321c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 322c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 323c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (int i = 0; i < count; i++) { 324c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memories[i].Close(); 325c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 326c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 327c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 328c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// On POSIX it is especially important we test shmem across processes, 329c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// not just across threads. But the test is enabled on all platforms. 3303f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenclass SharedMemoryProcessTest : public MultiProcessTest { 331c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public: 332c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 333c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott static void CleanUp() { 334c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SharedMemory memory; 335c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memory.Delete(s_test_name_); 336c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 337c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 338c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott static int TaskTestMain() { 339c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int errors = 0; 340731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick mac::ScopedNSAutoreleasePool pool; // noop if not OSX 341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const uint32 kDataSize = 1024; 342c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SharedMemory memory; 343513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch bool rv = memory.CreateNamed(s_test_name_, true, kDataSize); 344c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EXPECT_TRUE(rv); 345c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (rv != true) 346c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott errors++; 347c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rv = memory.Map(kDataSize); 348c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EXPECT_TRUE(rv); 349c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (rv != true) 350c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott errors++; 351c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int *ptr = static_cast<int*>(memory.memory()); 352c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 353c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (int idx = 0; idx < 20; idx++) { 354c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memory.Lock(); 355c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int i = (1 << 16) + idx; 356c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *ptr = i; 357c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PlatformThread::Sleep(10); // Short wait. 358c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (*ptr != i) 359c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott errors++; 360c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memory.Unlock(); 361c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 362c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 363c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memory.Close(); 364c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return errors; 365c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 366c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 367c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private: 3683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick static const char* const s_test_name_; 369c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 370c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 3713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst char* const SharedMemoryProcessTest::s_test_name_ = "MPMem"; 372c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 373c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 374513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#if defined(OS_MACOSX) 375513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#define MAYBE_Tasks FLAKY_Tasks 376513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#else 377513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#define MAYBE_Tasks Tasks 378513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#endif 379513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 380513209b27ff55e2841eac0e4120199c23acce758Ben MurdochTEST_F(SharedMemoryProcessTest, MAYBE_Tasks) { 381c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SharedMemoryProcessTest::CleanUp(); 382c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 3833f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen ProcessHandle handles[kNumTasks]; 384c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (int index = 0; index < kNumTasks; ++index) { 3853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick handles[index] = SpawnChild("SharedMemoryTestMain", false); 386c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 387c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 388c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int exit_code = 0; 389c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (int index = 0; index < kNumTasks; ++index) { 3903f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen EXPECT_TRUE(WaitForExitCode(handles[index], &exit_code)); 391c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EXPECT_TRUE(exit_code == 0); 392c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 393c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 394c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SharedMemoryProcessTest::CleanUp(); 395c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 396c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 397c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottMULTIPROCESS_TEST_MAIN(SharedMemoryTestMain) { 398c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return SharedMemoryProcessTest::TaskTestMain(); 399c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 400c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 401c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} // namespace base 402