29
from bzrlib.tests import (
35
from bzrlib import _dirstate_helpers_pyx
36
has_dirstate_helpers_pyx = True
38
has_dirstate_helpers_pyx = False
41
compiled_dirstate_helpers_feature = tests.ModuleAvailableFeature(
42
'bzrlib._dirstate_helpers_pyx')
45
def load_tests(basic_tests, module, loader):
46
# FIXME: we should also parametrize against SHA1Provider !
47
suite = loader.suiteClass()
48
remaining_tests = basic_tests
50
dir_reader_scenarios = test_osutils.dir_reader_scenarios()
52
ue_scenarios = [('dirstate_Python',
53
{'update_entry': dirstate.py_update_entry})]
54
if compiled_dirstate_helpers_feature.available():
55
update_entry = compiled_dirstate_helpers_feature.module.update_entry
56
pyrex_scenario = ('dirstate_Pyrex', {'update_entry': update_entry})
57
ue_scenarios.append(pyrex_scenario)
58
process_entry_tests, remaining_tests = tests.split_suite_by_condition(
59
remaining_tests, tests.condition_isinstance(TestUpdateEntry))
60
tests.multiply_tests(process_entry_tests,
61
tests.multiply_scenarios(dir_reader_scenarios,
65
pe_scenarios = [('dirstate_Python',
66
{'_process_entry': dirstate.ProcessEntryPython})]
67
if compiled_dirstate_helpers_feature.available():
68
process_entry = compiled_dirstate_helpers_feature.module.ProcessEntryC
69
pyrex_scenario = ('dirstate_Pyrex', {'_process_entry': process_entry})
70
pe_scenarios.append(pyrex_scenario)
71
process_entry_tests, remaining_tests = tests.split_suite_by_condition(
72
remaining_tests, tests.condition_isinstance(TestProcessEntry))
73
tests.multiply_tests(process_entry_tests,
74
tests.multiply_scenarios(dir_reader_scenarios,
78
dir_reader_tests, remaining_tests = tests.split_suite_by_condition(
79
remaining_tests, tests.condition_isinstance(
80
test_dirstate.TestCaseWithDirState))
81
tests.multiply_tests(dir_reader_tests, dir_reader_scenarios, suite)
82
suite.addTest(remaining_tests)
34
from .test_osutils import dir_reader_scenarios
35
from .scenarios import (
36
load_tests_apply_scenarios,
44
load_tests = load_tests_apply_scenarios
47
compiled_dirstate_helpers_feature = features.ModuleAvailableFeature(
48
'breezy.bzr._dirstate_helpers_pyx')
51
# FIXME: we should also parametrize against SHA1Provider !
53
ue_scenarios = [('dirstate_Python',
54
{'update_entry': dirstate.py_update_entry})]
55
if compiled_dirstate_helpers_feature.available():
56
update_entry = compiled_dirstate_helpers_feature.module.update_entry
57
ue_scenarios.append(('dirstate_Pyrex', {'update_entry': update_entry}))
59
pe_scenarios = [('dirstate_Python',
60
{'_process_entry': dirstate.ProcessEntryPython})]
61
if compiled_dirstate_helpers_feature.available():
62
process_entry = compiled_dirstate_helpers_feature.module.ProcessEntryC
63
pe_scenarios.append(('dirstate_Pyrex', {'_process_entry': process_entry}))
65
helper_scenarios = [('dirstate_Python', {'helpers': _dirstate_helpers_py})]
66
if compiled_dirstate_helpers_feature.available():
67
helper_scenarios.append(('dirstate_Pyrex',
68
{'helpers': compiled_dirstate_helpers_feature.module}))
87
71
class TestBisectPathMixin(object):
389
373
_test_needs_features = [compiled_dirstate_helpers_feature]
391
375
def get_bisect_dirblock(self):
392
from bzrlib._dirstate_helpers_pyx import bisect_dirblock
376
from breezy.bzr._dirstate_helpers_pyx import bisect_dirblock
393
377
return bisect_dirblock
396
class TestCmpByDirs(tests.TestCase):
397
"""Test an implementation of cmp_by_dirs()
380
class TestLtByDirs(tests.TestCase):
381
"""Test an implementation of lt_by_dirs()
399
cmp_by_dirs() compares 2 paths by their directory sections, rather than as
383
lt_by_dirs() compares 2 paths by their directory sections, rather than as
402
Child test cases can override ``get_cmp_by_dirs`` to test a specific
386
Child test cases can override ``get_lt_by_dirs`` to test a specific
406
def get_cmp_by_dirs(self):
407
"""Get a specific implementation of cmp_by_dirs."""
408
from bzrlib._dirstate_helpers_py import cmp_by_dirs
390
def get_lt_by_dirs(self):
391
"""Get a specific implementation of lt_by_dirs."""
392
from ..bzr._dirstate_helpers_py import lt_by_dirs
411
395
def assertCmpByDirs(self, expected, str1, str2):
412
396
"""Compare the two strings, in both directions.
416
400
:param str1: string to compare
417
401
:param str2: string to compare
419
cmp_by_dirs = self.get_cmp_by_dirs()
403
lt_by_dirs = self.get_lt_by_dirs()
420
404
if expected == 0:
421
405
self.assertEqual(str1, str2)
422
self.assertEqual(0, cmp_by_dirs(str1, str2))
423
self.assertEqual(0, cmp_by_dirs(str2, str1))
406
self.assertFalse(lt_by_dirs(str1, str2))
407
self.assertFalse(lt_by_dirs(str2, str1))
424
408
elif expected > 0:
425
self.assertPositive(cmp_by_dirs(str1, str2))
426
self.assertNegative(cmp_by_dirs(str2, str1))
409
self.assertFalse(lt_by_dirs(str1, str2))
410
self.assertTrue(lt_by_dirs(str2, str1))
428
self.assertNegative(cmp_by_dirs(str1, str2))
429
self.assertPositive(cmp_by_dirs(str2, str1))
412
self.assertTrue(lt_by_dirs(str1, str2))
413
self.assertFalse(lt_by_dirs(str2, str1))
431
415
def test_cmp_empty(self):
432
416
"""Compare against the empty string."""
492
476
self.assertCmpByDirs(-1, 'ab/cd', 'ab-cd')
494
478
def test_cmp_unicode_not_allowed(self):
495
cmp_by_dirs = self.get_cmp_by_dirs()
496
self.assertRaises(TypeError, cmp_by_dirs, u'Unicode', 'str')
497
self.assertRaises(TypeError, cmp_by_dirs, 'str', u'Unicode')
498
self.assertRaises(TypeError, cmp_by_dirs, u'Unicode', u'Unicode')
479
lt_by_dirs = self.get_lt_by_dirs()
480
self.assertRaises(TypeError, lt_by_dirs, u'Unicode', 'str')
481
self.assertRaises(TypeError, lt_by_dirs, 'str', u'Unicode')
482
self.assertRaises(TypeError, lt_by_dirs, u'Unicode', u'Unicode')
500
484
def test_cmp_non_ascii(self):
501
485
self.assertCmpByDirs(-1, '\xc2\xb5', '\xc3\xa5') # u'\xb5', u'\xe5'
505
489
self.assertCmpByDirs(-1, 'b/a', 'b/\xc2\xb5') # u'b/a', u'b/\xb5'
508
class TestCompiledCmpByDirs(TestCmpByDirs):
509
"""Test the pyrex implementation of cmp_by_dirs"""
492
class TestCompiledLtByDirs(TestLtByDirs):
493
"""Test the pyrex implementation of lt_by_dirs"""
511
495
_test_needs_features = [compiled_dirstate_helpers_feature]
513
def get_cmp_by_dirs(self):
514
from bzrlib._dirstate_helpers_pyx import cmp_by_dirs
518
class TestCmpPathByDirblock(tests.TestCase):
519
"""Test an implementation of _cmp_path_by_dirblock()
521
_cmp_path_by_dirblock() compares two paths using the sort order used by
497
def get_lt_by_dirs(self):
498
from ..bzr._dirstate_helpers_pyx import lt_by_dirs
502
class TestLtPathByDirblock(tests.TestCase):
503
"""Test an implementation of _lt_path_by_dirblock()
505
_lt_path_by_dirblock() compares two paths using the sort order used by
522
506
DirState. All paths in the same directory are sorted together.
524
Child test cases can override ``get_cmp_path_by_dirblock`` to test a specific
508
Child test cases can override ``get_lt_path_by_dirblock`` to test a specific
528
def get_cmp_path_by_dirblock(self):
529
"""Get a specific implementation of _cmp_path_by_dirblock."""
530
from bzrlib._dirstate_helpers_py import _cmp_path_by_dirblock
531
return _cmp_path_by_dirblock
512
def get_lt_path_by_dirblock(self):
513
"""Get a specific implementation of _lt_path_by_dirblock."""
514
from ..bzr._dirstate_helpers_py import _lt_path_by_dirblock
515
return _lt_path_by_dirblock
533
def assertCmpPathByDirblock(self, paths):
517
def assertLtPathByDirblock(self, paths):
534
518
"""Compare all paths and make sure they evaluate to the correct order.
536
520
This does N^2 comparisons. It is assumed that ``paths`` is properly
544
528
return dirname.split('/'), basename
545
529
self.assertEqual(sorted(paths, key=_key), paths)
547
cmp_path_by_dirblock = self.get_cmp_path_by_dirblock()
531
lt_path_by_dirblock = self.get_lt_path_by_dirblock()
548
532
for idx1, path1 in enumerate(paths):
549
533
for idx2, path2 in enumerate(paths):
550
cmp_val = cmp_path_by_dirblock(path1, path2)
552
self.assertTrue(cmp_val < 0,
553
'%s did not state that %r came before %r, cmp=%s'
554
% (cmp_path_by_dirblock.__name__,
555
path1, path2, cmp_val))
557
self.assertTrue(cmp_val > 0,
558
'%s did not state that %r came after %r, cmp=%s'
559
% (cmp_path_by_dirblock.__name__,
560
path1, path2, cmp_val))
562
self.assertTrue(cmp_val == 0,
563
'%s did not state that %r == %r, cmp=%s'
564
% (cmp_path_by_dirblock.__name__,
565
path1, path2, cmp_val))
534
lt_result = lt_path_by_dirblock(path1, path2)
535
self.assertEqual(idx1 < idx2, lt_result,
536
'%s did not state that %r < %r, lt=%s'
537
% (lt_path_by_dirblock.__name__,
538
path1, path2, lt_result))
567
540
def test_cmp_simple_paths(self):
568
541
"""Compare against the empty string."""
569
self.assertCmpPathByDirblock(['', 'a', 'ab', 'abc', 'a/b/c', 'b/d/e'])
570
self.assertCmpPathByDirblock(['kl', 'ab/cd', 'ab/ef', 'gh/ij'])
542
self.assertLtPathByDirblock(['', 'a', 'ab', 'abc', 'a/b/c', 'b/d/e'])
543
self.assertLtPathByDirblock(['kl', 'ab/cd', 'ab/ef', 'gh/ij'])
572
545
def test_tricky_paths(self):
573
self.assertCmpPathByDirblock([
546
self.assertLtPathByDirblock([
575
548
'', 'a', 'a-a', 'a=a', 'b',
576
549
# Contents of 'a'
631
604
def test_unicode_not_allowed(self):
632
cmp_path_by_dirblock = self.get_cmp_path_by_dirblock()
633
self.assertRaises(TypeError, cmp_path_by_dirblock, u'Uni', 'str')
634
self.assertRaises(TypeError, cmp_path_by_dirblock, 'str', u'Uni')
635
self.assertRaises(TypeError, cmp_path_by_dirblock, u'Uni', u'Uni')
636
self.assertRaises(TypeError, cmp_path_by_dirblock, u'x/Uni', 'x/str')
637
self.assertRaises(TypeError, cmp_path_by_dirblock, 'x/str', u'x/Uni')
638
self.assertRaises(TypeError, cmp_path_by_dirblock, u'x/Uni', u'x/Uni')
605
lt_path_by_dirblock = self.get_lt_path_by_dirblock()
606
self.assertRaises(TypeError, lt_path_by_dirblock, u'Uni', 'str')
607
self.assertRaises(TypeError, lt_path_by_dirblock, 'str', u'Uni')
608
self.assertRaises(TypeError, lt_path_by_dirblock, u'Uni', u'Uni')
609
self.assertRaises(TypeError, lt_path_by_dirblock, u'x/Uni', 'x/str')
610
self.assertRaises(TypeError, lt_path_by_dirblock, 'x/str', u'x/Uni')
611
self.assertRaises(TypeError, lt_path_by_dirblock, u'x/Uni', u'x/Uni')
640
613
def test_nonascii(self):
641
self.assertCmpPathByDirblock([
614
self.assertLtPathByDirblock([
643
616
'', 'a', '\xc2\xb5', '\xc3\xa5',
775
750
def test_bisect_dirblock(self):
776
751
if compiled_dirstate_helpers_feature.available():
777
from bzrlib._dirstate_helpers_pyx import bisect_dirblock
752
from breezy.bzr._dirstate_helpers_pyx import bisect_dirblock
779
from bzrlib._dirstate_helpers_py import bisect_dirblock
754
from breezy.bzr._dirstate_helpers_py import bisect_dirblock
780
755
self.assertIs(bisect_dirblock, dirstate.bisect_dirblock)
782
757
def test__bisect_path_left(self):
783
758
if compiled_dirstate_helpers_feature.available():
784
from bzrlib._dirstate_helpers_pyx import _bisect_path_left
759
from breezy.bzr._dirstate_helpers_pyx import _bisect_path_left
786
from bzrlib._dirstate_helpers_py import _bisect_path_left
761
from breezy.bzr._dirstate_helpers_py import _bisect_path_left
787
762
self.assertIs(_bisect_path_left, dirstate._bisect_path_left)
789
764
def test__bisect_path_right(self):
790
765
if compiled_dirstate_helpers_feature.available():
791
from bzrlib._dirstate_helpers_pyx import _bisect_path_right
766
from breezy.bzr._dirstate_helpers_pyx import _bisect_path_right
793
from bzrlib._dirstate_helpers_py import _bisect_path_right
768
from breezy.bzr._dirstate_helpers_py import _bisect_path_right
794
769
self.assertIs(_bisect_path_right, dirstate._bisect_path_right)
796
def test_cmp_by_dirs(self):
771
def test_lt_by_dirs(self):
797
772
if compiled_dirstate_helpers_feature.available():
798
from bzrlib._dirstate_helpers_pyx import cmp_by_dirs
773
from ..bzr._dirstate_helpers_pyx import lt_by_dirs
800
from bzrlib._dirstate_helpers_py import cmp_by_dirs
801
self.assertIs(cmp_by_dirs, dirstate.cmp_by_dirs)
775
from ..bzr._dirstate_helpers_py import lt_by_dirs
776
self.assertIs(lt_by_dirs, dirstate.lt_by_dirs)
803
778
def test__read_dirblocks(self):
804
779
if compiled_dirstate_helpers_feature.available():
805
from bzrlib._dirstate_helpers_pyx import _read_dirblocks
780
from breezy.bzr._dirstate_helpers_pyx import _read_dirblocks
807
from bzrlib._dirstate_helpers_py import _read_dirblocks
782
from breezy.bzr._dirstate_helpers_py import _read_dirblocks
808
783
self.assertIs(_read_dirblocks, dirstate._read_dirblocks)
810
785
def test_update_entry(self):
811
786
if compiled_dirstate_helpers_feature.available():
812
from bzrlib._dirstate_helpers_pyx import update_entry
787
from breezy.bzr._dirstate_helpers_pyx import update_entry
814
from bzrlib.dirstate import update_entry
789
from breezy.bzr.dirstate import update_entry
815
790
self.assertIs(update_entry, dirstate.update_entry)
817
792
def test_process_entry(self):
818
793
if compiled_dirstate_helpers_feature.available():
819
from bzrlib._dirstate_helpers_pyx import ProcessEntryC
794
from breezy.bzr._dirstate_helpers_pyx import ProcessEntryC
820
795
self.assertIs(ProcessEntryC, dirstate._process_entry)
822
from bzrlib.dirstate import ProcessEntryPython
797
from breezy.bzr.dirstate import ProcessEntryPython
823
798
self.assertIs(ProcessEntryPython, dirstate._process_entry)
826
801
class TestUpdateEntry(test_dirstate.TestCaseWithDirState):
827
802
"""Test the DirState.update_entry functions"""
804
scenarios = multiply_scenarios(
805
dir_reader_scenarios(), ue_scenarios)
829
807
# Set by load_tests
830
808
update_entry = None
837
815
"""Create a DirState tracking a single object named 'a'"""
838
816
state = test_dirstate.InstrumentedDirState.initialize('dirstate')
839
817
self.addCleanup(state.unlock)
840
state.add('a', 'a-id', 'file', None, '')
818
state.add('a', b'a-id', 'file', None, '')
841
819
entry = state._get_entry(0, path_utf8='a')
842
820
return state, entry
844
822
def test_observed_sha1_cachable(self):
845
823
state, entry = self.get_state_with_a()
846
825
atime = time.time() - 10
847
826
self.build_tree(['a'])
848
statvalue = os.lstat('a')
849
statvalue = test_dirstate._FakeStat(statvalue.st_size, atime, atime,
850
statvalue.st_dev, statvalue.st_ino, statvalue.st_mode)
827
statvalue = test_dirstate._FakeStat.from_stat(os.lstat('a'))
828
statvalue.st_mtime = statvalue.st_ctime = atime
829
self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
830
state._dirblock_state)
851
831
state._observed_sha1(entry, "foo", statvalue)
852
832
self.assertEqual('foo', entry[1][0][1])
853
833
packed_stat = dirstate.pack_stat(statvalue)
854
834
self.assertEqual(packed_stat, entry[1][0][4])
835
self.assertEqual(dirstate.DirState.IN_MEMORY_HASH_MODIFIED,
836
state._dirblock_state)
856
838
def test_observed_sha1_not_cachable(self):
857
839
state, entry = self.get_state_with_a()
858
841
oldval = entry[1][0][1]
859
842
oldstat = entry[1][0][4]
860
843
self.build_tree(['a'])
861
844
statvalue = os.lstat('a')
845
self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
846
state._dirblock_state)
862
847
state._observed_sha1(entry, "foo", statvalue)
863
848
self.assertEqual(oldval, entry[1][0][1])
864
849
self.assertEqual(oldstat, entry[1][0][4])
850
self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
851
state._dirblock_state)
866
853
def test_update_entry(self):
867
854
state, _ = self.get_state_with_a()
977
967
# Dirblock is not updated (the link is too new)
978
968
self.assertEqual([('l', '', 6, False, dirstate.DirState.NULLSTAT)],
980
self.assertEqual(dirstate.DirState.IN_MEMORY_MODIFIED,
970
# The file entry turned into a symlink, that is considered
971
# HASH modified worthy.
972
self.assertEqual(dirstate.DirState.IN_MEMORY_HASH_MODIFIED,
981
973
state._dirblock_state)
983
975
# Because the stat_value looks new, we should re-read the target
984
977
link_or_sha1 = self.update_entry(state, entry, abspath='a',
985
978
stat_value=stat_value)
986
979
self.assertEqual('target', link_or_sha1)
987
self.assertEqual([('read_link', 'a', ''),
988
('read_link', 'a', ''),
980
self.assertEqual([('read_link', 'a', '')], state._log)
990
981
self.assertEqual([('l', '', 6, False, dirstate.DirState.NULLSTAT)],
992
984
state.adjust_time(+20) # Skip into the future, all files look old
993
986
link_or_sha1 = self.update_entry(state, entry, abspath='a',
994
987
stat_value=stat_value)
988
# The symlink stayed a symlink. So while it is new enough to cache, we
989
# don't bother setting the flag, because it is not really worth saving
990
# (when we stat the symlink, we'll have paged in the target.)
991
self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
992
state._dirblock_state)
995
993
self.assertEqual('target', link_or_sha1)
996
994
# We need to re-read the link because only now can we cache it
997
self.assertEqual([('read_link', 'a', ''),
998
('read_link', 'a', ''),
999
('read_link', 'a', ''),
995
self.assertEqual([('read_link', 'a', '')], state._log)
1001
996
self.assertEqual([('l', 'target', 6, False, packed_stat)],
1004
1000
# Another call won't re-read the link
1005
self.assertEqual([('read_link', 'a', ''),
1006
('read_link', 'a', ''),
1007
('read_link', 'a', ''),
1001
self.assertEqual([], state._log)
1009
1002
link_or_sha1 = self.update_entry(state, entry, abspath='a',
1010
1003
stat_value=stat_value)
1011
1004
self.assertEqual('target', link_or_sha1)
1026
1019
self.build_tree(['a/'])
1027
1020
state.adjust_time(+20)
1028
1021
self.assertIs(None, self.do_update_entry(state, entry, 'a'))
1022
# a/ used to be a file, but is now a directory, worth saving
1029
1023
self.assertEqual(dirstate.DirState.IN_MEMORY_MODIFIED,
1030
1024
state._dirblock_state)
1032
1026
self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
1033
1027
state._dirblock_state)
1034
self.assertIs(None, self.do_update_entry(state, entry, 'a'))
1028
# No changes to a/ means not worth saving.
1029
self.assertIs(None, self.do_update_entry(state, entry, 'a'))
1030
self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
1031
state._dirblock_state)
1032
# Change the last-modified time for the directory
1033
t = time.time() - 100.0
1035
os.utime('a', (t, t))
1037
# It looks like Win32 + FAT doesn't allow to change times on a dir.
1038
raise tests.TestSkipped("can't update mtime of a dir on FAT")
1039
saved_packed_stat = entry[1][0][-1]
1040
self.assertIs(None, self.do_update_entry(state, entry, 'a'))
1041
# We *do* go ahead and update the information in the dirblocks, but we
1042
# don't bother setting IN_MEMORY_MODIFIED because it is trivial to
1044
self.assertNotEqual(saved_packed_stat, entry[1][0][-1])
1035
1045
self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
1036
1046
state._dirblock_state)
1305
1317
def test_simple_changes(self):
1306
1318
tree = self.make_branch_and_tree('tree')
1307
1319
self.build_tree(['tree/file'])
1308
tree.add(['file'], ['file-id'])
1309
self.assertChangedFileIds([tree.get_root_id(), 'file-id'], tree)
1320
tree.add(['file'], [b'file-id'])
1321
self.assertChangedFileIds([tree.get_root_id(), b'file-id'], tree)
1310
1322
tree.commit('one')
1311
1323
self.assertChangedFileIds([], tree)
1313
1325
def test_sha1provider_stat_and_sha1_used(self):
1314
1326
tree = self.make_branch_and_tree('tree')
1315
1327
self.build_tree(['tree/file'])
1316
tree.add(['file'], ['file-id'])
1328
tree.add(['file'], [b'file-id'])
1317
1329
tree.commit('one')
1318
1330
tree.lock_write()
1319
1331
self.addCleanup(tree.unlock)
1320
1332
state = tree._current_dirstate()
1321
1333
state._sha1_provider = UppercaseSHA1Provider()
1322
self.assertChangedFileIds(['file-id'], tree)
1334
self.assertChangedFileIds([b'file-id'], tree)
1337
class TestPackStat(tests.TestCase):
1338
"""Check packed representaton of stat values is robust on all inputs"""
1340
scenarios = helper_scenarios
1342
def pack(self, statlike_tuple):
1343
return self.helpers.pack_stat(os.stat_result(statlike_tuple))
1346
def unpack_field(packed_string, stat_field):
1347
return _dirstate_helpers_py._unpack_stat(packed_string)[stat_field]
1349
def test_result(self):
1350
self.assertEqual("AAAQAAAAABAAAAARAAAAAgAAAAEAAIHk",
1351
self.pack((33252, 1, 2, 0, 0, 0, 4096, 15.5, 16.5, 17.5)))
1353
def test_giant_inode(self):
1354
packed = self.pack((33252, 0xF80000ABC, 0, 0, 0, 0, 0, 0, 0, 0))
1355
self.assertEqual(0x80000ABC, self.unpack_field(packed, "st_ino"))
1357
def test_giant_size(self):
1358
packed = self.pack((33252, 0, 0, 0, 0, 0, (1 << 33) + 4096, 0, 0, 0))
1359
self.assertEqual(4096, self.unpack_field(packed, "st_size"))
1361
def test_fractional_mtime(self):
1362
packed = self.pack((33252, 0, 0, 0, 0, 0, 0, 0, 16.9375, 0))
1363
self.assertEqual(16, self.unpack_field(packed, "st_mtime"))
1365
def test_ancient_mtime(self):
1366
packed = self.pack((33252, 0, 0, 0, 0, 0, 0, 0, -11644473600.0, 0))
1367
self.assertEqual(1240428288, self.unpack_field(packed, "st_mtime"))
1369
def test_distant_mtime(self):
1370
packed = self.pack((33252, 0, 0, 0, 0, 0, 0, 0, 64060588800.0, 0))
1371
self.assertEqual(3931046656, self.unpack_field(packed, "st_mtime"))
1373
def test_fractional_ctime(self):
1374
packed = self.pack((33252, 0, 0, 0, 0, 0, 0, 0, 0, 17.5625))
1375
self.assertEqual(17, self.unpack_field(packed, "st_ctime"))
1377
def test_ancient_ctime(self):
1378
packed = self.pack((33252, 0, 0, 0, 0, 0, 0, 0, 0, -11644473600.0))
1379
self.assertEqual(1240428288, self.unpack_field(packed, "st_ctime"))
1381
def test_distant_ctime(self):
1382
packed = self.pack((33252, 0, 0, 0, 0, 0, 0, 0, 0, 64060588800.0))
1383
self.assertEqual(3931046656, self.unpack_field(packed, "st_ctime"))
1385
def test_negative_dev(self):
1386
packed = self.pack((33252, 0, -0xFFFFFCDE, 0, 0, 0, 0, 0, 0, 0))
1387
self.assertEqual(0x322, self.unpack_field(packed, "st_dev"))