annotate tests/test-atomictempfile.py @ 29352:37c7f9fb7040

localrepo: make restoring from backup at rollback avoid ambiguity of file stat Rollback of previous transaction restores contents of files below by renaming from 'undo.*' file. If renaming keeps ctime, mtime and size of a file, restoring is overlooked, and old contents cached before restoring isn't invalidated as expected. - .hg/bookmarks - .hg/phaseroots To avoid ambiguity of file stat at restoring, this patch invokes vfs.rename() with checkambig=True. BTW, .hg/dirstate is also restored at rollback. But it is restored by dirstate.restorebackup(), and previous patch already made it invoke vfs.rename() with checkambig=True. This patch is a part of "Exact Cache Validation Plan": https://www.mercurial-scm.org/wiki/ExactCacheValidationPlan
author FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
date Mon, 13 Jun 2016 05:11:56 +0900
parents a109bf7e0dc2
children 1acf654f0985
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
29194
3bea82dd4c4e py3: make tests/test-atomictempfile.py use absolute_import
Pulkit Goyal <7895pulkit@gmail.com>
parents: 29188
diff changeset
1 from __future__ import absolute_import
3bea82dd4c4e py3: make tests/test-atomictempfile.py use absolute_import
Pulkit Goyal <7895pulkit@gmail.com>
parents: 29188
diff changeset
2
3bea82dd4c4e py3: make tests/test-atomictempfile.py use absolute_import
Pulkit Goyal <7895pulkit@gmail.com>
parents: 29188
diff changeset
3 import glob
14007
d764463b433e atomictempfile: avoid infinite recursion in __del__().
Greg Ward <greg@gerg.ca>
parents:
diff changeset
4 import os
18666
fb9d1c2805ff test-atomictempfile: convert to unit test
Idan Kamara <idankk86@gmail.com>
parents: 15057
diff changeset
5 import unittest
fb9d1c2805ff test-atomictempfile: convert to unit test
Idan Kamara <idankk86@gmail.com>
parents: 15057
diff changeset
6
29194
3bea82dd4c4e py3: make tests/test-atomictempfile.py use absolute_import
Pulkit Goyal <7895pulkit@gmail.com>
parents: 29188
diff changeset
7 from mercurial import (
3bea82dd4c4e py3: make tests/test-atomictempfile.py use absolute_import
Pulkit Goyal <7895pulkit@gmail.com>
parents: 29188
diff changeset
8 util,
3bea82dd4c4e py3: make tests/test-atomictempfile.py use absolute_import
Pulkit Goyal <7895pulkit@gmail.com>
parents: 29188
diff changeset
9 )
3bea82dd4c4e py3: make tests/test-atomictempfile.py use absolute_import
Pulkit Goyal <7895pulkit@gmail.com>
parents: 29188
diff changeset
10 atomictempfile = util.atomictempfile
14007
d764463b433e atomictempfile: avoid infinite recursion in __del__().
Greg Ward <greg@gerg.ca>
parents:
diff changeset
11
18666
fb9d1c2805ff test-atomictempfile: convert to unit test
Idan Kamara <idankk86@gmail.com>
parents: 15057
diff changeset
12 class testatomictempfile(unittest.TestCase):
fb9d1c2805ff test-atomictempfile: convert to unit test
Idan Kamara <idankk86@gmail.com>
parents: 15057
diff changeset
13 def test1_simple(self):
fb9d1c2805ff test-atomictempfile: convert to unit test
Idan Kamara <idankk86@gmail.com>
parents: 15057
diff changeset
14 if os.path.exists('foo'):
fb9d1c2805ff test-atomictempfile: convert to unit test
Idan Kamara <idankk86@gmail.com>
parents: 15057
diff changeset
15 os.remove('foo')
fb9d1c2805ff test-atomictempfile: convert to unit test
Idan Kamara <idankk86@gmail.com>
parents: 15057
diff changeset
16 file = atomictempfile('foo')
fb9d1c2805ff test-atomictempfile: convert to unit test
Idan Kamara <idankk86@gmail.com>
parents: 15057
diff changeset
17 (dir, basename) = os.path.split(file._tempname)
fb9d1c2805ff test-atomictempfile: convert to unit test
Idan Kamara <idankk86@gmail.com>
parents: 15057
diff changeset
18 self.assertFalse(os.path.isfile('foo'))
fb9d1c2805ff test-atomictempfile: convert to unit test
Idan Kamara <idankk86@gmail.com>
parents: 15057
diff changeset
19 self.assertTrue(basename in glob.glob('.foo-*'))
14007
d764463b433e atomictempfile: avoid infinite recursion in __del__().
Greg Ward <greg@gerg.ca>
parents:
diff changeset
20
29188
f00f1de16454 tests: mark test-atomictempfile.py write as binary
timeless <timeless@mozdev.org>
parents: 18666
diff changeset
21 file.write(b'argh\n')
18666
fb9d1c2805ff test-atomictempfile: convert to unit test
Idan Kamara <idankk86@gmail.com>
parents: 15057
diff changeset
22 file.close()
14007
d764463b433e atomictempfile: avoid infinite recursion in __del__().
Greg Ward <greg@gerg.ca>
parents:
diff changeset
23
18666
fb9d1c2805ff test-atomictempfile: convert to unit test
Idan Kamara <idankk86@gmail.com>
parents: 15057
diff changeset
24 self.assertTrue(os.path.isfile('foo'))
fb9d1c2805ff test-atomictempfile: convert to unit test
Idan Kamara <idankk86@gmail.com>
parents: 15057
diff changeset
25 self.assertTrue(basename not in glob.glob('.foo-*'))
14007
d764463b433e atomictempfile: avoid infinite recursion in __del__().
Greg Ward <greg@gerg.ca>
parents:
diff changeset
26
18666
fb9d1c2805ff test-atomictempfile: convert to unit test
Idan Kamara <idankk86@gmail.com>
parents: 15057
diff changeset
27 # discard() removes the temp file without making the write permanent
fb9d1c2805ff test-atomictempfile: convert to unit test
Idan Kamara <idankk86@gmail.com>
parents: 15057
diff changeset
28 def test2_discard(self):
fb9d1c2805ff test-atomictempfile: convert to unit test
Idan Kamara <idankk86@gmail.com>
parents: 15057
diff changeset
29 if os.path.exists('foo'):
fb9d1c2805ff test-atomictempfile: convert to unit test
Idan Kamara <idankk86@gmail.com>
parents: 15057
diff changeset
30 os.remove('foo')
fb9d1c2805ff test-atomictempfile: convert to unit test
Idan Kamara <idankk86@gmail.com>
parents: 15057
diff changeset
31 file = atomictempfile('foo')
fb9d1c2805ff test-atomictempfile: convert to unit test
Idan Kamara <idankk86@gmail.com>
parents: 15057
diff changeset
32 (dir, basename) = os.path.split(file._tempname)
14007
d764463b433e atomictempfile: avoid infinite recursion in __del__().
Greg Ward <greg@gerg.ca>
parents:
diff changeset
33
29188
f00f1de16454 tests: mark test-atomictempfile.py write as binary
timeless <timeless@mozdev.org>
parents: 18666
diff changeset
34 file.write(b'yo\n')
18666
fb9d1c2805ff test-atomictempfile: convert to unit test
Idan Kamara <idankk86@gmail.com>
parents: 15057
diff changeset
35 file.discard()
14007
d764463b433e atomictempfile: avoid infinite recursion in __del__().
Greg Ward <greg@gerg.ca>
parents:
diff changeset
36
18666
fb9d1c2805ff test-atomictempfile: convert to unit test
Idan Kamara <idankk86@gmail.com>
parents: 15057
diff changeset
37 self.assertFalse(os.path.isfile('foo'))
fb9d1c2805ff test-atomictempfile: convert to unit test
Idan Kamara <idankk86@gmail.com>
parents: 15057
diff changeset
38 self.assertTrue(basename not in os.listdir('.'))
fb9d1c2805ff test-atomictempfile: convert to unit test
Idan Kamara <idankk86@gmail.com>
parents: 15057
diff changeset
39
fb9d1c2805ff test-atomictempfile: convert to unit test
Idan Kamara <idankk86@gmail.com>
parents: 15057
diff changeset
40 # if a programmer screws up and passes bad args to atomictempfile, they
fb9d1c2805ff test-atomictempfile: convert to unit test
Idan Kamara <idankk86@gmail.com>
parents: 15057
diff changeset
41 # get a plain ordinary TypeError, not infinite recursion
fb9d1c2805ff test-atomictempfile: convert to unit test
Idan Kamara <idankk86@gmail.com>
parents: 15057
diff changeset
42 def test3_oops(self):
fb9d1c2805ff test-atomictempfile: convert to unit test
Idan Kamara <idankk86@gmail.com>
parents: 15057
diff changeset
43 self.assertRaises(TypeError, atomictempfile)
14007
d764463b433e atomictempfile: avoid infinite recursion in __del__().
Greg Ward <greg@gerg.ca>
parents:
diff changeset
44
29201
a109bf7e0dc2 util: make atomictempfile avoid ambiguity of file stat if needed
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29194
diff changeset
45 # checkambig=True avoids ambiguity of timestamp
a109bf7e0dc2 util: make atomictempfile avoid ambiguity of file stat if needed
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29194
diff changeset
46 def test4_checkambig(self):
a109bf7e0dc2 util: make atomictempfile avoid ambiguity of file stat if needed
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29194
diff changeset
47 def atomicwrite(checkambig):
a109bf7e0dc2 util: make atomictempfile avoid ambiguity of file stat if needed
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29194
diff changeset
48 f = atomictempfile('foo', checkambig=checkambig)
a109bf7e0dc2 util: make atomictempfile avoid ambiguity of file stat if needed
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29194
diff changeset
49 f.write('FOO')
a109bf7e0dc2 util: make atomictempfile avoid ambiguity of file stat if needed
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29194
diff changeset
50 f.close()
a109bf7e0dc2 util: make atomictempfile avoid ambiguity of file stat if needed
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29194
diff changeset
51
a109bf7e0dc2 util: make atomictempfile avoid ambiguity of file stat if needed
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29194
diff changeset
52 # try some times, because reproduction of ambiguity depends on
a109bf7e0dc2 util: make atomictempfile avoid ambiguity of file stat if needed
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29194
diff changeset
53 # "filesystem time"
a109bf7e0dc2 util: make atomictempfile avoid ambiguity of file stat if needed
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29194
diff changeset
54 for i in xrange(5):
a109bf7e0dc2 util: make atomictempfile avoid ambiguity of file stat if needed
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29194
diff changeset
55 atomicwrite(False)
a109bf7e0dc2 util: make atomictempfile avoid ambiguity of file stat if needed
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29194
diff changeset
56 oldstat = os.stat('foo')
a109bf7e0dc2 util: make atomictempfile avoid ambiguity of file stat if needed
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29194
diff changeset
57 if oldstat.st_ctime != oldstat.st_mtime:
a109bf7e0dc2 util: make atomictempfile avoid ambiguity of file stat if needed
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29194
diff changeset
58 # subsequent changing never causes ambiguity
a109bf7e0dc2 util: make atomictempfile avoid ambiguity of file stat if needed
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29194
diff changeset
59 continue
a109bf7e0dc2 util: make atomictempfile avoid ambiguity of file stat if needed
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29194
diff changeset
60
a109bf7e0dc2 util: make atomictempfile avoid ambiguity of file stat if needed
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29194
diff changeset
61 repetition = 3
a109bf7e0dc2 util: make atomictempfile avoid ambiguity of file stat if needed
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29194
diff changeset
62
a109bf7e0dc2 util: make atomictempfile avoid ambiguity of file stat if needed
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29194
diff changeset
63 # repeat atomic write with checkambig=True, to examine
a109bf7e0dc2 util: make atomictempfile avoid ambiguity of file stat if needed
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29194
diff changeset
64 # whether st_mtime is advanced multiple times as expecetd
a109bf7e0dc2 util: make atomictempfile avoid ambiguity of file stat if needed
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29194
diff changeset
65 for j in xrange(repetition):
a109bf7e0dc2 util: make atomictempfile avoid ambiguity of file stat if needed
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29194
diff changeset
66 atomicwrite(True)
a109bf7e0dc2 util: make atomictempfile avoid ambiguity of file stat if needed
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29194
diff changeset
67 newstat = os.stat('foo')
a109bf7e0dc2 util: make atomictempfile avoid ambiguity of file stat if needed
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29194
diff changeset
68 if oldstat.st_ctime != newstat.st_ctime:
a109bf7e0dc2 util: make atomictempfile avoid ambiguity of file stat if needed
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29194
diff changeset
69 # timestamp ambiguity was naturally avoided while repetition
a109bf7e0dc2 util: make atomictempfile avoid ambiguity of file stat if needed
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29194
diff changeset
70 continue
a109bf7e0dc2 util: make atomictempfile avoid ambiguity of file stat if needed
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29194
diff changeset
71
a109bf7e0dc2 util: make atomictempfile avoid ambiguity of file stat if needed
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29194
diff changeset
72 # st_mtime should be advanced "repetition" times, because
a109bf7e0dc2 util: make atomictempfile avoid ambiguity of file stat if needed
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29194
diff changeset
73 # all atomicwrite() occured at same time (in sec)
a109bf7e0dc2 util: make atomictempfile avoid ambiguity of file stat if needed
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29194
diff changeset
74 self.assertTrue(newstat.st_mtime ==
a109bf7e0dc2 util: make atomictempfile avoid ambiguity of file stat if needed
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29194
diff changeset
75 ((oldstat.st_mtime + repetition) & 0x7fffffff))
a109bf7e0dc2 util: make atomictempfile avoid ambiguity of file stat if needed
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29194
diff changeset
76 # no more examination is needed, if assumption above is true
a109bf7e0dc2 util: make atomictempfile avoid ambiguity of file stat if needed
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29194
diff changeset
77 break
a109bf7e0dc2 util: make atomictempfile avoid ambiguity of file stat if needed
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29194
diff changeset
78 else:
a109bf7e0dc2 util: make atomictempfile avoid ambiguity of file stat if needed
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29194
diff changeset
79 # This platform seems too slow to examine anti-ambiguity
a109bf7e0dc2 util: make atomictempfile avoid ambiguity of file stat if needed
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29194
diff changeset
80 # of file timestamp (or test happened to be executed at
a109bf7e0dc2 util: make atomictempfile avoid ambiguity of file stat if needed
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29194
diff changeset
81 # bad timing). Exit silently in this case, because running
a109bf7e0dc2 util: make atomictempfile avoid ambiguity of file stat if needed
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29194
diff changeset
82 # on other faster platforms can detect problems
a109bf7e0dc2 util: make atomictempfile avoid ambiguity of file stat if needed
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29194
diff changeset
83 pass
a109bf7e0dc2 util: make atomictempfile avoid ambiguity of file stat if needed
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29194
diff changeset
84
14007
d764463b433e atomictempfile: avoid infinite recursion in __del__().
Greg Ward <greg@gerg.ca>
parents:
diff changeset
85 if __name__ == '__main__':
29194
3bea82dd4c4e py3: make tests/test-atomictempfile.py use absolute_import
Pulkit Goyal <7895pulkit@gmail.com>
parents: 29188
diff changeset
86 import silenttestrunner
18666
fb9d1c2805ff test-atomictempfile: convert to unit test
Idan Kamara <idankk86@gmail.com>
parents: 15057
diff changeset
87 silenttestrunner.main(__name__)