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