diff options
Diffstat (limited to 'chrome/common/multi_process_lock_unittest.cc')
-rw-r--r-- | chrome/common/multi_process_lock_unittest.cc | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/chrome/common/multi_process_lock_unittest.cc b/chrome/common/multi_process_lock_unittest.cc new file mode 100644 index 0000000..d408db7 --- /dev/null +++ b/chrome/common/multi_process_lock_unittest.cc @@ -0,0 +1,157 @@ +// Copyright (c) 2010 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 "base/basictypes.h" +#include "base/environment.h" +#include "base/logging.h" +#include "base/rand_util.h" +#include "base/scoped_ptr.h" +#include "base/stringprintf.h" +#include "base/test/multiprocess_test.h" +#include "base/time.h" +#include "chrome/common/multi_process_lock.h" +#include "testing/multiprocess_func_list.h" + +class MultiProcessLockTest : public base::MultiProcessTest { + public: + static const char kLockEnviromentVarName[]; + + class ScopedEnvironmentVariable { + public: + ScopedEnvironmentVariable(const std::string &name, + const std::string &value) + : name_(name), environment_(base::Environment::Create()) { + environment_->SetVar(name_.c_str(), value); + } + ~ScopedEnvironmentVariable() { + environment_->UnSetVar(name_.c_str()); + } + + private: + std::string name_; + scoped_ptr<base::Environment> environment_; + DISALLOW_COPY_AND_ASSIGN(ScopedEnvironmentVariable); + }; + + std::string GenerateLockName(); + void ExpectLockIsLocked(const std::string &name); + void ExpectLockIsUnlocked(const std::string &name); +}; + +const char MultiProcessLockTest::kLockEnviromentVarName[] + = "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) { + ScopedEnvironmentVariable var(kLockEnviromentVarName, name); + base::ProcessHandle handle = SpawnChild("MultiProcessLockTryFailMain", false); + ASSERT_TRUE(handle); + int exit_code = 0; + EXPECT_TRUE(base::WaitForExitCode(handle, &exit_code)); + EXPECT_EQ(exit_code, 0); +} + +void MultiProcessLockTest::ExpectLockIsUnlocked( + const std::string &name) { + ScopedEnvironmentVariable var(kLockEnviromentVarName, name); + base::ProcessHandle handle = SpawnChild("MultiProcessLockTrySucceedMain", + false); + ASSERT_TRUE(handle); + int exit_code = 0; + EXPECT_TRUE(base::WaitForExitCode(handle, &exit_code)); + EXPECT_EQ(exit_code, 0); +} + +TEST_F(MultiProcessLockTest, BasicCreationTest) { + // Test basic creation/destruction with no lock taken + std::string name = GenerateLockName(); + scoped_ptr<MultiProcessLock> scoped(MultiProcessLock::Create(name)); + ExpectLockIsUnlocked(name); + scoped.reset(NULL); +} + +TEST_F(MultiProcessLockTest, LongNameTest) { + // Linux has a max path name of 108 characters. + // http://lxr.linux.no/linux+v2.6.36/include/linux/un.h + // This is enforced on all platforms. + LOG(INFO) << "Following error log due to long name is expected"; + std::string name("This is a name that is longer than one hundred and eight " + "characters to make sure that we fail appropriately on linux when we " + "have a path that is to long for linux to handle"); + scoped_ptr<MultiProcessLock> test_lock(MultiProcessLock::Create(name)); + EXPECT_FALSE(test_lock->TryLock()); +} + +TEST_F(MultiProcessLockTest, SimpleLock) { + std::string name = GenerateLockName(); + scoped_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(); + scoped_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(); + { + scoped_ptr<MultiProcessLock> test_lock(MultiProcessLock::Create(name)); + EXPECT_TRUE(test_lock->TryLock()); + ExpectLockIsLocked(name); + } + ExpectLockIsUnlocked(name); +} + +MULTIPROCESS_TEST_MAIN(MultiProcessLockTryFailMain) { + std::string name; + scoped_ptr<base::Environment> environment(base::Environment::Create()); + EXPECT_TRUE(environment->GetVar(MultiProcessLockTest::kLockEnviromentVarName, + &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) + scoped_ptr<MultiProcessLock> test_lock( + MultiProcessLock::Create(name)); + EXPECT_FALSE(test_lock->TryLock()); + return 0; +} + +MULTIPROCESS_TEST_MAIN(MultiProcessLockTrySucceedMain) { + std::string name; + scoped_ptr<base::Environment> environment(base::Environment::Create()); + EXPECT_TRUE(environment->GetVar(MultiProcessLockTest::kLockEnviromentVarName, + &name)); + scoped_ptr<MultiProcessLock> test_lock( + MultiProcessLock::Create(name)); + EXPECT_TRUE(test_lock->TryLock()); + return 0; +} |