Skip to content

borg2 on cygwin failures #7218

@ThomasWaldmann

Description

@ThomasWaldmann
$ pytest --benchmark-skip -vv
========================================================================== test session starts ===========================================================================
platform cygwin -- Python 3.9.10, pytest-7.2.0, pluggy-1.0.0 -- /home/admin/w/borg-env/bin/python
cachedir: .pytest_cache
benchmark: 4.0.0 (defaults: timer=time.perf_counter disable_gc=False min_rounds=5 min_time=0.000005 max_time=1.0 calibration_precision=10 warmup=False warmup_iterations=100000)
Tests enabled: root, symlinks, hardlinks, atime/mtime, modes
Tests disabled: BSD flags, fuse2, fuse3
rootdir: /home/admin/w/borg, configfile: setup.cfg
plugins: benchmark-4.0.0, cov-4.0.0, forked-1.4.0, xdist-3.0.2
collected 1559 items

...
================================================================================ FAILURES ================================================================================
_________________________________________________________________ TestExclusiveLock.test_race_condition __________________________________________________________________

self = <borg.testsuite.locking.TestExclusiveLock object at 0x6ffffd4fa220>, lockpath = '/tmp/pytest-of-admin/pytest-32/test_race_condition0/lock'

    def test_race_condition(self, lockpath):
        class SynchronizedCounter:
            def __init__(self, count=0):
                self.lock = ThreadingLock()
                self.count = count
                self.maxcount = count

            def value(self):
                with self.lock:
                    return self.count

            def maxvalue(self):
                with self.lock:
                    return self.maxcount

            def incr(self):
                with self.lock:
                    self.count += 1
                    if self.count > self.maxcount:
                        self.maxcount = self.count
                    return self.count

            def decr(self):
                with self.lock:
                    self.count -= 1
                    return self.count

        def print_locked(msg):
            with print_lock:
                print(msg)

        def acquire_release_loop(
            id, timeout, thread_id, lock_owner_counter, exception_counter, print_lock, last_thread=None
        ):
            print_locked(
                "Thread %2d: Starting acquire_release_loop(id=%s, timeout=%d); lockpath=%s"
                % (thread_id, id, timeout, lockpath)
            )
            timer = TimeoutTimer(timeout, -1).start()
            cycle = 0

            while not timer.timed_out():
                cycle += 1
                try:
                    with ExclusiveLock(
                        lockpath, id=id, timeout=timeout / 20, sleep=-1
                    ):  # This timeout is only for not exceeding the given timeout by more than 5%. With sleep<0 it's constantly polling anyway.
                        lock_owner_count = lock_owner_counter.incr()
                        print_locked(
                            "Thread %2d: Acquired the lock. It's my %d. loop cycle. I am the %d. who has the lock concurrently."
                            % (thread_id, cycle, lock_owner_count)
                        )
                        time.sleep(0.005)
                        lock_owner_count = lock_owner_counter.decr()
                        print_locked(
                            "Thread %2d: Releasing the lock, finishing my %d. loop cycle. Currently, %d colleagues still have the lock."
                            % (thread_id, cycle, lock_owner_count)
                        )
                except LockTimeout:
                    print_locked("Thread %2d: Got LockTimeout, finishing my %d. loop cycle." % (thread_id, cycle))
                except:
                    exception_count = exception_counter.incr()
                    e = format_exc()
                    print_locked(
                        "Thread %2d: Exception thrown, finishing my %d. loop cycle. It's the %d. exception seen until now: %s"
                        % (thread_id, cycle, exception_count, e)
                    )

            print_locked("Thread %2d: Loop timed out--terminating after %d loop cycles." % (thread_id, cycle))
            if last_thread is not None:  # joining its predecessor, if any
                last_thread.join()

        print("")
        lock_owner_counter = SynchronizedCounter()
        exception_counter = SynchronizedCounter()
        print_lock = ThreadingLock()
        thread = None
        for thread_id in range(RACE_TEST_NUM_THREADS):
            thread = Thread(
                target=acquire_release_loop,
                args=(
                    ("foo", thread_id, 0),
                    RACE_TEST_DURATION,
                    thread_id,
                    lock_owner_counter,
                    exception_counter,
                    print_lock,
                    thread,
                ),
            )
            thread.start()
        thread.join()  # joining the last thread

        assert lock_owner_counter.maxvalue() > 0, "Never gained the lock? Something went wrong here..."
>       assert (
            lock_owner_counter.maxvalue() <= 1
        ), "Maximal number of concurrent lock holders was %d. So exclusivity is broken." % (
            lock_owner_counter.maxvalue()
        )
E       AssertionError: Maximal number of concurrent lock holders was 4. So exclusivity is broken.
E       assert 4 <= 1
E        +  where 4 = <bound method TestExclusiveLock.test_race_condition.<locals>.SynchronizedCounter.maxvalue of <borg.testsuite.locking.TestExclusiveLock.test_race_condition.<locals>.SynchronizedCounter object at 0x6ffffce78490>>()
E        +    where <bound method TestExclusiveLock.test_race_condition.<locals>.SynchronizedCounter.maxvalue of <borg.testsuite.locking.TestExclusiveLock.test_race_condition.<locals>.SynchronizedCounter object at 0x6ffffce78490>> = <borg.testsuite.locking.TestExclusiveLock.test_race_condition.<locals>.SynchronizedCounter object at 0x6ffffce78490>.maxvalue

src/borg/testsuite/locking.py:201: AssertionError
-------------------------------------------------------------------------- Captured stdout call --------------------------------------------------------------------------

...
Thread 16: Acquired the lock. It's my 1. loop cycle. I am the 2. who has the lock concurrently.
Thread  4: Acquired the lock. It's my 2. loop cycle. I am the 4. who has the lock concurrently.
...
Thread  8: Releasing the lock, finishing my 2. loop cycle. Currently, 3 colleagues still have the lock.
...
...
Thread 33: Got LockTimeout, finishing my 1. loop cycle.
Thread 16: Exception thrown, finishing my 1. loop cycle. It's the 2. exception seen until now: Traceback (most recent call last):
  File "/home/admin/w/borg/src/borg/testsuite/locking.py", line 161, in acquire_release_loop
    print_locked(
  File "/home/admin/w/borg/src/borg/locking.py", line 120, in __exit__
    self.release()
  File "/home/admin/w/borg/src/borg/locking.py", line 171, in release
    raise NotMyLock(self.path)
borg.locking.NotMyLock: Failed to release the lock /tmp/pytest-of-admin/pytest-32/test_race_condition0/lock (was/is locked, but not by me).

Thread  8: Exception thrown, finishing my 2. loop cycle. It's the 1. exception seen until now: Traceback (most recent call last):
  File "/home/admin/w/borg/src/borg/testsuite/locking.py", line 161, in acquire_release_loop
    print_locked(
  File "/home/admin/w/borg/src/borg/locking.py", line 120, in __exit__
    self.release()
  File "/home/admin/w/borg/src/borg/locking.py", line 171, in release
    raise NotMyLock(self.path)
borg.locking.NotMyLock: Failed to release the lock /tmp/pytest-of-admin/pytest-32/test_race_condition0/lock (was/is locked, but not by me).

Thread  4: Exception thrown, finishing my 2. loop cycle. It's the 3. exception seen until now: Traceback (most recent call last):
  File "/home/admin/w/borg/src/borg/testsuite/locking.py", line 161, in acquire_release_loop
    print_locked(
  File "/home/admin/w/borg/src/borg/locking.py", line 120, in __exit__
    self.release()
  File "/home/admin/w/borg/src/borg/locking.py", line 171, in release
    raise NotMyLock(self.path)
borg.locking.NotMyLock: Failed to release the lock /tmp/pytest-of-admin/pytest-32/test_race_condition0/lock (was/is locked, but not by me).

...
Thread 26: Got LockTimeout, finishing my 3. loop cycle.
Thread 23: Exception thrown, finishing my 3. loop cycle. It's the 4. exception seen until now: Traceback (most recent call last):
  File "/home/admin/w/borg/src/borg/testsuite/locking.py", line 161, in acquire_release_loop
    print_locked(
  File "/home/admin/w/borg/src/borg/locking.py", line 120, in __exit__
    self.release()
  File "/home/admin/w/borg/src/borg/locking.py", line 178, in release
    raise err
  File "/home/admin/w/borg/src/borg/locking.py", line 174, in release
    os.rmdir(self.path)
PermissionError: [Errno 13] Permission denied: '/tmp/pytest-of-admin/pytest-32/test_race_condition0/lock'

...

Thread  8: Releasing the lock, finishing my 5. loop cycle. Currently, 0 colleagues still have the lock.
Thread 36: Exception thrown, finishing my 5. loop cycle. It's the 5. exception seen until now: Traceback (most recent call last):
  File "/home/admin/w/borg/src/borg/testsuite/locking.py", line 161, in acquire_release_loop
    print_locked(
  File "/home/admin/w/borg/src/borg/locking.py", line 120, in __exit__
    self.release()
  File "/home/admin/w/borg/src/borg/locking.py", line 171, in release
    raise NotMyLock(self.path)
borg.locking.NotMyLock: Failed to release the lock /tmp/pytest-of-admin/pytest-32/test_race_condition0/lock (was/is locked, but not by me).

...
Thread 36: Exception thrown, finishing my 7. loop cycle. It's the 6. exception seen until now: Traceback (most recent call last):
  File "/home/admin/w/borg/src/borg/testsuite/locking.py", line 161, in acquire_release_loop
    print_locked(
  File "/home/admin/w/borg/src/borg/locking.py", line 120, in __exit__
    self.release()
  File "/home/admin/w/borg/src/borg/locking.py", line 172, in release
    os.unlink(self.unique_name)
FileNotFoundError: [Errno 2] No such file or directory: '/tmp/pytest-of-admin/pytest-32/test_race_condition0/lock/foo.36-0'

...
Thread  9: Exception thrown, finishing my 8. loop cycle. It's the 7. exception seen until now: Traceback (most recent call last):
  File "/home/admin/w/borg/src/borg/locking.py", line 144, in acquire
    os.rename(temp_path, self.path)
OSError: [Errno 90] Directory not empty: '/tmp/pytest-of-admin/pytest-32/test_race_condition0/lock.bc71_db8.tmp' -> '/tmp/pytest-of-admin/pytest-32/test_race_condition0/lock'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/admin/w/borg/src/borg/testsuite/locking.py", line 151, in acquire_release_loop
    with ExclusiveLock(
  File "/home/admin/w/borg/src/borg/locking.py", line 117, in __enter__
    return self.acquire()
  File "/home/admin/w/borg/src/borg/locking.py", line 148, in acquire
    self.kill_stale_lock()
  File "/home/admin/w/borg/src/borg/locking.py", line 191, in kill_stale_lock
    names = os.listdir(self.path)
PermissionError: [Errno 13] Permission denied: '/tmp/pytest-of-admin/pytest-32/test_race_condition0/lock'

...
______________________________________________________________________ ArchiverTestCase.test_atime _______________________________________________________________________

self = <borg.testsuite.archiver.extract_cmd.ArchiverTestCase testMethod=test_atime>

    @pytest.mark.skipif(not is_utime_fully_supported(), reason="cannot properly setup and execute test without utime")
    def test_atime(self):
        def has_noatime(some_file):
            atime_before = os.stat(some_file).st_atime_ns
            try:
                with open(os.open(some_file, flags_noatime)) as file:
                    file.read()
            except PermissionError:
                return False
            else:
                atime_after = os.stat(some_file).st_atime_ns
                noatime_used = flags_noatime != flags_normal
                return noatime_used and atime_before == atime_after

        self.create_test_files()
        atime, mtime = 123456780, 234567890
        have_noatime = has_noatime("input/file1")
        os.utime("input/file1", (atime, mtime))
        self.cmd(f"--repo={self.repository_location}", "rcreate", RK_ENCRYPTION)
        self.cmd(f"--repo={self.repository_location}", "create", "--atime", "test", "input")
        with changedir("output"):
            self.cmd(f"--repo={self.repository_location}", "extract", "test")
        sti = os.stat("input/file1")
        sto = os.stat("output/input/file1")
        assert sti.st_mtime_ns == sto.st_mtime_ns == mtime * 1e9
        if have_noatime:
            assert sti.st_atime_ns == sto.st_atime_ns == atime * 1e9
        else:
            # it touched the input file's atime while backing it up
>           assert sto.st_atime_ns == atime * 1e9
E           assert 1671377299453455500 == (123456780 * 1000000000.0)
E            +  where 1671377299453455500 = os.stat_result(st_mode=35309, st_ino=1688849860568944, st_dev=2550678920, st_nlink=2, st_uid=197609, st_gid=197121, st_size=81920, st_atime=1671377299, st_mtime=234567890, st_ctime=1671377299).st_atime_ns

src/borg/testsuite/archiver/extract_cmd.py:91: AssertionError
___________________________________________________________________ RemoteArchiverTestCase.test_atime ____________________________________________________________________

self = <borg.testsuite.archiver.extract_cmd.RemoteArchiverTestCase testMethod=test_atime>

    @pytest.mark.skipif(not is_utime_fully_supported(), reason="cannot properly setup and execute test without utime")
    def test_atime(self):
        def has_noatime(some_file):
            atime_before = os.stat(some_file).st_atime_ns
            try:
                with open(os.open(some_file, flags_noatime)) as file:
                    file.read()
            except PermissionError:
                return False
            else:
                atime_after = os.stat(some_file).st_atime_ns
                noatime_used = flags_noatime != flags_normal
                return noatime_used and atime_before == atime_after

        self.create_test_files()
        atime, mtime = 123456780, 234567890
        have_noatime = has_noatime("input/file1")
        os.utime("input/file1", (atime, mtime))
        self.cmd(f"--repo={self.repository_location}", "rcreate", RK_ENCRYPTION)
        self.cmd(f"--repo={self.repository_location}", "create", "--atime", "test", "input")
        with changedir("output"):
            self.cmd(f"--repo={self.repository_location}", "extract", "test")
        sti = os.stat("input/file1")
        sto = os.stat("output/input/file1")
        assert sti.st_mtime_ns == sto.st_mtime_ns == mtime * 1e9
        if have_noatime:
            assert sti.st_atime_ns == sto.st_atime_ns == atime * 1e9
        else:
            # it touched the input file's atime while backing it up
>           assert sto.st_atime_ns == atime * 1e9
E           assert 1671377311454228200 == (123456780 * 1000000000.0)
E            +  where 1671377311454228200 = os.stat_result(st_mode=35309, st_ino=3096224744287459, st_dev=2550678920, st_nlink=2, st_uid=197609, st_gid=197121, st_size=81920, st_atime=1671377311, st_mtime=234567890, st_ctime=1671377311).st_atime_ns

src/borg/testsuite/archiver/extract_cmd.py:91: AssertionError

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions