xref: /aosp_15_r20/external/cronet/base/files/file_locking_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2015 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #include "base/command_line.h"
6*6777b538SAndroid Build Coastguard Worker #include "base/files/file.h"
7*6777b538SAndroid Build Coastguard Worker #include "base/files/file_util.h"
8*6777b538SAndroid Build Coastguard Worker #include "base/files/scoped_temp_dir.h"
9*6777b538SAndroid Build Coastguard Worker #include "base/test/multiprocess_test.h"
10*6777b538SAndroid Build Coastguard Worker #include "base/test/test_timeouts.h"
11*6777b538SAndroid Build Coastguard Worker #include "base/threading/platform_thread.h"
12*6777b538SAndroid Build Coastguard Worker #include "base/time/time.h"
13*6777b538SAndroid Build Coastguard Worker #include "build/build_config.h"
14*6777b538SAndroid Build Coastguard Worker #include "testing/gtest/include/gtest/gtest.h"
15*6777b538SAndroid Build Coastguard Worker #include "testing/multiprocess_func_list.h"
16*6777b538SAndroid Build Coastguard Worker 
17*6777b538SAndroid Build Coastguard Worker using base::File;
18*6777b538SAndroid Build Coastguard Worker using base::FilePath;
19*6777b538SAndroid Build Coastguard Worker 
20*6777b538SAndroid Build Coastguard Worker namespace {
21*6777b538SAndroid Build Coastguard Worker 
22*6777b538SAndroid Build Coastguard Worker // Flag for the parent to share a temp dir to the child.
23*6777b538SAndroid Build Coastguard Worker const char kTempDirFlag[] = "temp-dir";
24*6777b538SAndroid Build Coastguard Worker 
25*6777b538SAndroid Build Coastguard Worker // Flags to control how the process locks the file.
26*6777b538SAndroid Build Coastguard Worker const char kFileLockShared[] = "file-lock-shared";
27*6777b538SAndroid Build Coastguard Worker const char kFileLockExclusive[] = "file-lock-exclusive";
28*6777b538SAndroid Build Coastguard Worker 
29*6777b538SAndroid Build Coastguard Worker // Flags to control how the subprocess unlocks the file.
30*6777b538SAndroid Build Coastguard Worker const char kFileUnlock[] = "file-unlock";
31*6777b538SAndroid Build Coastguard Worker const char kCloseUnlock[] = "close-unlock";
32*6777b538SAndroid Build Coastguard Worker const char kExitUnlock[] = "exit-unlock";
33*6777b538SAndroid Build Coastguard Worker 
34*6777b538SAndroid Build Coastguard Worker // File to lock in temp dir.
35*6777b538SAndroid Build Coastguard Worker const char kLockFile[] = "lockfile";
36*6777b538SAndroid Build Coastguard Worker 
37*6777b538SAndroid Build Coastguard Worker // Constants for various requests and responses, used as |signal_file| parameter
38*6777b538SAndroid Build Coastguard Worker // to signal/wait helpers.
39*6777b538SAndroid Build Coastguard Worker const char kSignalLockFileLocked[] = "locked.signal";
40*6777b538SAndroid Build Coastguard Worker const char kSignalLockFileClose[] = "close.signal";
41*6777b538SAndroid Build Coastguard Worker const char kSignalLockFileClosed[] = "closed.signal";
42*6777b538SAndroid Build Coastguard Worker const char kSignalLockFileUnlock[] = "unlock.signal";
43*6777b538SAndroid Build Coastguard Worker const char kSignalLockFileUnlocked[] = "unlocked.signal";
44*6777b538SAndroid Build Coastguard Worker const char kSignalExit[] = "exit.signal";
45*6777b538SAndroid Build Coastguard Worker 
46*6777b538SAndroid Build Coastguard Worker // Signal an event by creating a file which didn't previously exist.
SignalEvent(const FilePath & signal_dir,const char * signal_file)47*6777b538SAndroid Build Coastguard Worker bool SignalEvent(const FilePath& signal_dir, const char* signal_file) {
48*6777b538SAndroid Build Coastguard Worker   File file(signal_dir.AppendASCII(signal_file),
49*6777b538SAndroid Build Coastguard Worker             File::FLAG_CREATE | File::FLAG_WRITE);
50*6777b538SAndroid Build Coastguard Worker   return file.IsValid();
51*6777b538SAndroid Build Coastguard Worker }
52*6777b538SAndroid Build Coastguard Worker 
53*6777b538SAndroid Build Coastguard Worker // Check whether an event was signaled.
CheckEvent(const FilePath & signal_dir,const char * signal_file)54*6777b538SAndroid Build Coastguard Worker bool CheckEvent(const FilePath& signal_dir, const char* signal_file) {
55*6777b538SAndroid Build Coastguard Worker   File file(signal_dir.AppendASCII(signal_file),
56*6777b538SAndroid Build Coastguard Worker             File::FLAG_OPEN | File::FLAG_READ);
57*6777b538SAndroid Build Coastguard Worker   return file.IsValid();
58*6777b538SAndroid Build Coastguard Worker }
59*6777b538SAndroid Build Coastguard Worker 
60*6777b538SAndroid Build Coastguard Worker // Busy-wait for an event to be signaled, returning false for timeout.
WaitForEventWithTimeout(const FilePath & signal_dir,const char * signal_file,const base::TimeDelta & timeout)61*6777b538SAndroid Build Coastguard Worker bool WaitForEventWithTimeout(const FilePath& signal_dir,
62*6777b538SAndroid Build Coastguard Worker                              const char* signal_file,
63*6777b538SAndroid Build Coastguard Worker                              const base::TimeDelta& timeout) {
64*6777b538SAndroid Build Coastguard Worker   const base::Time finish_by = base::Time::Now() + timeout;
65*6777b538SAndroid Build Coastguard Worker   while (!CheckEvent(signal_dir, signal_file)) {
66*6777b538SAndroid Build Coastguard Worker     if (base::Time::Now() > finish_by)
67*6777b538SAndroid Build Coastguard Worker       return false;
68*6777b538SAndroid Build Coastguard Worker     base::PlatformThread::Sleep(base::Milliseconds(10));
69*6777b538SAndroid Build Coastguard Worker   }
70*6777b538SAndroid Build Coastguard Worker   return true;
71*6777b538SAndroid Build Coastguard Worker }
72*6777b538SAndroid Build Coastguard Worker 
73*6777b538SAndroid Build Coastguard Worker // Wait forever for the event to be signaled (should never return false).
WaitForEvent(const FilePath & signal_dir,const char * signal_file)74*6777b538SAndroid Build Coastguard Worker bool WaitForEvent(const FilePath& signal_dir, const char* signal_file) {
75*6777b538SAndroid Build Coastguard Worker   return WaitForEventWithTimeout(signal_dir, signal_file,
76*6777b538SAndroid Build Coastguard Worker                                  base::TimeDelta::Max());
77*6777b538SAndroid Build Coastguard Worker }
78*6777b538SAndroid Build Coastguard Worker 
79*6777b538SAndroid Build Coastguard Worker // Keep these in sync so StartChild*() can refer to correct test main.
80*6777b538SAndroid Build Coastguard Worker #define ChildMain ChildLockUnlock
81*6777b538SAndroid Build Coastguard Worker #define ChildMainString "ChildLockUnlock"
82*6777b538SAndroid Build Coastguard Worker 
83*6777b538SAndroid Build Coastguard Worker // Subprocess to test getting a file lock then releasing it.  |kTempDirFlag|
84*6777b538SAndroid Build Coastguard Worker // must pass in an existing temporary directory for the lockfile and signal
85*6777b538SAndroid Build Coastguard Worker // files.  One of the following flags must be passed to determine how to unlock
86*6777b538SAndroid Build Coastguard Worker // the lock file:
87*6777b538SAndroid Build Coastguard Worker // - |kFileUnlock| calls Unlock() to unlock.
88*6777b538SAndroid Build Coastguard Worker // - |kCloseUnlock| calls Close() while the lock is held.
89*6777b538SAndroid Build Coastguard Worker // - |kExitUnlock| exits while the lock is held.
MULTIPROCESS_TEST_MAIN(ChildMain)90*6777b538SAndroid Build Coastguard Worker MULTIPROCESS_TEST_MAIN(ChildMain) {
91*6777b538SAndroid Build Coastguard Worker   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
92*6777b538SAndroid Build Coastguard Worker   const FilePath temp_path = command_line->GetSwitchValuePath(kTempDirFlag);
93*6777b538SAndroid Build Coastguard Worker   CHECK(base::DirectoryExists(temp_path));
94*6777b538SAndroid Build Coastguard Worker 
95*6777b538SAndroid Build Coastguard Worker   const bool use_shared_lock = command_line->HasSwitch(kFileLockShared);
96*6777b538SAndroid Build Coastguard Worker   const bool use_exclusive_lock = command_line->HasSwitch(kFileLockExclusive);
97*6777b538SAndroid Build Coastguard Worker   CHECK_NE(use_shared_lock, use_exclusive_lock);
98*6777b538SAndroid Build Coastguard Worker 
99*6777b538SAndroid Build Coastguard Worker   const File::LockMode mode =
100*6777b538SAndroid Build Coastguard Worker       use_exclusive_lock ? File::LockMode::kExclusive : File::LockMode::kShared;
101*6777b538SAndroid Build Coastguard Worker 
102*6777b538SAndroid Build Coastguard Worker   // Immediately lock the file.
103*6777b538SAndroid Build Coastguard Worker   File file(temp_path.AppendASCII(kLockFile),
104*6777b538SAndroid Build Coastguard Worker             File::FLAG_OPEN | File::FLAG_READ | File::FLAG_WRITE);
105*6777b538SAndroid Build Coastguard Worker   CHECK(file.IsValid());
106*6777b538SAndroid Build Coastguard Worker   CHECK_EQ(File::FILE_OK, file.Lock(mode));
107*6777b538SAndroid Build Coastguard Worker   CHECK(SignalEvent(temp_path, kSignalLockFileLocked));
108*6777b538SAndroid Build Coastguard Worker 
109*6777b538SAndroid Build Coastguard Worker   if (command_line->HasSwitch(kFileUnlock)) {
110*6777b538SAndroid Build Coastguard Worker     // Wait for signal to unlock, then unlock the file.
111*6777b538SAndroid Build Coastguard Worker     CHECK(WaitForEvent(temp_path, kSignalLockFileUnlock));
112*6777b538SAndroid Build Coastguard Worker     CHECK_EQ(File::FILE_OK, file.Unlock());
113*6777b538SAndroid Build Coastguard Worker     CHECK(SignalEvent(temp_path, kSignalLockFileUnlocked));
114*6777b538SAndroid Build Coastguard Worker   } else if (command_line->HasSwitch(kCloseUnlock)) {
115*6777b538SAndroid Build Coastguard Worker     // Wait for the signal to close, then close the file.
116*6777b538SAndroid Build Coastguard Worker     CHECK(WaitForEvent(temp_path, kSignalLockFileClose));
117*6777b538SAndroid Build Coastguard Worker     file.Close();
118*6777b538SAndroid Build Coastguard Worker     CHECK(!file.IsValid());
119*6777b538SAndroid Build Coastguard Worker     CHECK(SignalEvent(temp_path, kSignalLockFileClosed));
120*6777b538SAndroid Build Coastguard Worker   } else {
121*6777b538SAndroid Build Coastguard Worker     CHECK(command_line->HasSwitch(kExitUnlock));
122*6777b538SAndroid Build Coastguard Worker   }
123*6777b538SAndroid Build Coastguard Worker 
124*6777b538SAndroid Build Coastguard Worker   // Wait for signal to exit, so that unlock or close can be distinguished from
125*6777b538SAndroid Build Coastguard Worker   // exit.
126*6777b538SAndroid Build Coastguard Worker   CHECK(WaitForEvent(temp_path, kSignalExit));
127*6777b538SAndroid Build Coastguard Worker   return 0;
128*6777b538SAndroid Build Coastguard Worker }
129*6777b538SAndroid Build Coastguard Worker 
130*6777b538SAndroid Build Coastguard Worker }  // namespace
131*6777b538SAndroid Build Coastguard Worker 
132*6777b538SAndroid Build Coastguard Worker class FileLockingTest : public testing::Test {
133*6777b538SAndroid Build Coastguard Worker  public:
134*6777b538SAndroid Build Coastguard Worker   FileLockingTest() = default;
135*6777b538SAndroid Build Coastguard Worker   FileLockingTest(const FileLockingTest&) = delete;
136*6777b538SAndroid Build Coastguard Worker   FileLockingTest& operator=(const FileLockingTest&) = delete;
137*6777b538SAndroid Build Coastguard Worker 
138*6777b538SAndroid Build Coastguard Worker  protected:
SetUp()139*6777b538SAndroid Build Coastguard Worker   void SetUp() override {
140*6777b538SAndroid Build Coastguard Worker     testing::Test::SetUp();
141*6777b538SAndroid Build Coastguard Worker 
142*6777b538SAndroid Build Coastguard Worker     // Setup the temp dir and the lock file.
143*6777b538SAndroid Build Coastguard Worker     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
144*6777b538SAndroid Build Coastguard Worker     lock_file_.Initialize(
145*6777b538SAndroid Build Coastguard Worker         temp_dir_.GetPath().AppendASCII(kLockFile),
146*6777b538SAndroid Build Coastguard Worker         File::FLAG_CREATE | File::FLAG_READ | File::FLAG_WRITE);
147*6777b538SAndroid Build Coastguard Worker     ASSERT_TRUE(lock_file_.IsValid());
148*6777b538SAndroid Build Coastguard Worker   }
149*6777b538SAndroid Build Coastguard Worker 
SignalEvent(const char * signal_file)150*6777b538SAndroid Build Coastguard Worker   bool SignalEvent(const char* signal_file) {
151*6777b538SAndroid Build Coastguard Worker     return ::SignalEvent(temp_dir_.GetPath(), signal_file);
152*6777b538SAndroid Build Coastguard Worker   }
153*6777b538SAndroid Build Coastguard Worker 
WaitForEventOrTimeout(const char * signal_file)154*6777b538SAndroid Build Coastguard Worker   bool WaitForEventOrTimeout(const char* signal_file) {
155*6777b538SAndroid Build Coastguard Worker     return ::WaitForEventWithTimeout(temp_dir_.GetPath(), signal_file,
156*6777b538SAndroid Build Coastguard Worker                                      TestTimeouts::action_timeout());
157*6777b538SAndroid Build Coastguard Worker   }
158*6777b538SAndroid Build Coastguard Worker 
159*6777b538SAndroid Build Coastguard Worker   // Start a child process set to use the specified locking mode and unlock
160*6777b538SAndroid Build Coastguard Worker   // action, and wait for it to lock the file.
StartChildAndSignalLock(File::LockMode lock_mode,const char * unlock_action)161*6777b538SAndroid Build Coastguard Worker   void StartChildAndSignalLock(File::LockMode lock_mode,
162*6777b538SAndroid Build Coastguard Worker                                const char* unlock_action) {
163*6777b538SAndroid Build Coastguard Worker     // Create a temporary dir and spin up a ChildLockExit subprocess against it.
164*6777b538SAndroid Build Coastguard Worker     const FilePath temp_path = temp_dir_.GetPath();
165*6777b538SAndroid Build Coastguard Worker     base::CommandLine child_command_line(
166*6777b538SAndroid Build Coastguard Worker         base::GetMultiProcessTestChildBaseCommandLine());
167*6777b538SAndroid Build Coastguard Worker     child_command_line.AppendSwitchPath(kTempDirFlag, temp_path);
168*6777b538SAndroid Build Coastguard Worker     child_command_line.AppendSwitch(unlock_action);
169*6777b538SAndroid Build Coastguard Worker     switch (lock_mode) {
170*6777b538SAndroid Build Coastguard Worker       case File::LockMode::kExclusive:
171*6777b538SAndroid Build Coastguard Worker         child_command_line.AppendSwitch(kFileLockExclusive);
172*6777b538SAndroid Build Coastguard Worker         break;
173*6777b538SAndroid Build Coastguard Worker       case File::LockMode::kShared:
174*6777b538SAndroid Build Coastguard Worker         child_command_line.AppendSwitch(kFileLockShared);
175*6777b538SAndroid Build Coastguard Worker         break;
176*6777b538SAndroid Build Coastguard Worker     }
177*6777b538SAndroid Build Coastguard Worker     lock_child_ = base::SpawnMultiProcessTestChild(
178*6777b538SAndroid Build Coastguard Worker         ChildMainString, child_command_line, base::LaunchOptions());
179*6777b538SAndroid Build Coastguard Worker     ASSERT_TRUE(lock_child_.IsValid());
180*6777b538SAndroid Build Coastguard Worker 
181*6777b538SAndroid Build Coastguard Worker     // Wait for the child to lock the file.
182*6777b538SAndroid Build Coastguard Worker     ASSERT_TRUE(WaitForEventOrTimeout(kSignalLockFileLocked));
183*6777b538SAndroid Build Coastguard Worker   }
184*6777b538SAndroid Build Coastguard Worker 
185*6777b538SAndroid Build Coastguard Worker   // Signal the child to exit cleanly.
ExitChildCleanly()186*6777b538SAndroid Build Coastguard Worker   void ExitChildCleanly() {
187*6777b538SAndroid Build Coastguard Worker     ASSERT_TRUE(SignalEvent(kSignalExit));
188*6777b538SAndroid Build Coastguard Worker     int rv = -1;
189*6777b538SAndroid Build Coastguard Worker     ASSERT_TRUE(WaitForMultiprocessTestChildExit(
190*6777b538SAndroid Build Coastguard Worker         lock_child_, TestTimeouts::action_timeout(), &rv));
191*6777b538SAndroid Build Coastguard Worker     ASSERT_EQ(0, rv);
192*6777b538SAndroid Build Coastguard Worker   }
193*6777b538SAndroid Build Coastguard Worker 
194*6777b538SAndroid Build Coastguard Worker   base::ScopedTempDir temp_dir_;
195*6777b538SAndroid Build Coastguard Worker   base::File lock_file_;
196*6777b538SAndroid Build Coastguard Worker   base::Process lock_child_;
197*6777b538SAndroid Build Coastguard Worker };
198*6777b538SAndroid Build Coastguard Worker 
199*6777b538SAndroid Build Coastguard Worker // Test that locks are released by Unlock().
TEST_F(FileLockingTest,LockAndUnlockExclusive)200*6777b538SAndroid Build Coastguard Worker TEST_F(FileLockingTest, LockAndUnlockExclusive) {
201*6777b538SAndroid Build Coastguard Worker   StartChildAndSignalLock(File::LockMode::kExclusive, kFileUnlock);
202*6777b538SAndroid Build Coastguard Worker 
203*6777b538SAndroid Build Coastguard Worker   ASSERT_NE(File::FILE_OK, lock_file_.Lock(File::LockMode::kExclusive));
204*6777b538SAndroid Build Coastguard Worker   ASSERT_NE(File::FILE_OK, lock_file_.Lock(File::LockMode::kShared));
205*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(SignalEvent(kSignalLockFileUnlock));
206*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(WaitForEventOrTimeout(kSignalLockFileUnlocked));
207*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(File::FILE_OK, lock_file_.Lock(File::LockMode::kShared));
208*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(File::FILE_OK, lock_file_.Unlock());
209*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(File::FILE_OK, lock_file_.Lock(File::LockMode::kExclusive));
210*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(File::FILE_OK, lock_file_.Unlock());
211*6777b538SAndroid Build Coastguard Worker 
212*6777b538SAndroid Build Coastguard Worker   ExitChildCleanly();
213*6777b538SAndroid Build Coastguard Worker }
TEST_F(FileLockingTest,LockAndUnlockShared)214*6777b538SAndroid Build Coastguard Worker TEST_F(FileLockingTest, LockAndUnlockShared) {
215*6777b538SAndroid Build Coastguard Worker   StartChildAndSignalLock(File::LockMode::kShared, kFileUnlock);
216*6777b538SAndroid Build Coastguard Worker 
217*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(File::FILE_OK, lock_file_.Lock(File::LockMode::kShared));
218*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(File::FILE_OK, lock_file_.Unlock());
219*6777b538SAndroid Build Coastguard Worker   ASSERT_NE(File::FILE_OK, lock_file_.Lock(File::LockMode::kExclusive));
220*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(SignalEvent(kSignalLockFileUnlock));
221*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(WaitForEventOrTimeout(kSignalLockFileUnlocked));
222*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(File::FILE_OK, lock_file_.Lock(File::LockMode::kShared));
223*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(File::FILE_OK, lock_file_.Unlock());
224*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(File::FILE_OK, lock_file_.Lock(File::LockMode::kExclusive));
225*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(File::FILE_OK, lock_file_.Unlock());
226*6777b538SAndroid Build Coastguard Worker 
227*6777b538SAndroid Build Coastguard Worker   ExitChildCleanly();
228*6777b538SAndroid Build Coastguard Worker }
229*6777b538SAndroid Build Coastguard Worker 
230*6777b538SAndroid Build Coastguard Worker // Test that locks are released on Close().
TEST_F(FileLockingTest,UnlockOnCloseExclusive)231*6777b538SAndroid Build Coastguard Worker TEST_F(FileLockingTest, UnlockOnCloseExclusive) {
232*6777b538SAndroid Build Coastguard Worker   StartChildAndSignalLock(File::LockMode::kExclusive, kCloseUnlock);
233*6777b538SAndroid Build Coastguard Worker 
234*6777b538SAndroid Build Coastguard Worker   ASSERT_NE(File::FILE_OK, lock_file_.Lock(File::LockMode::kExclusive));
235*6777b538SAndroid Build Coastguard Worker   ASSERT_NE(File::FILE_OK, lock_file_.Lock(File::LockMode::kShared));
236*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(SignalEvent(kSignalLockFileClose));
237*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(WaitForEventOrTimeout(kSignalLockFileClosed));
238*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(File::FILE_OK, lock_file_.Lock(File::LockMode::kShared));
239*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(File::FILE_OK, lock_file_.Unlock());
240*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(File::FILE_OK, lock_file_.Lock(File::LockMode::kExclusive));
241*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(File::FILE_OK, lock_file_.Unlock());
242*6777b538SAndroid Build Coastguard Worker 
243*6777b538SAndroid Build Coastguard Worker   ExitChildCleanly();
244*6777b538SAndroid Build Coastguard Worker }
TEST_F(FileLockingTest,UnlockOnCloseShared)245*6777b538SAndroid Build Coastguard Worker TEST_F(FileLockingTest, UnlockOnCloseShared) {
246*6777b538SAndroid Build Coastguard Worker   StartChildAndSignalLock(File::LockMode::kShared, kCloseUnlock);
247*6777b538SAndroid Build Coastguard Worker 
248*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(File::FILE_OK, lock_file_.Lock(File::LockMode::kShared));
249*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(File::FILE_OK, lock_file_.Unlock());
250*6777b538SAndroid Build Coastguard Worker   ASSERT_NE(File::FILE_OK, lock_file_.Lock(File::LockMode::kExclusive));
251*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(SignalEvent(kSignalLockFileClose));
252*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(WaitForEventOrTimeout(kSignalLockFileClosed));
253*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(File::FILE_OK, lock_file_.Lock(File::LockMode::kShared));
254*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(File::FILE_OK, lock_file_.Unlock());
255*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(File::FILE_OK, lock_file_.Lock(File::LockMode::kExclusive));
256*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(File::FILE_OK, lock_file_.Unlock());
257*6777b538SAndroid Build Coastguard Worker 
258*6777b538SAndroid Build Coastguard Worker   ExitChildCleanly();
259*6777b538SAndroid Build Coastguard Worker }
260*6777b538SAndroid Build Coastguard Worker 
261*6777b538SAndroid Build Coastguard Worker // Test that locks are released on exit.
TEST_F(FileLockingTest,UnlockOnExitExclusive)262*6777b538SAndroid Build Coastguard Worker TEST_F(FileLockingTest, UnlockOnExitExclusive) {
263*6777b538SAndroid Build Coastguard Worker   StartChildAndSignalLock(File::LockMode::kExclusive, kExitUnlock);
264*6777b538SAndroid Build Coastguard Worker 
265*6777b538SAndroid Build Coastguard Worker   ASSERT_NE(File::FILE_OK, lock_file_.Lock(File::LockMode::kExclusive));
266*6777b538SAndroid Build Coastguard Worker   ASSERT_NE(File::FILE_OK, lock_file_.Lock(File::LockMode::kShared));
267*6777b538SAndroid Build Coastguard Worker   ExitChildCleanly();
268*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(File::FILE_OK, lock_file_.Lock(File::LockMode::kShared));
269*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(File::FILE_OK, lock_file_.Unlock());
270*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(File::FILE_OK, lock_file_.Lock(File::LockMode::kExclusive));
271*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(File::FILE_OK, lock_file_.Unlock());
272*6777b538SAndroid Build Coastguard Worker }
TEST_F(FileLockingTest,UnlockOnExitShared)273*6777b538SAndroid Build Coastguard Worker TEST_F(FileLockingTest, UnlockOnExitShared) {
274*6777b538SAndroid Build Coastguard Worker   StartChildAndSignalLock(File::LockMode::kShared, kExitUnlock);
275*6777b538SAndroid Build Coastguard Worker 
276*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(File::FILE_OK, lock_file_.Lock(File::LockMode::kShared));
277*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(File::FILE_OK, lock_file_.Unlock());
278*6777b538SAndroid Build Coastguard Worker   ASSERT_NE(File::FILE_OK, lock_file_.Lock(File::LockMode::kExclusive));
279*6777b538SAndroid Build Coastguard Worker   ExitChildCleanly();
280*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(File::FILE_OK, lock_file_.Lock(File::LockMode::kShared));
281*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(File::FILE_OK, lock_file_.Unlock());
282*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(File::FILE_OK, lock_file_.Lock(File::LockMode::kExclusive));
283*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(File::FILE_OK, lock_file_.Unlock());
284*6777b538SAndroid Build Coastguard Worker }
285*6777b538SAndroid Build Coastguard Worker 
286*6777b538SAndroid Build Coastguard Worker // Test that killing the process releases the lock.  This should cover crashing.
287*6777b538SAndroid Build Coastguard Worker // Flaky on Android (http://crbug.com/747518)
288*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_ANDROID)
289*6777b538SAndroid Build Coastguard Worker #define MAYBE_UnlockOnTerminate DISABLED_UnlockOnTerminate
290*6777b538SAndroid Build Coastguard Worker #else
291*6777b538SAndroid Build Coastguard Worker #define MAYBE_UnlockOnTerminate UnlockOnTerminate
292*6777b538SAndroid Build Coastguard Worker #endif
TEST_F(FileLockingTest,MAYBE_UnlockOnTerminate)293*6777b538SAndroid Build Coastguard Worker TEST_F(FileLockingTest, MAYBE_UnlockOnTerminate) {
294*6777b538SAndroid Build Coastguard Worker   // The child will wait for an exit which never arrives.
295*6777b538SAndroid Build Coastguard Worker   StartChildAndSignalLock(File::LockMode::kExclusive, kExitUnlock);
296*6777b538SAndroid Build Coastguard Worker 
297*6777b538SAndroid Build Coastguard Worker   ASSERT_NE(File::FILE_OK, lock_file_.Lock(File::LockMode::kExclusive));
298*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(TerminateMultiProcessTestChild(lock_child_, 0, true));
299*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(File::FILE_OK, lock_file_.Lock(File::LockMode::kShared));
300*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(File::FILE_OK, lock_file_.Unlock());
301*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(File::FILE_OK, lock_file_.Lock(File::LockMode::kExclusive));
302*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(File::FILE_OK, lock_file_.Unlock());
303*6777b538SAndroid Build Coastguard Worker }
304