comparison hgext3rd/fastimport/vendor/python_fastimport/tests/test_parser.py @ 86:28704a2a7461 vendor/python-fastimport

Import python-fastimport-0.9.8
author Roy Marples <roy@marples.name>
date Tue, 19 Jan 2021 22:56:34 +0000
parents
children
comparison
equal deleted inserted replaced
85:1f5544a8870b 86:28704a2a7461
1 # Copyright (C) 2008 Canonical Ltd
2 #
3 # This program is free software; you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation; either version 2 of the License, or
6 # (at your option) any later version.
7 #
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
12 #
13 # You should have received a copy of the GNU General Public License
14 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
16 """Test the Import parsing"""
17 import io
18 import time
19 import unittest
20
21 from fastimport import (
22 commands,
23 errors,
24 parser,
25 )
26
27
28 class TestLineBasedParser(unittest.TestCase):
29
30 def test_push_line(self):
31 s = io.BytesIO(b"foo\nbar\nbaz\n")
32 p = parser.LineBasedParser(s)
33 self.assertEqual(b'foo', p.next_line())
34 self.assertEqual(b'bar', p.next_line())
35 p.push_line(b'bar')
36 self.assertEqual(b'bar', p.next_line())
37 self.assertEqual(b'baz', p.next_line())
38 self.assertEqual(None, p.next_line())
39
40 def test_read_bytes(self):
41 s = io.BytesIO(b"foo\nbar\nbaz\n")
42 p = parser.LineBasedParser(s)
43 self.assertEqual(b'fo', p.read_bytes(2))
44 self.assertEqual(b'o\nb', p.read_bytes(3))
45 self.assertEqual(b'ar', p.next_line())
46 # Test that the line buffer is ignored
47 p.push_line(b'bar')
48 self.assertEqual(b'baz', p.read_bytes(3))
49 # Test missing bytes
50 self.assertRaises(errors.MissingBytes, p.read_bytes, 10)
51
52 def test_read_until(self):
53 # TODO
54 return
55 s = io.BytesIO(b"foo\nbar\nbaz\nabc\ndef\nghi\n")
56 p = parser.LineBasedParser(s)
57 self.assertEqual(b'foo\nbar', p.read_until(b'baz'))
58 self.assertEqual(b'abc', p.next_line())
59 # Test that the line buffer is ignored
60 p.push_line(b'abc')
61 self.assertEqual(b'def', p.read_until(b'ghi'))
62 # Test missing terminator
63 self.assertRaises(errors.MissingTerminator, p.read_until(b'>>>'))
64
65
66 # Sample text
67 _sample_import_text = b"""
68 progress completed
69 # Test blob formats
70 blob
71 mark :1
72 data 4
73 aaaablob
74 data 5
75 bbbbb
76 # Commit formats
77 commit refs/heads/master
78 mark :2
79 committer bugs bunny <bugs@bunny.org> now
80 data 14
81 initial import
82 M 644 inline README
83 data 18
84 Welcome from bugs
85 commit refs/heads/master
86 committer <bugs@bunny.org> now
87 data 13
88 second commit
89 from :2
90 M 644 inline README
91 data 23
92 Welcome from bugs, etc.
93 # Miscellaneous
94 checkpoint
95 progress completed
96 # Test a commit without sub-commands (bug #351717)
97 commit refs/heads/master
98 mark :3
99 author <bugs@bunny.org> now
100 committer <bugs@bunny.org> now
101 data 20
102 first commit, empty
103 # Test a commit with a heredoc-style (delimited_data) messsage (bug #400960)
104 commit refs/heads/master
105 mark :4
106 author <bugs@bunny.org> now
107 committer <bugs@bunny.org> now
108 data <<EOF
109 Commit with heredoc-style message
110 EOF
111 # Test a "submodule"/tree-reference
112 commit refs/heads/master
113 mark :5
114 author <bugs@bunny.org> now
115 committer <bugs@bunny.org> now
116 data 15
117 submodule test
118 M 160000 rev-id tree-id
119 # Test features
120 feature whatever
121 feature foo=bar
122 # Test commit with properties
123 commit refs/heads/master
124 mark :6
125 committer <bugs@bunny.org> now
126 data 18
127 test of properties
128 property p1
129 property p2 5 hohum
130 property p3 16 alpha
131 beta
132 gamma
133 property p4 8 whatever
134 # Test a commit with multiple authors
135 commit refs/heads/master
136 mark :7
137 author Fluffy <fluffy@bunny.org> now
138 author Daffy <daffy@duck.org> now
139 author Donald <donald@duck.org> now
140 committer <bugs@bunny.org> now
141 data 17
142 multi-author test
143 """
144
145 _timefunc = time.time
146 class TestImportParser(unittest.TestCase):
147 def setUp(self):
148 self.fake_time = 42.0123
149 time.time = lambda: self.fake_time
150 def tearDown(self):
151 time.time = _timefunc
152 del self.fake_time
153
154 def test_iter_commands(self):
155 s = io.BytesIO(_sample_import_text)
156 p = parser.ImportParser(s)
157 result = []
158 for cmd in p.iter_commands():
159 result.append(cmd)
160 if cmd.name == b'commit':
161 for fc in cmd.iter_files():
162 result.append(fc)
163
164 self.assertEqual(len(result), 17)
165 cmd1 = result.pop(0)
166 self.assertEqual(b'progress', cmd1.name)
167 self.assertEqual(b'completed', cmd1.message)
168 cmd2 = result.pop(0)
169 self.assertEqual(b'blob', cmd2.name)
170 self.assertEqual(b'1', cmd2.mark)
171 self.assertEqual(b':1', cmd2.id)
172 self.assertEqual(b'aaaa', cmd2.data)
173 self.assertEqual(4, cmd2.lineno)
174 cmd3 = result.pop(0)
175 self.assertEqual(b'blob', cmd3.name)
176 self.assertEqual(b'@7', cmd3.id)
177 self.assertEqual(None, cmd3.mark)
178 self.assertEqual(b'bbbbb', cmd3.data)
179 self.assertEqual(7, cmd3.lineno)
180 cmd4 = result.pop(0)
181 self.assertEqual(b'commit', cmd4.name)
182 self.assertEqual(b'2', cmd4.mark)
183 self.assertEqual(b':2', cmd4.id)
184 self.assertEqual(b'initial import', cmd4.message)
185
186 self.assertEqual((b'bugs bunny', b'bugs@bunny.org', self.fake_time, 0), cmd4.committer)
187 # namedtuple attributes
188 self.assertEqual(b'bugs bunny', cmd4.committer.name)
189 self.assertEqual(b'bugs@bunny.org', cmd4.committer.email)
190 self.assertEqual(self.fake_time, cmd4.committer.timestamp)
191 self.assertEqual(0, cmd4.committer.timezone)
192
193 self.assertEqual(None, cmd4.author)
194 self.assertEqual(11, cmd4.lineno)
195 self.assertEqual(b'refs/heads/master', cmd4.ref)
196 self.assertEqual(None, cmd4.from_)
197 self.assertEqual([], cmd4.merges)
198 file_cmd1 = result.pop(0)
199 self.assertEqual(b'filemodify', file_cmd1.name)
200 self.assertEqual(b'README', file_cmd1.path)
201 self.assertEqual(0o100644, file_cmd1.mode)
202 self.assertEqual(b'Welcome from bugs\n', file_cmd1.data)
203 cmd5 = result.pop(0)
204 self.assertEqual(b'commit', cmd5.name)
205 self.assertEqual(None, cmd5.mark)
206 self.assertEqual(b'@19', cmd5.id)
207 self.assertEqual(b'second commit', cmd5.message)
208 self.assertEqual((b'', b'bugs@bunny.org', self.fake_time, 0), cmd5.committer)
209 self.assertEqual(None, cmd5.author)
210 self.assertEqual(19, cmd5.lineno)
211 self.assertEqual(b'refs/heads/master', cmd5.ref)
212 self.assertEqual(b':2', cmd5.from_)
213 self.assertEqual([], cmd5.merges)
214 file_cmd2 = result.pop(0)
215 self.assertEqual(b'filemodify', file_cmd2.name)
216 self.assertEqual(b'README', file_cmd2.path)
217 self.assertEqual(0o100644, file_cmd2.mode)
218 self.assertEqual(b'Welcome from bugs, etc.', file_cmd2.data)
219 cmd6 = result.pop(0)
220 self.assertEqual(cmd6.name, b'checkpoint')
221 cmd7 = result.pop(0)
222 self.assertEqual(b'progress', cmd7.name)
223 self.assertEqual(b'completed', cmd7.message)
224 cmd = result.pop(0)
225 self.assertEqual(b'commit', cmd.name)
226 self.assertEqual(b'3', cmd.mark)
227 self.assertEqual(None, cmd.from_)
228 cmd = result.pop(0)
229 self.assertEqual(b'commit', cmd.name)
230 self.assertEqual(b'4', cmd.mark)
231 self.assertEqual(b'Commit with heredoc-style message\n', cmd.message)
232 cmd = result.pop(0)
233 self.assertEqual(b'commit', cmd.name)
234 self.assertEqual(b'5', cmd.mark)
235 self.assertEqual(b'submodule test\n', cmd.message)
236 file_cmd1 = result.pop(0)
237 self.assertEqual(b'filemodify', file_cmd1.name)
238 self.assertEqual(b'tree-id', file_cmd1.path)
239 self.assertEqual(0o160000, file_cmd1.mode)
240 self.assertEqual(b"rev-id", file_cmd1.dataref)
241 cmd = result.pop(0)
242 self.assertEqual(b'feature', cmd.name)
243 self.assertEqual(b'whatever', cmd.feature_name)
244 self.assertEqual(None, cmd.value)
245 cmd = result.pop(0)
246 self.assertEqual(b'feature', cmd.name)
247 self.assertEqual(b'foo', cmd.feature_name)
248 self.assertEqual(b'bar', cmd.value)
249 cmd = result.pop(0)
250 self.assertEqual(b'commit', cmd.name)
251 self.assertEqual(b'6', cmd.mark)
252 self.assertEqual(b'test of properties', cmd.message)
253 self.assertEqual({
254 b'p1': None,
255 b'p2': b'hohum',
256 b'p3': b'alpha\nbeta\ngamma',
257 b'p4': b'whatever',
258 }, cmd.properties)
259 cmd = result.pop(0)
260 self.assertEqual(b'commit', cmd.name)
261 self.assertEqual(b'7', cmd.mark)
262 self.assertEqual(b'multi-author test', cmd.message)
263 self.assertEqual(b'', cmd.committer[0])
264 self.assertEqual(b'bugs@bunny.org', cmd.committer[1])
265 self.assertEqual(b'Fluffy', cmd.author[0])
266 self.assertEqual(b'fluffy@bunny.org', cmd.author[1])
267 self.assertEqual(b'Daffy', cmd.more_authors[0][0])
268 self.assertEqual(b'daffy@duck.org', cmd.more_authors[0][1])
269 self.assertEqual(b'Donald', cmd.more_authors[1][0])
270 self.assertEqual(b'donald@duck.org', cmd.more_authors[1][1])
271
272 def test_done_feature_missing_done(self):
273 s = io.BytesIO(b"""feature done
274 """)
275 p = parser.ImportParser(s)
276 cmds = p.iter_commands()
277 self.assertEqual(b"feature", next(cmds).name)
278 self.assertRaises(errors.PrematureEndOfStream, lambda: next(cmds))
279
280 def test_done_with_feature(self):
281 s = io.BytesIO(b"""feature done
282 done
283 more data
284 """)
285 p = parser.ImportParser(s)
286 cmds = p.iter_commands()
287 self.assertEqual(b"feature", next(cmds).name)
288 self.assertRaises(StopIteration, lambda: next(cmds))
289
290 def test_done_without_feature(self):
291 s = io.BytesIO(b"""done
292 more data
293 """)
294 p = parser.ImportParser(s)
295 cmds = p.iter_commands()
296 self.assertEqual([], list(cmds))
297
298
299 class TestStringParsing(unittest.TestCase):
300
301 def test_unquote(self):
302 s = br'hello \"sweet\" wo\\r\tld'
303 self.assertEqual(br'hello "sweet" wo\r' + b'\tld',
304 parser._unquote_c_string(s))
305
306
307 class TestPathPairParsing(unittest.TestCase):
308
309 def test_path_pair_simple(self):
310 p = parser.ImportParser(b'')
311 self.assertEqual([b'foo', b'bar'], p._path_pair(b'foo bar'))
312
313 def test_path_pair_spaces_in_first(self):
314 p = parser.ImportParser("")
315 self.assertEqual([b'foo bar', b'baz'],
316 p._path_pair(b'"foo bar" baz'))
317
318
319 class TestTagParsing(unittest.TestCase):
320
321 def test_tagger_with_email(self):
322 p = parser.ImportParser(io.BytesIO(
323 b"tag refs/tags/v1.0\n"
324 b"from :xxx\n"
325 b"tagger Joe Wong <joe@example.com> 1234567890 -0600\n"
326 b"data 11\n"
327 b"create v1.0"))
328 cmds = list(p.iter_commands())
329 self.assertEqual(1, len(cmds))
330 self.assertTrue(isinstance(cmds[0], commands.TagCommand))
331 self.assertEqual(cmds[0].tagger,
332 (b'Joe Wong', b'joe@example.com', 1234567890.0, -21600))
333
334 def test_tagger_no_email_strict(self):
335 p = parser.ImportParser(io.BytesIO(
336 b"tag refs/tags/v1.0\n"
337 b"from :xxx\n"
338 b"tagger Joe Wong\n"
339 b"data 11\n"
340 b"create v1.0"))
341 self.assertRaises(errors.BadFormat, list, p.iter_commands())
342
343 def test_tagger_no_email_not_strict(self):
344 p = parser.ImportParser(io.BytesIO(
345 b"tag refs/tags/v1.0\n"
346 b"from :xxx\n"
347 b"tagger Joe Wong\n"
348 b"data 11\n"
349 b"create v1.0"), strict=False)
350 cmds = list(p.iter_commands())
351 self.assertEqual(1, len(cmds))
352 self.assertTrue(isinstance(cmds[0], commands.TagCommand))
353 self.assertEqual(cmds[0].tagger[:2], (b'Joe Wong', None))