145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// Copyright (c) 2012 The Chromium Authors. All rights reserved.
245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// Use of this source code is governed by a BSD-style license that can be
345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// found in the LICENSE file.
445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
594ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez#include "base/memory/shared_memory.h"
694ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez
745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#include <stddef.h>
845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#include <stdint.h>
945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
1094ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez#include <memory>
1194ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez
1245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#include "base/atomicops.h"
1345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#include "base/macros.h"
1445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#include "base/memory/shared_memory_handle.h"
1545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#include "base/process/kill.h"
1645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#include "base/rand_util.h"
1745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#include "base/strings/string_number_conversions.h"
1845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#include "base/sys_info.h"
1945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#include "base/test/multiprocess_test.h"
2045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#include "base/threading/platform_thread.h"
2145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#include "base/time/time.h"
2245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#include "build/build_config.h"
2345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#include "testing/gtest/include/gtest/gtest.h"
2445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#include "testing/multiprocess_func_list.h"
2545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
2645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#if defined(OS_POSIX)
2745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#include <errno.h>
2845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#include <fcntl.h>
2945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#include <sys/mman.h>
3045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#include <sys/stat.h>
3145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#include <sys/types.h>
3245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#include <unistd.h>
3345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#endif
3445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
3545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#if defined(OS_WIN)
3645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#include "base/win/scoped_handle.h"
3745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#endif
3845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
3945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenkonamespace base {
4045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
4145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenkonamespace {
4245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
4345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#if !defined(OS_MACOSX)
4445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// Each thread will open the shared memory.  Each thread will take a different 4
4545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// byte int pointer, and keep changing it, with some small pauses in between.
4645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// Verify that each thread's value in the shared memory is always correct.
4745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenkoclass MultipleThreadMain : public PlatformThread::Delegate {
4845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko public:
4945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  explicit MultipleThreadMain(int16_t id) : id_(id) {}
5045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  ~MultipleThreadMain() override {}
5145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
5245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  static void CleanUp() {
5345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko    SharedMemory memory;
5445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko    memory.Delete(s_test_name_);
5545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  }
5645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
5745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  // PlatformThread::Delegate interface.
5845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  void ThreadMain() override {
5945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko    const uint32_t kDataSize = 1024;
6045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko    SharedMemory memory;
6145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko    bool rv = memory.CreateNamedDeprecated(s_test_name_, true, kDataSize);
6245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko    EXPECT_TRUE(rv);
6345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko    rv = memory.Map(kDataSize);
6445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko    EXPECT_TRUE(rv);
6545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko    int* ptr = static_cast<int*>(memory.memory()) + id_;
6645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko    EXPECT_EQ(0, *ptr);
6745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
6845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko    for (int idx = 0; idx < 100; idx++) {
6945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko      *ptr = idx;
7045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko      PlatformThread::Sleep(TimeDelta::FromMilliseconds(1));
7145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko      EXPECT_EQ(*ptr, idx);
7245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko    }
7345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko    // Reset back to 0 for the next test that uses the same name.
7445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko    *ptr = 0;
7545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
7645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko    memory.Close();
7745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  }
7845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
7945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko private:
8045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  int16_t id_;
8145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
8245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  static const char s_test_name_[];
8345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
8445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  DISALLOW_COPY_AND_ASSIGN(MultipleThreadMain);
8545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko};
8645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
8745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenkoconst char MultipleThreadMain::s_test_name_[] =
8845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko    "SharedMemoryOpenThreadTest";
8945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#endif  // !defined(OS_MACOSX)
9045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
9145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko}  // namespace
9245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
9345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// Android/Mac doesn't support SharedMemory::Open/Delete/
9445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// CreateNamedDeprecated(openExisting=true)
9545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#if !defined(OS_ANDROID) && !defined(OS_MACOSX)
9645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex VakulenkoTEST(SharedMemoryTest, OpenClose) {
9745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  const uint32_t kDataSize = 1024;
9845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  std::string test_name = "SharedMemoryOpenCloseTest";
9945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
10045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  // Open two handles to a memory segment, confirm that they are mapped
10145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  // separately yet point to the same space.
10245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  SharedMemory memory1;
10345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  bool rv = memory1.Delete(test_name);
10445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_TRUE(rv);
10545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  rv = memory1.Delete(test_name);
10645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_TRUE(rv);
10745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  rv = memory1.Open(test_name, false);
10845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_FALSE(rv);
10945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  rv = memory1.CreateNamedDeprecated(test_name, false, kDataSize);
11045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_TRUE(rv);
11145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  rv = memory1.Map(kDataSize);
11245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_TRUE(rv);
11345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  SharedMemory memory2;
11445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  rv = memory2.Open(test_name, false);
11545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_TRUE(rv);
11645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  rv = memory2.Map(kDataSize);
11745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_TRUE(rv);
11845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_NE(memory1.memory(), memory2.memory());  // Compare the pointers.
11945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
12045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  // Make sure we don't segfault. (it actually happened!)
12145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  ASSERT_NE(memory1.memory(), static_cast<void*>(NULL));
12245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  ASSERT_NE(memory2.memory(), static_cast<void*>(NULL));
12345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
12445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  // Write data to the first memory segment, verify contents of second.
12545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  memset(memory1.memory(), '1', kDataSize);
12645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_EQ(memcmp(memory1.memory(), memory2.memory(), kDataSize), 0);
12745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
12845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  // Close the first memory segment, and verify the second has the right data.
12945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  memory1.Close();
13045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  char* start_ptr = static_cast<char*>(memory2.memory());
13145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  char* end_ptr = start_ptr + kDataSize;
13245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  for (char* ptr = start_ptr; ptr < end_ptr; ptr++)
13345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko    EXPECT_EQ(*ptr, '1');
13445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
13545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  // Close the second memory segment.
13645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  memory2.Close();
13745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
13845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  rv = memory1.Delete(test_name);
13945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_TRUE(rv);
14045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  rv = memory2.Delete(test_name);
14145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_TRUE(rv);
14245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko}
14345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
14445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex VakulenkoTEST(SharedMemoryTest, OpenExclusive) {
14545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  const uint32_t kDataSize = 1024;
14645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  const uint32_t kDataSize2 = 2048;
14745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  std::ostringstream test_name_stream;
14845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  test_name_stream << "SharedMemoryOpenExclusiveTest."
14945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko                   << Time::Now().ToDoubleT();
15045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  std::string test_name = test_name_stream.str();
15145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
15245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  // Open two handles to a memory segment and check that
15345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  // open_existing_deprecated works as expected.
15445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  SharedMemory memory1;
15545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  bool rv = memory1.CreateNamedDeprecated(test_name, false, kDataSize);
15645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_TRUE(rv);
15745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
15845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  // Memory1 knows it's size because it created it.
15945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_EQ(memory1.requested_size(), kDataSize);
16045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
16145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  rv = memory1.Map(kDataSize);
16245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_TRUE(rv);
16345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
16445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  // The mapped memory1 must be at least the size we asked for.
16545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_GE(memory1.mapped_size(), kDataSize);
16645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
16745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  // The mapped memory1 shouldn't exceed rounding for allocation granularity.
16845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_LT(memory1.mapped_size(),
16945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko            kDataSize + SysInfo::VMAllocationGranularity());
17045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
17145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  memset(memory1.memory(), 'G', kDataSize);
17245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
17345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  SharedMemory memory2;
17445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  // Should not be able to create if openExisting is false.
17545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  rv = memory2.CreateNamedDeprecated(test_name, false, kDataSize2);
17645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_FALSE(rv);
17745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
17845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  // Should be able to create with openExisting true.
17945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  rv = memory2.CreateNamedDeprecated(test_name, true, kDataSize2);
18045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_TRUE(rv);
18145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
18245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  // Memory2 shouldn't know the size because we didn't create it.
18345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_EQ(memory2.requested_size(), 0U);
18445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
18545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  // We should be able to map the original size.
18645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  rv = memory2.Map(kDataSize);
18745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_TRUE(rv);
18845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
18945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  // The mapped memory2 must be at least the size of the original.
19045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_GE(memory2.mapped_size(), kDataSize);
19145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
19245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  // The mapped memory2 shouldn't exceed rounding for allocation granularity.
19345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_LT(memory2.mapped_size(),
19445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko            kDataSize2 + SysInfo::VMAllocationGranularity());
19545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
19645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  // Verify that opening memory2 didn't truncate or delete memory 1.
19745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  char* start_ptr = static_cast<char*>(memory2.memory());
19845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  char* end_ptr = start_ptr + kDataSize;
19945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  for (char* ptr = start_ptr; ptr < end_ptr; ptr++) {
20045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko    EXPECT_EQ(*ptr, 'G');
20145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  }
20245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
20345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  memory1.Close();
20445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  memory2.Close();
20545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
20645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  rv = memory1.Delete(test_name);
20745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_TRUE(rv);
20845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko}
20945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#endif  // !defined(OS_ANDROID) && !defined(OS_MACOSX)
21045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
21145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// Check that memory is still mapped after its closed.
21245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex VakulenkoTEST(SharedMemoryTest, CloseNoUnmap) {
21345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  const size_t kDataSize = 4096;
21445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
21545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  SharedMemory memory;
21645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  ASSERT_TRUE(memory.CreateAndMapAnonymous(kDataSize));
21745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  char* ptr = static_cast<char*>(memory.memory());
21845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  ASSERT_NE(ptr, static_cast<void*>(NULL));
21945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  memset(ptr, 'G', kDataSize);
22045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
22145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  memory.Close();
22245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
22345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_EQ(ptr, memory.memory());
22445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_EQ(SharedMemory::NULLHandle(), memory.handle());
22545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
22645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  for (size_t i = 0; i < kDataSize; i++) {
22745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko    EXPECT_EQ('G', ptr[i]);
22845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  }
22945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
23045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  memory.Unmap();
23145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_EQ(nullptr, memory.memory());
23245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko}
23345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
23445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#if !defined(OS_MACOSX)
23545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// Create a set of N threads to each open a shared memory segment and write to
23645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// it. Verify that they are always reading/writing consistent data.
23745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex VakulenkoTEST(SharedMemoryTest, MultipleThreads) {
23845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  const int kNumThreads = 5;
23945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
24045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  MultipleThreadMain::CleanUp();
24145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  // On POSIX we have a problem when 2 threads try to create the shmem
24245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  // (a file) at exactly the same time, since create both creates the
24345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  // file and zerofills it.  We solve the problem for this unit test
24445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  // (make it not flaky) by starting with 1 thread, then
24545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  // intentionally don't clean up its shmem before running with
24645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  // kNumThreads.
24745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
24845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  int threadcounts[] = { 1, kNumThreads };
24945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  for (size_t i = 0; i < arraysize(threadcounts); i++) {
25045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko    int numthreads = threadcounts[i];
25194ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez    std::unique_ptr<PlatformThreadHandle[]> thread_handles;
25294ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez    std::unique_ptr<MultipleThreadMain* []> thread_delegates;
25345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
25445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko    thread_handles.reset(new PlatformThreadHandle[numthreads]);
25545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko    thread_delegates.reset(new MultipleThreadMain*[numthreads]);
25645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
25745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko    // Spawn the threads.
25845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko    for (int16_t index = 0; index < numthreads; index++) {
25945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko      PlatformThreadHandle pth;
26045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko      thread_delegates[index] = new MultipleThreadMain(index);
26145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko      EXPECT_TRUE(PlatformThread::Create(0, thread_delegates[index], &pth));
26245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko      thread_handles[index] = pth;
26345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko    }
26445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
26545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko    // Wait for the threads to finish.
26645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko    for (int index = 0; index < numthreads; index++) {
26745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko      PlatformThread::Join(thread_handles[index]);
26845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko      delete thread_delegates[index];
26945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko    }
27045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  }
27145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  MultipleThreadMain::CleanUp();
27245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko}
27345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#endif
27445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
27545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// Allocate private (unique) shared memory with an empty string for a
27645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// name.  Make sure several of them don't point to the same thing as
27745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// we might expect if the names are equal.
27845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex VakulenkoTEST(SharedMemoryTest, AnonymousPrivate) {
27945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  int i, j;
28045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  int count = 4;
28145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  bool rv;
28245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  const uint32_t kDataSize = 8192;
28345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
28494ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez  std::unique_ptr<SharedMemory[]> memories(new SharedMemory[count]);
28594ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez  std::unique_ptr<int* []> pointers(new int*[count]);
28645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  ASSERT_TRUE(memories.get());
28745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  ASSERT_TRUE(pointers.get());
28845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
28945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  for (i = 0; i < count; i++) {
29045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko    rv = memories[i].CreateAndMapAnonymous(kDataSize);
29145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko    EXPECT_TRUE(rv);
29245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko    int* ptr = static_cast<int*>(memories[i].memory());
29345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko    EXPECT_TRUE(ptr);
29445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko    pointers[i] = ptr;
29545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  }
29645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
29745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  for (i = 0; i < count; i++) {
29845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko    // zero out the first int in each except for i; for that one, make it 100.
29945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko    for (j = 0; j < count; j++) {
30045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko      if (i == j)
30145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko        pointers[j][0] = 100;
30245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko      else
30345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko        pointers[j][0] = 0;
30445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko    }
30545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko    // make sure there is no bleeding of the 100 into the other pointers
30645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko    for (j = 0; j < count; j++) {
30745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko      if (i == j)
30845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko        EXPECT_EQ(100, pointers[j][0]);
30945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko      else
31045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko        EXPECT_EQ(0, pointers[j][0]);
31145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko    }
31245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  }
31345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
31445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  for (int i = 0; i < count; i++) {
31545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko    memories[i].Close();
31645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  }
31745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko}
31845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
31945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex VakulenkoTEST(SharedMemoryTest, ShareReadOnly) {
32045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  StringPiece contents = "Hello World";
32145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
32245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  SharedMemory writable_shmem;
32345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  SharedMemoryCreateOptions options;
32445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  options.size = contents.size();
32545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  options.share_read_only = true;
32636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#if defined(OS_MACOSX) && !defined(OS_IOS)
32736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // The Mach functionality is tested in shared_memory_mac_unittest.cc.
32836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  options.type = SharedMemoryHandle::POSIX;
32936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#endif
33045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  ASSERT_TRUE(writable_shmem.Create(options));
33145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  ASSERT_TRUE(writable_shmem.Map(options.size));
33245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  memcpy(writable_shmem.memory(), contents.data(), contents.size());
33345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_TRUE(writable_shmem.Unmap());
33445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
33545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  SharedMemoryHandle readonly_handle;
33645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  ASSERT_TRUE(writable_shmem.ShareReadOnlyToProcess(GetCurrentProcessHandle(),
33745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko                                                    &readonly_handle));
33845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  SharedMemory readonly_shmem(readonly_handle, /*readonly=*/true);
33945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
34045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  ASSERT_TRUE(readonly_shmem.Map(contents.size()));
34145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_EQ(contents,
34245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko            StringPiece(static_cast<const char*>(readonly_shmem.memory()),
34345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko                        contents.size()));
34445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_TRUE(readonly_shmem.Unmap());
34545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
34645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  // Make sure the writable instance is still writable.
34745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  ASSERT_TRUE(writable_shmem.Map(contents.size()));
34845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  StringPiece new_contents = "Goodbye";
34945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  memcpy(writable_shmem.memory(), new_contents.data(), new_contents.size());
35045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_EQ(new_contents,
35145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko            StringPiece(static_cast<const char*>(writable_shmem.memory()),
35245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko                        new_contents.size()));
35345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
35445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  // We'd like to check that if we send the read-only segment to another
35545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  // process, then that other process can't reopen it read/write.  (Since that
35645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  // would be a security hole.)  Setting up multiple processes is hard in a
35745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  // unittest, so this test checks that the *current* process can't reopen the
35845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  // segment read/write.  I think the test here is stronger than we actually
35945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  // care about, but there's a remote possibility that sending a file over a
36045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  // pipe would transform it into read/write.
36145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  SharedMemoryHandle handle = readonly_shmem.handle();
36245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
36345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#if defined(OS_ANDROID)
36445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  // The "read-only" handle is still writable on Android:
36545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  // http://crbug.com/320865
36645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  (void)handle;
36745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#elif defined(OS_POSIX)
36845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  int handle_fd = SharedMemory::GetFdFromSharedMemoryHandle(handle);
36945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_EQ(O_RDONLY, fcntl(handle_fd, F_GETFL) & O_ACCMODE)
37045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko      << "The descriptor itself should be read-only.";
37145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
37245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  errno = 0;
37345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  void* writable = mmap(NULL, contents.size(), PROT_READ | PROT_WRITE,
37445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko                        MAP_SHARED, handle_fd, 0);
37545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  int mmap_errno = errno;
37645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_EQ(MAP_FAILED, writable)
37745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko      << "It shouldn't be possible to re-mmap the descriptor writable.";
37845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_EQ(EACCES, mmap_errno) << strerror(mmap_errno);
37945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  if (writable != MAP_FAILED)
38045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko    EXPECT_EQ(0, munmap(writable, readonly_shmem.mapped_size()));
38145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
38245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#elif defined(OS_WIN)
38345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_EQ(NULL, MapViewOfFile(handle.GetHandle(), FILE_MAP_WRITE, 0, 0, 0))
38445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko      << "Shouldn't be able to map memory writable.";
38545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
38645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  HANDLE temp_handle;
38745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  BOOL rv = ::DuplicateHandle(GetCurrentProcess(), handle.GetHandle(),
38845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko                              GetCurrentProcess(), &temp_handle,
38945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko                              FILE_MAP_ALL_ACCESS, false, 0);
39045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_EQ(FALSE, rv)
39145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko      << "Shouldn't be able to duplicate the handle into a writable one.";
39245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  if (rv)
39345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko    win::ScopedHandle writable_handle(temp_handle);
39445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  rv = ::DuplicateHandle(GetCurrentProcess(), handle.GetHandle(),
39545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko                         GetCurrentProcess(), &temp_handle, FILE_MAP_READ,
39645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko                         false, 0);
39745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_EQ(TRUE, rv)
39845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko      << "Should be able to duplicate the handle into a readable one.";
39945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  if (rv)
40045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko    win::ScopedHandle writable_handle(temp_handle);
40145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#else
40245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#error Unexpected platform; write a test that tries to make 'handle' writable.
40345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#endif  // defined(OS_POSIX) || defined(OS_WIN)
40445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko}
40545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
40645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex VakulenkoTEST(SharedMemoryTest, ShareToSelf) {
40745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  StringPiece contents = "Hello World";
40845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
40945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  SharedMemory shmem;
41045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  ASSERT_TRUE(shmem.CreateAndMapAnonymous(contents.size()));
41145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  memcpy(shmem.memory(), contents.data(), contents.size());
41245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_TRUE(shmem.Unmap());
41345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
41445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  SharedMemoryHandle shared_handle;
41545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  ASSERT_TRUE(shmem.ShareToProcess(GetCurrentProcessHandle(), &shared_handle));
41645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#if defined(OS_WIN)
41745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  ASSERT_TRUE(shared_handle.OwnershipPassesToIPC());
41845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#endif
41945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  SharedMemory shared(shared_handle, /*readonly=*/false);
42045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
42145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  ASSERT_TRUE(shared.Map(contents.size()));
42245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_EQ(
42345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko      contents,
42445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko      StringPiece(static_cast<const char*>(shared.memory()), contents.size()));
42545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
42645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  shared_handle = SharedMemoryHandle();
42745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  ASSERT_TRUE(shmem.ShareToProcess(GetCurrentProcessHandle(), &shared_handle));
42845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#if defined(OS_WIN)
42945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  ASSERT_TRUE(shared_handle.OwnershipPassesToIPC());
43045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#endif
43145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  SharedMemory readonly(shared_handle, /*readonly=*/true);
43245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
43345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  ASSERT_TRUE(readonly.Map(contents.size()));
43445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_EQ(contents,
43545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko            StringPiece(static_cast<const char*>(readonly.memory()),
43645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko                        contents.size()));
43745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko}
43845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
43945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex VakulenkoTEST(SharedMemoryTest, MapAt) {
44045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  ASSERT_TRUE(SysInfo::VMAllocationGranularity() >= sizeof(uint32_t));
44145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  const size_t kCount = SysInfo::VMAllocationGranularity();
44245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  const size_t kDataSize = kCount * sizeof(uint32_t);
44345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
44445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  SharedMemory memory;
44545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  ASSERT_TRUE(memory.CreateAndMapAnonymous(kDataSize));
44645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  uint32_t* ptr = static_cast<uint32_t*>(memory.memory());
44745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  ASSERT_NE(ptr, static_cast<void*>(NULL));
44845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
44945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  for (size_t i = 0; i < kCount; ++i) {
45045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko    ptr[i] = i;
45145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  }
45245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
45345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  memory.Unmap();
45445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
45545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  off_t offset = SysInfo::VMAllocationGranularity();
45645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  ASSERT_TRUE(memory.MapAt(offset, kDataSize - offset));
45745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  offset /= sizeof(uint32_t);
45845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  ptr = static_cast<uint32_t*>(memory.memory());
45945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  ASSERT_NE(ptr, static_cast<void*>(NULL));
46045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  for (size_t i = offset; i < kCount; ++i) {
46145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko    EXPECT_EQ(ptr[i - offset], i);
46245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  }
46345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko}
46445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
46545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex VakulenkoTEST(SharedMemoryTest, MapTwice) {
46645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  const uint32_t kDataSize = 1024;
46745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  SharedMemory memory;
46845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  bool rv = memory.CreateAndMapAnonymous(kDataSize);
46945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_TRUE(rv);
47045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
47145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  void* old_address = memory.memory();
47245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
47345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  rv = memory.Map(kDataSize);
47445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_FALSE(rv);
47545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_EQ(old_address, memory.memory());
47645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko}
47745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
47836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#if defined(OS_POSIX)
47945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// This test is not applicable for iOS (crbug.com/399384).
48045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#if !defined(OS_IOS)
48145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// Create a shared memory object, mmap it, and mprotect it to PROT_EXEC.
48245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex VakulenkoTEST(SharedMemoryTest, AnonymousExecutable) {
48345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  const uint32_t kTestSize = 1 << 16;
48445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
48545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  SharedMemory shared_memory;
48645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  SharedMemoryCreateOptions options;
48745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  options.size = kTestSize;
48845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  options.executable = true;
48936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#if defined(OS_MACOSX) && !defined(OS_IOS)
49036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // The Mach functionality is tested in shared_memory_mac_unittest.cc.
49136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  options.type = SharedMemoryHandle::POSIX;
49236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#endif
49345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
49445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_TRUE(shared_memory.Create(options));
49545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_TRUE(shared_memory.Map(shared_memory.requested_size()));
49645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
49745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_EQ(0, mprotect(shared_memory.memory(), shared_memory.requested_size(),
49845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko                        PROT_READ | PROT_EXEC));
49945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko}
50045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#endif  // !defined(OS_IOS)
50145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
50245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// Android supports a different permission model than POSIX for its "ashmem"
50345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// shared memory implementation. So the tests about file permissions are not
50445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// included on Android.
50545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#if !defined(OS_ANDROID)
50645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
50745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// Set a umask and restore the old mask on destruction.
50845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenkoclass ScopedUmaskSetter {
50945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko public:
51045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  explicit ScopedUmaskSetter(mode_t target_mask) {
51145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko    old_umask_ = umask(target_mask);
51245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  }
51345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  ~ScopedUmaskSetter() { umask(old_umask_); }
51445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko private:
51545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  mode_t old_umask_;
51645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  DISALLOW_IMPLICIT_CONSTRUCTORS(ScopedUmaskSetter);
51745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko};
51845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
51945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// Create a shared memory object, check its permissions.
52045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex VakulenkoTEST(SharedMemoryTest, FilePermissionsAnonymous) {
52145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  const uint32_t kTestSize = 1 << 8;
52245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
52345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  SharedMemory shared_memory;
52445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  SharedMemoryCreateOptions options;
52545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  options.size = kTestSize;
52636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#if defined(OS_MACOSX) && !defined(OS_IOS)
52736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // The Mach functionality is tested in shared_memory_mac_unittest.cc.
52836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  options.type = SharedMemoryHandle::POSIX;
52936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#endif
53045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  // Set a file mode creation mask that gives all permissions.
53145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  ScopedUmaskSetter permissive_mask(S_IWGRP | S_IWOTH);
53245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
53345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_TRUE(shared_memory.Create(options));
53445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
53545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  int shm_fd =
53645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko      SharedMemory::GetFdFromSharedMemoryHandle(shared_memory.handle());
53745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  struct stat shm_stat;
53845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_EQ(0, fstat(shm_fd, &shm_stat));
53945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  // Neither the group, nor others should be able to read the shared memory
54045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  // file.
54145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_FALSE(shm_stat.st_mode & S_IRWXO);
54245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_FALSE(shm_stat.st_mode & S_IRWXG);
54345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko}
54445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
54545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// Create a shared memory object, check its permissions.
54645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex VakulenkoTEST(SharedMemoryTest, FilePermissionsNamed) {
54745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  const uint32_t kTestSize = 1 << 8;
54845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
54945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  SharedMemory shared_memory;
55045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  SharedMemoryCreateOptions options;
55145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  options.size = kTestSize;
55236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#if defined(OS_MACOSX) && !defined(OS_IOS)
55336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // The Mach functionality is tested in shared_memory_mac_unittest.cc.
55436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  options.type = SharedMemoryHandle::POSIX;
55536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#endif
55645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
55745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  // Set a file mode creation mask that gives all permissions.
55845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  ScopedUmaskSetter permissive_mask(S_IWGRP | S_IWOTH);
55945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
56045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_TRUE(shared_memory.Create(options));
56145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
56245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  int fd = SharedMemory::GetFdFromSharedMemoryHandle(shared_memory.handle());
56345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  struct stat shm_stat;
56445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_EQ(0, fstat(fd, &shm_stat));
56545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  // Neither the group, nor others should have been able to open the shared
56645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  // memory file while its name existed.
56745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_FALSE(shm_stat.st_mode & S_IRWXO);
56845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_FALSE(shm_stat.st_mode & S_IRWXG);
56945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko}
57045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#endif  // !defined(OS_ANDROID)
57145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
57236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#endif  // defined(OS_POSIX)
57345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
57445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// Map() will return addresses which are aligned to the platform page size, this
57545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// varies from platform to platform though.  Since we'd like to advertise a
57645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// minimum alignment that callers can count on, test for it here.
57745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex VakulenkoTEST(SharedMemoryTest, MapMinimumAlignment) {
57845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  static const int kDataSize = 8192;
57945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
58045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  SharedMemory shared_memory;
58145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  ASSERT_TRUE(shared_memory.CreateAndMapAnonymous(kDataSize));
58245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_EQ(0U, reinterpret_cast<uintptr_t>(
58345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko      shared_memory.memory()) & (SharedMemory::MAP_MINIMUM_ALIGNMENT - 1));
58445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  shared_memory.Close();
58545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko}
58645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
58745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#if defined(OS_WIN)
58845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex VakulenkoTEST(SharedMemoryTest, UnsafeImageSection) {
58945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  const char kTestSectionName[] = "UnsafeImageSection";
59045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  wchar_t path[MAX_PATH];
59145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_GT(::GetModuleFileName(nullptr, path, arraysize(path)), 0U);
59245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
59345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  // Map the current executable image to save us creating a new PE file on disk.
59494ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez  base::win::ScopedHandle file_handle(::CreateFile(
59594ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez      path, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr));
59645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_TRUE(file_handle.IsValid());
59745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  base::win::ScopedHandle section_handle(
59845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko      ::CreateFileMappingA(file_handle.Get(), nullptr,
59945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko                           PAGE_READONLY | SEC_IMAGE, 0, 0, kTestSectionName));
60045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_TRUE(section_handle.IsValid());
60145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
60245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  // Check direct opening by name, from handle and duplicated from handle.
60345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  SharedMemory shared_memory_open;
60445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_TRUE(shared_memory_open.Open(kTestSectionName, true));
60545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_FALSE(shared_memory_open.Map(1));
60645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_EQ(nullptr, shared_memory_open.memory());
60745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
60845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  SharedMemory shared_memory_handle_local(
60945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko      SharedMemoryHandle(section_handle.Take(), ::GetCurrentProcessId()), true);
61045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_FALSE(shared_memory_handle_local.Map(1));
61145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_EQ(nullptr, shared_memory_handle_local.memory());
61245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
61345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  // Check that a handle without SECTION_QUERY also can't be mapped as it can't
61445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  // be checked.
61545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  SharedMemory shared_memory_handle_dummy;
61645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  SharedMemoryCreateOptions options;
61745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  options.size = 0x1000;
61845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_TRUE(shared_memory_handle_dummy.Create(options));
61945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  HANDLE handle_no_query;
62045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_TRUE(::DuplicateHandle(
62145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko      ::GetCurrentProcess(), shared_memory_handle_dummy.handle().GetHandle(),
62245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko      ::GetCurrentProcess(), &handle_no_query, FILE_MAP_READ, FALSE, 0));
62345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  SharedMemory shared_memory_handle_no_query(
62445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko      SharedMemoryHandle(handle_no_query, ::GetCurrentProcessId()), true);
62545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_FALSE(shared_memory_handle_no_query.Map(1));
62645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_EQ(nullptr, shared_memory_handle_no_query.memory());
62745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko}
62845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#endif  // defined(OS_WIN)
62945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
63045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// iOS does not allow multiple processes.
63145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// Android ashmem does not support named shared memory.
63245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// Mac SharedMemory does not support named shared memory. crbug.com/345734
63345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#if !defined(OS_IOS) && !defined(OS_ANDROID) && !defined(OS_MACOSX)
63445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// On POSIX it is especially important we test shmem across processes,
63545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// not just across threads.  But the test is enabled on all platforms.
63645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenkoclass SharedMemoryProcessTest : public MultiProcessTest {
63745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko public:
63845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  static void CleanUp() {
63945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko    SharedMemory memory;
64045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko    memory.Delete(s_test_name_);
64145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  }
64245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
64345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  static int TaskTestMain() {
64445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko    int errors = 0;
64545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko    SharedMemory memory;
64645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko    bool rv = memory.CreateNamedDeprecated(s_test_name_, true, s_data_size_);
64745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko    EXPECT_TRUE(rv);
64845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko    if (rv != true)
64945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko      errors++;
65045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko    rv = memory.Map(s_data_size_);
65145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko    EXPECT_TRUE(rv);
65245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko    if (rv != true)
65345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko      errors++;
65445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko    int* ptr = static_cast<int*>(memory.memory());
65545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
65645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko    // This runs concurrently in multiple processes. Writes need to be atomic.
65745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko    subtle::Barrier_AtomicIncrement(ptr, 1);
65845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko    memory.Close();
65945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko    return errors;
66045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  }
66145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
66245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  static const char s_test_name_[];
66345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  static const uint32_t s_data_size_;
66445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko};
66545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
66645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenkoconst char SharedMemoryProcessTest::s_test_name_[] = "MPMem";
66745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenkoconst uint32_t SharedMemoryProcessTest::s_data_size_ = 1024;
66845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
66945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex VakulenkoTEST_F(SharedMemoryProcessTest, SharedMemoryAcrossProcesses) {
67045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  const int kNumTasks = 5;
67145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
67245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  SharedMemoryProcessTest::CleanUp();
67345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
67445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  // Create a shared memory region. Set the first word to 0.
67545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  SharedMemory memory;
67645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  bool rv = memory.CreateNamedDeprecated(s_test_name_, true, s_data_size_);
67745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  ASSERT_TRUE(rv);
67845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  rv = memory.Map(s_data_size_);
67945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  ASSERT_TRUE(rv);
68045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  int* ptr = static_cast<int*>(memory.memory());
68145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  *ptr = 0;
68245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
68345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  // Start |kNumTasks| processes, each of which atomically increments the first
68445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  // word by 1.
685319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski  SpawnChildResult children[kNumTasks];
68645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  for (int index = 0; index < kNumTasks; ++index) {
687319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    children[index] = SpawnChild("SharedMemoryTestMain");
688319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    ASSERT_TRUE(children[index].process.IsValid());
68945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  }
69045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
69145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  // Check that each process exited correctly.
69245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  int exit_code = 0;
69345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  for (int index = 0; index < kNumTasks; ++index) {
694319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski    EXPECT_TRUE(children[index].process.WaitForExit(&exit_code));
69545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko    EXPECT_EQ(0, exit_code);
69645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  }
69745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
69845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  // Check that the shared memory region reflects |kNumTasks| increments.
69945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  ASSERT_EQ(kNumTasks, *ptr);
70045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
70145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  memory.Close();
70245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  SharedMemoryProcessTest::CleanUp();
70345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko}
70445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
70545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex VakulenkoMULTIPROCESS_TEST_MAIN(SharedMemoryTestMain) {
70645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  return SharedMemoryProcessTest::TaskTestMain();
70745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko}
70845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#endif  // !defined(OS_IOS) && !defined(OS_ANDROID) && !defined(OS_MACOSX)
70945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
71045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko}  // namespace base
711