Repository: borgbackup/borg

Issue:
testsuite failure on hurd-i386
Hi, following the error:
(note: hurd-i386 is not a release architecture, so you can just close this issue)
https://buildd.debian.org/status/fetch.php?pkg=borgbackup&arch=hurd-i386&ver=1.0.5-2&stamp=1468279201

```
plugins: cov-2.2.1
collected 554 items

borg/testsuite/archive.py ...............................
borg/testsuite/archiver.py .s..F.............s..............X.........sssssssssssssssssssssssssssssssssssssssss........F......s......s..............X...........
borg/testsuite/chunker.py ...
borg/testsuite/compress.py ........
borg/testsuite/crypto.py .....
borg/testsuite/hashindex.py .....................
borg/testsuite/helpers.py ...............................................................................................................................................................
borg/testsuite/key.py ....
borg/testsuite/locking.py ..............
borg/testsuite/logger.py ....
borg/testsuite/lrucache.py ..
borg/testsuite/platform.py sssss
borg/testsuite/repository.py .........................................
borg/testsuite/shellpattern.py .............................................................
borg/testsuite/upgrader.py sssss..
borg/testsuite/xattr.py s

=================================== FAILURES ===================================
_________________________ ArchiverTestCase.test_atime __________________________

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

    def test_atime(self):
        self.create_test_files()
        atime, mtime = 123456780, 234567890
        os.utime('input/file1', (atime, mtime))
        self.cmd('init', self.repository_location)
        self.cmd('create', self.repository_location + '::test', 'input')
        with changedir('output'):
            self.cmd('extract', self.repository_location + '::test')
        sti = os.stat('input/file1')
        sto = os.stat('output/input/file1')
        assert sti.st_mtime_ns == sto.st_mtime_ns == mtime * 1e9
        if hasattr(os, 'O_NOATIME'):
>           assert sti.st_atime_ns == sto.st_atime_ns == atime * 1e9
E           AssertionError: assert 1468278979000000000 == 123456780000000000
E            +  where 1468278979000000000 = os.stat_result(st_mode=35309, st_ino=253216, st_dev=5, st_nlink=2, st_uid=100, st_gid=200, st_size=81920, st_atime=1468278979, st_mtime=234567890, st_ctime=1468278979).st_atime_ns
E            +  and   123456780000000000 = os.stat_result(st_mode=35309, st_ino=32704, st_dev=5, st_nlink=2, st_uid=100, st_gid=200, st_size=81920, st_atime=123456780, st_mtime=234567890, st_ctime=1468278979).st_atime_ns

borg/testsuite/archiver.py:369: AssertionError
______________________ RemoteArchiverTestCase.test_atime _______________________

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

    def test_atime(self):
        self.create_test_files()
        atime, mtime = 123456780, 234567890
        os.utime('input/file1', (atime, mtime))
        self.cmd('init', self.repository_location)
        self.cmd('create', self.repository_location + '::test', 'input')
        with changedir('output'):
            self.cmd('extract', self.repository_location + '::test')
        sti = os.stat('input/file1')
        sto = os.stat('output/input/file1')
        assert sti.st_mtime_ns == sto.st_mtime_ns == mtime * 1e9
        if hasattr(os, 'O_NOATIME'):
>           assert sti.st_atime_ns == sto.st_atime_ns == atime * 1e9
E           AssertionError: assert 1468279041000000000 == 123456780000000000
E            +  where 1468279041000000000 = os.stat_result(st_mode=35309, st_ino=539078, st_dev=5, st_nlink=2, st_uid=100, st_gid=200, st_size=81920, st_atime=1468279041, st_mtime=234567890, st_ctime=1468279041).st_atime_ns
E            +  and   123456780000000000 = os.stat_result(st_mode=35309, st_ino=552, st_dev=5, st_nlink=2, st_uid=100, st_gid=200, st_size=81920, st_atime=123456780, st_mtime=234567890, st_ctime=1468279042).st_atime_ns

borg/testsuite/archiver.py:369: AssertionError
========= 55 tests deselected by '-knot benchmark and not fuse_mount' ==========
= 2 failed, 439 passed, 56 skipped, 55 deselected, 2 xpassed in 221.08 seconds =
E: pybuild pybuild:274: test: plugin distutils failed with: exit code=1: cd /«PKGBUILDDIR»/.pybuild/pythonX.Y_3.5/build; python3.5 -m pytest -k 'not benchmark and not fuse_mount' --pyargs borg.testsuite
dh_auto_test: pybuild --test -i python{version} -p 3.5 returned exit code 13
/bin/fakeauth: Error 13 for child 4500
/bin/settrans: Error 13 for child 4499
debian/rules:63: recipe for target 'override_dh_auto_test' failed
make[1]: *** [override_dh_auto_test] Error 13
make[1]: Leaving directory '/«PKGBUILDDIR»'
```



Discussion:

Resolving patch:
diff --git a/borg/testsuite/archiver.py b/borg/testsuite/archiver.py
--- a/borg/testsuite/archiver.py
+++ b/borg/testsuite/archiver.py
@@ -17,7 +17,7 @@
 import pytest
 
 from .. import xattr
-from ..archive import Archive, ChunkBuffer, CHUNK_MAX_EXP
+from ..archive import Archive, ChunkBuffer, CHUNK_MAX_EXP, flags_noatime, flags_normal
 from ..archiver import Archiver
 from ..cache import Cache
 from ..crypto import bytes_to_long, num_aes_blocks
@@ -363,8 +363,20 @@ def filter(output):
         self.assert_equal(filter(info_output), filter(info_output2))
 
     def test_atime(self):
+        def has_noatime(some_file):
+            atime_before = os.stat(some_file).st_atime_ns
+            try:
+                os.close(os.open(some_file, flags_noatime))
+            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('init', self.repository_location)
         self.cmd('create', self.repository_location + '::test', 'input')
@@ -373,7 +385,7 @@ def test_atime(self):
         sti = os.stat('input/file1')
         sto = os.stat('output/input/file1')
         assert sti.st_mtime_ns == sto.st_mtime_ns == mtime * 1e9
-        if hasattr(os, 'O_NOATIME'):
+        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


Test patch: