1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 24a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch// Use of this source code is governed by a BSD-style license that can be 34a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch// found in the LICENSE file. 44a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 54a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "base/basictypes.h" 64a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "base/environment.h" 74a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "base/logging.h" 8ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/scoped_ptr.h" 94a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "base/rand_util.h" 104a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "base/stringprintf.h" 114a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "base/test/multiprocess_test.h" 124a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "base/time.h" 134a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "chrome/common/multi_process_lock.h" 144a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "testing/multiprocess_func_list.h" 154a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 164a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochclass MultiProcessLockTest : public base::MultiProcessTest { 174a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch public: 184a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch static const char kLockEnviromentVarName[]; 194a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 204a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch class ScopedEnvironmentVariable { 214a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch public: 224a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch ScopedEnvironmentVariable(const std::string &name, 234a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch const std::string &value) 244a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch : name_(name), environment_(base::Environment::Create()) { 254a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch environment_->SetVar(name_.c_str(), value); 264a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 274a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch ~ScopedEnvironmentVariable() { 284a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch environment_->UnSetVar(name_.c_str()); 294a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 304a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 314a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch private: 324a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch std::string name_; 334a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch scoped_ptr<base::Environment> environment_; 344a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch DISALLOW_COPY_AND_ASSIGN(ScopedEnvironmentVariable); 354a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch }; 364a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 374a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch std::string GenerateLockName(); 384a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch void ExpectLockIsLocked(const std::string &name); 394a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch void ExpectLockIsUnlocked(const std::string &name); 404a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch}; 414a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 424a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochconst char MultiProcessLockTest::kLockEnviromentVarName[] 434a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch = "MULTI_PROCESS_TEST_LOCK_NAME"; 444a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 454a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochstd::string MultiProcessLockTest::GenerateLockName() { 464a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch base::Time now = base::Time::NowFromSystemTime(); 474a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return base::StringPrintf("multi_process_test_lock %lf%lf", 484a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch now.ToDoubleT(), base::RandDouble()); 494a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch} 504a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 514a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochvoid MultiProcessLockTest::ExpectLockIsLocked(const std::string &name) { 524a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch ScopedEnvironmentVariable var(kLockEnviromentVarName, name); 534a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch base::ProcessHandle handle = SpawnChild("MultiProcessLockTryFailMain", false); 544a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch ASSERT_TRUE(handle); 554a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch int exit_code = 0; 564a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch EXPECT_TRUE(base::WaitForExitCode(handle, &exit_code)); 574a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch EXPECT_EQ(exit_code, 0); 584a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch} 594a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 604a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochvoid MultiProcessLockTest::ExpectLockIsUnlocked( 614a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch const std::string &name) { 624a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch ScopedEnvironmentVariable var(kLockEnviromentVarName, name); 634a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch base::ProcessHandle handle = SpawnChild("MultiProcessLockTrySucceedMain", 644a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch false); 654a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch ASSERT_TRUE(handle); 664a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch int exit_code = 0; 674a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch EXPECT_TRUE(base::WaitForExitCode(handle, &exit_code)); 684a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch EXPECT_EQ(exit_code, 0); 694a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch} 704a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 714a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben MurdochTEST_F(MultiProcessLockTest, BasicCreationTest) { 724a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch // Test basic creation/destruction with no lock taken 734a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch std::string name = GenerateLockName(); 744a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch scoped_ptr<MultiProcessLock> scoped(MultiProcessLock::Create(name)); 754a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch ExpectLockIsUnlocked(name); 764a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch scoped.reset(NULL); 774a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch} 784a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 794a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben MurdochTEST_F(MultiProcessLockTest, LongNameTest) { 804a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch // Linux has a max path name of 108 characters. 814a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch // http://lxr.linux.no/linux+v2.6.36/include/linux/un.h 824a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch // This is enforced on all platforms. 834a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch LOG(INFO) << "Following error log due to long name is expected"; 844a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch std::string name("This is a name that is longer than one hundred and eight " 854a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch "characters to make sure that we fail appropriately on linux when we " 864a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch "have a path that is to long for linux to handle"); 874a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch scoped_ptr<MultiProcessLock> test_lock(MultiProcessLock::Create(name)); 884a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch EXPECT_FALSE(test_lock->TryLock()); 894a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch} 904a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 914a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben MurdochTEST_F(MultiProcessLockTest, SimpleLock) { 924a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch std::string name = GenerateLockName(); 934a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch scoped_ptr<MultiProcessLock> test_lock(MultiProcessLock::Create(name)); 944a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch EXPECT_TRUE(test_lock->TryLock()); 954a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch ExpectLockIsLocked(name); 964a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch test_lock->Unlock(); 974a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch ExpectLockIsUnlocked(name); 984a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch} 994a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 1004a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben MurdochTEST_F(MultiProcessLockTest, RecursiveLock) { 1014a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch std::string name = GenerateLockName(); 1024a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch scoped_ptr<MultiProcessLock> test_lock(MultiProcessLock::Create(name)); 1034a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch EXPECT_TRUE(test_lock->TryLock()); 1044a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch ExpectLockIsLocked(name); 1054a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch LOG(INFO) << "Following error log " 1064a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch << "'MultiProcessLock is already locked' is expected"; 1074a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch EXPECT_TRUE(test_lock->TryLock()); 1084a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch ExpectLockIsLocked(name); 1094a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch test_lock->Unlock(); 1104a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch ExpectLockIsUnlocked(name); 1114a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch LOG(INFO) << "Following error log " 1124a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch << "'Over-unlocked MultiProcessLock' is expected"; 1134a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch test_lock->Unlock(); 1144a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch ExpectLockIsUnlocked(name); 1154a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch test_lock.reset(); 1164a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch} 1174a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 1184a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben MurdochTEST_F(MultiProcessLockTest, LockScope) { 1194a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch // Check to see that lock is released when it goes out of scope. 1204a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch std::string name = GenerateLockName(); 1214a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch { 1224a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch scoped_ptr<MultiProcessLock> test_lock(MultiProcessLock::Create(name)); 1234a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch EXPECT_TRUE(test_lock->TryLock()); 1244a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch ExpectLockIsLocked(name); 1254a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 1264a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch ExpectLockIsUnlocked(name); 1274a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch} 1284a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 1294a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben MurdochMULTIPROCESS_TEST_MAIN(MultiProcessLockTryFailMain) { 1304a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch std::string name; 1314a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch scoped_ptr<base::Environment> environment(base::Environment::Create()); 1324a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch EXPECT_TRUE(environment->GetVar(MultiProcessLockTest::kLockEnviromentVarName, 1334a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch &name)); 1344a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#if defined(OS_MACOSX) 1354a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch // OS X sends out a log if a lock fails. 1364a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch // Hopefully this will keep people from panicking about it when they 1374a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch // are perusing the build logs. 1384a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch LOG(INFO) << "Following error log " 1394a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch << "\"CFMessagePort: bootstrap_register(): failed 1100 (0x44c) " 1404a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch << "'Permission denied'\" is expected"; 1414a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#endif // defined(OS_MACOSX) 1424a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch scoped_ptr<MultiProcessLock> test_lock( 1434a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch MultiProcessLock::Create(name)); 1444a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch EXPECT_FALSE(test_lock->TryLock()); 1454a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return 0; 1464a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch} 1474a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 1484a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben MurdochMULTIPROCESS_TEST_MAIN(MultiProcessLockTrySucceedMain) { 1494a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch std::string name; 1504a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch scoped_ptr<base::Environment> environment(base::Environment::Create()); 1514a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch EXPECT_TRUE(environment->GetVar(MultiProcessLockTest::kLockEnviromentVarName, 1524a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch &name)); 1534a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch scoped_ptr<MultiProcessLock> test_lock( 1544a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch MultiProcessLock::Create(name)); 1554a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch EXPECT_TRUE(test_lock->TryLock()); 1564a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return 0; 1574a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch} 158