shared_memory_unittest.cc revision 36040ed30c39d2106a2cd5ec033e98b71302a744
1d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti// Use of this source code is governed by a BSD-style license that can be
3d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti// found in the LICENSE file.
4d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti
5d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti#include "base/memory/shared_memory.h"
6d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti
7d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti#include <stddef.h>
8d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti#include <stdint.h>
9d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti
10d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti#include <memory>
11d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti
12d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti#include "base/atomicops.h"
13d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti#include "base/macros.h"
14d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti#include "base/memory/shared_memory_handle.h"
15d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti#include "base/process/kill.h"
16d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti#include "base/rand_util.h"
17d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti#include "base/strings/string_number_conversions.h"
18d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti#include "base/sys_info.h"
19d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti#include "base/test/multiprocess_test.h"
20d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti#include "base/threading/platform_thread.h"
21d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti#include "base/time/time.h"
22d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti#include "build/build_config.h"
23d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti#include "testing/gtest/include/gtest/gtest.h"
24d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti#include "testing/multiprocess_func_list.h"
25a86af3ac653113b302dcfa9facc6c67159fabf1bDanny van Bruggen
26d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti#if defined(OS_POSIX)
27d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti#include <errno.h>
287e85803c3a66d340e1cbdbc6c98081104ad412c3Federico Tomassetti#include <fcntl.h>
290c57e5931daabf22632ad49f2ad0657df59b858bFederico Tomassetti#include <sys/mman.h>
30f0f313058c4389cd48052112e3fb906c060be30fFederico Tomassetti#include <sys/stat.h>
31f8f8a6fc81e2d717568c0ab9895605c1f4b69bbcFederico Tomassetti#include <sys/types.h>
32d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti#include <unistd.h>
33d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti#endif
34d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti
35de11a2ae80166defacd1f9c51b77f52be4b53eb1Federico Tomassetti#if defined(OS_WIN)
36d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti#include "base/win/scoped_handle.h"
3703df427399267338f87748888d1f921bb9a1c0daFederico Tomassetti#endif
3803df427399267338f87748888d1f921bb9a1c0daFederico Tomassetti
399e91a1d76dbfb28f2bc7c32028fe459b073ee861Federico Tomassettinamespace base {
4003df427399267338f87748888d1f921bb9a1c0daFederico Tomassetti
41d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassettinamespace {
4215cb49e74025eb4011187f31735aa4772993fb5dFederico Tomassetti
43d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti#if !defined(OS_MACOSX)
44d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti// Each thread will open the shared memory.  Each thread will take a different 4
45d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti// byte int pointer, and keep changing it, with some small pauses in between.
46d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti// Verify that each thread's value in the shared memory is always correct.
47d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetticlass MultipleThreadMain : public PlatformThread::Delegate {
48d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti public:
49d6aebf46978852659303ad0fe057e1cddd9e391dFederico Tomassetti  explicit MultipleThreadMain(int16_t id) : id_(id) {}
50d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti  ~MultipleThreadMain() override {}
51d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti
52d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti  static void CleanUp() {
5383d60da8afce695e7356af94c549e30ab585448cDanny van Bruggen    SharedMemory memory;
546a1ee724c337694ee28b2a09af41c236b880ba66Danny van Bruggen    memory.Delete(s_test_name_);
558324ea0bfcac6db2f2ef2c3d12a84744842aa8adDanny van Bruggen  }
56d4db09d04aca5a9df4278652d55d680c4a826efcFederico Tomassetti
5748789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen  // PlatformThread::Delegate interface.
5840d239e3cb84cc77fcd16c3f9fde3f4f8b635419Federico Tomassetti  void ThreadMain() override {
59d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti    const uint32_t kDataSize = 1024;
60d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti    SharedMemory memory;
619a228915f61892f6ba99fcf1e42e42e1e2622a00Danny van Bruggen    bool rv = memory.CreateNamedDeprecated(s_test_name_, true, kDataSize);
628324ea0bfcac6db2f2ef2c3d12a84744842aa8adDanny van Bruggen    EXPECT_TRUE(rv);
63d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti    rv = memory.Map(kDataSize);
64d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti    EXPECT_TRUE(rv);
65d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti    int* ptr = static_cast<int*>(memory.memory()) + id_;
66a86af3ac653113b302dcfa9facc6c67159fabf1bDanny van Bruggen    EXPECT_EQ(0, *ptr);
67a86af3ac653113b302dcfa9facc6c67159fabf1bDanny van Bruggen
68a86af3ac653113b302dcfa9facc6c67159fabf1bDanny van Bruggen    for (int idx = 0; idx < 100; idx++) {
6948789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen      *ptr = idx;
7048789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen      PlatformThread::Sleep(TimeDelta::FromMilliseconds(1));
71a86af3ac653113b302dcfa9facc6c67159fabf1bDanny van Bruggen      EXPECT_EQ(*ptr, idx);
72d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti    }
73d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti    // Reset back to 0 for the next test that uses the same name.
74d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti    *ptr = 0;
75d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti
76d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti    memory.Close();
77d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti  }
7848789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen
796149218487aac50fad2256c8723639671747d7bbDanny van Bruggen private:
80d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti  int16_t id_;
8140d239e3cb84cc77fcd16c3f9fde3f4f8b635419Federico Tomassetti
8240d239e3cb84cc77fcd16c3f9fde3f4f8b635419Federico Tomassetti  static const char s_test_name_[];
83d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti
8440d239e3cb84cc77fcd16c3f9fde3f4f8b635419Federico Tomassetti  DISALLOW_COPY_AND_ASSIGN(MultipleThreadMain);
8540d239e3cb84cc77fcd16c3f9fde3f4f8b635419Federico Tomassetti};
8640d239e3cb84cc77fcd16c3f9fde3f4f8b635419Federico Tomassetti
8740d239e3cb84cc77fcd16c3f9fde3f4f8b635419Federico Tomassetticonst char MultipleThreadMain::s_test_name_[] =
888324ea0bfcac6db2f2ef2c3d12a84744842aa8adDanny van Bruggen    "SharedMemoryOpenThreadTest";
89d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti#endif  // !defined(OS_MACOSX)
90d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti
91d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti}  // namespace
92dd0f96d32e589249fdd05ab40f9d087c79415730Danny van Bruggen
93dd0f96d32e589249fdd05ab40f9d087c79415730Danny van Bruggen// Android/Mac doesn't support SharedMemory::Open/Delete/
94dd0f96d32e589249fdd05ab40f9d087c79415730Danny van Bruggen// CreateNamedDeprecated(openExisting=true)
95dd0f96d32e589249fdd05ab40f9d087c79415730Danny van Bruggen#if !defined(OS_ANDROID) && !defined(OS_MACOSX)
9648789abfd3738d660abb6f8cd758a40c57379597Danny van BruggenTEST(SharedMemoryTest, OpenClose) {
9748789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen  const uint32_t kDataSize = 1024;
9848789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen  std::string test_name = "SharedMemoryOpenCloseTest";
9948789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen
100dd0f96d32e589249fdd05ab40f9d087c79415730Danny van Bruggen  // Open two handles to a memory segment, confirm that they are mapped
10148789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen  // separately yet point to the same space.
102dd0f96d32e589249fdd05ab40f9d087c79415730Danny van Bruggen  SharedMemory memory1;
103dd0f96d32e589249fdd05ab40f9d087c79415730Danny van Bruggen  bool rv = memory1.Delete(test_name);
104dd0f96d32e589249fdd05ab40f9d087c79415730Danny van Bruggen  EXPECT_TRUE(rv);
1058324ea0bfcac6db2f2ef2c3d12a84744842aa8adDanny van Bruggen  rv = memory1.Delete(test_name);
1066149218487aac50fad2256c8723639671747d7bbDanny van Bruggen  EXPECT_TRUE(rv);
1078324ea0bfcac6db2f2ef2c3d12a84744842aa8adDanny van Bruggen  rv = memory1.Open(test_name, false);
1088324ea0bfcac6db2f2ef2c3d12a84744842aa8adDanny van Bruggen  EXPECT_FALSE(rv);
109d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti  rv = memory1.CreateNamedDeprecated(test_name, false, kDataSize);
1107a48b21bb866b8d4baf2ce50992c0dfd93f4bc3bFederico Tomassetti  EXPECT_TRUE(rv);
1116149218487aac50fad2256c8723639671747d7bbDanny van Bruggen  rv = memory1.Map(kDataSize);
1127a48b21bb866b8d4baf2ce50992c0dfd93f4bc3bFederico Tomassetti  EXPECT_TRUE(rv);
1138324ea0bfcac6db2f2ef2c3d12a84744842aa8adDanny van Bruggen  SharedMemory memory2;
1148324ea0bfcac6db2f2ef2c3d12a84744842aa8adDanny van Bruggen  rv = memory2.Open(test_name, false);
115dd0f96d32e589249fdd05ab40f9d087c79415730Danny van Bruggen  EXPECT_TRUE(rv);
116d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti  rv = memory2.Map(kDataSize);
1179a228915f61892f6ba99fcf1e42e42e1e2622a00Danny van Bruggen  EXPECT_TRUE(rv);
1186149218487aac50fad2256c8723639671747d7bbDanny van Bruggen  EXPECT_NE(memory1.memory(), memory2.memory());  // Compare the pointers.
1196149218487aac50fad2256c8723639671747d7bbDanny van Bruggen
1206149218487aac50fad2256c8723639671747d7bbDanny van Bruggen  // Make sure we don't segfault. (it actually happened!)
121d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti  ASSERT_NE(memory1.memory(), static_cast<void*>(NULL));
1226149218487aac50fad2256c8723639671747d7bbDanny van Bruggen  ASSERT_NE(memory2.memory(), static_cast<void*>(NULL));
1236149218487aac50fad2256c8723639671747d7bbDanny van Bruggen
1246149218487aac50fad2256c8723639671747d7bbDanny van Bruggen  // Write data to the first memory segment, verify contents of second.
1256149218487aac50fad2256c8723639671747d7bbDanny van Bruggen  memset(memory1.memory(), '1', kDataSize);
1266149218487aac50fad2256c8723639671747d7bbDanny van Bruggen  EXPECT_EQ(memcmp(memory1.memory(), memory2.memory(), kDataSize), 0);
1276149218487aac50fad2256c8723639671747d7bbDanny van Bruggen
1286149218487aac50fad2256c8723639671747d7bbDanny van Bruggen  // Close the first memory segment, and verify the second has the right data.
1296149218487aac50fad2256c8723639671747d7bbDanny van Bruggen  memory1.Close();
1306149218487aac50fad2256c8723639671747d7bbDanny van Bruggen  char* start_ptr = static_cast<char*>(memory2.memory());
1316149218487aac50fad2256c8723639671747d7bbDanny van Bruggen  char* end_ptr = start_ptr + kDataSize;
132d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti  for (char* ptr = start_ptr; ptr < end_ptr; ptr++)
133d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti    EXPECT_EQ(*ptr, '1');
134d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti
13540d239e3cb84cc77fcd16c3f9fde3f4f8b635419Federico Tomassetti  // Close the second memory segment.
13640d239e3cb84cc77fcd16c3f9fde3f4f8b635419Federico Tomassetti  memory2.Close();
137d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti
138d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti  rv = memory1.Delete(test_name);
1395e40a8838a5118df43a847ce8c52dddac0843b22Federico Tomassetti  EXPECT_TRUE(rv);
140d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti  rv = memory2.Delete(test_name);
141d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti  EXPECT_TRUE(rv);
142793f207b1b17498cdb201309ba94c25cb9e4fe20Federico Tomassetti}
14308bd6db12a6e7a8c9eebba117981bbde6399d4ffFederico Tomassetti
14408bd6db12a6e7a8c9eebba117981bbde6399d4ffFederico TomassettiTEST(SharedMemoryTest, OpenExclusive) {
14508bd6db12a6e7a8c9eebba117981bbde6399d4ffFederico Tomassetti  const uint32_t kDataSize = 1024;
1466149218487aac50fad2256c8723639671747d7bbDanny van Bruggen  const uint32_t kDataSize2 = 2048;
1477a48b21bb866b8d4baf2ce50992c0dfd93f4bc3bFederico Tomassetti  std::ostringstream test_name_stream;
14808bd6db12a6e7a8c9eebba117981bbde6399d4ffFederico Tomassetti  test_name_stream << "SharedMemoryOpenExclusiveTest."
14908bd6db12a6e7a8c9eebba117981bbde6399d4ffFederico Tomassetti                   << Time::Now().ToDoubleT();
15048789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen  std::string test_name = test_name_stream.str();
1516a1ee724c337694ee28b2a09af41c236b880ba66Danny van Bruggen
1527a48b21bb866b8d4baf2ce50992c0dfd93f4bc3bFederico Tomassetti  // Open two handles to a memory segment and check that
15308bd6db12a6e7a8c9eebba117981bbde6399d4ffFederico Tomassetti  // open_existing_deprecated works as expected.
15448789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen  SharedMemory memory1;
15583d60da8afce695e7356af94c549e30ab585448cDanny van Bruggen  bool rv = memory1.CreateNamedDeprecated(test_name, false, kDataSize);
15648789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen  EXPECT_TRUE(rv);
15708bd6db12a6e7a8c9eebba117981bbde6399d4ffFederico Tomassetti
15808bd6db12a6e7a8c9eebba117981bbde6399d4ffFederico Tomassetti  // Memory1 knows it's size because it created it.
15908bd6db12a6e7a8c9eebba117981bbde6399d4ffFederico Tomassetti  EXPECT_EQ(memory1.requested_size(), kDataSize);
16008bd6db12a6e7a8c9eebba117981bbde6399d4ffFederico Tomassetti
16108bd6db12a6e7a8c9eebba117981bbde6399d4ffFederico Tomassetti  rv = memory1.Map(kDataSize);
1629192b9d17903947058b755b987d1c57a05821e58Danny van Bruggen  EXPECT_TRUE(rv);
16308bd6db12a6e7a8c9eebba117981bbde6399d4ffFederico Tomassetti
16408bd6db12a6e7a8c9eebba117981bbde6399d4ffFederico Tomassetti  // The mapped memory1 must be at least the size we asked for.
16508bd6db12a6e7a8c9eebba117981bbde6399d4ffFederico Tomassetti  EXPECT_GE(memory1.mapped_size(), kDataSize);
16608bd6db12a6e7a8c9eebba117981bbde6399d4ffFederico Tomassetti
16708bd6db12a6e7a8c9eebba117981bbde6399d4ffFederico Tomassetti  // The mapped memory1 shouldn't exceed rounding for allocation granularity.
168516947a3d4eda478d20dcbb4216d6c52cf11d169Federico Tomassetti  EXPECT_LT(memory1.mapped_size(),
16908bd6db12a6e7a8c9eebba117981bbde6399d4ffFederico Tomassetti            kDataSize + SysInfo::VMAllocationGranularity());
17048789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen
17183d60da8afce695e7356af94c549e30ab585448cDanny van Bruggen  memset(memory1.memory(), 'G', kDataSize);
17248789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen
17308bd6db12a6e7a8c9eebba117981bbde6399d4ffFederico Tomassetti  SharedMemory memory2;
17408bd6db12a6e7a8c9eebba117981bbde6399d4ffFederico Tomassetti  // Should not be able to create if openExisting is false.
17508bd6db12a6e7a8c9eebba117981bbde6399d4ffFederico Tomassetti  rv = memory2.CreateNamedDeprecated(test_name, false, kDataSize2);
17648789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen  EXPECT_FALSE(rv);
17783d60da8afce695e7356af94c549e30ab585448cDanny van Bruggen
17808bd6db12a6e7a8c9eebba117981bbde6399d4ffFederico Tomassetti  // Should be able to create with openExisting true.
17908bd6db12a6e7a8c9eebba117981bbde6399d4ffFederico Tomassetti  rv = memory2.CreateNamedDeprecated(test_name, true, kDataSize2);
18008bd6db12a6e7a8c9eebba117981bbde6399d4ffFederico Tomassetti  EXPECT_TRUE(rv);
18108bd6db12a6e7a8c9eebba117981bbde6399d4ffFederico Tomassetti
182793f207b1b17498cdb201309ba94c25cb9e4fe20Federico Tomassetti  // Memory2 shouldn't know the size because we didn't create it.
1836149218487aac50fad2256c8723639671747d7bbDanny van Bruggen  EXPECT_EQ(memory2.requested_size(), 0U);
184f0f313058c4389cd48052112e3fb906c060be30fFederico Tomassetti
185f0f313058c4389cd48052112e3fb906c060be30fFederico Tomassetti  // We should be able to map the original size.
186f0f313058c4389cd48052112e3fb906c060be30fFederico Tomassetti  rv = memory2.Map(kDataSize);
187f0f313058c4389cd48052112e3fb906c060be30fFederico Tomassetti  EXPECT_TRUE(rv);
188c73ae5d79b62de91209477538b45ab5216fb108eFederico Tomassetti
189c73ae5d79b62de91209477538b45ab5216fb108eFederico Tomassetti  // The mapped memory2 must be at least the size of the original.
190d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti  EXPECT_GE(memory2.mapped_size(), kDataSize);
191d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti
192d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti  // The mapped memory2 shouldn't exceed rounding for allocation granularity.
19315cb49e74025eb4011187f31735aa4772993fb5dFederico Tomassetti  EXPECT_LT(memory2.mapped_size(),
1946149218487aac50fad2256c8723639671747d7bbDanny van Bruggen            kDataSize2 + SysInfo::VMAllocationGranularity());
195d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti
19646d1656c7a0b6a5313077495d02f4f98f69be414Danny van Bruggen  // Verify that opening memory2 didn't truncate or delete memory 1.
197d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti  char* start_ptr = static_cast<char*>(memory2.memory());
19848789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen  char* end_ptr = start_ptr + kDataSize;
199d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti  for (char* ptr = start_ptr; ptr < end_ptr; ptr++) {
200d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti    EXPECT_EQ(*ptr, 'G');
201d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti  }
202d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti
203ca2826ef2cf2a40c0c0d061ee68ba525d2481becFederico Tomassetti  memory1.Close();
204ca2826ef2cf2a40c0c0d061ee68ba525d2481becFederico Tomassetti  memory2.Close();
20515cb49e74025eb4011187f31735aa4772993fb5dFederico Tomassetti
2066149218487aac50fad2256c8723639671747d7bbDanny van Bruggen  rv = memory1.Delete(test_name);
20746d1656c7a0b6a5313077495d02f4f98f69be414Danny van Bruggen  EXPECT_TRUE(rv);
208ca2826ef2cf2a40c0c0d061ee68ba525d2481becFederico Tomassetti}
209d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti#endif  // !defined(OS_ANDROID) && !defined(OS_MACOSX)
210d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti
211d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti// Check that memory is still mapped after its closed.
2126149218487aac50fad2256c8723639671747d7bbDanny van BruggenTEST(SharedMemoryTest, CloseNoUnmap) {
213198c4d502c00c07c674543bfb1eebedafcf4b193Federico Tomassetti  const size_t kDataSize = 4096;
214d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti
2158a2ab8b7cc640f95ca1fb10bc0e8534d766e9299Sergey Reshetnik  SharedMemory memory;
2168a2ab8b7cc640f95ca1fb10bc0e8534d766e9299Sergey Reshetnik  ASSERT_TRUE(memory.CreateAndMapAnonymous(kDataSize));
2178a2ab8b7cc640f95ca1fb10bc0e8534d766e9299Sergey Reshetnik  char* ptr = static_cast<char*>(memory.memory());
2188324ea0bfcac6db2f2ef2c3d12a84744842aa8adDanny van Bruggen  ASSERT_NE(ptr, static_cast<void*>(NULL));
2193608acd141a4d3c2105672b4b19b26e4d2badb5cDanny van Bruggen  memset(ptr, 'G', kDataSize);
2202a393b02804ec16ccec1877ca3a0289c924cc384Sergey Reshetnik
2212a393b02804ec16ccec1877ca3a0289c924cc384Sergey Reshetnik  memory.Close();
2222a393b02804ec16ccec1877ca3a0289c924cc384Sergey Reshetnik
2232a393b02804ec16ccec1877ca3a0289c924cc384Sergey Reshetnik  EXPECT_EQ(ptr, memory.memory());
224d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti  EXPECT_EQ(SharedMemory::NULLHandle(), memory.handle());
225d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti
226d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti  for (size_t i = 0; i < kDataSize; i++) {
227d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti    EXPECT_EQ('G', ptr[i]);
228d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti  }
229d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti
230d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti  memory.Unmap();
231d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti  EXPECT_EQ(nullptr, memory.memory());
232d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti}
233d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti
2349a7cda9c8fb4cbb33b5f38daea68921ae201ef31Federico Tomassetti#if !defined(OS_MACOSX)
2356149218487aac50fad2256c8723639671747d7bbDanny van Bruggen// Create a set of N threads to each open a shared memory segment and write to
2369a7cda9c8fb4cbb33b5f38daea68921ae201ef31Federico Tomassetti// it. Verify that they are always reading/writing consistent data.
237d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico TomassettiTEST(SharedMemoryTest, MultipleThreads) {
238d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti  const int kNumThreads = 5;
239d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti
240d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti  MultipleThreadMain::CleanUp();
2412a393b02804ec16ccec1877ca3a0289c924cc384Sergey Reshetnik  // On POSIX we have a problem when 2 threads try to create the shmem
2422a393b02804ec16ccec1877ca3a0289c924cc384Sergey Reshetnik  // (a file) at exactly the same time, since create both creates the
2432a393b02804ec16ccec1877ca3a0289c924cc384Sergey Reshetnik  // file and zerofills it.  We solve the problem for this unit test
2442a393b02804ec16ccec1877ca3a0289c924cc384Sergey Reshetnik  // (make it not flaky) by starting with 1 thread, then
2452a393b02804ec16ccec1877ca3a0289c924cc384Sergey Reshetnik  // intentionally don't clean up its shmem before running with
2462a393b02804ec16ccec1877ca3a0289c924cc384Sergey Reshetnik  // kNumThreads.
2472a393b02804ec16ccec1877ca3a0289c924cc384Sergey Reshetnik
2482a393b02804ec16ccec1877ca3a0289c924cc384Sergey Reshetnik  int threadcounts[] = { 1, kNumThreads };
2492a393b02804ec16ccec1877ca3a0289c924cc384Sergey Reshetnik  for (size_t i = 0; i < arraysize(threadcounts); i++) {
2502a393b02804ec16ccec1877ca3a0289c924cc384Sergey Reshetnik    int numthreads = threadcounts[i];
2512a393b02804ec16ccec1877ca3a0289c924cc384Sergey Reshetnik    std::unique_ptr<PlatformThreadHandle[]> thread_handles;
2522a393b02804ec16ccec1877ca3a0289c924cc384Sergey Reshetnik    std::unique_ptr<MultipleThreadMain* []> thread_delegates;
2532a393b02804ec16ccec1877ca3a0289c924cc384Sergey Reshetnik
2542a393b02804ec16ccec1877ca3a0289c924cc384Sergey Reshetnik    thread_handles.reset(new PlatformThreadHandle[numthreads]);
2552a393b02804ec16ccec1877ca3a0289c924cc384Sergey Reshetnik    thread_delegates.reset(new MultipleThreadMain*[numthreads]);
2562a393b02804ec16ccec1877ca3a0289c924cc384Sergey Reshetnik
2572a393b02804ec16ccec1877ca3a0289c924cc384Sergey Reshetnik    // Spawn the threads.
2586149218487aac50fad2256c8723639671747d7bbDanny van Bruggen    for (int16_t index = 0; index < numthreads; index++) {
259d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti      PlatformThreadHandle pth;
260d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti      thread_delegates[index] = new MultipleThreadMain(index);
261d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti      EXPECT_TRUE(PlatformThread::Create(0, thread_delegates[index], &pth));
262d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti      thread_handles[index] = pth;
263d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti    }
264f671c0e58dbbe6688926060fee6a9b6cbc9d8f76Federico Tomassetti
265516947a3d4eda478d20dcbb4216d6c52cf11d169Federico Tomassetti    // Wait for the threads to finish.
266516947a3d4eda478d20dcbb4216d6c52cf11d169Federico Tomassetti    for (int index = 0; index < numthreads; index++) {
267516947a3d4eda478d20dcbb4216d6c52cf11d169Federico Tomassetti      PlatformThread::Join(thread_handles[index]);
2686149218487aac50fad2256c8723639671747d7bbDanny van Bruggen      delete thread_delegates[index];
269f671c0e58dbbe6688926060fee6a9b6cbc9d8f76Federico Tomassetti    }
270d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti  }
271d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti  MultipleThreadMain::CleanUp();
2723608acd141a4d3c2105672b4b19b26e4d2badb5cDanny van Bruggen}
273d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti#endif
27448789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen
2756149218487aac50fad2256c8723639671747d7bbDanny van Bruggen// Allocate private (unique) shared memory with an empty string for a
276d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti// name.  Make sure several of them don't point to the same thing as
2772a393b02804ec16ccec1877ca3a0289c924cc384Sergey Reshetnik// we might expect if the names are equal.
278d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico TomassettiTEST(SharedMemoryTest, AnonymousPrivate) {
279de11a2ae80166defacd1f9c51b77f52be4b53eb1Federico Tomassetti  int i, j;
280de11a2ae80166defacd1f9c51b77f52be4b53eb1Federico Tomassetti  int count = 4;
281de11a2ae80166defacd1f9c51b77f52be4b53eb1Federico Tomassetti  bool rv;
2826149218487aac50fad2256c8723639671747d7bbDanny van Bruggen  const uint32_t kDataSize = 8192;
283de11a2ae80166defacd1f9c51b77f52be4b53eb1Federico Tomassetti
28446d1656c7a0b6a5313077495d02f4f98f69be414Danny van Bruggen  std::unique_ptr<SharedMemory[]> memories(new SharedMemory[count]);
285de11a2ae80166defacd1f9c51b77f52be4b53eb1Federico Tomassetti  std::unique_ptr<int* []> pointers(new int*[count]);
286de711eeae58ca512235ce47ed433ed24658f4098Federico Tomassetti  ASSERT_TRUE(memories.get());
287de711eeae58ca512235ce47ed433ed24658f4098Federico Tomassetti  ASSERT_TRUE(pointers.get());
288de711eeae58ca512235ce47ed433ed24658f4098Federico Tomassetti
289de11a2ae80166defacd1f9c51b77f52be4b53eb1Federico Tomassetti  for (i = 0; i < count; i++) {
290de711eeae58ca512235ce47ed433ed24658f4098Federico Tomassetti    rv = memories[i].CreateAndMapAnonymous(kDataSize);
291de711eeae58ca512235ce47ed433ed24658f4098Federico Tomassetti    EXPECT_TRUE(rv);
292de711eeae58ca512235ce47ed433ed24658f4098Federico Tomassetti    int* ptr = static_cast<int*>(memories[i].memory());
293de711eeae58ca512235ce47ed433ed24658f4098Federico Tomassetti    EXPECT_TRUE(ptr);
294de711eeae58ca512235ce47ed433ed24658f4098Federico Tomassetti    pointers[i] = ptr;
295de711eeae58ca512235ce47ed433ed24658f4098Federico Tomassetti  }
296de711eeae58ca512235ce47ed433ed24658f4098Federico Tomassetti
297de711eeae58ca512235ce47ed433ed24658f4098Federico Tomassetti  for (i = 0; i < count; i++) {
298de711eeae58ca512235ce47ed433ed24658f4098Federico Tomassetti    // zero out the first int in each except for i; for that one, make it 100.
299de711eeae58ca512235ce47ed433ed24658f4098Federico Tomassetti    for (j = 0; j < count; j++) {
300de711eeae58ca512235ce47ed433ed24658f4098Federico Tomassetti      if (i == j)
301de11a2ae80166defacd1f9c51b77f52be4b53eb1Federico Tomassetti        pointers[j][0] = 100;
302dea490b3c4b649d5ede5f12dbf6740b816681cf2Federico Tomassetti      else
303de11a2ae80166defacd1f9c51b77f52be4b53eb1Federico Tomassetti        pointers[j][0] = 0;
304de11a2ae80166defacd1f9c51b77f52be4b53eb1Federico Tomassetti    }
305de11a2ae80166defacd1f9c51b77f52be4b53eb1Federico Tomassetti    // make sure there is no bleeding of the 100 into the other pointers
306de11a2ae80166defacd1f9c51b77f52be4b53eb1Federico Tomassetti    for (j = 0; j < count; j++) {
307d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti      if (i == j)
308d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti        EXPECT_EQ(100, pointers[j][0]);
309d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti      else
310d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti        EXPECT_EQ(0, pointers[j][0]);
311d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti    }
312d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti  }
3136149218487aac50fad2256c8723639671747d7bbDanny van Bruggen
314d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti  for (int i = 0; i < count; i++) {
315d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti    memories[i].Close();
316d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti  }
317d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti}
318d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti
319d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico TomassettiTEST(SharedMemoryTest, ShareReadOnly) {
320d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti  StringPiece contents = "Hello World";
321d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti
322d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti  SharedMemory writable_shmem;
323d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti  SharedMemoryCreateOptions options;
324d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti  options.size = contents.size();
325d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti  options.share_read_only = true;
3266149218487aac50fad2256c8723639671747d7bbDanny van Bruggen#if defined(OS_MACOSX) && !defined(OS_IOS)
327a86af3ac653113b302dcfa9facc6c67159fabf1bDanny van Bruggen  // The Mach functionality is tested in shared_memory_mac_unittest.cc.
328eeb2701b8cbc85c513d0759d6fa3f2fc41b81ebcFederico Tomassetti  options.type = SharedMemoryHandle::POSIX;
329d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti#endif
330a86af3ac653113b302dcfa9facc6c67159fabf1bDanny van Bruggen  ASSERT_TRUE(writable_shmem.Create(options));
331eeb2701b8cbc85c513d0759d6fa3f2fc41b81ebcFederico Tomassetti  ASSERT_TRUE(writable_shmem.Map(options.size));
332d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti  memcpy(writable_shmem.memory(), contents.data(), contents.size());
333d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti  EXPECT_TRUE(writable_shmem.Unmap());
334d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti
335d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti  SharedMemoryHandle readonly_handle;
336d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti  ASSERT_TRUE(writable_shmem.ShareReadOnlyToProcess(GetCurrentProcessHandle(),
337d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti                                                    &readonly_handle));
33848789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen  SharedMemory readonly_shmem(readonly_handle, /*readonly=*/true);
339de11a2ae80166defacd1f9c51b77f52be4b53eb1Federico Tomassetti
34048789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen  ASSERT_TRUE(readonly_shmem.Map(contents.size()));
341dec68cfc83301b4e7ee2bbf1886959d6aa05f85aFederico Tomassetti  EXPECT_EQ(contents,
342521384346671f17f0f4e6c2af86ba413aad83ef5Federico Tomassetti            StringPiece(static_cast<const char*>(readonly_shmem.memory()),
34383d60da8afce695e7356af94c549e30ab585448cDanny van Bruggen                        contents.size()));
344521384346671f17f0f4e6c2af86ba413aad83ef5Federico Tomassetti  EXPECT_TRUE(readonly_shmem.Unmap());
345521384346671f17f0f4e6c2af86ba413aad83ef5Federico Tomassetti
34683d60da8afce695e7356af94c549e30ab585448cDanny van Bruggen  // Make sure the writable instance is still writable.
347521384346671f17f0f4e6c2af86ba413aad83ef5Federico Tomassetti  ASSERT_TRUE(writable_shmem.Map(contents.size()));
348521384346671f17f0f4e6c2af86ba413aad83ef5Federico Tomassetti  StringPiece new_contents = "Goodbye";
34983d60da8afce695e7356af94c549e30ab585448cDanny van Bruggen  memcpy(writable_shmem.memory(), new_contents.data(), new_contents.size());
350521384346671f17f0f4e6c2af86ba413aad83ef5Federico Tomassetti  EXPECT_EQ(new_contents,
351521384346671f17f0f4e6c2af86ba413aad83ef5Federico Tomassetti            StringPiece(static_cast<const char*>(writable_shmem.memory()),
35283d60da8afce695e7356af94c549e30ab585448cDanny van Bruggen                        new_contents.size()));
353521384346671f17f0f4e6c2af86ba413aad83ef5Federico Tomassetti
354dec68cfc83301b4e7ee2bbf1886959d6aa05f85aFederico Tomassetti  // We'd like to check that if we send the read-only segment to another
35583d60da8afce695e7356af94c549e30ab585448cDanny van Bruggen  // process, then that other process can't reopen it read/write.  (Since that
356dec68cfc83301b4e7ee2bbf1886959d6aa05f85aFederico Tomassetti  // would be a security hole.)  Setting up multiple processes is hard in a
357521384346671f17f0f4e6c2af86ba413aad83ef5Federico Tomassetti  // unittest, so this test checks that the *current* process can't reopen the
35883d60da8afce695e7356af94c549e30ab585448cDanny van Bruggen  // segment read/write.  I think the test here is stronger than we actually
359521384346671f17f0f4e6c2af86ba413aad83ef5Federico Tomassetti  // care about, but there's a remote possibility that sending a file over a
360521384346671f17f0f4e6c2af86ba413aad83ef5Federico Tomassetti  // pipe would transform it into read/write.
36183d60da8afce695e7356af94c549e30ab585448cDanny van Bruggen  SharedMemoryHandle handle = readonly_shmem.handle();
362521384346671f17f0f4e6c2af86ba413aad83ef5Federico Tomassetti
363521384346671f17f0f4e6c2af86ba413aad83ef5Federico Tomassetti#if defined(OS_ANDROID)
36483d60da8afce695e7356af94c549e30ab585448cDanny van Bruggen  // The "read-only" handle is still writable on Android:
365521384346671f17f0f4e6c2af86ba413aad83ef5Federico Tomassetti  // http://crbug.com/320865
366dec68cfc83301b4e7ee2bbf1886959d6aa05f85aFederico Tomassetti  (void)handle;
367dec68cfc83301b4e7ee2bbf1886959d6aa05f85aFederico Tomassetti#elif defined(OS_POSIX)
368dec68cfc83301b4e7ee2bbf1886959d6aa05f85aFederico Tomassetti  int handle_fd = SharedMemory::GetFdFromSharedMemoryHandle(handle);
36948789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen  EXPECT_EQ(O_RDONLY, fcntl(handle_fd, F_GETFL) & O_ACCMODE)
370de11a2ae80166defacd1f9c51b77f52be4b53eb1Federico Tomassetti      << "The descriptor itself should be read-only.";
371f0f313058c4389cd48052112e3fb906c060be30fFederico Tomassetti
37248789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen  errno = 0;
37348789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen  void* writable = mmap(NULL, contents.size(), PROT_READ | PROT_WRITE,
374f0f313058c4389cd48052112e3fb906c060be30fFederico Tomassetti                        MAP_SHARED, handle_fd, 0);
375de11a2ae80166defacd1f9c51b77f52be4b53eb1Federico Tomassetti  int mmap_errno = errno;
37648789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen  EXPECT_EQ(MAP_FAILED, writable)
37703df427399267338f87748888d1f921bb9a1c0daFederico Tomassetti      << "It shouldn't be possible to re-mmap the descriptor writable.";
37803df427399267338f87748888d1f921bb9a1c0daFederico Tomassetti  EXPECT_EQ(EACCES, mmap_errno) << strerror(mmap_errno);
3796149218487aac50fad2256c8723639671747d7bbDanny van Bruggen  if (writable != MAP_FAILED)
38003df427399267338f87748888d1f921bb9a1c0daFederico Tomassetti    EXPECT_EQ(0, munmap(writable, readonly_shmem.mapped_size()));
38187b56cb1f18252c95d88b979a449f06d55def290Federico Tomassetti
38287db3c76d76680bd1bea566d44ab74b4dca55b71Federico Tomassetti#elif defined(OS_WIN)
38387b56cb1f18252c95d88b979a449f06d55def290Federico Tomassetti  EXPECT_EQ(NULL, MapViewOfFile(handle.GetHandle(), FILE_MAP_WRITE, 0, 0, 0))
38487db3c76d76680bd1bea566d44ab74b4dca55b71Federico Tomassetti      << "Shouldn't be able to map memory writable.";
38503df427399267338f87748888d1f921bb9a1c0daFederico Tomassetti
38648789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen  HANDLE temp_handle;
38746d1656c7a0b6a5313077495d02f4f98f69be414Danny van Bruggen  BOOL rv = ::DuplicateHandle(GetCurrentProcess(), handle.GetHandle(),
38887db3c76d76680bd1bea566d44ab74b4dca55b71Federico Tomassetti                              GetCurrentProcess(), &temp_handle,
38987db3c76d76680bd1bea566d44ab74b4dca55b71Federico Tomassetti                              FILE_MAP_ALL_ACCESS, false, 0);
39003df427399267338f87748888d1f921bb9a1c0daFederico Tomassetti  EXPECT_EQ(FALSE, rv)
39103df427399267338f87748888d1f921bb9a1c0daFederico Tomassetti      << "Shouldn't be able to duplicate the handle into a writable one.";
3929e91a1d76dbfb28f2bc7c32028fe459b073ee861Federico Tomassetti  if (rv)
3939e91a1d76dbfb28f2bc7c32028fe459b073ee861Federico Tomassetti    win::ScopedHandle writable_handle(temp_handle);
39487db3c76d76680bd1bea566d44ab74b4dca55b71Federico Tomassetti  rv = ::DuplicateHandle(GetCurrentProcess(), handle.GetHandle(),
39587db3c76d76680bd1bea566d44ab74b4dca55b71Federico Tomassetti                         GetCurrentProcess(), &temp_handle, FILE_MAP_READ,
39687db3c76d76680bd1bea566d44ab74b4dca55b71Federico Tomassetti                         false, 0);
39787db3c76d76680bd1bea566d44ab74b4dca55b71Federico Tomassetti  EXPECT_EQ(TRUE, rv)
3989e91a1d76dbfb28f2bc7c32028fe459b073ee861Federico Tomassetti      << "Should be able to duplicate the handle into a readable one.";
39948789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen  if (rv)
4009e91a1d76dbfb28f2bc7c32028fe459b073ee861Federico Tomassetti    win::ScopedHandle writable_handle(temp_handle);
40103df427399267338f87748888d1f921bb9a1c0daFederico Tomassetti#else
40203df427399267338f87748888d1f921bb9a1c0daFederico Tomassetti#error Unexpected platform; write a test that tries to make 'handle' writable.
40303df427399267338f87748888d1f921bb9a1c0daFederico Tomassetti#endif  // defined(OS_POSIX) || defined(OS_WIN)
40403df427399267338f87748888d1f921bb9a1c0daFederico Tomassetti}
4057e85803c3a66d340e1cbdbc6c98081104ad412c3Federico Tomassetti
4067e85803c3a66d340e1cbdbc6c98081104ad412c3Federico TomassettiTEST(SharedMemoryTest, ShareToSelf) {
4077e85803c3a66d340e1cbdbc6c98081104ad412c3Federico Tomassetti  StringPiece contents = "Hello World";
4089a228915f61892f6ba99fcf1e42e42e1e2622a00Danny van Bruggen
40948789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen  SharedMemory shmem;
41048789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen  ASSERT_TRUE(shmem.CreateAndMapAnonymous(contents.size()));
41148789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen  memcpy(shmem.memory(), contents.data(), contents.size());
41248789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen  EXPECT_TRUE(shmem.Unmap());
41348789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen
41448789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen  SharedMemoryHandle shared_handle;
41548789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen  ASSERT_TRUE(shmem.ShareToProcess(GetCurrentProcessHandle(), &shared_handle));
41648789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen#if defined(OS_WIN)
41748789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen  ASSERT_TRUE(shared_handle.OwnershipPassesToIPC());
4187e85803c3a66d340e1cbdbc6c98081104ad412c3Federico Tomassetti#endif
41903df427399267338f87748888d1f921bb9a1c0daFederico Tomassetti  SharedMemory shared(shared_handle, /*readonly=*/false);
420d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti
421d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti  ASSERT_TRUE(shared.Map(contents.size()));
422d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti  EXPECT_EQ(
4236149218487aac50fad2256c8723639671747d7bbDanny van Bruggen      contents,
424a86af3ac653113b302dcfa9facc6c67159fabf1bDanny van Bruggen      StringPiece(static_cast<const char*>(shared.memory()), contents.size()));
4256149218487aac50fad2256c8723639671747d7bbDanny van Bruggen
426a86af3ac653113b302dcfa9facc6c67159fabf1bDanny van Bruggen  shared_handle = SharedMemoryHandle();
427fab5a9b624d0748ef3e924573f55386010a2694eFederico Tomassetti  ASSERT_TRUE(shmem.ShareToProcess(GetCurrentProcessHandle(), &shared_handle));
428d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti#if defined(OS_WIN)
429a86af3ac653113b302dcfa9facc6c67159fabf1bDanny van Bruggen  ASSERT_TRUE(shared_handle.OwnershipPassesToIPC());
430d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti#endif
431d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti  SharedMemory readonly(shared_handle, /*readonly=*/true);
4324002ee095f065fb93ce3ad4355bc5fb7b63dafaaFederico Tomassetti
4336149218487aac50fad2256c8723639671747d7bbDanny van Bruggen  ASSERT_TRUE(readonly.Map(contents.size()));
434152592f7c8110f04ea6ca6e6c6d57360fd40ee16Federico Tomassetti  EXPECT_EQ(contents,
435de11a2ae80166defacd1f9c51b77f52be4b53eb1Federico Tomassetti            StringPiece(static_cast<const char*>(readonly.memory()),
436de11a2ae80166defacd1f9c51b77f52be4b53eb1Federico Tomassetti                        contents.size()));
437de11a2ae80166defacd1f9c51b77f52be4b53eb1Federico Tomassetti}
43883d60da8afce695e7356af94c549e30ab585448cDanny van Bruggen
4399192b9d17903947058b755b987d1c57a05821e58Danny van BruggenTEST(SharedMemoryTest, MapAt) {
440152592f7c8110f04ea6ca6e6c6d57360fd40ee16Federico Tomassetti  ASSERT_TRUE(SysInfo::VMAllocationGranularity() >= sizeof(uint32_t));
441152592f7c8110f04ea6ca6e6c6d57360fd40ee16Federico Tomassetti  const size_t kCount = SysInfo::VMAllocationGranularity();
442152592f7c8110f04ea6ca6e6c6d57360fd40ee16Federico Tomassetti  const size_t kDataSize = kCount * sizeof(uint32_t);
443152592f7c8110f04ea6ca6e6c6d57360fd40ee16Federico Tomassetti
444152592f7c8110f04ea6ca6e6c6d57360fd40ee16Federico Tomassetti  SharedMemory memory;
445152592f7c8110f04ea6ca6e6c6d57360fd40ee16Federico Tomassetti  ASSERT_TRUE(memory.CreateAndMapAnonymous(kDataSize));
44648789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen  uint32_t* ptr = static_cast<uint32_t*>(memory.memory());
447152592f7c8110f04ea6ca6e6c6d57360fd40ee16Federico Tomassetti  ASSERT_NE(ptr, static_cast<void*>(NULL));
448152592f7c8110f04ea6ca6e6c6d57360fd40ee16Federico Tomassetti
449de11a2ae80166defacd1f9c51b77f52be4b53eb1Federico Tomassetti  for (size_t i = 0; i < kCount; ++i) {
450de11a2ae80166defacd1f9c51b77f52be4b53eb1Federico Tomassetti    ptr[i] = i;
451152592f7c8110f04ea6ca6e6c6d57360fd40ee16Federico Tomassetti  }
452de11a2ae80166defacd1f9c51b77f52be4b53eb1Federico Tomassetti
453de11a2ae80166defacd1f9c51b77f52be4b53eb1Federico Tomassetti  memory.Unmap();
454d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti
455d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti  off_t offset = SysInfo::VMAllocationGranularity();
456d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti  ASSERT_TRUE(memory.MapAt(offset, kDataSize - offset));
457d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti  offset /= sizeof(uint32_t);
458d6aebf46978852659303ad0fe057e1cddd9e391dFederico Tomassetti  ptr = static_cast<uint32_t*>(memory.memory());
459d6aebf46978852659303ad0fe057e1cddd9e391dFederico Tomassetti  ASSERT_NE(ptr, static_cast<void*>(NULL));
460d6aebf46978852659303ad0fe057e1cddd9e391dFederico Tomassetti  for (size_t i = offset; i < kCount; ++i) {
461d6aebf46978852659303ad0fe057e1cddd9e391dFederico Tomassetti    EXPECT_EQ(ptr[i - offset], i);
462d6aebf46978852659303ad0fe057e1cddd9e391dFederico Tomassetti  }
463d6aebf46978852659303ad0fe057e1cddd9e391dFederico Tomassetti}
464d6aebf46978852659303ad0fe057e1cddd9e391dFederico Tomassetti
465d6aebf46978852659303ad0fe057e1cddd9e391dFederico TomassettiTEST(SharedMemoryTest, MapTwice) {
466d6aebf46978852659303ad0fe057e1cddd9e391dFederico Tomassetti  const uint32_t kDataSize = 1024;
467a86af3ac653113b302dcfa9facc6c67159fabf1bDanny van Bruggen  SharedMemory memory;
468d6aebf46978852659303ad0fe057e1cddd9e391dFederico Tomassetti  bool rv = memory.CreateAndMapAnonymous(kDataSize);
469d6aebf46978852659303ad0fe057e1cddd9e391dFederico Tomassetti  EXPECT_TRUE(rv);
470d533531b8d35f2d899f9e826e1993a16226e7580Federico Tomassetti
471d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti  void* old_address = memory.memory();
472d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti
473d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti  rv = memory.Map(kDataSize);
474d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti  EXPECT_FALSE(rv);
4751fa1ea21c227ad0cf06a3d12638f63061186f02fFederico Tomassetti  EXPECT_EQ(old_address, memory.memory());
4761fa1ea21c227ad0cf06a3d12638f63061186f02fFederico Tomassetti}
4771fa1ea21c227ad0cf06a3d12638f63061186f02fFederico Tomassetti
4781fa1ea21c227ad0cf06a3d12638f63061186f02fFederico Tomassetti#if defined(OS_POSIX)
47948789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen// This test is not applicable for iOS (crbug.com/399384).
480d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti#if !defined(OS_IOS)
481d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti// Create a shared memory object, mmap it, and mprotect it to PROT_EXEC.
482d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico TomassettiTEST(SharedMemoryTest, AnonymousExecutable) {
483d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti  const uint32_t kTestSize = 1 << 16;
484d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti
485d4db09d04aca5a9df4278652d55d680c4a826efcFederico Tomassetti  SharedMemory shared_memory;
486d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti  SharedMemoryCreateOptions options;
487d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti  options.size = kTestSize;
488d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti  options.executable = true;
489d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti#if defined(OS_MACOSX) && !defined(OS_IOS)
490d6aebf46978852659303ad0fe057e1cddd9e391dFederico Tomassetti  // The Mach functionality is tested in shared_memory_mac_unittest.cc.
491d6aebf46978852659303ad0fe057e1cddd9e391dFederico Tomassetti  options.type = SharedMemoryHandle::POSIX;
49248789abfd3738d660abb6f8cd758a40c57379597Danny van Bruggen#endif
493d6aebf46978852659303ad0fe057e1cddd9e391dFederico Tomassetti
494d6aebf46978852659303ad0fe057e1cddd9e391dFederico Tomassetti  EXPECT_TRUE(shared_memory.Create(options));
495d6aebf46978852659303ad0fe057e1cddd9e391dFederico Tomassetti  EXPECT_TRUE(shared_memory.Map(shared_memory.requested_size()));
496d6aebf46978852659303ad0fe057e1cddd9e391dFederico Tomassetti
497d6aebf46978852659303ad0fe057e1cddd9e391dFederico Tomassetti  EXPECT_EQ(0, mprotect(shared_memory.memory(), shared_memory.requested_size(),
498d6aebf46978852659303ad0fe057e1cddd9e391dFederico Tomassetti                        PROT_READ | PROT_EXEC));
499d6aebf46978852659303ad0fe057e1cddd9e391dFederico Tomassetti}
500d6aebf46978852659303ad0fe057e1cddd9e391dFederico Tomassetti#endif  // !defined(OS_IOS)
501d6aebf46978852659303ad0fe057e1cddd9e391dFederico Tomassetti
502d6aebf46978852659303ad0fe057e1cddd9e391dFederico Tomassetti// Android supports a different permission model than POSIX for its "ashmem"
503d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti// shared memory implementation. So the tests about file permissions are not
504d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti// included on Android.
505d6aebf46978852659303ad0fe057e1cddd9e391dFederico Tomassetti#if !defined(OS_ANDROID)
506d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti
507d25e79e2c567cc2fc312fabe15fa35be886f31b2Federico Tomassetti// Set a umask and restore the old mask on destruction.
508class ScopedUmaskSetter {
509 public:
510  explicit ScopedUmaskSetter(mode_t target_mask) {
511    old_umask_ = umask(target_mask);
512  }
513  ~ScopedUmaskSetter() { umask(old_umask_); }
514 private:
515  mode_t old_umask_;
516  DISALLOW_IMPLICIT_CONSTRUCTORS(ScopedUmaskSetter);
517};
518
519// Create a shared memory object, check its permissions.
520TEST(SharedMemoryTest, FilePermissionsAnonymous) {
521  const uint32_t kTestSize = 1 << 8;
522
523  SharedMemory shared_memory;
524  SharedMemoryCreateOptions options;
525  options.size = kTestSize;
526#if defined(OS_MACOSX) && !defined(OS_IOS)
527  // The Mach functionality is tested in shared_memory_mac_unittest.cc.
528  options.type = SharedMemoryHandle::POSIX;
529#endif
530  // Set a file mode creation mask that gives all permissions.
531  ScopedUmaskSetter permissive_mask(S_IWGRP | S_IWOTH);
532
533  EXPECT_TRUE(shared_memory.Create(options));
534
535  int shm_fd =
536      SharedMemory::GetFdFromSharedMemoryHandle(shared_memory.handle());
537  struct stat shm_stat;
538  EXPECT_EQ(0, fstat(shm_fd, &shm_stat));
539  // Neither the group, nor others should be able to read the shared memory
540  // file.
541  EXPECT_FALSE(shm_stat.st_mode & S_IRWXO);
542  EXPECT_FALSE(shm_stat.st_mode & S_IRWXG);
543}
544
545// Create a shared memory object, check its permissions.
546TEST(SharedMemoryTest, FilePermissionsNamed) {
547  const uint32_t kTestSize = 1 << 8;
548
549  SharedMemory shared_memory;
550  SharedMemoryCreateOptions options;
551  options.size = kTestSize;
552#if defined(OS_MACOSX) && !defined(OS_IOS)
553  // The Mach functionality is tested in shared_memory_mac_unittest.cc.
554  options.type = SharedMemoryHandle::POSIX;
555#endif
556
557  // Set a file mode creation mask that gives all permissions.
558  ScopedUmaskSetter permissive_mask(S_IWGRP | S_IWOTH);
559
560  EXPECT_TRUE(shared_memory.Create(options));
561
562  int fd = SharedMemory::GetFdFromSharedMemoryHandle(shared_memory.handle());
563  struct stat shm_stat;
564  EXPECT_EQ(0, fstat(fd, &shm_stat));
565  // Neither the group, nor others should have been able to open the shared
566  // memory file while its name existed.
567  EXPECT_FALSE(shm_stat.st_mode & S_IRWXO);
568  EXPECT_FALSE(shm_stat.st_mode & S_IRWXG);
569}
570#endif  // !defined(OS_ANDROID)
571
572#endif  // defined(OS_POSIX)
573
574// Map() will return addresses which are aligned to the platform page size, this
575// varies from platform to platform though.  Since we'd like to advertise a
576// minimum alignment that callers can count on, test for it here.
577TEST(SharedMemoryTest, MapMinimumAlignment) {
578  static const int kDataSize = 8192;
579
580  SharedMemory shared_memory;
581  ASSERT_TRUE(shared_memory.CreateAndMapAnonymous(kDataSize));
582  EXPECT_EQ(0U, reinterpret_cast<uintptr_t>(
583      shared_memory.memory()) & (SharedMemory::MAP_MINIMUM_ALIGNMENT - 1));
584  shared_memory.Close();
585}
586
587#if defined(OS_WIN)
588TEST(SharedMemoryTest, UnsafeImageSection) {
589  const char kTestSectionName[] = "UnsafeImageSection";
590  wchar_t path[MAX_PATH];
591  EXPECT_GT(::GetModuleFileName(nullptr, path, arraysize(path)), 0U);
592
593  // Map the current executable image to save us creating a new PE file on disk.
594  base::win::ScopedHandle file_handle(::CreateFile(
595      path, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr));
596  EXPECT_TRUE(file_handle.IsValid());
597  base::win::ScopedHandle section_handle(
598      ::CreateFileMappingA(file_handle.Get(), nullptr,
599                           PAGE_READONLY | SEC_IMAGE, 0, 0, kTestSectionName));
600  EXPECT_TRUE(section_handle.IsValid());
601
602  // Check direct opening by name, from handle and duplicated from handle.
603  SharedMemory shared_memory_open;
604  EXPECT_TRUE(shared_memory_open.Open(kTestSectionName, true));
605  EXPECT_FALSE(shared_memory_open.Map(1));
606  EXPECT_EQ(nullptr, shared_memory_open.memory());
607
608  SharedMemory shared_memory_handle_local(
609      SharedMemoryHandle(section_handle.Take(), ::GetCurrentProcessId()), true);
610  EXPECT_FALSE(shared_memory_handle_local.Map(1));
611  EXPECT_EQ(nullptr, shared_memory_handle_local.memory());
612
613  // Check that a handle without SECTION_QUERY also can't be mapped as it can't
614  // be checked.
615  SharedMemory shared_memory_handle_dummy;
616  SharedMemoryCreateOptions options;
617  options.size = 0x1000;
618  EXPECT_TRUE(shared_memory_handle_dummy.Create(options));
619  HANDLE handle_no_query;
620  EXPECT_TRUE(::DuplicateHandle(
621      ::GetCurrentProcess(), shared_memory_handle_dummy.handle().GetHandle(),
622      ::GetCurrentProcess(), &handle_no_query, FILE_MAP_READ, FALSE, 0));
623  SharedMemory shared_memory_handle_no_query(
624      SharedMemoryHandle(handle_no_query, ::GetCurrentProcessId()), true);
625  EXPECT_FALSE(shared_memory_handle_no_query.Map(1));
626  EXPECT_EQ(nullptr, shared_memory_handle_no_query.memory());
627}
628#endif  // defined(OS_WIN)
629
630// iOS does not allow multiple processes.
631// Android ashmem does not support named shared memory.
632// Mac SharedMemory does not support named shared memory. crbug.com/345734
633#if !defined(OS_IOS) && !defined(OS_ANDROID) && !defined(OS_MACOSX)
634// On POSIX it is especially important we test shmem across processes,
635// not just across threads.  But the test is enabled on all platforms.
636class SharedMemoryProcessTest : public MultiProcessTest {
637 public:
638  static void CleanUp() {
639    SharedMemory memory;
640    memory.Delete(s_test_name_);
641  }
642
643  static int TaskTestMain() {
644    int errors = 0;
645    SharedMemory memory;
646    bool rv = memory.CreateNamedDeprecated(s_test_name_, true, s_data_size_);
647    EXPECT_TRUE(rv);
648    if (rv != true)
649      errors++;
650    rv = memory.Map(s_data_size_);
651    EXPECT_TRUE(rv);
652    if (rv != true)
653      errors++;
654    int* ptr = static_cast<int*>(memory.memory());
655
656    // This runs concurrently in multiple processes. Writes need to be atomic.
657    subtle::Barrier_AtomicIncrement(ptr, 1);
658    memory.Close();
659    return errors;
660  }
661
662  static const char s_test_name_[];
663  static const uint32_t s_data_size_;
664};
665
666const char SharedMemoryProcessTest::s_test_name_[] = "MPMem";
667const uint32_t SharedMemoryProcessTest::s_data_size_ = 1024;
668
669TEST_F(SharedMemoryProcessTest, SharedMemoryAcrossProcesses) {
670  const int kNumTasks = 5;
671
672  SharedMemoryProcessTest::CleanUp();
673
674  // Create a shared memory region. Set the first word to 0.
675  SharedMemory memory;
676  bool rv = memory.CreateNamedDeprecated(s_test_name_, true, s_data_size_);
677  ASSERT_TRUE(rv);
678  rv = memory.Map(s_data_size_);
679  ASSERT_TRUE(rv);
680  int* ptr = static_cast<int*>(memory.memory());
681  *ptr = 0;
682
683  // Start |kNumTasks| processes, each of which atomically increments the first
684  // word by 1.
685  Process processes[kNumTasks];
686  for (int index = 0; index < kNumTasks; ++index) {
687    processes[index] = SpawnChild("SharedMemoryTestMain");
688    ASSERT_TRUE(processes[index].IsValid());
689  }
690
691  // Check that each process exited correctly.
692  int exit_code = 0;
693  for (int index = 0; index < kNumTasks; ++index) {
694    EXPECT_TRUE(processes[index].WaitForExit(&exit_code));
695    EXPECT_EQ(0, exit_code);
696  }
697
698  // Check that the shared memory region reflects |kNumTasks| increments.
699  ASSERT_EQ(kNumTasks, *ptr);
700
701  memory.Close();
702  SharedMemoryProcessTest::CleanUp();
703}
704
705MULTIPROCESS_TEST_MAIN(SharedMemoryTestMain) {
706  return SharedMemoryProcessTest::TaskTestMain();
707}
708#endif  // !defined(OS_IOS) && !defined(OS_ANDROID) && !defined(OS_MACOSX)
709
710}  // namespace base
711