15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/environment.h"
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
9a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include "base/process/kill.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/rand_util.h"
11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/test/multiprocess_test.h"
13eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/multi_process_lock.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/multiprocess_func_list.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MultiProcessLockTest : public base::MultiProcessTest {
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char kLockEnviromentVarName[];
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  class ScopedEnvironmentVariable {
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   public:
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ScopedEnvironmentVariable(const std::string &name,
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              const std::string &value)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        : name_(name), environment_(base::Environment::Create()) {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      environment_->SetVar(name_.c_str(), value);
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ~ScopedEnvironmentVariable() {
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      environment_->UnSetVar(name_.c_str());
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   private:
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string name_;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<base::Environment> environment_;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DISALLOW_COPY_AND_ASSIGN(ScopedEnvironmentVariable);
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string GenerateLockName();
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ExpectLockIsLocked(const std::string &name);
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ExpectLockIsUnlocked(const std::string &name);
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char MultiProcessLockTest::kLockEnviromentVarName[]
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    = "MULTI_PROCESS_TEST_LOCK_NAME";
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string MultiProcessLockTest::GenerateLockName() {
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Time now = base::Time::NowFromSystemTime();
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return base::StringPrintf("multi_process_test_lock %lf%lf",
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            now.ToDoubleT(), base::RandDouble());
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MultiProcessLockTest::ExpectLockIsLocked(const std::string &name) {
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedEnvironmentVariable var(kLockEnviromentVarName, name);
54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  base::ProcessHandle handle = SpawnChild("MultiProcessLockTryFailMain");
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(handle);
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int exit_code = 0;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(base::WaitForExitCode(handle, &exit_code));
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(exit_code, 0);
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MultiProcessLockTest::ExpectLockIsUnlocked(
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string &name) {
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedEnvironmentVariable var(kLockEnviromentVarName, name);
64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  base::ProcessHandle handle = SpawnChild("MultiProcessLockTrySucceedMain");
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(handle);
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int exit_code = 0;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(base::WaitForExitCode(handle, &exit_code));
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(exit_code, 0);
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(MultiProcessLockTest, BasicCreationTest) {
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test basic creation/destruction with no lock taken
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string name = GenerateLockName();
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<MultiProcessLock> scoped(MultiProcessLock::Create(name));
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExpectLockIsUnlocked(name);
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped.reset(NULL);
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(MultiProcessLockTest, LongNameTest) {
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Every platform has has it's own max path name size,
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // so different checks are needed for them.
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // POSIX: sizeof(address.sun_path) - 2
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Mac OS X: BOOTSTRAP_MAX_NAME_LEN
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Windows: MAX_PATH
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LOG(INFO) << "Following error log due to long name is expected";
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_MACOSX)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string name("This is a name that is longer than one hundred and "
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "twenty-eight characters to make sure that we fail appropriately on "
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Mac OS X when we have a path that is too long for Mac OS X to handle");
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_POSIX)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string name("This is a name that is longer than one hundred and eight "
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "characters to make sure that we fail appropriately on POSIX systems "
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "when we have a path that is too long for the system to handle");
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_WIN)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string name("This is a name that is longer than two hundred and sixty "
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "characters to make sure that we fail appropriately on Windows when we "
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "have a path that is too long for Windows to handle "
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "This limitation comes from the MAX_PATH definition which is obviously "
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "defined to be a maximum of two hundred and sixty characters ");
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<MultiProcessLock> test_lock(MultiProcessLock::Create(name));
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(test_lock->TryLock());
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(MultiProcessLockTest, SimpleLock) {
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string name = GenerateLockName();
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<MultiProcessLock> test_lock(MultiProcessLock::Create(name));
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(test_lock->TryLock());
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExpectLockIsLocked(name);
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test_lock->Unlock();
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExpectLockIsUnlocked(name);
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(MultiProcessLockTest, RecursiveLock) {
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string name = GenerateLockName();
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<MultiProcessLock> test_lock(MultiProcessLock::Create(name));
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(test_lock->TryLock());
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExpectLockIsLocked(name);
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LOG(INFO) << "Following error log "
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            << "'MultiProcessLock is already locked' is expected";
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(test_lock->TryLock());
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExpectLockIsLocked(name);
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test_lock->Unlock();
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExpectLockIsUnlocked(name);
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LOG(INFO) << "Following error log "
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            << "'Over-unlocked MultiProcessLock' is expected";
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test_lock->Unlock();
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExpectLockIsUnlocked(name);
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test_lock.reset();
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(MultiProcessLockTest, LockScope) {
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check to see that lock is released when it goes out of scope.
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string name = GenerateLockName();
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<MultiProcessLock> test_lock(MultiProcessLock::Create(name));
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(test_lock->TryLock());
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ExpectLockIsLocked(name);
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExpectLockIsUnlocked(name);
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MULTIPROCESS_TEST_MAIN(MultiProcessLockTryFailMain) {
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string name;
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<base::Environment> environment(base::Environment::Create());
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(environment->GetVar(MultiProcessLockTest::kLockEnviromentVarName,
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  &name));
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_MACOSX)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // OS X sends out a log if a lock fails.
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Hopefully this will keep people from panicking about it when they
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // are perusing the build logs.
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LOG(INFO) << "Following error log "
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            << "\"CFMessagePort: bootstrap_register(): failed 1100 (0x44c) "
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            << "'Permission denied'\" is expected";
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // defined(OS_MACOSX)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<MultiProcessLock> test_lock(
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      MultiProcessLock::Create(name));
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(test_lock->TryLock());
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MULTIPROCESS_TEST_MAIN(MultiProcessLockTrySucceedMain) {
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string name;
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<base::Environment> environment(base::Environment::Create());
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(environment->GetVar(MultiProcessLockTest::kLockEnviromentVarName,
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  &name));
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<MultiProcessLock> test_lock(
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      MultiProcessLock::Create(name));
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(test_lock->TryLock());
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
172