| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/common/multi_process_lock.h" |
| 6 |
| 7 #include <memory> |
| 8 |
| 5 #include "base/environment.h" | 9 #include "base/environment.h" |
| 6 #include "base/logging.h" | 10 #include "base/logging.h" |
| 7 #include "base/macros.h" | 11 #include "base/macros.h" |
| 8 #include "base/memory/scoped_ptr.h" | |
| 9 #include "base/process/kill.h" | 12 #include "base/process/kill.h" |
| 10 #include "base/rand_util.h" | 13 #include "base/rand_util.h" |
| 11 #include "base/strings/stringprintf.h" | 14 #include "base/strings/stringprintf.h" |
| 12 #include "base/test/multiprocess_test.h" | 15 #include "base/test/multiprocess_test.h" |
| 13 #include "base/time/time.h" | 16 #include "base/time/time.h" |
| 14 #include "build/build_config.h" | 17 #include "build/build_config.h" |
| 15 #include "chrome/common/multi_process_lock.h" | |
| 16 #include "testing/multiprocess_func_list.h" | 18 #include "testing/multiprocess_func_list.h" |
| 17 | 19 |
| 18 class MultiProcessLockTest : public base::MultiProcessTest { | 20 class MultiProcessLockTest : public base::MultiProcessTest { |
| 19 public: | 21 public: |
| 20 static const char kLockEnviromentVarName[]; | 22 static const char kLockEnviromentVarName[]; |
| 21 | 23 |
| 22 class ScopedEnvironmentVariable { | 24 class ScopedEnvironmentVariable { |
| 23 public: | 25 public: |
| 24 ScopedEnvironmentVariable(const std::string &name, | 26 ScopedEnvironmentVariable(const std::string &name, |
| 25 const std::string &value) | 27 const std::string &value) |
| 26 : name_(name), environment_(base::Environment::Create()) { | 28 : name_(name), environment_(base::Environment::Create()) { |
| 27 environment_->SetVar(name_.c_str(), value); | 29 environment_->SetVar(name_.c_str(), value); |
| 28 } | 30 } |
| 29 ~ScopedEnvironmentVariable() { | 31 ~ScopedEnvironmentVariable() { |
| 30 environment_->UnSetVar(name_.c_str()); | 32 environment_->UnSetVar(name_.c_str()); |
| 31 } | 33 } |
| 32 | 34 |
| 33 private: | 35 private: |
| 34 std::string name_; | 36 std::string name_; |
| 35 scoped_ptr<base::Environment> environment_; | 37 std::unique_ptr<base::Environment> environment_; |
| 36 DISALLOW_COPY_AND_ASSIGN(ScopedEnvironmentVariable); | 38 DISALLOW_COPY_AND_ASSIGN(ScopedEnvironmentVariable); |
| 37 }; | 39 }; |
| 38 | 40 |
| 39 std::string GenerateLockName(); | 41 std::string GenerateLockName(); |
| 40 void ExpectLockIsLocked(const std::string &name); | 42 void ExpectLockIsLocked(const std::string &name); |
| 41 void ExpectLockIsUnlocked(const std::string &name); | 43 void ExpectLockIsUnlocked(const std::string &name); |
| 42 }; | 44 }; |
| 43 | 45 |
| 44 const char MultiProcessLockTest::kLockEnviromentVarName[] | 46 const char MultiProcessLockTest::kLockEnviromentVarName[] |
| 45 = "MULTI_PROCESS_TEST_LOCK_NAME"; | 47 = "MULTI_PROCESS_TEST_LOCK_NAME"; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 65 base::Process process = SpawnChild("MultiProcessLockTrySucceedMain"); | 67 base::Process process = SpawnChild("MultiProcessLockTrySucceedMain"); |
| 66 ASSERT_TRUE(process.IsValid()); | 68 ASSERT_TRUE(process.IsValid()); |
| 67 int exit_code = -1; | 69 int exit_code = -1; |
| 68 EXPECT_TRUE(process.WaitForExit(&exit_code)); | 70 EXPECT_TRUE(process.WaitForExit(&exit_code)); |
| 69 EXPECT_EQ(0, exit_code); | 71 EXPECT_EQ(0, exit_code); |
| 70 } | 72 } |
| 71 | 73 |
| 72 TEST_F(MultiProcessLockTest, BasicCreationTest) { | 74 TEST_F(MultiProcessLockTest, BasicCreationTest) { |
| 73 // Test basic creation/destruction with no lock taken | 75 // Test basic creation/destruction with no lock taken |
| 74 std::string name = GenerateLockName(); | 76 std::string name = GenerateLockName(); |
| 75 scoped_ptr<MultiProcessLock> scoped(MultiProcessLock::Create(name)); | 77 std::unique_ptr<MultiProcessLock> scoped(MultiProcessLock::Create(name)); |
| 76 ExpectLockIsUnlocked(name); | 78 ExpectLockIsUnlocked(name); |
| 77 scoped.reset(NULL); | 79 scoped.reset(NULL); |
| 78 } | 80 } |
| 79 | 81 |
| 80 TEST_F(MultiProcessLockTest, LongNameTest) { | 82 TEST_F(MultiProcessLockTest, LongNameTest) { |
| 81 // Every platform has has it's own max path name size, | 83 // Every platform has has it's own max path name size, |
| 82 // so different checks are needed for them. | 84 // so different checks are needed for them. |
| 83 // POSIX: sizeof(address.sun_path) - 2 | 85 // POSIX: sizeof(address.sun_path) - 2 |
| 84 // Mac OS X: BOOTSTRAP_MAX_NAME_LEN | 86 // Mac OS X: BOOTSTRAP_MAX_NAME_LEN |
| 85 // Windows: MAX_PATH | 87 // Windows: MAX_PATH |
| 86 LOG(INFO) << "Following error log due to long name is expected"; | 88 LOG(INFO) << "Following error log due to long name is expected"; |
| 87 #if defined(OS_MACOSX) | 89 #if defined(OS_MACOSX) |
| 88 std::string name("This is a name that is longer than one hundred and " | 90 std::string name("This is a name that is longer than one hundred and " |
| 89 "twenty-eight characters to make sure that we fail appropriately on " | 91 "twenty-eight characters to make sure that we fail appropriately on " |
| 90 "Mac OS X when we have a path that is too long for Mac OS X to handle"); | 92 "Mac OS X when we have a path that is too long for Mac OS X to handle"); |
| 91 #elif defined(OS_POSIX) | 93 #elif defined(OS_POSIX) |
| 92 std::string name("This is a name that is longer than one hundred and eight " | 94 std::string name("This is a name that is longer than one hundred and eight " |
| 93 "characters to make sure that we fail appropriately on POSIX systems " | 95 "characters to make sure that we fail appropriately on POSIX systems " |
| 94 "when we have a path that is too long for the system to handle"); | 96 "when we have a path that is too long for the system to handle"); |
| 95 #elif defined(OS_WIN) | 97 #elif defined(OS_WIN) |
| 96 std::string name("This is a name that is longer than two hundred and sixty " | 98 std::string name("This is a name that is longer than two hundred and sixty " |
| 97 "characters to make sure that we fail appropriately on Windows when we " | 99 "characters to make sure that we fail appropriately on Windows when we " |
| 98 "have a path that is too long for Windows to handle " | 100 "have a path that is too long for Windows to handle " |
| 99 "This limitation comes from the MAX_PATH definition which is obviously " | 101 "This limitation comes from the MAX_PATH definition which is obviously " |
| 100 "defined to be a maximum of two hundred and sixty characters "); | 102 "defined to be a maximum of two hundred and sixty characters "); |
| 101 #endif | 103 #endif |
| 102 scoped_ptr<MultiProcessLock> test_lock(MultiProcessLock::Create(name)); | 104 std::unique_ptr<MultiProcessLock> test_lock(MultiProcessLock::Create(name)); |
| 103 EXPECT_FALSE(test_lock->TryLock()); | 105 EXPECT_FALSE(test_lock->TryLock()); |
| 104 } | 106 } |
| 105 | 107 |
| 106 TEST_F(MultiProcessLockTest, SimpleLock) { | 108 TEST_F(MultiProcessLockTest, SimpleLock) { |
| 107 std::string name = GenerateLockName(); | 109 std::string name = GenerateLockName(); |
| 108 scoped_ptr<MultiProcessLock> test_lock(MultiProcessLock::Create(name)); | 110 std::unique_ptr<MultiProcessLock> test_lock(MultiProcessLock::Create(name)); |
| 109 EXPECT_TRUE(test_lock->TryLock()); | 111 EXPECT_TRUE(test_lock->TryLock()); |
| 110 ExpectLockIsLocked(name); | 112 ExpectLockIsLocked(name); |
| 111 test_lock->Unlock(); | 113 test_lock->Unlock(); |
| 112 ExpectLockIsUnlocked(name); | 114 ExpectLockIsUnlocked(name); |
| 113 } | 115 } |
| 114 | 116 |
| 115 TEST_F(MultiProcessLockTest, RecursiveLock) { | 117 TEST_F(MultiProcessLockTest, RecursiveLock) { |
| 116 std::string name = GenerateLockName(); | 118 std::string name = GenerateLockName(); |
| 117 scoped_ptr<MultiProcessLock> test_lock(MultiProcessLock::Create(name)); | 119 std::unique_ptr<MultiProcessLock> test_lock(MultiProcessLock::Create(name)); |
| 118 EXPECT_TRUE(test_lock->TryLock()); | 120 EXPECT_TRUE(test_lock->TryLock()); |
| 119 ExpectLockIsLocked(name); | 121 ExpectLockIsLocked(name); |
| 120 LOG(INFO) << "Following error log " | 122 LOG(INFO) << "Following error log " |
| 121 << "'MultiProcessLock is already locked' is expected"; | 123 << "'MultiProcessLock is already locked' is expected"; |
| 122 EXPECT_TRUE(test_lock->TryLock()); | 124 EXPECT_TRUE(test_lock->TryLock()); |
| 123 ExpectLockIsLocked(name); | 125 ExpectLockIsLocked(name); |
| 124 test_lock->Unlock(); | 126 test_lock->Unlock(); |
| 125 ExpectLockIsUnlocked(name); | 127 ExpectLockIsUnlocked(name); |
| 126 LOG(INFO) << "Following error log " | 128 LOG(INFO) << "Following error log " |
| 127 << "'Over-unlocked MultiProcessLock' is expected"; | 129 << "'Over-unlocked MultiProcessLock' is expected"; |
| 128 test_lock->Unlock(); | 130 test_lock->Unlock(); |
| 129 ExpectLockIsUnlocked(name); | 131 ExpectLockIsUnlocked(name); |
| 130 test_lock.reset(); | 132 test_lock.reset(); |
| 131 } | 133 } |
| 132 | 134 |
| 133 TEST_F(MultiProcessLockTest, LockScope) { | 135 TEST_F(MultiProcessLockTest, LockScope) { |
| 134 // Check to see that lock is released when it goes out of scope. | 136 // Check to see that lock is released when it goes out of scope. |
| 135 std::string name = GenerateLockName(); | 137 std::string name = GenerateLockName(); |
| 136 { | 138 { |
| 137 scoped_ptr<MultiProcessLock> test_lock(MultiProcessLock::Create(name)); | 139 std::unique_ptr<MultiProcessLock> test_lock(MultiProcessLock::Create(name)); |
| 138 EXPECT_TRUE(test_lock->TryLock()); | 140 EXPECT_TRUE(test_lock->TryLock()); |
| 139 ExpectLockIsLocked(name); | 141 ExpectLockIsLocked(name); |
| 140 } | 142 } |
| 141 ExpectLockIsUnlocked(name); | 143 ExpectLockIsUnlocked(name); |
| 142 } | 144 } |
| 143 | 145 |
| 144 MULTIPROCESS_TEST_MAIN(MultiProcessLockTryFailMain) { | 146 MULTIPROCESS_TEST_MAIN(MultiProcessLockTryFailMain) { |
| 145 std::string name; | 147 std::string name; |
| 146 scoped_ptr<base::Environment> environment(base::Environment::Create()); | 148 std::unique_ptr<base::Environment> environment(base::Environment::Create()); |
| 147 EXPECT_TRUE(environment->GetVar(MultiProcessLockTest::kLockEnviromentVarName, | 149 EXPECT_TRUE(environment->GetVar(MultiProcessLockTest::kLockEnviromentVarName, |
| 148 &name)); | 150 &name)); |
| 149 #if defined(OS_MACOSX) | 151 #if defined(OS_MACOSX) |
| 150 // OS X sends out a log if a lock fails. | 152 // OS X sends out a log if a lock fails. |
| 151 // Hopefully this will keep people from panicking about it when they | 153 // Hopefully this will keep people from panicking about it when they |
| 152 // are perusing the build logs. | 154 // are perusing the build logs. |
| 153 LOG(INFO) << "Following error log " | 155 LOG(INFO) << "Following error log " |
| 154 << "\"CFMessagePort: bootstrap_register(): failed 1100 (0x44c) " | 156 << "\"CFMessagePort: bootstrap_register(): failed 1100 (0x44c) " |
| 155 << "'Permission denied'\" is expected"; | 157 << "'Permission denied'\" is expected"; |
| 156 #endif // defined(OS_MACOSX) | 158 #endif // defined(OS_MACOSX) |
| 157 scoped_ptr<MultiProcessLock> test_lock( | 159 std::unique_ptr<MultiProcessLock> test_lock(MultiProcessLock::Create(name)); |
| 158 MultiProcessLock::Create(name)); | |
| 159 | 160 |
| 160 // Expect locking to fail because it is claimed by another process. | 161 // Expect locking to fail because it is claimed by another process. |
| 161 bool locked_successfully = test_lock->TryLock(); | 162 bool locked_successfully = test_lock->TryLock(); |
| 162 EXPECT_FALSE(locked_successfully); | 163 EXPECT_FALSE(locked_successfully); |
| 163 return locked_successfully; | 164 return locked_successfully; |
| 164 } | 165 } |
| 165 | 166 |
| 166 MULTIPROCESS_TEST_MAIN(MultiProcessLockTrySucceedMain) { | 167 MULTIPROCESS_TEST_MAIN(MultiProcessLockTrySucceedMain) { |
| 167 std::string name; | 168 std::string name; |
| 168 scoped_ptr<base::Environment> environment(base::Environment::Create()); | 169 std::unique_ptr<base::Environment> environment(base::Environment::Create()); |
| 169 EXPECT_TRUE(environment->GetVar(MultiProcessLockTest::kLockEnviromentVarName, | 170 EXPECT_TRUE(environment->GetVar(MultiProcessLockTest::kLockEnviromentVarName, |
| 170 &name)); | 171 &name)); |
| 171 scoped_ptr<MultiProcessLock> test_lock( | 172 std::unique_ptr<MultiProcessLock> test_lock(MultiProcessLock::Create(name)); |
| 172 MultiProcessLock::Create(name)); | |
| 173 | 173 |
| 174 // Expect locking to succeed because it is not claimed yet. | 174 // Expect locking to succeed because it is not claimed yet. |
| 175 bool locked_successfully = test_lock->TryLock(); | 175 bool locked_successfully = test_lock->TryLock(); |
| 176 EXPECT_TRUE(locked_successfully); | 176 EXPECT_TRUE(locked_successfully); |
| 177 return !locked_successfully; | 177 return !locked_successfully; |
| 178 } | 178 } |
| OLD | NEW |