blob: 20459d1d74f6efbafdd185957f5e254668d33e8c [file] [log] [blame]
Mike Frysinger04122b72019-07-31 23:32:58 -04001# Copyright (C) 2019 The Android Open Source Project
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15"""Unittests for the manifest_xml.py module."""
16
Mike Frysingerd9254592020-02-19 22:36:26 -050017import os
Raman Tenneti080877e2021-03-09 15:19:06 -080018import platform
Peter Kjellerstedt5d58c182021-04-12 21:16:36 +020019import re
Mike Frysinger8c1e9cb2020-09-06 14:53:18 -040020import shutil
21import tempfile
Mike Frysinger04122b72019-07-31 23:32:58 -040022import unittest
Mike Frysingerbb8ee7f2020-02-22 05:30:12 -050023import xml.dom.minidom
Mike Frysinger04122b72019-07-31 23:32:58 -040024
25import error
26import manifest_xml
27
28
Mike Frysingera29424e2021-02-25 21:53:49 -050029# Invalid paths that we don't want in the filesystem.
30INVALID_FS_PATHS = (
31 '',
32 '.',
33 '..',
34 '../',
35 './',
Mike Frysinger0458faa2021-03-10 23:35:44 -050036 './/',
Mike Frysingera29424e2021-02-25 21:53:49 -050037 'foo/',
38 './foo',
39 '../foo',
40 'foo/./bar',
41 'foo/../../bar',
42 '/foo',
43 './../foo',
44 '.git/foo',
45 # Check case folding.
46 '.GIT/foo',
47 'blah/.git/foo',
48 '.repo/foo',
49 '.repoconfig',
50 # Block ~ due to 8.3 filenames on Windows filesystems.
51 '~',
52 'foo~',
53 'blah/foo~',
54 # Block Unicode characters that get normalized out by filesystems.
55 u'foo\u200Cbar',
Mike Frysingerf69c7ee2021-04-29 23:15:31 -040056 # Block newlines.
57 'f\n/bar',
58 'f\r/bar',
Mike Frysingera29424e2021-02-25 21:53:49 -050059)
60
61# Make sure platforms that use path separators (e.g. Windows) are also
62# rejected properly.
63if os.path.sep != '/':
64 INVALID_FS_PATHS += tuple(x.replace('/', os.path.sep) for x in INVALID_FS_PATHS)
65
66
Peter Kjellerstedt5d58c182021-04-12 21:16:36 +020067def sort_attributes(manifest):
68 """Sort the attributes of all elements alphabetically.
69
70 This is needed because different versions of the toxml() function from
71 xml.dom.minidom outputs the attributes of elements in different orders.
72 Before Python 3.8 they were output alphabetically, later versions preserve
73 the order specified by the user.
74
75 Args:
76 manifest: String containing an XML manifest.
77
78 Returns:
79 The XML manifest with the attributes of all elements sorted alphabetically.
80 """
81 new_manifest = ''
82 # This will find every element in the XML manifest, whether they have
83 # attributes or not. This simplifies recreating the manifest below.
84 matches = re.findall(r'(<[/?]?[a-z-]+\s*)((?:\S+?="[^"]+"\s*?)*)(\s*[/?]?>)', manifest)
85 for head, attrs, tail in matches:
86 m = re.findall(r'\S+?="[^"]+"', attrs)
87 new_manifest += head + ' '.join(sorted(m)) + tail
88 return new_manifest
89
90
Mike Frysinger37ac3d62021-02-25 04:54:56 -050091class ManifestParseTestCase(unittest.TestCase):
92 """TestCase for parsing manifests."""
93
94 def setUp(self):
95 self.tempdir = tempfile.mkdtemp(prefix='repo_tests')
96 self.repodir = os.path.join(self.tempdir, '.repo')
97 self.manifest_dir = os.path.join(self.repodir, 'manifests')
98 self.manifest_file = os.path.join(
99 self.repodir, manifest_xml.MANIFEST_FILE_NAME)
100 self.local_manifest_dir = os.path.join(
101 self.repodir, manifest_xml.LOCAL_MANIFESTS_DIR_NAME)
102 os.mkdir(self.repodir)
103 os.mkdir(self.manifest_dir)
104
105 # The manifest parsing really wants a git repo currently.
106 gitdir = os.path.join(self.repodir, 'manifests.git')
107 os.mkdir(gitdir)
108 with open(os.path.join(gitdir, 'config'), 'w') as fp:
109 fp.write("""[remote "origin"]
110 url = https://localhost:0/manifest
111""")
112
113 def tearDown(self):
114 shutil.rmtree(self.tempdir, ignore_errors=True)
115
116 def getXmlManifest(self, data):
117 """Helper to initialize a manifest for testing."""
118 with open(self.manifest_file, 'w') as fp:
119 fp.write(data)
120 return manifest_xml.XmlManifest(self.repodir, self.manifest_file)
121
Mike Frysingerf69c7ee2021-04-29 23:15:31 -0400122 @staticmethod
123 def encodeXmlAttr(attr):
124 """Encode |attr| using XML escape rules."""
125 return attr.replace('\r', ' ').replace('\n', ' ')
126
Mike Frysinger37ac3d62021-02-25 04:54:56 -0500127
Mike Frysinger04122b72019-07-31 23:32:58 -0400128class ManifestValidateFilePaths(unittest.TestCase):
129 """Check _ValidateFilePaths helper.
130
131 This doesn't access a real filesystem.
132 """
133
134 def check_both(self, *args):
135 manifest_xml.XmlManifest._ValidateFilePaths('copyfile', *args)
136 manifest_xml.XmlManifest._ValidateFilePaths('linkfile', *args)
137
138 def test_normal_path(self):
139 """Make sure good paths are accepted."""
140 self.check_both('foo', 'bar')
141 self.check_both('foo/bar', 'bar')
142 self.check_both('foo', 'bar/bar')
143 self.check_both('foo/bar', 'bar/bar')
144
145 def test_symlink_targets(self):
146 """Some extra checks for symlinks."""
147 def check(*args):
148 manifest_xml.XmlManifest._ValidateFilePaths('linkfile', *args)
149
150 # We allow symlinks to end in a slash since we allow them to point to dirs
151 # in general. Technically the slash isn't necessary.
152 check('foo/', 'bar')
Mike Frysingerae625412020-02-10 17:10:03 -0500153 # We allow a single '.' to get a reference to the project itself.
154 check('.', 'bar')
Mike Frysinger04122b72019-07-31 23:32:58 -0400155
156 def test_bad_paths(self):
157 """Make sure bad paths (src & dest) are rejected."""
Mike Frysingera29424e2021-02-25 21:53:49 -0500158 for path in INVALID_FS_PATHS:
Mike Frysinger04122b72019-07-31 23:32:58 -0400159 self.assertRaises(
160 error.ManifestInvalidPathError, self.check_both, path, 'a')
161 self.assertRaises(
162 error.ManifestInvalidPathError, self.check_both, 'a', path)
Mike Frysingerbb8ee7f2020-02-22 05:30:12 -0500163
164
165class ValueTests(unittest.TestCase):
166 """Check utility parsing code."""
167
168 def _get_node(self, text):
169 return xml.dom.minidom.parseString(text).firstChild
170
171 def test_bool_default(self):
172 """Check XmlBool default handling."""
173 node = self._get_node('')
174 self.assertIsNone(manifest_xml.XmlBool(node, 'a'))
175 self.assertIsNone(manifest_xml.XmlBool(node, 'a', None))
176 self.assertEqual(123, manifest_xml.XmlBool(node, 'a', 123))
177
178 node = self._get_node('')
179 self.assertIsNone(manifest_xml.XmlBool(node, 'a'))
180
181 def test_bool_invalid(self):
182 """Check XmlBool invalid handling."""
183 node = self._get_node('')
184 self.assertEqual(123, manifest_xml.XmlBool(node, 'a', 123))
185
186 def test_bool_true(self):
187 """Check XmlBool true values."""
188 for value in ('yes', 'true', '1'):
189 node = self._get_node('' % (value,))
190 self.assertTrue(manifest_xml.XmlBool(node, 'a'))
191
192 def test_bool_false(self):
193 """Check XmlBool false values."""
194 for value in ('no', 'false', '0'):
195 node = self._get_node('' % (value,))
196 self.assertFalse(manifest_xml.XmlBool(node, 'a'))
197
198 def test_int_default(self):
199 """Check XmlInt default handling."""
200 node = self._get_node('')
201 self.assertIsNone(manifest_xml.XmlInt(node, 'a'))
202 self.assertIsNone(manifest_xml.XmlInt(node, 'a', None))
203 self.assertEqual(123, manifest_xml.XmlInt(node, 'a', 123))
204
205 node = self._get_node('')
206 self.assertIsNone(manifest_xml.XmlInt(node, 'a'))
207
208 def test_int_good(self):
209 """Check XmlInt numeric handling."""
210 for value in (-1, 0, 1, 50000):
211 node = self._get_node('' % (value,))
212 self.assertEqual(value, manifest_xml.XmlInt(node, 'a'))
213
214 def test_int_invalid(self):
215 """Check XmlInt invalid handling."""
216 with self.assertRaises(error.ManifestParseError):
217 node = self._get_node('')
218 manifest_xml.XmlInt(node, 'a')
Mike Frysinger8c1e9cb2020-09-06 14:53:18 -0400219
220
Mike Frysinger37ac3d62021-02-25 04:54:56 -0500221class XmlManifestTests(ManifestParseTestCase):
Mike Frysinger8c1e9cb2020-09-06 14:53:18 -0400222 """Check manifest processing."""
223
Mike Frysinger8c1e9cb2020-09-06 14:53:18 -0400224 def test_empty(self):
225 """Parse an 'empty' manifest file."""
226 manifest = self.getXmlManifest(
227 ''
228 '')
229 self.assertEqual(manifest.remotes, {})
230 self.assertEqual(manifest.projects, [])
231
232 def test_link(self):
233 """Verify Link handling with new names."""
234 manifest = manifest_xml.XmlManifest(self.repodir, self.manifest_file)
235 with open(os.path.join(self.manifest_dir, 'foo.xml'), 'w') as fp:
236 fp.write('')
237 manifest.Link('foo.xml')
238 with open(self.manifest_file) as fp:
239 self.assertIn('', fp.read())
240
241 def test_toxml_empty(self):
242 """Verify the ToXml() helper."""
243 manifest = self.getXmlManifest(
244 ''
245 '')
246 self.assertEqual(manifest.ToXml().toxml(), '')
247
248 def test_todict_empty(self):
249 """Verify the ToDict() helper."""
250 manifest = self.getXmlManifest(
251 ''
252 '')
253 self.assertEqual(manifest.ToDict(), {})
254
Mike Frysinger51e39d52020-12-04 05:32:06 -0500255 def test_repo_hooks(self):
256 """Check repo-hooks settings."""
257 manifest = self.getXmlManifest("""
258
259
260
261
262
263
264""")
265 self.assertEqual(manifest.repo_hooks_project.name, 'repohooks')
266 self.assertEqual(manifest.repo_hooks_project.enabled_repo_hooks, ['a', 'b'])
267
Jack Neusa84f43a2021-09-21 22:23:55 +0000268 def test_repo_hooks_unordered(self):
269 """Check repo-hooks settings work even if the project def comes second."""
270 manifest = self.getXmlManifest("""
271
272
273
274
275
276
277""")
278 self.assertEqual(manifest.repo_hooks_project.name, 'repohooks')
279 self.assertEqual(manifest.repo_hooks_project.enabled_repo_hooks, ['a', 'b'])
280
Raman Tenneti48b2d102021-01-11 12:18:47 -0800281 def test_unknown_tags(self):
282 """Check superproject settings."""
283 manifest = self.getXmlManifest("""
284
285
286
287
288
289 X tags are always ignored
290
291""")
292 self.assertEqual(manifest.superproject['name'], 'superproject')
293 self.assertEqual(manifest.superproject['remote'].name, 'test-remote')
294 self.assertEqual(
Peter Kjellerstedt5d58c182021-04-12 21:16:36 +0200295 sort_attributes(manifest.ToXml().toxml()),
Raman Tenneti1c3f57e2021-05-04 12:32:13 -0700296 ''
Peter Kjellerstedt5d58c182021-04-12 21:16:36 +0200297 ''
Raman Tenneti1c3f57e2021-05-04 12:32:13 -0700298 ''
299 ''
Raman Tenneti48b2d102021-01-11 12:18:47 -0800300 '')
301
Jack Neus6ea0cae2021-07-20 20:52:33 +0000302 def test_remote_annotations(self):
303 """Check remote settings."""
304 manifest = self.getXmlManifest("""
305
306
307
308
309
310""")
311 self.assertEqual(manifest.remotes['test-remote'].annotations[0].name, 'foo')
312 self.assertEqual(manifest.remotes['test-remote'].annotations[0].value, 'bar')
313 self.assertEqual(
314 sort_attributes(manifest.ToXml().toxml()),
315 ''
316 ''
317 ''
318 ''
319 '')
320
Fredrik de Groot352c93b2020-10-06 12:55:14 +0200321
Mike Frysingera29424e2021-02-25 21:53:49 -0500322class IncludeElementTests(ManifestParseTestCase):
323 """Tests for ."""
Raman Tennetib5c5a5e2021-02-06 09:44:15 -0800324
Mike Frysingera29424e2021-02-25 21:53:49 -0500325 def test_group_levels(self):
Fredrik de Groot352c93b2020-10-06 12:55:14 +0200326 root_m = os.path.join(self.manifest_dir, 'root.xml')
327 with open(root_m, 'w') as fp:
328 fp.write("""
329
330
331
332
333
334
335
336""")
337 with open(os.path.join(self.manifest_dir, 'level1.xml'), 'w') as fp:
338 fp.write("""
339
340
341
342
343""")
344 with open(os.path.join(self.manifest_dir, 'level2.xml'), 'w') as fp:
345 fp.write("""
346
347
348
349""")
350 include_m = manifest_xml.XmlManifest(self.repodir, root_m)
351 for proj in include_m.projects:
352 if proj.name == 'root-name1':
353 # Check include group not set on root level proj.
354 self.assertNotIn('level1-group', proj.groups)
355 if proj.name == 'root-name2':
356 # Check root proj group not removed.
357 self.assertIn('r2g1', proj.groups)
358 if proj.name == 'level1-name1':
359 # Check level1 proj has inherited group level 1.
360 self.assertIn('level1-group', proj.groups)
361 if proj.name == 'level2-name1':
362 # Check level2 proj has inherited group levels 1 and 2.
363 self.assertIn('level1-group', proj.groups)
364 self.assertIn('level2-group', proj.groups)
365 # Check level2 proj group not removed.
366 self.assertIn('l2g1', proj.groups)
Mike Frysinger37ac3d62021-02-25 04:54:56 -0500367
Mike Frysinger54133972021-03-01 21:38:08 -0500368 def test_allow_bad_name_from_user(self):
369 """Check handling of bad name attribute from the user's input."""
Mike Frysingera29424e2021-02-25 21:53:49 -0500370 def parse(name):
Mike Frysingerf69c7ee2021-04-29 23:15:31 -0400371 name = self.encodeXmlAttr(name)
Mike Frysingera29424e2021-02-25 21:53:49 -0500372 manifest = self.getXmlManifest(f"""
373
374
375
376
377
378""")
379 # Force the manifest to be parsed.
380 manifest.ToXml()
Mike Frysinger37ac3d62021-02-25 04:54:56 -0500381
Mike Frysinger54133972021-03-01 21:38:08 -0500382 # Setup target of the include.
383 target = os.path.join(self.tempdir, 'target.xml')
384 with open(target, 'w') as fp:
385 fp.write('')
386
387 # Include with absolute path.
388 parse(os.path.abspath(target))
389
390 # Include with relative path.
391 parse(os.path.relpath(target, self.manifest_dir))
392
393 def test_bad_name_checks(self):
394 """Check handling of bad name attribute."""
395 def parse(name):
Mike Frysingerf69c7ee2021-04-29 23:15:31 -0400396 name = self.encodeXmlAttr(name)
Mike Frysinger54133972021-03-01 21:38:08 -0500397 # Setup target of the include.
398 with open(os.path.join(self.manifest_dir, 'target.xml'), 'w') as fp:
399 fp.write(f'')
400
401 manifest = self.getXmlManifest("""
402
403
404
405
406
407""")
408 # Force the manifest to be parsed.
409 manifest.ToXml()
410
Mike Frysingera29424e2021-02-25 21:53:49 -0500411 # Handle empty name explicitly because a different codepath rejects it.
412 with self.assertRaises(error.ManifestParseError):
413 parse('')
414
415 for path in INVALID_FS_PATHS:
416 if not path:
417 continue
418
419 with self.assertRaises(error.ManifestInvalidPathError):
420 parse(path)
421
422
423class ProjectElementTests(ManifestParseTestCase):
424 """Tests for ."""
425
426 def test_group(self):
427 """Check project group settings."""
428 manifest = self.getXmlManifest("""
429
430
431
432
433
434
435""")
436 self.assertEqual(len(manifest.projects), 2)
437 # Ordering isn't guaranteed.
438 result = {
439 manifest.projects[0].name: manifest.projects[0].groups,
440 manifest.projects[1].name: manifest.projects[1].groups,
441 }
442 project = manifest.projects[0]
443 self.assertCountEqual(
444 result['test-name'],
445 ['name:test-name', 'all', 'path:test-path'])
446 self.assertCountEqual(
447 result['extras'],
448 ['g1', 'g2', 'g1', 'name:extras', 'all', 'path:path'])
Raman Tenneti080877e2021-03-09 15:19:06 -0800449 groupstr = 'default,platform-' + platform.system().lower()
450 self.assertEqual(groupstr, manifest.GetGroupsStr())
451 groupstr = 'g1,g2,g1'
452 manifest.manifestProject.config.SetString('manifest.groups', groupstr)
453 self.assertEqual(groupstr, manifest.GetGroupsStr())
Mike Frysingera29424e2021-02-25 21:53:49 -0500454
455 def test_set_revision_id(self):
456 """Check setting of project's revisionId."""
457 manifest = self.getXmlManifest("""
458
459
460
461
462
463""")
464 self.assertEqual(len(manifest.projects), 1)
465 project = manifest.projects[0]
466 project.SetRevisionId('ABCDEF')
467 self.assertEqual(
Peter Kjellerstedt5d58c182021-04-12 21:16:36 +0200468 sort_attributes(manifest.ToXml().toxml()),
Raman Tenneti1c3f57e2021-05-04 12:32:13 -0700469 ''
Peter Kjellerstedt5d58c182021-04-12 21:16:36 +0200470 ''
Raman Tenneti1c3f57e2021-05-04 12:32:13 -0700471 ''
Xin Li0e776a52021-06-29 21:42:34 +0000472 ''
Mike Frysingera29424e2021-02-25 21:53:49 -0500473 '')
474
475 def test_trailing_slash(self):
476 """Check handling of trailing slashes in attributes."""
477 def parse(name, path):
Mike Frysingerf69c7ee2021-04-29 23:15:31 -0400478 name = self.encodeXmlAttr(name)
479 path = self.encodeXmlAttr(path)
Mike Frysingera29424e2021-02-25 21:53:49 -0500480 return self.getXmlManifest(f"""
481
482
483
484
485
486""")
487
488 manifest = parse('a/path/', 'foo')
489 self.assertEqual(manifest.projects[0].gitdir,
490 os.path.join(self.tempdir, '.repo/projects/foo.git'))
491 self.assertEqual(manifest.projects[0].objdir,
492 os.path.join(self.tempdir, '.repo/project-objects/a/path.git'))
493
494 manifest = parse('a/path', 'foo/')
495 self.assertEqual(manifest.projects[0].gitdir,
496 os.path.join(self.tempdir, '.repo/projects/foo.git'))
497 self.assertEqual(manifest.projects[0].objdir,
498 os.path.join(self.tempdir, '.repo/project-objects/a/path.git'))
499
Mike Frysinger0458faa2021-03-10 23:35:44 -0500500 manifest = parse('a/path', 'foo//////')
501 self.assertEqual(manifest.projects[0].gitdir,
502 os.path.join(self.tempdir, '.repo/projects/foo.git'))
503 self.assertEqual(manifest.projects[0].objdir,
504 os.path.join(self.tempdir, '.repo/project-objects/a/path.git'))
505
506 def test_toplevel_path(self):
507 """Check handling of path=. specially."""
508 def parse(name, path):
Mike Frysingerf69c7ee2021-04-29 23:15:31 -0400509 name = self.encodeXmlAttr(name)
510 path = self.encodeXmlAttr(path)
Mike Frysinger0458faa2021-03-10 23:35:44 -0500511 return self.getXmlManifest(f"""
512
513
514
515
516
517""")
518
519 for path in ('.', './', './/', './//'):
520 manifest = parse('server/path', path)
521 self.assertEqual(manifest.projects[0].gitdir,
522 os.path.join(self.tempdir, '.repo/projects/..git'))
523
Mike Frysingera29424e2021-02-25 21:53:49 -0500524 def test_bad_path_name_checks(self):
525 """Check handling of bad path & name attributes."""
526 def parse(name, path):
Mike Frysingerf69c7ee2021-04-29 23:15:31 -0400527 name = self.encodeXmlAttr(name)
528 path = self.encodeXmlAttr(path)
Mike Frysingera29424e2021-02-25 21:53:49 -0500529 manifest = self.getXmlManifest(f"""
530
531
532
533
534
535""")
536 # Force the manifest to be parsed.
537 manifest.ToXml()
538
539 # Verify the parser is valid by default to avoid buggy tests below.
540 parse('ok', 'ok')
541
542 # Handle empty name explicitly because a different codepath rejects it.
543 # Empty path is OK because it defaults to the name field.
544 with self.assertRaises(error.ManifestParseError):
545 parse('', 'ok')
546
547 for path in INVALID_FS_PATHS:
548 if not path or path.endswith('/'):
549 continue
550
551 with self.assertRaises(error.ManifestInvalidPathError):
552 parse(path, 'ok')
Mike Frysinger0458faa2021-03-10 23:35:44 -0500553
554 # We have a dedicated test for path=".".
555 if path not in {'.'}:
556 with self.assertRaises(error.ManifestInvalidPathError):
557 parse('ok', path)
Mike Frysingera29424e2021-02-25 21:53:49 -0500558
559
560class SuperProjectElementTests(ManifestParseTestCase):
Mike Frysinger37ac3d62021-02-25 04:54:56 -0500561 """Tests for ."""
562
563 def test_superproject(self):
564 """Check superproject settings."""
565 manifest = self.getXmlManifest("""
566
567
568
569
570
571""")
572 self.assertEqual(manifest.superproject['name'], 'superproject')
573 self.assertEqual(manifest.superproject['remote'].name, 'test-remote')
574 self.assertEqual(manifest.superproject['remote'].url, 'http://localhost/superproject')
575 self.assertEqual(
Peter Kjellerstedt5d58c182021-04-12 21:16:36 +0200576 sort_attributes(manifest.ToXml().toxml()),
Raman Tenneti1c3f57e2021-05-04 12:32:13 -0700577 ''
Peter Kjellerstedt5d58c182021-04-12 21:16:36 +0200578 ''
Raman Tenneti1c3f57e2021-05-04 12:32:13 -0700579 ''
580 ''
Mike Frysinger37ac3d62021-02-25 04:54:56 -0500581 '')
582
583 def test_remote(self):
584 """Check superproject settings with a remote."""
585 manifest = self.getXmlManifest("""
586
587
588
589
590
591
592""")
593 self.assertEqual(manifest.superproject['name'], 'platform/superproject')
594 self.assertEqual(manifest.superproject['remote'].name, 'superproject-remote')
595 self.assertEqual(manifest.superproject['remote'].url, 'http://localhost/platform/superproject')
596 self.assertEqual(
Peter Kjellerstedt5d58c182021-04-12 21:16:36 +0200597 sort_attributes(manifest.ToXml().toxml()),
Raman Tenneti1c3f57e2021-05-04 12:32:13 -0700598 ''
Peter Kjellerstedt5d58c182021-04-12 21:16:36 +0200599 ''
600 ''
Raman Tenneti1c3f57e2021-05-04 12:32:13 -0700601 ''
602 ''
Mike Frysinger37ac3d62021-02-25 04:54:56 -0500603 '')
604
605 def test_defalut_remote(self):
606 """Check superproject settings with a default remote."""
607 manifest = self.getXmlManifest("""
608
609
610
611
612
613""")
614 self.assertEqual(manifest.superproject['name'], 'superproject')
615 self.assertEqual(manifest.superproject['remote'].name, 'default-remote')
616 self.assertEqual(
Peter Kjellerstedt5d58c182021-04-12 21:16:36 +0200617 sort_attributes(manifest.ToXml().toxml()),
Raman Tenneti1c3f57e2021-05-04 12:32:13 -0700618 ''
Peter Kjellerstedt5d58c182021-04-12 21:16:36 +0200619 ''
Raman Tenneti1c3f57e2021-05-04 12:32:13 -0700620 ''
621 ''
Mike Frysinger37ac3d62021-02-25 04:54:56 -0500622 '')
Raman Tenneti1c3f57e2021-05-04 12:32:13 -0700623
624
625class ContactinfoElementTests(ManifestParseTestCase):
626 """Tests for ."""
627
628 def test_contactinfo(self):
629 """Check contactinfo settings."""
630 bugurl = 'http://localhost/contactinfo'
631 manifest = self.getXmlManifest(f"""
632
633
634
635""")
Raman Tenneti993af5e2021-05-12 12:00:31 -0700636 self.assertEqual(manifest.contactinfo.bugurl, bugurl)
Raman Tenneti1c3f57e2021-05-04 12:32:13 -0700637 self.assertEqual(
638 manifest.ToXml().toxml(),
Raman Tenneti2f8fdbe2021-05-04 18:54:52 -0700639 ''
640 f''
641 '')
Jack Neus5ba21202021-06-09 15:21:25 +0000642
643
644class DefaultElementTests(ManifestParseTestCase):
645 """Tests for ."""
646
647 def test_default(self):
648 """Check default settings."""
649 a = manifest_xml._Default()
650 a.revisionExpr = 'foo'
651 a.remote = manifest_xml._XmlRemote(name='remote')
652 b = manifest_xml._Default()
653 b.revisionExpr = 'bar'
654 self.assertEqual(a, a)
655 self.assertNotEqual(a, b)
656 self.assertNotEqual(b, a.remote)
657 self.assertNotEqual(a, 123)
658 self.assertNotEqual(a, None)
659
660
661class RemoteElementTests(ManifestParseTestCase):
662 """Tests for ."""
663
664 def test_remote(self):
665 """Check remote settings."""
666 a = manifest_xml._XmlRemote(name='foo')
Jack Neus6ea0cae2021-07-20 20:52:33 +0000667 a.AddAnnotation('key1', 'value1', 'true')
668 b = manifest_xml._XmlRemote(name='foo')
669 b.AddAnnotation('key2', 'value1', 'true')
670 c = manifest_xml._XmlRemote(name='foo')
671 c.AddAnnotation('key1', 'value2', 'true')
672 d = manifest_xml._XmlRemote(name='foo')
673 d.AddAnnotation('key1', 'value1', 'false')
Jack Neus5ba21202021-06-09 15:21:25 +0000674 self.assertEqual(a, a)
675 self.assertNotEqual(a, b)
Jack Neus6ea0cae2021-07-20 20:52:33 +0000676 self.assertNotEqual(a, c)
677 self.assertNotEqual(a, d)
Jack Neus5ba21202021-06-09 15:21:25 +0000678 self.assertNotEqual(a, manifest_xml._Default())
679 self.assertNotEqual(a, 123)
680 self.assertNotEqual(a, None)
Michael Kelly06da9982021-06-30 01:58:28 -0700681
682
683class RemoveProjectElementTests(ManifestParseTestCase):
684 """Tests for ."""
685
686 def test_remove_one_project(self):
687 manifest = self.getXmlManifest("""
688
689
690
691
692
693
694""")
695 self.assertEqual(manifest.projects, [])
696
697 def test_remove_one_project_one_remains(self):
698 manifest = self.getXmlManifest("""
699
700
701
702
703
704
705
706""")
707
708 self.assertEqual(len(manifest.projects), 1)
709 self.assertEqual(manifest.projects[0].name, 'yourproject')
710
711 def test_remove_one_project_doesnt_exist(self):
712 with self.assertRaises(manifest_xml.ManifestParseError):
713 manifest = self.getXmlManifest("""
714
715
716
717
718
719""")
720 manifest.projects
721
722 def test_remove_one_optional_project_doesnt_exist(self):
723 manifest = self.getXmlManifest("""
724
725
726
727
728
729""")
730 self.assertEqual(manifest.projects, [])