summaryrefslogtreecommitdiffstats
path: root/testing/mozbase/manifestparser/tests/test_manifestparser.py
diff options
context:
space:
mode:
Diffstat (limited to 'testing/mozbase/manifestparser/tests/test_manifestparser.py')
-rwxr-xr-xtesting/mozbase/manifestparser/tests/test_manifestparser.py627
1 files changed, 627 insertions, 0 deletions
diff --git a/testing/mozbase/manifestparser/tests/test_manifestparser.py b/testing/mozbase/manifestparser/tests/test_manifestparser.py
new file mode 100755
index 0000000000..f1774cfffb
--- /dev/null
+++ b/testing/mozbase/manifestparser/tests/test_manifestparser.py
@@ -0,0 +1,627 @@
+#!/usr/bin/env python
+
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this file,
+# You can obtain one at http://mozilla.org/MPL/2.0/.
+
+import os
+import shutil
+import tempfile
+import unittest
+from io import StringIO
+
+import manifestparser.toml
+import mozunit
+from manifestparser import ManifestParser
+from tomlkit import TOMLDocument
+
+here = os.path.dirname(os.path.abspath(__file__))
+
+
+class TestManifestParser(unittest.TestCase):
+ """
+ Test the manifest parser
+
+ You must have manifestparser installed before running these tests.
+ Run ``python manifestparser.py setup develop`` with setuptools installed.
+ """
+
+ def test_sanity_toml(self):
+ """Ensure basic parser is sane (TOML)"""
+
+ parser = ManifestParser(use_toml=True)
+ mozmill_example = os.path.join(here, "mozmill-example.toml")
+ parser.read(mozmill_example)
+ tests = parser.tests
+ self.assertEqual(
+ len(tests), len(open(mozmill_example).read().strip().splitlines())
+ )
+
+ # Ensure that capitalization and order aren't an issue:
+ lines = ['["%s"]' % test["name"] for test in tests]
+ self.assertEqual(lines, open(mozmill_example).read().strip().splitlines())
+
+ # Show how you select subsets of tests:
+ mozmill_restart_example = os.path.join(here, "mozmill-restart-example.toml")
+ parser.read(mozmill_restart_example)
+ restart_tests = parser.get(type="restart")
+ self.assertTrue(len(restart_tests) < len(parser.tests))
+ self.assertEqual(
+ len(restart_tests), len(parser.get(manifest=mozmill_restart_example))
+ )
+ self.assertFalse(
+ [
+ test
+ for test in restart_tests
+ if test["manifest"]
+ != os.path.join(here, "mozmill-restart-example.toml")
+ ]
+ )
+ self.assertEqual(
+ parser.get("name", tags=["foo"]),
+ [
+ "restartTests/testExtensionInstallUninstall/test2.js",
+ "restartTests/testExtensionInstallUninstall/test1.js",
+ ],
+ )
+ self.assertEqual(
+ parser.get("name", foo="bar"),
+ ["restartTests/testExtensionInstallUninstall/test2.js"],
+ )
+
+ def test_include(self):
+ """Illustrate how include works"""
+
+ include_example = os.path.join(here, "include-example.toml")
+ parser = ManifestParser(manifests=(include_example,), use_toml=False)
+
+ # All of the tests should be included, in order:
+ self.assertEqual(parser.get("name"), ["crash-handling", "fleem", "flowers"])
+ self.assertEqual(
+ [
+ (test["name"], os.path.basename(test["manifest"]))
+ for test in parser.tests
+ ],
+ [
+ ("crash-handling", "bar.toml"),
+ ("fleem", "include-example.toml"),
+ ("flowers", "foo.toml"),
+ ],
+ )
+
+ # The including manifest is always reported as a part of the generated test object.
+ self.assertTrue(
+ all(
+ [
+ t["ancestor_manifest"] == "include-example.toml"
+ for t in parser.tests
+ if t["name"] != "fleem"
+ ]
+ )
+ )
+
+ # The manifests should be there too:
+ self.assertEqual(len(parser.manifests()), 3)
+
+ # We already have the root directory:
+ self.assertEqual(here, parser.rootdir)
+
+ # DEFAULT values should persist across includes, unless they're
+ # overwritten. In this example, include-example.toml sets foo=bar, but
+ # it's overridden to fleem in bar.toml
+ self.assertEqual(parser.get("name", foo="bar"), ["fleem", "flowers"])
+ self.assertEqual(parser.get("name", foo="fleem"), ["crash-handling"])
+
+ # Passing parameters in the include section allows defining variables in
+ # the submodule scope:
+ self.assertEqual(parser.get("name", tags=["red"]), ["flowers"])
+
+ # However, this should be overridable from the DEFAULT section in the
+ # included file and that overridable via the key directly connected to
+ # the test:
+ self.assertEqual(parser.get(name="flowers")[0]["blue"], "ocean")
+ self.assertEqual(parser.get(name="flowers")[0]["yellow"], "submarine")
+
+ # You can query multiple times if you need to:
+ flowers = parser.get(foo="bar")
+ self.assertEqual(len(flowers), 2)
+
+ # Using the inverse flag should invert the set of tests returned:
+ self.assertEqual(
+ parser.get("name", inverse=True, tags=["red"]), ["crash-handling", "fleem"]
+ )
+
+ # All of the included tests actually exist:
+ self.assertEqual([i["name"] for i in parser.missing()], [])
+
+ # Write the output to a manifest:
+ buffer = StringIO()
+ parser.write(fp=buffer, global_kwargs={"foo": "bar"})
+ expected_output = """[DEFAULT]
+foo = bar
+
+[fleem]
+
+[include/flowers]
+blue = ocean
+red = roses
+yellow = submarine""" # noqa
+
+ self.assertEqual(buffer.getvalue().strip(), expected_output)
+
+ def test_include_toml(self):
+ """Illustrate how include works (TOML)"""
+
+ include_example = os.path.join(here, "include-example.toml")
+ parser = ManifestParser(manifests=(include_example,), use_toml=True)
+
+ # All of the tests should be included, in order:
+ self.assertEqual(parser.get("name"), ["crash-handling", "fleem", "flowers"])
+ self.assertEqual(
+ [
+ (test["name"], os.path.basename(test["manifest"]))
+ for test in parser.tests
+ ],
+ [
+ ("crash-handling", "bar.toml"),
+ ("fleem", "include-example.toml"),
+ ("flowers", "foo.toml"),
+ ],
+ )
+
+ # The including manifest is always reported as a part of the generated test object.
+ self.assertTrue(
+ all(
+ [
+ t["ancestor_manifest"] == "include-example.toml"
+ for t in parser.tests
+ if t["name"] != "fleem"
+ ]
+ )
+ )
+
+ # The manifests should be there too:
+ self.assertEqual(len(parser.manifests()), 3)
+
+ # We already have the root directory:
+ self.assertEqual(here, parser.rootdir)
+
+ # DEFAULT values should persist across includes, unless they're
+ # overwritten. In this example, include-example.toml sets foo=bar, but
+ # it's overridden to fleem in bar.toml
+ self.assertEqual(parser.get("name", foo="bar"), ["fleem", "flowers"])
+ self.assertEqual(parser.get("name", foo="fleem"), ["crash-handling"])
+
+ # Passing parameters in the include section allows defining variables in
+ # the submodule scope:
+ self.assertEqual(parser.get("name", tags=["red"]), ["flowers"])
+
+ # However, this should be overridable from the DEFAULT section in the
+ # included file and that overridable via the key directly connected to
+ # the test:
+ self.assertEqual(parser.get(name="flowers")[0]["blue"], "ocean")
+ self.assertEqual(parser.get(name="flowers")[0]["yellow"], "submarine")
+
+ # You can query multiple times if you need to:
+ flowers = parser.get(foo="bar")
+ self.assertEqual(len(flowers), 2)
+
+ # Using the inverse flag should invert the set of tests returned:
+ self.assertEqual(
+ parser.get("name", inverse=True, tags=["red"]), ["crash-handling", "fleem"]
+ )
+
+ # All of the included tests actually exist:
+ self.assertEqual([i["name"] for i in parser.missing()], [])
+
+ # Write the output to a manifest:
+ buffer = StringIO()
+ parser.write(fp=buffer, global_kwargs={"foo": "bar"})
+ expected_output = """[DEFAULT]
+foo = bar
+
+[fleem]
+
+[include/flowers]
+blue = ocean
+red = roses
+yellow = submarine""" # noqa
+
+ self.assertEqual(buffer.getvalue().strip(), expected_output)
+
+ def test_include_manifest_defaults_toml(self):
+ """
+ Test that manifest_defaults and manifests() are correctly populated
+ when includes are used. (TOML)
+ """
+
+ include_example = os.path.join(here, "include-example.toml")
+ noinclude_example = os.path.join(here, "just-defaults.toml")
+ bar_path = os.path.join(here, "include", "bar.toml")
+ foo_path = os.path.join(here, "include", "foo.toml")
+
+ parser = ManifestParser(
+ manifests=(include_example, noinclude_example), rootdir=here, use_toml=True
+ )
+
+ # Standalone manifests must be appear as-is.
+ self.assertTrue(include_example in parser.manifest_defaults)
+ self.assertTrue(noinclude_example in parser.manifest_defaults)
+
+ # Included manifests must only appear together with the parent manifest
+ # that included the manifest.
+ self.assertFalse(bar_path in parser.manifest_defaults)
+ self.assertFalse(foo_path in parser.manifest_defaults)
+ ancestor_toml = os.path.relpath(include_example, parser.rootdir)
+ self.assertTrue((ancestor_toml, bar_path) in parser.manifest_defaults)
+ self.assertTrue((ancestor_toml, foo_path) in parser.manifest_defaults)
+
+ # manifests() must only return file paths (strings).
+ manifests = parser.manifests()
+ self.assertEqual(len(manifests), 4)
+ self.assertIn(foo_path, manifests)
+ self.assertIn(bar_path, manifests)
+ self.assertIn(include_example, manifests)
+ self.assertIn(noinclude_example, manifests)
+
+ def test_include_handle_defaults_False_toml(self):
+ """
+ Test that manifest_defaults and manifests() are correct even when
+ handle_defaults is set to False. (TOML)
+ """
+ manifest = os.path.join(here, "include-example.toml")
+ foo_path = os.path.join(here, "include", "foo.toml")
+
+ parser = ManifestParser(
+ manifests=(manifest,), handle_defaults=False, rootdir=here, use_toml=True
+ )
+ ancestor_ini = os.path.relpath(manifest, parser.rootdir)
+
+ self.assertIn(manifest, parser.manifest_defaults)
+ self.assertNotIn(foo_path, parser.manifest_defaults)
+ self.assertIn((ancestor_ini, foo_path), parser.manifest_defaults)
+ self.assertEqual(
+ parser.manifest_defaults[manifest],
+ {
+ "foo": "bar",
+ "here": here,
+ },
+ )
+ self.assertEqual(
+ parser.manifest_defaults[(ancestor_ini, foo_path)],
+ {
+ "here": os.path.join(here, "include"),
+ "red": "roses",
+ "blue": "ocean",
+ "yellow": "daffodils",
+ },
+ )
+
+ def test_include_repeated_toml(self):
+ """
+ Test that repeatedly included manifests are independent of each other. (TOML)
+ """
+ include_example = os.path.join(here, "include-example.toml")
+ included_foo = os.path.join(here, "include", "foo.toml")
+
+ # In the expected output, blue and yellow have the values from foo.toml
+ # (ocean, submarine) instead of the ones from include-example.toml
+ # (violets, daffodils), because the defaults in the included file take
+ # precedence over the values from the parent.
+ include_output = """[include/crash-handling]
+foo = fleem
+
+[fleem]
+foo = bar
+
+[include/flowers]
+blue = ocean
+foo = bar
+red = roses
+yellow = submarine
+
+"""
+ included_output = """[include/flowers]
+blue = ocean
+yellow = submarine
+
+"""
+
+ parser = ManifestParser(
+ manifests=(include_example, included_foo), rootdir=here, use_toml=True
+ )
+ self.assertEqual(
+ parser.get("name"), ["crash-handling", "fleem", "flowers", "flowers"]
+ )
+ self.assertEqual(
+ [
+ (test["name"], os.path.basename(test["manifest"]))
+ for test in parser.tests
+ ],
+ [
+ ("crash-handling", "bar.toml"),
+ ("fleem", "include-example.toml"),
+ ("flowers", "foo.toml"),
+ ("flowers", "foo.toml"),
+ ],
+ )
+ self.check_included_repeat(
+ parser,
+ parser.tests[3],
+ parser.tests[2],
+ "%s%s" % (include_output, included_output),
+ True,
+ )
+
+ # Same tests, but with the load order of the manifests swapped.
+ parser = ManifestParser(
+ manifests=(included_foo, include_example), rootdir=here, use_toml=True
+ )
+ self.assertEqual(
+ parser.get("name"), ["flowers", "crash-handling", "fleem", "flowers"]
+ )
+ self.assertEqual(
+ [
+ (test["name"], os.path.basename(test["manifest"]))
+ for test in parser.tests
+ ],
+ [
+ ("flowers", "foo.toml"),
+ ("crash-handling", "bar.toml"),
+ ("fleem", "include-example.toml"),
+ ("flowers", "foo.toml"),
+ ],
+ )
+ self.check_included_repeat(
+ parser,
+ parser.tests[0],
+ parser.tests[3],
+ "%s%s" % (included_output, include_output),
+ True,
+ )
+
+ def check_included_repeat(
+ self, parser, isolated_test, included_test, expected_output, use_toml=False
+ ):
+ if use_toml:
+ include_example_filename = "include-example.toml"
+ foo_filename = "foo.toml"
+ else:
+ include_example_filename = "include-example.toml"
+ foo_filename = "foo.toml"
+ include_example = os.path.join(here, include_example_filename)
+ included_foo = os.path.join(here, "include", foo_filename)
+ ancestor_ini = os.path.relpath(include_example, parser.rootdir)
+ manifest_default_key = (ancestor_ini, included_foo)
+
+ self.assertFalse("ancestor_manifest" in isolated_test)
+ self.assertEqual(included_test["ancestor_manifest"], include_example_filename)
+
+ self.assertTrue(include_example in parser.manifest_defaults)
+ self.assertTrue(included_foo in parser.manifest_defaults)
+ self.assertTrue(manifest_default_key in parser.manifest_defaults)
+ self.assertEqual(
+ parser.manifest_defaults[manifest_default_key],
+ {
+ "foo": "bar",
+ "here": os.path.join(here, "include"),
+ "red": "roses",
+ "blue": "ocean",
+ "yellow": "daffodils",
+ },
+ )
+
+ buffer = StringIO()
+ parser.write(fp=buffer)
+ self.assertEqual(buffer.getvalue(), expected_output)
+
+ def test_invalid_path_toml(self):
+ """
+ Test invalid path should not throw when not strict (TOML)
+ """
+ manifest = os.path.join(here, "include-invalid.toml")
+ ManifestParser(manifests=(manifest,), strict=False, use_toml=True)
+
+ def test_copy_toml(self):
+ """Test our ability to copy a set of manifests (TOML)"""
+
+ tempdir = tempfile.mkdtemp()
+ include_example = os.path.join(here, "include-example.toml")
+ manifest = ManifestParser(manifests=(include_example,), use_toml=True)
+ manifest.copy(tempdir)
+ self.assertEqual(
+ sorted(os.listdir(tempdir)), ["fleem", "include", "include-example.toml"]
+ )
+ self.assertEqual(
+ sorted(os.listdir(os.path.join(tempdir, "include"))),
+ ["bar.toml", "crash-handling", "flowers", "foo.toml"],
+ )
+ from_manifest = ManifestParser(manifests=(include_example,), use_toml=True)
+ to_manifest = os.path.join(tempdir, "include-example.toml")
+ to_manifest = ManifestParser(manifests=(to_manifest,), use_toml=True)
+ self.assertEqual(to_manifest.get("name"), from_manifest.get("name"))
+ shutil.rmtree(tempdir)
+
+ def test_path_override_toml(self):
+ """You can override the path in the section too.
+ This shows that you can use a relative path"""
+ path_example = os.path.join(here, "path-example.toml")
+ manifest = ManifestParser(manifests=(path_example,), use_toml=True)
+ self.assertEqual(manifest.tests[0]["path"], os.path.join(here, "fleem"))
+
+ def test_relative_path_toml(self):
+ """
+ Relative test paths are correctly calculated. (TOML)
+ """
+ relative_path = os.path.join(here, "relative-path.toml")
+ manifest = ManifestParser(manifests=(relative_path,), use_toml=True)
+ self.assertEqual(
+ manifest.tests[0]["path"], os.path.join(os.path.dirname(here), "fleem")
+ )
+ self.assertEqual(manifest.tests[0]["relpath"], os.path.join("..", "fleem"))
+ self.assertEqual(
+ manifest.tests[1]["relpath"], os.path.join("..", "testsSIBLING", "example")
+ )
+
+ def test_path_from_fd(self):
+ """
+ Test paths are left untouched when manifest is a file-like object.
+ """
+ fp = StringIO("[section]\npath=fleem")
+ manifest = ManifestParser(manifests=(fp,))
+ self.assertEqual(manifest.tests[0]["path"], "fleem")
+ self.assertEqual(manifest.tests[0]["relpath"], "fleem")
+ self.assertEqual(manifest.tests[0]["manifest"], None)
+
+ def test_comments_toml(self):
+ """
+ ensure comments work, see
+ https://bugzilla.mozilla.org/show_bug.cgi?id=813674
+ (TOML)
+ """
+ comment_example = os.path.join(here, "comment-example.toml")
+ manifest = ManifestParser(manifests=(comment_example,), use_toml=True)
+ self.assertEqual(len(manifest.tests), 8)
+ names = [i["name"] for i in manifest.tests]
+ self.assertFalse("test_0202_app_launch_apply_update_dirlocked.js" in names)
+
+ def test_verifyDirectory_toml(self):
+ directory = os.path.join(here, "verifyDirectory")
+
+ # correct manifest
+ manifest_path = os.path.join(directory, "verifyDirectory.toml")
+ manifest = ManifestParser(manifests=(manifest_path,), use_toml=True)
+ missing = manifest.verifyDirectory(directory, extensions=(".js",))
+ self.assertEqual(missing, (set(), set()))
+
+ # manifest is missing test_1.js
+ test_1 = os.path.join(directory, "test_1.js")
+ manifest_path = os.path.join(directory, "verifyDirectory_incomplete.toml")
+ manifest = ManifestParser(manifests=(manifest_path,), use_toml=True)
+ missing = manifest.verifyDirectory(directory, extensions=(".js",))
+ self.assertEqual(missing, (set(), set([test_1])))
+
+ # filesystem is missing test_notappearinginthisfilm.js
+ missing_test = os.path.join(directory, "test_notappearinginthisfilm.js")
+ manifest_path = os.path.join(directory, "verifyDirectory_toocomplete.toml")
+ manifest = ManifestParser(manifests=(manifest_path,), use_toml=True)
+ missing = manifest.verifyDirectory(directory, extensions=(".js",))
+ self.assertEqual(missing, (set([missing_test]), set()))
+
+ def test_just_defaults_toml(self):
+ """Ensure a manifest with just a DEFAULT section exposes that data. (TOML)"""
+
+ parser = ManifestParser(use_toml=True)
+ manifest = os.path.join(here, "just-defaults.toml")
+ parser.read(manifest)
+ self.assertEqual(len(parser.tests), 0)
+ self.assertTrue(manifest in parser.manifest_defaults)
+ self.assertEqual(parser.manifest_defaults[manifest]["foo"], "bar")
+
+ def test_manifest_list_toml(self):
+ """
+ Ensure a manifest with just a DEFAULT section still returns
+ itself from the manifests() method. (TOML)
+ """
+
+ parser = ManifestParser(use_toml=True)
+ manifest = os.path.join(here, "no-tests.toml")
+ parser.read(manifest)
+ self.assertEqual(len(parser.tests), 0)
+ self.assertTrue(len(parser.manifests()) == 1)
+
+ def test_manifest_with_invalid_condition_toml(self):
+ """
+ Ensure a skip-if or similar condition with an assignment in it
+ causes errors. (TOML)
+ """
+
+ parser = ManifestParser(use_toml=True)
+ manifest = os.path.join(here, "broken-skip-if.toml")
+ with self.assertRaisesRegex(
+ Exception, "Should not assign in skip-if condition for DEFAULT"
+ ):
+ parser.read(manifest)
+
+ def test_parse_error_toml(self):
+ """
+ Verify handling of a mal-formed TOML file
+ """
+
+ parser = ManifestParser(use_toml=True)
+ manifest = os.path.join(here, "parse-error.toml")
+ with self.assertRaisesRegex(
+ Exception,
+ r".*'str' object has no attribute 'keys'.*",
+ ):
+ parser.read(manifest)
+
+ def test_parse_error_tomlkit(self):
+ """
+ Verify handling of a mal-formed TOML file
+ """
+
+ parser = ManifestParser(use_toml=True, document=True)
+ manifest = os.path.join(here, "parse-error.toml")
+ with self.assertRaisesRegex(
+ Exception,
+ r".*'String' object has no attribute 'keys'.*",
+ ):
+ parser.read(manifest)
+
+ def test_edit_manifest(self):
+ """
+ Verify reading and writing TOML manifest with tomlkit
+ """
+ parser = ManifestParser(use_toml=True, document=True)
+ before = "edit-manifest-before.toml"
+ before_path = os.path.join(here, before)
+ parser.read(before_path)
+ assert before_path in parser.source_documents
+ manifest = parser.source_documents[before_path]
+ assert manifest is not None
+ assert isinstance(manifest, TOMLDocument)
+
+ filename = "bug_20.js"
+ assert filename in manifest
+ condition1a = "os == 'mac'"
+ bug = "Bug 20"
+ manifestparser.toml.add_skip_if(manifest, filename, condition1a, bug)
+ condition1b = "os == 'windows'"
+ manifestparser.toml.add_skip_if(manifest, filename, condition1b, bug)
+
+ filename2 = "test_foo.html"
+ assert filename2 in manifest
+ condition2 = "os == 'mac' && debug"
+ manifestparser.toml.add_skip_if(manifest, filename2, condition2)
+
+ filename3 = "test_bar.html"
+ assert filename3 in manifest
+ condition3a = "tsan"
+ bug3a = "Bug 444"
+ manifestparser.toml.add_skip_if(manifest, filename3, condition3a, bug3a)
+ condition3b = "os == 'linux'" # pre-existing, should be ignored
+ bug3b = "Bug 555"
+ manifestparser.toml.add_skip_if(manifest, filename3, condition3b, bug3b)
+
+ filename4 = "bug_100.js"
+ assert filename4 in manifest
+ condition4 = "apple_catalina"
+ bug4 = "Bug 200"
+ manifestparser.toml.add_skip_if(manifest, filename4, condition4, bug4)
+
+ filename5 = "bug_3.js"
+ assert filename5 in manifest
+ condition5 = "verify"
+ bug5 = "Bug 33333"
+ manifestparser.toml.add_skip_if(manifest, filename5, condition5, bug5)
+
+ manifest_str = manifestparser.toml.alphabetize_toml_str(manifest)
+ after = "edit-manifest-after.toml"
+ after_path = os.path.join(here, after)
+ after_str = open(after_path, "r", encoding="utf-8").read()
+ assert manifest_str == after_str
+
+
+if __name__ == "__main__":
+ mozunit.main()