Mercurial > hg
comparison tests/test-manifest.py @ 32551:0ff336a42c39
tests: make test-manifest.py portable to Python 3
Lots of b prefixes here, and https://bugs.python.org/issue29714 means
that this test is still very broken on Python 3.6 and 3.6.1, but 3.6.2
should things (based on testing using tip of the 3.6 branch from git).
#cleanup-only
author | Augie Fackler <raf@durin42.com> |
---|---|
date | Sun, 28 May 2017 21:31:29 -0400 |
parents | 0048a852b6aa |
children | 58c1368ab629 |
comparison
equal
deleted
inserted
replaced
32550:b98199a5c3e1 | 32551:0ff336a42c39 |
---|---|
8 from mercurial import ( | 8 from mercurial import ( |
9 manifest as manifestmod, | 9 manifest as manifestmod, |
10 match as matchmod, | 10 match as matchmod, |
11 ) | 11 ) |
12 | 12 |
13 EMTPY_MANIFEST = '' | 13 EMTPY_MANIFEST = b'' |
14 EMTPY_MANIFEST_V2 = '\0\n' | 14 EMTPY_MANIFEST_V2 = b'\0\n' |
15 | 15 |
16 HASH_1 = '1' * 40 | 16 HASH_1 = b'1' * 40 |
17 BIN_HASH_1 = binascii.unhexlify(HASH_1) | 17 BIN_HASH_1 = binascii.unhexlify(HASH_1) |
18 HASH_2 = 'f' * 40 | 18 HASH_2 = b'f' * 40 |
19 BIN_HASH_2 = binascii.unhexlify(HASH_2) | 19 BIN_HASH_2 = binascii.unhexlify(HASH_2) |
20 HASH_3 = '1234567890abcdef0987654321deadbeef0fcafe' | 20 HASH_3 = b'1234567890abcdef0987654321deadbeef0fcafe' |
21 BIN_HASH_3 = binascii.unhexlify(HASH_3) | 21 BIN_HASH_3 = binascii.unhexlify(HASH_3) |
22 A_SHORT_MANIFEST = ( | 22 A_SHORT_MANIFEST = ( |
23 'bar/baz/qux.py\0%(hash2)s%(flag2)s\n' | 23 b'bar/baz/qux.py\0%(hash2)s%(flag2)s\n' |
24 'foo\0%(hash1)s%(flag1)s\n' | 24 b'foo\0%(hash1)s%(flag1)s\n' |
25 ) % {'hash1': HASH_1, | 25 ) % {b'hash1': HASH_1, |
26 'flag1': '', | 26 b'flag1': b'', |
27 'hash2': HASH_2, | 27 b'hash2': HASH_2, |
28 'flag2': 'l', | 28 b'flag2': b'l', |
29 } | 29 } |
30 | 30 |
31 # Same data as A_SHORT_MANIFEST | 31 # Same data as A_SHORT_MANIFEST |
32 A_SHORT_MANIFEST_V2 = ( | 32 A_SHORT_MANIFEST_V2 = ( |
33 '\0\n' | 33 b'\0\n' |
34 '\x00bar/baz/qux.py\0%(flag2)s\n%(hash2)s\n' | 34 b'\x00bar/baz/qux.py\0%(flag2)s\n%(hash2)s\n' |
35 '\x00foo\0%(flag1)s\n%(hash1)s\n' | 35 b'\x00foo\0%(flag1)s\n%(hash1)s\n' |
36 ) % {'hash1': BIN_HASH_1, | 36 ) % {b'hash1': BIN_HASH_1, |
37 'flag1': '', | 37 b'flag1': b'', |
38 'hash2': BIN_HASH_2, | 38 b'hash2': BIN_HASH_2, |
39 'flag2': 'l', | 39 b'flag2': b'l', |
40 } | 40 } |
41 | 41 |
42 # Same data as A_SHORT_MANIFEST | 42 # Same data as A_SHORT_MANIFEST |
43 A_METADATA_MANIFEST = ( | 43 A_METADATA_MANIFEST = ( |
44 '\0foo\0bar\n' | 44 b'\0foo\0bar\n' |
45 '\x00bar/baz/qux.py\0%(flag2)s\0foo\0bar\n%(hash2)s\n' # flag and metadata | 45 b'\x00bar/baz/qux.py\0%(flag2)s\0foo\0bar\n%(hash2)s\n' # flag and metadata |
46 '\x00foo\0%(flag1)s\0foo\n%(hash1)s\n' # no flag, but metadata | 46 b'\x00foo\0%(flag1)s\0foo\n%(hash1)s\n' # no flag, but metadata |
47 ) % {'hash1': BIN_HASH_1, | 47 ) % {b'hash1': BIN_HASH_1, |
48 'flag1': '', | 48 b'flag1': b'', |
49 'hash2': BIN_HASH_2, | 49 b'hash2': BIN_HASH_2, |
50 'flag2': 'l', | 50 b'flag2': b'l', |
51 } | 51 } |
52 | 52 |
53 A_STEM_COMPRESSED_MANIFEST = ( | 53 A_STEM_COMPRESSED_MANIFEST = ( |
54 '\0\n' | 54 b'\0\n' |
55 '\x00bar/baz/qux.py\0%(flag2)s\n%(hash2)s\n' | 55 b'\x00bar/baz/qux.py\0%(flag2)s\n%(hash2)s\n' |
56 '\x04qux/foo.py\0%(flag1)s\n%(hash1)s\n' # simple case of 4 stem chars | 56 b'\x04qux/foo.py\0%(flag1)s\n%(hash1)s\n' # simple case of 4 stem chars |
57 '\x0az.py\0%(flag1)s\n%(hash1)s\n' # tricky newline = 10 stem characters | 57 b'\x0az.py\0%(flag1)s\n%(hash1)s\n' # tricky newline = 10 stem characters |
58 '\x00%(verylongdir)sx/x\0\n%(hash1)s\n' | 58 b'\x00%(verylongdir)sx/x\0\n%(hash1)s\n' |
59 '\xffx/y\0\n%(hash2)s\n' # more than 255 stem chars | 59 b'\xffx/y\0\n%(hash2)s\n' # more than 255 stem chars |
60 ) % {'hash1': BIN_HASH_1, | 60 ) % {b'hash1': BIN_HASH_1, |
61 'flag1': '', | 61 b'flag1': b'', |
62 'hash2': BIN_HASH_2, | 62 b'hash2': BIN_HASH_2, |
63 'flag2': 'l', | 63 b'flag2': b'l', |
64 'verylongdir': 255 * 'x', | 64 b'verylongdir': 255 * b'x', |
65 } | 65 } |
66 | 66 |
67 A_DEEPER_MANIFEST = ( | 67 A_DEEPER_MANIFEST = ( |
68 'a/b/c/bar.py\0%(hash3)s%(flag1)s\n' | 68 b'a/b/c/bar.py\0%(hash3)s%(flag1)s\n' |
69 'a/b/c/bar.txt\0%(hash1)s%(flag1)s\n' | 69 b'a/b/c/bar.txt\0%(hash1)s%(flag1)s\n' |
70 'a/b/c/foo.py\0%(hash3)s%(flag1)s\n' | 70 b'a/b/c/foo.py\0%(hash3)s%(flag1)s\n' |
71 'a/b/c/foo.txt\0%(hash2)s%(flag2)s\n' | 71 b'a/b/c/foo.txt\0%(hash2)s%(flag2)s\n' |
72 'a/b/d/baz.py\0%(hash3)s%(flag1)s\n' | 72 b'a/b/d/baz.py\0%(hash3)s%(flag1)s\n' |
73 'a/b/d/qux.py\0%(hash1)s%(flag2)s\n' | 73 b'a/b/d/qux.py\0%(hash1)s%(flag2)s\n' |
74 'a/b/d/ten.txt\0%(hash3)s%(flag2)s\n' | 74 b'a/b/d/ten.txt\0%(hash3)s%(flag2)s\n' |
75 'a/b/dog.py\0%(hash3)s%(flag1)s\n' | 75 b'a/b/dog.py\0%(hash3)s%(flag1)s\n' |
76 'a/b/fish.py\0%(hash2)s%(flag1)s\n' | 76 b'a/b/fish.py\0%(hash2)s%(flag1)s\n' |
77 'a/c/london.py\0%(hash3)s%(flag2)s\n' | 77 b'a/c/london.py\0%(hash3)s%(flag2)s\n' |
78 'a/c/paper.txt\0%(hash2)s%(flag2)s\n' | 78 b'a/c/paper.txt\0%(hash2)s%(flag2)s\n' |
79 'a/c/paris.py\0%(hash2)s%(flag1)s\n' | 79 b'a/c/paris.py\0%(hash2)s%(flag1)s\n' |
80 'a/d/apple.py\0%(hash3)s%(flag1)s\n' | 80 b'a/d/apple.py\0%(hash3)s%(flag1)s\n' |
81 'a/d/pizza.py\0%(hash3)s%(flag2)s\n' | 81 b'a/d/pizza.py\0%(hash3)s%(flag2)s\n' |
82 'a/green.py\0%(hash1)s%(flag2)s\n' | 82 b'a/green.py\0%(hash1)s%(flag2)s\n' |
83 'a/purple.py\0%(hash2)s%(flag1)s\n' | 83 b'a/purple.py\0%(hash2)s%(flag1)s\n' |
84 'app.py\0%(hash3)s%(flag1)s\n' | 84 b'app.py\0%(hash3)s%(flag1)s\n' |
85 'readme.txt\0%(hash2)s%(flag1)s\n' | 85 b'readme.txt\0%(hash2)s%(flag1)s\n' |
86 ) % {'hash1': HASH_1, | 86 ) % {b'hash1': HASH_1, |
87 'flag1': '', | 87 b'flag1': b'', |
88 'hash2': HASH_2, | 88 b'hash2': HASH_2, |
89 'flag2': 'l', | 89 b'flag2': b'l', |
90 'hash3': HASH_3, | 90 b'hash3': HASH_3, |
91 } | 91 } |
92 | 92 |
93 HUGE_MANIFEST_ENTRIES = 200001 | 93 HUGE_MANIFEST_ENTRIES = 200001 |
94 | 94 |
95 izip = getattr(itertools, 'izip', zip) | 95 izip = getattr(itertools, 'izip', zip) |
96 if 'xrange' not in globals(): | 96 if 'xrange' not in globals(): |
97 xrange = range | 97 xrange = range |
98 | 98 |
99 A_HUGE_MANIFEST = ''.join(sorted( | 99 A_HUGE_MANIFEST = b''.join(sorted( |
100 'file%d\0%s%s\n' % (i, h, f) for i, h, f in | 100 b'file%d\0%s%s\n' % (i, h, f) for i, h, f in |
101 izip(xrange(200001), | 101 izip(xrange(200001), |
102 itertools.cycle((HASH_1, HASH_2)), | 102 itertools.cycle((HASH_1, HASH_2)), |
103 itertools.cycle(('', 'x', 'l'))))) | 103 itertools.cycle((b'', b'x', b'l'))))) |
104 | 104 |
105 class basemanifesttests(object): | 105 class basemanifesttests(object): |
106 def parsemanifest(self, text): | 106 def parsemanifest(self, text): |
107 raise NotImplementedError('parsemanifest not implemented by test case') | 107 raise NotImplementedError('parsemanifest not implemented by test case') |
108 | 108 |
116 self.assertEqual(0, len(m)) | 116 self.assertEqual(0, len(m)) |
117 self.assertEqual([], list(m)) | 117 self.assertEqual([], list(m)) |
118 | 118 |
119 def testManifest(self): | 119 def testManifest(self): |
120 m = self.parsemanifest(A_SHORT_MANIFEST) | 120 m = self.parsemanifest(A_SHORT_MANIFEST) |
121 self.assertEqual(['bar/baz/qux.py', 'foo'], list(m)) | 121 self.assertEqual([b'bar/baz/qux.py', b'foo'], list(m)) |
122 self.assertEqual(BIN_HASH_2, m['bar/baz/qux.py']) | 122 self.assertEqual(BIN_HASH_2, m[b'bar/baz/qux.py']) |
123 self.assertEqual('l', m.flags('bar/baz/qux.py')) | 123 self.assertEqual(b'l', m.flags(b'bar/baz/qux.py')) |
124 self.assertEqual(BIN_HASH_1, m['foo']) | 124 self.assertEqual(BIN_HASH_1, m[b'foo']) |
125 self.assertEqual('', m.flags('foo')) | 125 self.assertEqual(b'', m.flags(b'foo')) |
126 with self.assertRaises(KeyError): | 126 with self.assertRaises(KeyError): |
127 m['wat'] | 127 m[b'wat'] |
128 | 128 |
129 def testParseManifestV2(self): | 129 def testParseManifestV2(self): |
130 m1 = self.parsemanifest(A_SHORT_MANIFEST) | 130 m1 = self.parsemanifest(A_SHORT_MANIFEST) |
131 m2 = self.parsemanifest(A_SHORT_MANIFEST_V2) | 131 m2 = self.parsemanifest(A_SHORT_MANIFEST_V2) |
132 # Should have same content as A_SHORT_MANIFEST | 132 # Should have same content as A_SHORT_MANIFEST |
137 m = self.parsemanifest(A_METADATA_MANIFEST) | 137 m = self.parsemanifest(A_METADATA_MANIFEST) |
138 self.assertEqual(A_SHORT_MANIFEST, m.text()) | 138 self.assertEqual(A_SHORT_MANIFEST, m.text()) |
139 | 139 |
140 def testParseManifestStemCompression(self): | 140 def testParseManifestStemCompression(self): |
141 m = self.parsemanifest(A_STEM_COMPRESSED_MANIFEST) | 141 m = self.parsemanifest(A_STEM_COMPRESSED_MANIFEST) |
142 self.assertIn('bar/baz/qux.py', m) | 142 self.assertIn(b'bar/baz/qux.py', m) |
143 self.assertIn('bar/qux/foo.py', m) | 143 self.assertIn(b'bar/qux/foo.py', m) |
144 self.assertIn('bar/qux/foz.py', m) | 144 self.assertIn(b'bar/qux/foz.py', m) |
145 self.assertIn(256 * 'x' + '/x', m) | 145 self.assertIn(256 * b'x' + b'/x', m) |
146 self.assertIn(256 * 'x' + '/y', m) | 146 self.assertIn(256 * b'x' + b'/y', m) |
147 self.assertEqual(A_STEM_COMPRESSED_MANIFEST, m.text(usemanifestv2=True)) | 147 self.assertEqual(A_STEM_COMPRESSED_MANIFEST, m.text(usemanifestv2=True)) |
148 | 148 |
149 def testTextV2(self): | 149 def testTextV2(self): |
150 m1 = self.parsemanifest(A_SHORT_MANIFEST) | 150 m1 = self.parsemanifest(A_SHORT_MANIFEST) |
151 v2text = m1.text(usemanifestv2=True) | 151 v2text = m1.text(usemanifestv2=True) |
153 | 153 |
154 def testSetItem(self): | 154 def testSetItem(self): |
155 want = BIN_HASH_1 | 155 want = BIN_HASH_1 |
156 | 156 |
157 m = self.parsemanifest(EMTPY_MANIFEST) | 157 m = self.parsemanifest(EMTPY_MANIFEST) |
158 m['a'] = want | 158 m[b'a'] = want |
159 self.assertIn('a', m) | 159 self.assertIn(b'a', m) |
160 self.assertEqual(want, m['a']) | 160 self.assertEqual(want, m[b'a']) |
161 self.assertEqual('a\0' + HASH_1 + '\n', m.text()) | 161 self.assertEqual(b'a\0' + HASH_1 + b'\n', m.text()) |
162 | 162 |
163 m = self.parsemanifest(A_SHORT_MANIFEST) | 163 m = self.parsemanifest(A_SHORT_MANIFEST) |
164 m['a'] = want | 164 m[b'a'] = want |
165 self.assertEqual(want, m['a']) | 165 self.assertEqual(want, m[b'a']) |
166 self.assertEqual('a\0' + HASH_1 + '\n' + A_SHORT_MANIFEST, | 166 self.assertEqual(b'a\0' + HASH_1 + b'\n' + A_SHORT_MANIFEST, |
167 m.text()) | 167 m.text()) |
168 | 168 |
169 def testSetFlag(self): | 169 def testSetFlag(self): |
170 want = 'x' | 170 want = b'x' |
171 | 171 |
172 m = self.parsemanifest(EMTPY_MANIFEST) | 172 m = self.parsemanifest(EMTPY_MANIFEST) |
173 # first add a file; a file-less flag makes no sense | 173 # first add a file; a file-less flag makes no sense |
174 m['a'] = BIN_HASH_1 | 174 m[b'a'] = BIN_HASH_1 |
175 m.setflag('a', want) | 175 m.setflag(b'a', want) |
176 self.assertEqual(want, m.flags('a')) | 176 self.assertEqual(want, m.flags(b'a')) |
177 self.assertEqual('a\0' + HASH_1 + want + '\n', m.text()) | 177 self.assertEqual(b'a\0' + HASH_1 + want + b'\n', m.text()) |
178 | 178 |
179 m = self.parsemanifest(A_SHORT_MANIFEST) | 179 m = self.parsemanifest(A_SHORT_MANIFEST) |
180 # first add a file; a file-less flag makes no sense | 180 # first add a file; a file-less flag makes no sense |
181 m['a'] = BIN_HASH_1 | 181 m[b'a'] = BIN_HASH_1 |
182 m.setflag('a', want) | 182 m.setflag(b'a', want) |
183 self.assertEqual(want, m.flags('a')) | 183 self.assertEqual(want, m.flags(b'a')) |
184 self.assertEqual('a\0' + HASH_1 + want + '\n' + A_SHORT_MANIFEST, | 184 self.assertEqual(b'a\0' + HASH_1 + want + b'\n' + A_SHORT_MANIFEST, |
185 m.text()) | 185 m.text()) |
186 | 186 |
187 def testCopy(self): | 187 def testCopy(self): |
188 m = self.parsemanifest(A_SHORT_MANIFEST) | 188 m = self.parsemanifest(A_SHORT_MANIFEST) |
189 m['a'] = BIN_HASH_1 | 189 m[b'a'] = BIN_HASH_1 |
190 m2 = m.copy() | 190 m2 = m.copy() |
191 del m | 191 del m |
192 del m2 # make sure we don't double free() anything | 192 del m2 # make sure we don't double free() anything |
193 | 193 |
194 def testCompaction(self): | 194 def testCompaction(self): |
195 unhex = binascii.unhexlify | 195 unhex = binascii.unhexlify |
196 h1, h2 = unhex(HASH_1), unhex(HASH_2) | 196 h1, h2 = unhex(HASH_1), unhex(HASH_2) |
197 m = self.parsemanifest(A_SHORT_MANIFEST) | 197 m = self.parsemanifest(A_SHORT_MANIFEST) |
198 m['alpha'] = h1 | 198 m[b'alpha'] = h1 |
199 m['beta'] = h2 | 199 m[b'beta'] = h2 |
200 del m['foo'] | 200 del m[b'foo'] |
201 want = 'alpha\0%s\nbar/baz/qux.py\0%sl\nbeta\0%s\n' % ( | 201 want = b'alpha\0%s\nbar/baz/qux.py\0%sl\nbeta\0%s\n' % ( |
202 HASH_1, HASH_2, HASH_2) | 202 HASH_1, HASH_2, HASH_2) |
203 self.assertEqual(want, m.text()) | 203 self.assertEqual(want, m.text()) |
204 self.assertEqual(3, len(m)) | 204 self.assertEqual(3, len(m)) |
205 self.assertEqual(['alpha', 'bar/baz/qux.py', 'beta'], list(m)) | 205 self.assertEqual([b'alpha', b'bar/baz/qux.py', b'beta'], list(m)) |
206 self.assertEqual(h1, m['alpha']) | 206 self.assertEqual(h1, m[b'alpha']) |
207 self.assertEqual(h2, m['bar/baz/qux.py']) | 207 self.assertEqual(h2, m[b'bar/baz/qux.py']) |
208 self.assertEqual(h2, m['beta']) | 208 self.assertEqual(h2, m[b'beta']) |
209 self.assertEqual('', m.flags('alpha')) | 209 self.assertEqual(b'', m.flags(b'alpha')) |
210 self.assertEqual('l', m.flags('bar/baz/qux.py')) | 210 self.assertEqual(b'l', m.flags(b'bar/baz/qux.py')) |
211 self.assertEqual('', m.flags('beta')) | 211 self.assertEqual(b'', m.flags(b'beta')) |
212 with self.assertRaises(KeyError): | 212 with self.assertRaises(KeyError): |
213 m['foo'] | 213 m[b'foo'] |
214 | 214 |
215 def testSetGetNodeSuffix(self): | 215 def testSetGetNodeSuffix(self): |
216 clean = self.parsemanifest(A_SHORT_MANIFEST) | 216 clean = self.parsemanifest(A_SHORT_MANIFEST) |
217 m = self.parsemanifest(A_SHORT_MANIFEST) | 217 m = self.parsemanifest(A_SHORT_MANIFEST) |
218 h = m['foo'] | 218 h = m[b'foo'] |
219 f = m.flags('foo') | 219 f = m.flags(b'foo') |
220 want = h + 'a' | 220 want = h + b'a' |
221 # Merge code wants to set 21-byte fake hashes at times | 221 # Merge code wants to set 21-byte fake hashes at times |
222 m['foo'] = want | 222 m[b'foo'] = want |
223 self.assertEqual(want, m['foo']) | 223 self.assertEqual(want, m[b'foo']) |
224 self.assertEqual([('bar/baz/qux.py', BIN_HASH_2), | 224 self.assertEqual([(b'bar/baz/qux.py', BIN_HASH_2), |
225 ('foo', BIN_HASH_1 + 'a')], | 225 (b'foo', BIN_HASH_1 + b'a')], |
226 list(m.iteritems())) | 226 list(m.iteritems())) |
227 # Sometimes it even tries a 22-byte fake hash, but we can | 227 # Sometimes it even tries a 22-byte fake hash, but we can |
228 # return 21 and it'll work out | 228 # return 21 and it'll work out |
229 m['foo'] = want + '+' | 229 m[b'foo'] = want + b'+' |
230 self.assertEqual(want, m['foo']) | 230 self.assertEqual(want, m[b'foo']) |
231 # make sure the suffix survives a copy | 231 # make sure the suffix survives a copy |
232 match = matchmod.match('', '', ['re:foo']) | 232 match = matchmod.match(b'', b'', [b're:foo']) |
233 m2 = m.matches(match) | 233 m2 = m.matches(match) |
234 self.assertEqual(want, m2['foo']) | 234 self.assertEqual(want, m2[b'foo']) |
235 self.assertEqual(1, len(m2)) | 235 self.assertEqual(1, len(m2)) |
236 m2 = m.copy() | 236 m2 = m.copy() |
237 self.assertEqual(want, m2['foo']) | 237 self.assertEqual(want, m2[b'foo']) |
238 # suffix with iteration | 238 # suffix with iteration |
239 self.assertEqual([('bar/baz/qux.py', BIN_HASH_2), | 239 self.assertEqual([(b'bar/baz/qux.py', BIN_HASH_2), |
240 ('foo', want)], | 240 (b'foo', want)], |
241 list(m.iteritems())) | 241 list(m.iteritems())) |
242 | 242 |
243 # shows up in diff | 243 # shows up in diff |
244 self.assertEqual({'foo': ((want, f), (h, ''))}, m.diff(clean)) | 244 self.assertEqual({b'foo': ((want, f), (h, b''))}, m.diff(clean)) |
245 self.assertEqual({'foo': ((h, ''), (want, f))}, clean.diff(m)) | 245 self.assertEqual({b'foo': ((h, b''), (want, f))}, clean.diff(m)) |
246 | 246 |
247 def testMatchException(self): | 247 def testMatchException(self): |
248 m = self.parsemanifest(A_SHORT_MANIFEST) | 248 m = self.parsemanifest(A_SHORT_MANIFEST) |
249 match = matchmod.match('', '', ['re:.*']) | 249 match = matchmod.match(b'', b'', [b're:.*']) |
250 def filt(path): | 250 def filt(path): |
251 if path == 'foo': | 251 if path == b'foo': |
252 assert False | 252 assert False |
253 return True | 253 return True |
254 match.matchfn = filt | 254 match.matchfn = filt |
255 with self.assertRaises(AssertionError): | 255 with self.assertRaises(AssertionError): |
256 m.matches(match) | 256 m.matches(match) |
257 | 257 |
258 def testRemoveItem(self): | 258 def testRemoveItem(self): |
259 m = self.parsemanifest(A_SHORT_MANIFEST) | 259 m = self.parsemanifest(A_SHORT_MANIFEST) |
260 del m['foo'] | 260 del m[b'foo'] |
261 with self.assertRaises(KeyError): | 261 with self.assertRaises(KeyError): |
262 m['foo'] | 262 m[b'foo'] |
263 self.assertEqual(1, len(m)) | 263 self.assertEqual(1, len(m)) |
264 self.assertEqual(1, len(list(m))) | 264 self.assertEqual(1, len(list(m))) |
265 # now restore and make sure everything works right | 265 # now restore and make sure everything works right |
266 m['foo'] = 'a' * 20 | 266 m[b'foo'] = b'a' * 20 |
267 self.assertEqual(2, len(m)) | 267 self.assertEqual(2, len(m)) |
268 self.assertEqual(2, len(list(m))) | 268 self.assertEqual(2, len(list(m))) |
269 | 269 |
270 def testManifestDiff(self): | 270 def testManifestDiff(self): |
271 MISSING = (None, '') | 271 MISSING = (None, b'') |
272 addl = 'z-only-in-left\0' + HASH_1 + '\n' | 272 addl = b'z-only-in-left\0' + HASH_1 + b'\n' |
273 addr = 'z-only-in-right\0' + HASH_2 + 'x\n' | 273 addr = b'z-only-in-right\0' + HASH_2 + b'x\n' |
274 left = self.parsemanifest( | 274 left = self.parsemanifest( |
275 A_SHORT_MANIFEST.replace(HASH_1, HASH_3 + 'x') + addl) | 275 A_SHORT_MANIFEST.replace(HASH_1, HASH_3 + b'x') + addl) |
276 right = self.parsemanifest(A_SHORT_MANIFEST + addr) | 276 right = self.parsemanifest(A_SHORT_MANIFEST + addr) |
277 want = { | 277 want = { |
278 'foo': ((BIN_HASH_3, 'x'), | 278 b'foo': ((BIN_HASH_3, b'x'), |
279 (BIN_HASH_1, '')), | 279 (BIN_HASH_1, b'')), |
280 'z-only-in-left': ((BIN_HASH_1, ''), MISSING), | 280 b'z-only-in-left': ((BIN_HASH_1, b''), MISSING), |
281 'z-only-in-right': (MISSING, (BIN_HASH_2, 'x')), | 281 b'z-only-in-right': (MISSING, (BIN_HASH_2, b'x')), |
282 } | 282 } |
283 self.assertEqual(want, left.diff(right)) | 283 self.assertEqual(want, left.diff(right)) |
284 | 284 |
285 want = { | 285 want = { |
286 'bar/baz/qux.py': (MISSING, (BIN_HASH_2, 'l')), | 286 b'bar/baz/qux.py': (MISSING, (BIN_HASH_2, b'l')), |
287 'foo': (MISSING, (BIN_HASH_3, 'x')), | 287 b'foo': (MISSING, (BIN_HASH_3, b'x')), |
288 'z-only-in-left': (MISSING, (BIN_HASH_1, '')), | 288 b'z-only-in-left': (MISSING, (BIN_HASH_1, b'')), |
289 } | 289 } |
290 self.assertEqual(want, self.parsemanifest(EMTPY_MANIFEST).diff(left)) | 290 self.assertEqual(want, self.parsemanifest(EMTPY_MANIFEST).diff(left)) |
291 | 291 |
292 want = { | 292 want = { |
293 'bar/baz/qux.py': ((BIN_HASH_2, 'l'), MISSING), | 293 b'bar/baz/qux.py': ((BIN_HASH_2, b'l'), MISSING), |
294 'foo': ((BIN_HASH_3, 'x'), MISSING), | 294 b'foo': ((BIN_HASH_3, b'x'), MISSING), |
295 'z-only-in-left': ((BIN_HASH_1, ''), MISSING), | 295 b'z-only-in-left': ((BIN_HASH_1, b''), MISSING), |
296 } | 296 } |
297 self.assertEqual(want, left.diff(self.parsemanifest(EMTPY_MANIFEST))) | 297 self.assertEqual(want, left.diff(self.parsemanifest(EMTPY_MANIFEST))) |
298 copy = right.copy() | 298 copy = right.copy() |
299 del copy['z-only-in-right'] | 299 del copy[b'z-only-in-right'] |
300 del right['foo'] | 300 del right[b'foo'] |
301 want = { | 301 want = { |
302 'foo': (MISSING, (BIN_HASH_1, '')), | 302 b'foo': (MISSING, (BIN_HASH_1, b'')), |
303 'z-only-in-right': ((BIN_HASH_2, 'x'), MISSING), | 303 b'z-only-in-right': ((BIN_HASH_2, b'x'), MISSING), |
304 } | 304 } |
305 self.assertEqual(want, right.diff(copy)) | 305 self.assertEqual(want, right.diff(copy)) |
306 | 306 |
307 short = self.parsemanifest(A_SHORT_MANIFEST) | 307 short = self.parsemanifest(A_SHORT_MANIFEST) |
308 pruned = short.copy() | 308 pruned = short.copy() |
309 del pruned['foo'] | 309 del pruned[b'foo'] |
310 want = { | 310 want = { |
311 'foo': ((BIN_HASH_1, ''), MISSING), | 311 b'foo': ((BIN_HASH_1, b''), MISSING), |
312 } | 312 } |
313 self.assertEqual(want, short.diff(pruned)) | 313 self.assertEqual(want, short.diff(pruned)) |
314 want = { | 314 want = { |
315 'foo': (MISSING, (BIN_HASH_1, '')), | 315 b'foo': (MISSING, (BIN_HASH_1, b'')), |
316 } | 316 } |
317 self.assertEqual(want, pruned.diff(short)) | 317 self.assertEqual(want, pruned.diff(short)) |
318 want = { | 318 want = { |
319 'bar/baz/qux.py': None, | 319 b'bar/baz/qux.py': None, |
320 'foo': (MISSING, (BIN_HASH_1, '')), | 320 b'foo': (MISSING, (BIN_HASH_1, b'')), |
321 } | 321 } |
322 self.assertEqual(want, pruned.diff(short, clean=True)) | 322 self.assertEqual(want, pruned.diff(short, clean=True)) |
323 | 323 |
324 def testReversedLines(self): | 324 def testReversedLines(self): |
325 backwards = ''.join( | 325 backwards = b''.join( |
326 l + '\n' for l in reversed(A_SHORT_MANIFEST.split('\n')) if l) | 326 l + b'\n' for l in reversed(A_SHORT_MANIFEST.split(b'\n')) if l) |
327 try: | 327 try: |
328 self.parsemanifest(backwards) | 328 self.parsemanifest(backwards) |
329 self.fail('Should have raised ValueError') | 329 self.fail('Should have raised ValueError') |
330 except ValueError as v: | 330 except ValueError as v: |
331 self.assertIn('Manifest lines not in sorted order.', str(v)) | 331 self.assertIn('Manifest lines not in sorted order.', str(v)) |
332 | 332 |
333 def testNoTerminalNewline(self): | 333 def testNoTerminalNewline(self): |
334 try: | 334 try: |
335 self.parsemanifest(A_SHORT_MANIFEST + 'wat') | 335 self.parsemanifest(A_SHORT_MANIFEST + b'wat') |
336 self.fail('Should have raised ValueError') | 336 self.fail('Should have raised ValueError') |
337 except ValueError as v: | 337 except ValueError as v: |
338 self.assertIn('Manifest did not end in a newline.', str(v)) | 338 self.assertIn('Manifest did not end in a newline.', str(v)) |
339 | 339 |
340 def testNoNewLineAtAll(self): | 340 def testNoNewLineAtAll(self): |
341 try: | 341 try: |
342 self.parsemanifest('wat') | 342 self.parsemanifest(b'wat') |
343 self.fail('Should have raised ValueError') | 343 self.fail('Should have raised ValueError') |
344 except ValueError as v: | 344 except ValueError as v: |
345 self.assertIn('Manifest did not end in a newline.', str(v)) | 345 self.assertIn('Manifest did not end in a newline.', str(v)) |
346 | 346 |
347 def testHugeManifest(self): | 347 def testHugeManifest(self): |
353 '''Tests matches() for a few specific files to make sure that both | 353 '''Tests matches() for a few specific files to make sure that both |
354 the set of files as well as their flags and nodeids are correct in | 354 the set of files as well as their flags and nodeids are correct in |
355 the resulting manifest.''' | 355 the resulting manifest.''' |
356 m = self.parsemanifest(A_HUGE_MANIFEST) | 356 m = self.parsemanifest(A_HUGE_MANIFEST) |
357 | 357 |
358 match = matchmod.match('/', '', | 358 match = matchmod.match(b'/', b'', |
359 ['file1', 'file200', 'file300'], exact=True) | 359 [b'file1', b'file200', b'file300'], exact=True) |
360 m2 = m.matches(match) | 360 m2 = m.matches(match) |
361 | 361 |
362 w = ('file1\0%sx\n' | 362 w = (b'file1\0%sx\n' |
363 'file200\0%sl\n' | 363 b'file200\0%sl\n' |
364 'file300\0%s\n') % (HASH_2, HASH_1, HASH_1) | 364 b'file300\0%s\n') % (HASH_2, HASH_1, HASH_1) |
365 self.assertEqual(w, m2.text()) | 365 self.assertEqual(w, m2.text()) |
366 | 366 |
367 def testMatchesNonexistentFile(self): | 367 def testMatchesNonexistentFile(self): |
368 '''Tests matches() for a small set of specific files, including one | 368 '''Tests matches() for a small set of specific files, including one |
369 nonexistent file to make sure in only matches against existing files. | 369 nonexistent file to make sure in only matches against existing files. |
370 ''' | 370 ''' |
371 m = self.parsemanifest(A_DEEPER_MANIFEST) | 371 m = self.parsemanifest(A_DEEPER_MANIFEST) |
372 | 372 |
373 match = matchmod.match('/', '', | 373 match = matchmod.match(b'/', b'', |
374 ['a/b/c/bar.txt', 'a/b/d/qux.py', 'readme.txt', 'nonexistent'], | 374 [b'a/b/c/bar.txt', b'a/b/d/qux.py', |
375 b'readme.txt', b'nonexistent'], | |
375 exact=True) | 376 exact=True) |
376 m2 = m.matches(match) | 377 m2 = m.matches(match) |
377 | 378 |
378 self.assertEqual( | 379 self.assertEqual( |
379 ['a/b/c/bar.txt', 'a/b/d/qux.py', 'readme.txt'], | 380 [b'a/b/c/bar.txt', b'a/b/d/qux.py', b'readme.txt'], |
380 m2.keys()) | 381 m2.keys()) |
381 | 382 |
382 def testMatchesNonexistentDirectory(self): | 383 def testMatchesNonexistentDirectory(self): |
383 '''Tests matches() for a relpath match on a directory that doesn't | 384 '''Tests matches() for a relpath match on a directory that doesn't |
384 actually exist.''' | 385 actually exist.''' |
385 m = self.parsemanifest(A_DEEPER_MANIFEST) | 386 m = self.parsemanifest(A_DEEPER_MANIFEST) |
386 | 387 |
387 match = matchmod.match('/', '', ['a/f'], default='relpath') | 388 match = matchmod.match(b'/', b'', [b'a/f'], default=b'relpath') |
388 m2 = m.matches(match) | 389 m2 = m.matches(match) |
389 | 390 |
390 self.assertEqual([], m2.keys()) | 391 self.assertEqual([], m2.keys()) |
391 | 392 |
392 def testMatchesExactLarge(self): | 393 def testMatchesExactLarge(self): |
393 '''Tests matches() for files matching a large list of exact files. | 394 '''Tests matches() for files matching a large list of exact files. |
394 ''' | 395 ''' |
395 m = self.parsemanifest(A_HUGE_MANIFEST) | 396 m = self.parsemanifest(A_HUGE_MANIFEST) |
396 | 397 |
397 flist = m.keys()[80:300] | 398 flist = m.keys()[80:300] |
398 match = matchmod.match('/', '', flist, exact=True) | 399 match = matchmod.match(b'/', b'', flist, exact=True) |
399 m2 = m.matches(match) | 400 m2 = m.matches(match) |
400 | 401 |
401 self.assertEqual(flist, m2.keys()) | 402 self.assertEqual(flist, m2.keys()) |
402 | 403 |
403 def testMatchesFull(self): | 404 def testMatchesFull(self): |
404 '''Tests matches() for what should be a full match.''' | 405 '''Tests matches() for what should be a full match.''' |
405 m = self.parsemanifest(A_DEEPER_MANIFEST) | 406 m = self.parsemanifest(A_DEEPER_MANIFEST) |
406 | 407 |
407 match = matchmod.match('/', '', ['']) | 408 match = matchmod.match(b'/', b'', [b'']) |
408 m2 = m.matches(match) | 409 m2 = m.matches(match) |
409 | 410 |
410 self.assertEqual(m.keys(), m2.keys()) | 411 self.assertEqual(m.keys(), m2.keys()) |
411 | 412 |
412 def testMatchesDirectory(self): | 413 def testMatchesDirectory(self): |
413 '''Tests matches() on a relpath match on a directory, which should | 414 '''Tests matches() on a relpath match on a directory, which should |
414 match against all files within said directory.''' | 415 match against all files within said directory.''' |
415 m = self.parsemanifest(A_DEEPER_MANIFEST) | 416 m = self.parsemanifest(A_DEEPER_MANIFEST) |
416 | 417 |
417 match = matchmod.match('/', '', ['a/b'], default='relpath') | 418 match = matchmod.match(b'/', b'', [b'a/b'], default=b'relpath') |
418 m2 = m.matches(match) | 419 m2 = m.matches(match) |
419 | 420 |
420 self.assertEqual([ | 421 self.assertEqual([ |
421 'a/b/c/bar.py', 'a/b/c/bar.txt', 'a/b/c/foo.py', 'a/b/c/foo.txt', | 422 b'a/b/c/bar.py', b'a/b/c/bar.txt', b'a/b/c/foo.py', |
422 'a/b/d/baz.py', 'a/b/d/qux.py', 'a/b/d/ten.txt', 'a/b/dog.py', | 423 b'a/b/c/foo.txt', |
423 'a/b/fish.py'], m2.keys()) | 424 b'a/b/d/baz.py', b'a/b/d/qux.py', b'a/b/d/ten.txt', b'a/b/dog.py', |
425 b'a/b/fish.py'], m2.keys()) | |
424 | 426 |
425 def testMatchesExactPath(self): | 427 def testMatchesExactPath(self): |
426 '''Tests matches() on an exact match on a directory, which should | 428 '''Tests matches() on an exact match on a directory, which should |
427 result in an empty manifest because you can't perform an exact match | 429 result in an empty manifest because you can't perform an exact match |
428 against a directory.''' | 430 against a directory.''' |
429 m = self.parsemanifest(A_DEEPER_MANIFEST) | 431 m = self.parsemanifest(A_DEEPER_MANIFEST) |
430 | 432 |
431 match = matchmod.match('/', '', ['a/b'], exact=True) | 433 match = matchmod.match(b'/', b'', [b'a/b'], exact=True) |
432 m2 = m.matches(match) | 434 m2 = m.matches(match) |
433 | 435 |
434 self.assertEqual([], m2.keys()) | 436 self.assertEqual([], m2.keys()) |
435 | 437 |
436 def testMatchesCwd(self): | 438 def testMatchesCwd(self): |
437 '''Tests matches() on a relpath match with the current directory ('.') | 439 '''Tests matches() on a relpath match with the current directory ('.') |
438 when not in the root directory.''' | 440 when not in the root directory.''' |
439 m = self.parsemanifest(A_DEEPER_MANIFEST) | 441 m = self.parsemanifest(A_DEEPER_MANIFEST) |
440 | 442 |
441 match = matchmod.match('/', 'a/b', ['.'], default='relpath') | 443 match = matchmod.match(b'/', b'a/b', [b'.'], default=b'relpath') |
442 m2 = m.matches(match) | 444 m2 = m.matches(match) |
443 | 445 |
444 self.assertEqual([ | 446 self.assertEqual([ |
445 'a/b/c/bar.py', 'a/b/c/bar.txt', 'a/b/c/foo.py', 'a/b/c/foo.txt', | 447 b'a/b/c/bar.py', b'a/b/c/bar.txt', b'a/b/c/foo.py', |
446 'a/b/d/baz.py', 'a/b/d/qux.py', 'a/b/d/ten.txt', 'a/b/dog.py', | 448 b'a/b/c/foo.txt', b'a/b/d/baz.py', b'a/b/d/qux.py', |
447 'a/b/fish.py'], m2.keys()) | 449 b'a/b/d/ten.txt', b'a/b/dog.py', b'a/b/fish.py'], m2.keys()) |
448 | 450 |
449 def testMatchesWithPattern(self): | 451 def testMatchesWithPattern(self): |
450 '''Tests matches() for files matching a pattern that reside | 452 '''Tests matches() for files matching a pattern that reside |
451 deeper than the specified directory.''' | 453 deeper than the specified directory.''' |
452 m = self.parsemanifest(A_DEEPER_MANIFEST) | 454 m = self.parsemanifest(A_DEEPER_MANIFEST) |
453 | 455 |
454 match = matchmod.match('/', '', ['a/b/*/*.txt']) | 456 match = matchmod.match(b'/', b'', [b'a/b/*/*.txt']) |
455 m2 = m.matches(match) | 457 m2 = m.matches(match) |
456 | 458 |
457 self.assertEqual( | 459 self.assertEqual( |
458 ['a/b/c/bar.txt', 'a/b/c/foo.txt', 'a/b/d/ten.txt'], | 460 [b'a/b/c/bar.txt', b'a/b/c/foo.txt', b'a/b/d/ten.txt'], |
459 m2.keys()) | 461 m2.keys()) |
460 | 462 |
461 class testmanifestdict(unittest.TestCase, basemanifesttests): | 463 class testmanifestdict(unittest.TestCase, basemanifesttests): |
462 def parsemanifest(self, text): | 464 def parsemanifest(self, text): |
463 return manifestmod.manifestdict(text) | 465 return manifestmod.manifestdict(text) |
464 | 466 |
465 class testtreemanifest(unittest.TestCase, basemanifesttests): | 467 class testtreemanifest(unittest.TestCase, basemanifesttests): |
466 def parsemanifest(self, text): | 468 def parsemanifest(self, text): |
467 return manifestmod.treemanifest('', text) | 469 return manifestmod.treemanifest(b'', text) |
468 | 470 |
469 def testWalkSubtrees(self): | 471 def testWalkSubtrees(self): |
470 m = self.parsemanifest(A_DEEPER_MANIFEST) | 472 m = self.parsemanifest(A_DEEPER_MANIFEST) |
471 | 473 |
472 dirs = [s._dir for s in m.walksubtrees()] | 474 dirs = [s._dir for s in m.walksubtrees()] |
473 self.assertEqual( | 475 self.assertEqual( |
474 sorted(['', 'a/', 'a/c/', 'a/d/', 'a/b/', 'a/b/c/', 'a/b/d/']), | 476 sorted([ |
477 b'', b'a/', b'a/c/', b'a/d/', b'a/b/', b'a/b/c/', b'a/b/d/']), | |
475 sorted(dirs) | 478 sorted(dirs) |
476 ) | 479 ) |
477 | 480 |
478 match = matchmod.match('/', '', ['path:a/b/']) | 481 match = matchmod.match(b'/', b'', [b'path:a/b/']) |
479 dirs = [s._dir for s in m.walksubtrees(matcher=match)] | 482 dirs = [s._dir for s in m.walksubtrees(matcher=match)] |
480 self.assertEqual( | 483 self.assertEqual( |
481 sorted(['a/b/', 'a/b/c/', 'a/b/d/']), | 484 sorted([b'a/b/', b'a/b/c/', b'a/b/d/']), |
482 sorted(dirs) | 485 sorted(dirs) |
483 ) | 486 ) |
484 | 487 |
485 if __name__ == '__main__': | 488 if __name__ == '__main__': |
486 silenttestrunner.main(__name__) | 489 silenttestrunner.main(__name__) |