diff options
Diffstat (limited to 'chromium/chrome/common/multi_process_lock_unittest.cc')
-rw-r--r-- | chromium/chrome/common/multi_process_lock_unittest.cc | 168 |
1 files changed, 168 insertions, 0 deletions
diff --git a/chromium/chrome/common/multi_process_lock_unittest.cc b/chromium/chrome/common/multi_process_lock_unittest.cc new file mode 100644 index 00000000000..4d59c5ad471 --- /dev/null +++ b/chromium/chrome/common/multi_process_lock_unittest.cc @@ -0,0 +1,168 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/common/multi_process_lock.h" + +#include <memory> + +#include "base/environment.h" +#include "base/logging.h" +#include "base/macros.h" +#include "base/process/kill.h" +#include "base/rand_util.h" +#include "base/strings/stringprintf.h" +#include "base/test/multiprocess_test.h" +#include "base/test/scoped_environment_variable_override.h" +#include "base/time/time.h" +#include "build/build_config.h" +#include "testing/multiprocess_func_list.h" + +class MultiProcessLockTest : public base::MultiProcessTest { + public: + static const char kLockEnvironmentVarName[]; + + std::string GenerateLockName(); + void ExpectLockIsLocked(const std::string &name); + void ExpectLockIsUnlocked(const std::string &name); +}; + +const char MultiProcessLockTest::kLockEnvironmentVarName[] = + "MULTI_PROCESS_TEST_LOCK_NAME"; + +std::string MultiProcessLockTest::GenerateLockName() { + base::Time now = base::Time::NowFromSystemTime(); + return base::StringPrintf("multi_process_test_lock %lf%lf", + now.ToDoubleT(), base::RandDouble()); +} + +void MultiProcessLockTest::ExpectLockIsLocked(const std::string &name) { + base::test::ScopedEnvironmentVariableOverride var(kLockEnvironmentVarName, + name); + EXPECT_FALSE(var.WasSet()); + + base::Process process = SpawnChild("MultiProcessLockTryFailMain"); + ASSERT_TRUE(process.IsValid()); + int exit_code = -1; + EXPECT_TRUE(process.WaitForExit(&exit_code)); + EXPECT_EQ(0, exit_code); +} + +void MultiProcessLockTest::ExpectLockIsUnlocked( + const std::string &name) { + base::test::ScopedEnvironmentVariableOverride var(kLockEnvironmentVarName, + name); + EXPECT_FALSE(var.WasSet()); + base::Process process = SpawnChild("MultiProcessLockTrySucceedMain"); + ASSERT_TRUE(process.IsValid()); + int exit_code = -1; + EXPECT_TRUE(process.WaitForExit(&exit_code)); + EXPECT_EQ(0, exit_code); +} + +TEST_F(MultiProcessLockTest, BasicCreationTest) { + // Test basic creation/destruction with no lock taken + std::string name = GenerateLockName(); + std::unique_ptr<MultiProcessLock> scoped = MultiProcessLock::Create(name); + ExpectLockIsUnlocked(name); + scoped.reset(NULL); +} + +TEST_F(MultiProcessLockTest, LongNameTest) { + // Every platform has has it's own max path name size, + // so different checks are needed for them. + // POSIX: sizeof(address.sun_path) - 2 + // Mac OS X: BOOTSTRAP_MAX_NAME_LEN + // Windows: MAX_PATH + LOG(INFO) << "Following error log due to long name is expected"; +#if defined(OS_MACOSX) + std::string name("This is a name that is longer than one hundred and " + "twenty-eight characters to make sure that we fail appropriately on " + "Mac OS X when we have a path that is too long for Mac OS X to handle"); +#elif defined(OS_POSIX) + std::string name("This is a name that is longer than one hundred and eight " + "characters to make sure that we fail appropriately on POSIX systems " + "when we have a path that is too long for the system to handle"); +#elif defined(OS_WIN) + std::string name("This is a name that is longer than two hundred and sixty " + "characters to make sure that we fail appropriately on Windows when we " + "have a path that is too long for Windows to handle " + "This limitation comes from the MAX_PATH definition which is obviously " + "defined to be a maximum of two hundred and sixty characters "); +#endif + std::unique_ptr<MultiProcessLock> test_lock = MultiProcessLock::Create(name); + EXPECT_FALSE(test_lock->TryLock()); +} + +TEST_F(MultiProcessLockTest, SimpleLock) { + std::string name = GenerateLockName(); + std::unique_ptr<MultiProcessLock> test_lock = MultiProcessLock::Create(name); + EXPECT_TRUE(test_lock->TryLock()); + ExpectLockIsLocked(name); + test_lock->Unlock(); + ExpectLockIsUnlocked(name); +} + +TEST_F(MultiProcessLockTest, RecursiveLock) { + std::string name = GenerateLockName(); + std::unique_ptr<MultiProcessLock> test_lock = MultiProcessLock::Create(name); + EXPECT_TRUE(test_lock->TryLock()); + ExpectLockIsLocked(name); + LOG(INFO) << "Following error log " + << "'MultiProcessLock is already locked' is expected"; + EXPECT_TRUE(test_lock->TryLock()); + ExpectLockIsLocked(name); + test_lock->Unlock(); + ExpectLockIsUnlocked(name); + LOG(INFO) << "Following error log " + << "'Over-unlocked MultiProcessLock' is expected"; + test_lock->Unlock(); + ExpectLockIsUnlocked(name); + test_lock.reset(); +} + +TEST_F(MultiProcessLockTest, LockScope) { + // Check to see that lock is released when it goes out of scope. + std::string name = GenerateLockName(); + { + std::unique_ptr<MultiProcessLock> test_lock = + MultiProcessLock::Create(name); + EXPECT_TRUE(test_lock->TryLock()); + ExpectLockIsLocked(name); + } + ExpectLockIsUnlocked(name); +} + +MULTIPROCESS_TEST_MAIN(MultiProcessLockTryFailMain) { + std::string name; + std::unique_ptr<base::Environment> environment(base::Environment::Create()); + EXPECT_TRUE(environment->GetVar(MultiProcessLockTest::kLockEnvironmentVarName, + &name)); +#if defined(OS_MACOSX) + // OS X sends out a log if a lock fails. + // Hopefully this will keep people from panicking about it when they + // are perusing the build logs. + LOG(INFO) << "Following error log " + << "\"CFMessagePort: bootstrap_register(): failed 1100 (0x44c) " + << "'Permission denied'\" is expected"; +#endif // defined(OS_MACOSX) + std::unique_ptr<MultiProcessLock> test_lock = MultiProcessLock::Create(name); + + // Expect locking to fail because it is claimed by another process. + bool locked_successfully = test_lock->TryLock(); + EXPECT_FALSE(locked_successfully); + return locked_successfully; +} + +MULTIPROCESS_TEST_MAIN(MultiProcessLockTrySucceedMain) { + std::string name; + std::unique_ptr<base::Environment> environment(base::Environment::Create()); + EXPECT_TRUE(environment->GetVar(MultiProcessLockTest::kLockEnvironmentVarName, + &name)); + std::unique_ptr<MultiProcessLock> test_lock = MultiProcessLock::Create(name); + + // Expect locking to succeed because it is not claimed yet. + bool locked_successfully = test_lock->TryLock(); + EXPECT_TRUE(locked_successfully); + return !locked_successfully; +} |