blob: e1408eedf5402bcb07ec4b91135d2a3b50d11252 [file] [log] [blame]
Kristian Monsenddb351d2011-06-28 21:49:31 +01001// Copyright (c) 2011 The Chromium Authors. All rights reserved.
Ben Murdoch4a5e2dc2010-11-25 19:40:10 +00002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "base/basictypes.h"
6#include "base/environment.h"
7#include "base/logging.h"
Kristian Monsenddb351d2011-06-28 21:49:31 +01008#include "base/memory/scoped_ptr.h"
Ben Murdoch4a5e2dc2010-11-25 19:40:10 +00009#include "base/rand_util.h"
Ben Murdoch4a5e2dc2010-11-25 19:40:10 +000010#include "base/stringprintf.h"
11#include "base/test/multiprocess_test.h"
12#include "base/time.h"
13#include "chrome/common/multi_process_lock.h"
14#include "testing/multiprocess_func_list.h"
15
16class MultiProcessLockTest : public base::MultiProcessTest {
17 public:
18 static const char kLockEnviromentVarName[];
19
20 class ScopedEnvironmentVariable {
21 public:
22 ScopedEnvironmentVariable(const std::string &name,
23 const std::string &value)
24 : name_(name), environment_(base::Environment::Create()) {
25 environment_->SetVar(name_.c_str(), value);
26 }
27 ~ScopedEnvironmentVariable() {
28 environment_->UnSetVar(name_.c_str());
29 }
30
31 private:
32 std::string name_;
33 scoped_ptr<base::Environment> environment_;
34 DISALLOW_COPY_AND_ASSIGN(ScopedEnvironmentVariable);
35 };
36
37 std::string GenerateLockName();
38 void ExpectLockIsLocked(const std::string &name);
39 void ExpectLockIsUnlocked(const std::string &name);
40};
41
42const char MultiProcessLockTest::kLockEnviromentVarName[]
43 = "MULTI_PROCESS_TEST_LOCK_NAME";
44
45std::string MultiProcessLockTest::GenerateLockName() {
46 base::Time now = base::Time::NowFromSystemTime();
47 return base::StringPrintf("multi_process_test_lock %lf%lf",
48 now.ToDoubleT(), base::RandDouble());
49}
50
51void MultiProcessLockTest::ExpectLockIsLocked(const std::string &name) {
52 ScopedEnvironmentVariable var(kLockEnviromentVarName, name);
53 base::ProcessHandle handle = SpawnChild("MultiProcessLockTryFailMain", false);
54 ASSERT_TRUE(handle);
55 int exit_code = 0;
56 EXPECT_TRUE(base::WaitForExitCode(handle, &exit_code));
57 EXPECT_EQ(exit_code, 0);
58}
59
60void MultiProcessLockTest::ExpectLockIsUnlocked(
61 const std::string &name) {
62 ScopedEnvironmentVariable var(kLockEnviromentVarName, name);
63 base::ProcessHandle handle = SpawnChild("MultiProcessLockTrySucceedMain",
64 false);
65 ASSERT_TRUE(handle);
66 int exit_code = 0;
67 EXPECT_TRUE(base::WaitForExitCode(handle, &exit_code));
68 EXPECT_EQ(exit_code, 0);
69}
70
71TEST_F(MultiProcessLockTest, BasicCreationTest) {
72 // Test basic creation/destruction with no lock taken
73 std::string name = GenerateLockName();
74 scoped_ptr<MultiProcessLock> scoped(MultiProcessLock::Create(name));
75 ExpectLockIsUnlocked(name);
76 scoped.reset(NULL);
77}
78
79TEST_F(MultiProcessLockTest, LongNameTest) {
80 // Linux has a max path name of 108 characters.
81 // http://lxr.linux.no/linux+v2.6.36/include/linux/un.h
82 // This is enforced on all platforms.
83 LOG(INFO) << "Following error log due to long name is expected";
84 std::string name("This is a name that is longer than one hundred and eight "
85 "characters to make sure that we fail appropriately on linux when we "
86 "have a path that is to long for linux to handle");
87 scoped_ptr<MultiProcessLock> test_lock(MultiProcessLock::Create(name));
88 EXPECT_FALSE(test_lock->TryLock());
89}
90
91TEST_F(MultiProcessLockTest, SimpleLock) {
92 std::string name = GenerateLockName();
93 scoped_ptr<MultiProcessLock> test_lock(MultiProcessLock::Create(name));
94 EXPECT_TRUE(test_lock->TryLock());
95 ExpectLockIsLocked(name);
96 test_lock->Unlock();
97 ExpectLockIsUnlocked(name);
98}
99
100TEST_F(MultiProcessLockTest, RecursiveLock) {
101 std::string name = GenerateLockName();
102 scoped_ptr<MultiProcessLock> test_lock(MultiProcessLock::Create(name));
103 EXPECT_TRUE(test_lock->TryLock());
104 ExpectLockIsLocked(name);
105 LOG(INFO) << "Following error log "
106 << "'MultiProcessLock is already locked' is expected";
107 EXPECT_TRUE(test_lock->TryLock());
108 ExpectLockIsLocked(name);
109 test_lock->Unlock();
110 ExpectLockIsUnlocked(name);
111 LOG(INFO) << "Following error log "
112 << "'Over-unlocked MultiProcessLock' is expected";
113 test_lock->Unlock();
114 ExpectLockIsUnlocked(name);
115 test_lock.reset();
116}
117
118TEST_F(MultiProcessLockTest, LockScope) {
119 // Check to see that lock is released when it goes out of scope.
120 std::string name = GenerateLockName();
121 {
122 scoped_ptr<MultiProcessLock> test_lock(MultiProcessLock::Create(name));
123 EXPECT_TRUE(test_lock->TryLock());
124 ExpectLockIsLocked(name);
125 }
126 ExpectLockIsUnlocked(name);
127}
128
129MULTIPROCESS_TEST_MAIN(MultiProcessLockTryFailMain) {
130 std::string name;
131 scoped_ptr<base::Environment> environment(base::Environment::Create());
132 EXPECT_TRUE(environment->GetVar(MultiProcessLockTest::kLockEnviromentVarName,
133 &name));
134#if defined(OS_MACOSX)
135 // OS X sends out a log if a lock fails.
136 // Hopefully this will keep people from panicking about it when they
137 // are perusing the build logs.
138 LOG(INFO) << "Following error log "
139 << "\"CFMessagePort: bootstrap_register(): failed 1100 (0x44c) "
140 << "'Permission denied'\" is expected";
141#endif // defined(OS_MACOSX)
142 scoped_ptr<MultiProcessLock> test_lock(
143 MultiProcessLock::Create(name));
144 EXPECT_FALSE(test_lock->TryLock());
145 return 0;
146}
147
148MULTIPROCESS_TEST_MAIN(MultiProcessLockTrySucceedMain) {
149 std::string name;
150 scoped_ptr<base::Environment> environment(base::Environment::Create());
151 EXPECT_TRUE(environment->GetVar(MultiProcessLockTest::kLockEnviromentVarName,
152 &name));
153 scoped_ptr<MultiProcessLock> test_lock(
154 MultiProcessLock::Create(name));
155 EXPECT_TRUE(test_lock->TryLock());
156 return 0;
157}