blob: d134aeaef3d634cb92c0f7083b85bec6c1f0b03f [file]
# Copyright 2026 The Pigweed Authors
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy of
# the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under
# the License.
"""Tests for pw_ide.lock"""
import os
import unittest
from unittest.mock import patch
from test_cases import TempDirTestCase
from pw_ide.lock import LockFile, LockAlreadyHeldError
class TestLockFile(TempDirTestCase):
"""Tests LockFile atomic locking."""
def test_acquire_and_release(self):
"""Tests that a lock is successfully acquired and released."""
lockfile_path = self.path_in_temp_dir("pw.lock")
lock = LockFile(lockfile_path)
self.assertFalse(lockfile_path.exists())
with lock:
self.assertTrue(lockfile_path.exists())
self.assertEqual(
lockfile_path.read_text().strip(), str(os.getpid())
)
self.assertFalse(lockfile_path.exists())
def test_acquire_fails_when_pid_alive(self):
"""Tests that acquire exits if another instance is alive."""
lockfile_path = self.path_in_temp_dir("pw.lock")
lockfile_path.write_text("99999") # Mock a running PID
lock = LockFile(lockfile_path)
with patch.object(lock, "_is_pid_alive", return_value=True):
with self.assertRaises(LockAlreadyHeldError) as cm:
lock.acquire()
self.assertEqual(cm.exception.pid, 99999)
def test_acquire_cleans_dead_pid(self):
"""Tests that acquire cleans up a dead PID and successfully retries."""
lockfile_path = self.path_in_temp_dir("pw.lock")
lockfile_path.write_text("99999") # Mock a dead PID
lock = LockFile(lockfile_path)
with patch.object(lock, "_is_pid_alive", return_value=False):
with lock:
self.assertTrue(lockfile_path.exists())
self.assertEqual(
lockfile_path.read_text().strip(), str(os.getpid())
)
def test_release_does_not_delete_unowned_lock(self):
"""Tests that release does not delete a lock owned by another PID."""
lockfile_path = self.path_in_temp_dir("pw.lock")
lockfile_path.write_text("99999")
lock = LockFile(lockfile_path)
lock.release()
self.assertTrue(lockfile_path.exists())
self.assertEqual(lockfile_path.read_text().strip(), "99999")
if __name__ == "__main__":
unittest.main()