summaryrefslogtreecommitdiff
path: root/chromium/chrome/common/multi_process_lock_unittest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/chrome/common/multi_process_lock_unittest.cc')
-rw-r--r--chromium/chrome/common/multi_process_lock_unittest.cc168
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;
+}