Bug 1380338 - Convert taskgraph unit tests to the |mach python-test| framework, r?dustin draft
authorAndrew Halberstadt <ahalberstadt@mozilla.com>
Wed, 12 Jul 2017 10:47:14 -0400
changeset 608295 11561de67c862c0b48fd4b5a37d30b57f8f51b77
parent 607967 30ea2905130e85f9e1d8d56fa3097901eec6514b
child 608296 dd0ac8c2e6b3ac99f2c1c5d39b7e39d227f0d99e
push id68234
push userahalberstadt@mozilla.com
push dateThu, 13 Jul 2017 12:48:03 +0000
reviewersdustin
bugs1380338
milestone56.0a1
Bug 1380338 - Convert taskgraph unit tests to the |mach python-test| framework, r?dustin These tests can now be run with: ./mach python-test taskcluster/taskgraph or: ./mach python-test taskcluster They can now run in parallel by passing in -j. MozReview-Commit-ID: JXeZV8B04Sf
js/src/make-source-package.sh
taskcluster/ci/source-test/python-tests.yml
taskcluster/mach_commands.py
taskcluster/moz.build
taskcluster/taskgraph/test/python.ini
taskcluster/taskgraph/test/test_create.py
taskcluster/taskgraph/test/test_decision.py
taskcluster/taskgraph/test/test_files_changed.py
taskcluster/taskgraph/test/test_graph.py
taskcluster/taskgraph/test/test_morph.py
taskcluster/taskgraph/test/test_optimize.py
taskcluster/taskgraph/test/test_parameters.py
taskcluster/taskgraph/test/test_target_tasks.py
taskcluster/taskgraph/test/test_taskgraph.py
taskcluster/taskgraph/test/test_try_option_syntax.py
taskcluster/taskgraph/test/test_util_attributes.py
taskcluster/taskgraph/test/test_util_docker.py
taskcluster/taskgraph/test/test_util_python_path.py
taskcluster/taskgraph/test/test_util_treeherder.py
taskcluster/taskgraph/test/test_util_yaml.py
--- a/js/src/make-source-package.sh
+++ b/js/src/make-source-package.sh
@@ -69,18 +69,19 @@ case $cmd in
     cp -pPR ${TOPSRCDIR}/configure.py \
        ${TOPSRCDIR}/moz.configure \
        ${TOPSRCDIR}/test.mozbuild \
        ${tgtpath}
 
     cp -pPR ${TOPSRCDIR}/js/moz.configure ${tgtpath}/js
     cp -pPR ${TOPSRCDIR}/js/ffi.configure ${tgtpath}/js
 
-    mkdir -p ${tgtpath}/taskcluster
+    mkdir -p ${tgtpath}/taskcluster/taskgraph
     cp -pPR ${TOPSRCDIR}/taskcluster/moz.build ${tgtpath}/taskcluster/
+    cp -pPR ${TOPSRCDIR}/taskcluster/taskgraph/test ${tgtpath}/taskcluster/taskgraph/
 
     # copy the embedded icu
     ${MKDIR} -p ${tgtpath}/intl
     cp -pPR ${TOPSRCDIR}/intl/icu ${tgtpath}/intl
 
     # copy main moz.build and Makefile.in
     cp -pPR ${TOPSRCDIR}/Makefile.in ${TOPSRCDIR}/moz.build ${tgtpath}
 
--- a/taskcluster/ci/source-test/python-tests.yml
+++ b/taskcluster/ci/source-test/python-tests.yml
@@ -6,17 +6,17 @@ taskgraph-tests:
         kind: test
         tier: 2
     worker-type: aws-provisioner-v1/gecko-t-linux-xlarge
     worker:
         docker-image: {in-tree: "lint"}
         max-run-time: 1800
     run:
         using: mach
-        mach: taskgraph python-tests
+        mach: python-test --subsuite taskgraph
     when:
         files-changed:
             - 'taskcluster/**/*.py'
             - 'config/mozunit.py'
             - 'python/mach/**/*.py'
 
 marionette-harness:
     description: testing/marionette/harness unit tests
--- a/taskcluster/mach_commands.py
+++ b/taskcluster/mach_commands.py
@@ -65,27 +65,16 @@ class MachCommands(MachCommandBase):
              description="Manipulate TaskCluster task graphs defined in-tree")
     def taskgraph(self):
         """The taskgraph subcommands all relate to the generation of task graphs
         for Gecko continuous integration.  A task graph is a set of tasks linked
         by dependencies: for example, a binary must be built before it is tested,
         and that build may further depend on various toolchains, libraries, etc.
         """
 
-    @SubCommand('taskgraph', 'python-tests',
-                description='Run the taskgraph unit tests')
-    def taskgraph_python_tests(self, **options):
-        import unittest
-        import mozunit
-        suite = unittest.defaultTestLoader.discover('taskgraph.test')
-        runner = mozunit.MozTestRunner(verbosity=2)
-        result = runner.run(suite)
-        if not result.wasSuccessful():
-            sys.exit(1)
-
     @ShowTaskGraphSubCommand('taskgraph', 'tasks',
                              description="Show all tasks in the taskgraph")
     def taskgraph_tasks(self, **options):
         return self.show_taskgraph('full_task_set', options)
 
     @ShowTaskGraphSubCommand('taskgraph', 'full',
                              description="Show the full taskgraph")
     def taskgraph_full(self, **options):
--- a/taskcluster/moz.build
+++ b/taskcluster/moz.build
@@ -21,9 +21,12 @@ with Files('docs/**'):
 
 #NOTE: scripts/* files included in docker images
 with Files('scripts/**'):
     BUG_COMPONENT = ('Taskcluster', 'Docker Images')
 
 with Files('taskgraph/**'):
     BUG_COMPONENT = ('Taskcluster', 'Task Configuration')
 
+PYTHON_UNITTEST_MANIFESTS += [
+    'taskgraph/test/python.ini',
+]
 SPHINX_TREES['taskcluster'] = 'docs'
new file mode 100644
--- /dev/null
+++ b/taskcluster/taskgraph/test/python.ini
@@ -0,0 +1,24 @@
+[DEFAULT]
+subsuite = taskgraph
+
+[test_create.py]
+[test_cron_util.py]
+[test_decision.py]
+[test_files_changed.py]
+[test_generator.py]
+[test_graph.py]
+[test_morph.py]
+[test_optimize.py]
+[test_parameters.py]
+[test_target_tasks.py]
+[test_taskgraph.py]
+[test_transforms_base.py]
+[test_try_option_syntax.py]
+[test_util_attributes.py]
+[test_util_docker.py]
+[test_util_python_path.py]
+[test_util_schema.py]
+[test_util_templates.py]
+[test_util_time.py]
+[test_util_treeherder.py]
+[test_util_yaml.py]
--- a/taskcluster/taskgraph/test/test_create.py
+++ b/taskcluster/taskgraph/test/test_create.py
@@ -2,20 +2,20 @@
 # 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/.
 
 from __future__ import absolute_import, print_function, unicode_literals
 
 import unittest
 import os
 
-from .. import create
-from ..graph import Graph
-from ..taskgraph import TaskGraph
-from ..task import Task
+from taskgraph import create
+from taskgraph.graph import Graph
+from taskgraph.taskgraph import TaskGraph
+from taskgraph.task import Task
 
 from mozunit import main
 
 
 class TestCreate(unittest.TestCase):
 
     def setUp(self):
         self.old_task_id = os.environ.get('TASK_ID')
--- a/taskcluster/taskgraph/test/test_decision.py
+++ b/taskcluster/taskgraph/test/test_decision.py
@@ -6,17 +6,17 @@ from __future__ import absolute_import, 
 
 import os
 import json
 import yaml
 import shutil
 import unittest
 import tempfile
 
-from .. import decision
+from taskgraph import decision
 from mozunit import main
 
 
 class TestDecision(unittest.TestCase):
 
     def test_write_artifact_json(self):
         data = [{'some': 'data'}]
         tmpdir = tempfile.mkdtemp()
--- a/taskcluster/taskgraph/test/test_files_changed.py
+++ b/taskcluster/taskgraph/test/test_files_changed.py
@@ -3,17 +3,18 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 from __future__ import absolute_import, print_function, unicode_literals
 
 import json
 import os
 import unittest
 
-from .. import files_changed
+from taskgraph import files_changed
+from mozunit import main
 
 PARAMS = {
     'head_repository': 'https://hg.mozilla.org/mozilla-central',
     'head_rev': 'a14f88a9af7a',
 }
 
 FILES_CHANGED = [
     'devtools/client/debugger/new/index.html',
@@ -66,8 +67,12 @@ class TestCheck(unittest.TestCase):
     def test_check_no_params(self):
         self.assertTrue(files_changed.check({}, ["ignored"]))
 
     def test_check_no_match(self):
         self.assertFalse(files_changed.check(PARAMS, ["nosuch/**"]))
 
     def test_check_match(self):
         self.assertTrue(files_changed.check(PARAMS, ["devtools/**"]))
+
+
+if __name__ == '__main__':
+    main()
--- a/taskcluster/taskgraph/test/test_graph.py
+++ b/taskcluster/taskgraph/test/test_graph.py
@@ -3,17 +3,17 @@
 # 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/.
 
 from __future__ import absolute_import, print_function, unicode_literals
 
 import unittest
 
-from ..graph import Graph
+from taskgraph.graph import Graph
 from mozunit import main
 
 
 class TestGraph(unittest.TestCase):
 
     tree = Graph(set(['a', 'b', 'c', 'd', 'e', 'f', 'g']), {
         ('a', 'b', 'L'),
         ('a', 'c', 'L'),
--- a/taskcluster/taskgraph/test/test_morph.py
+++ b/taskcluster/taskgraph/test/test_morph.py
@@ -1,20 +1,20 @@
 # 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/.
 
 from __future__ import absolute_import, print_function, unicode_literals
 
 import unittest
 
-from .. import morph
-from ..graph import Graph
-from ..taskgraph import TaskGraph
-from ..task import Task
+from taskgraph import morph
+from taskgraph.graph import Graph
+from taskgraph.taskgraph import TaskGraph
+from taskgraph.task import Task
 
 from mozunit import main
 
 
 class TestIndexTask(unittest.TestCase):
 
     def test_make_index_tasks(self):
         task_def = {
--- a/taskcluster/taskgraph/test/test_optimize.py
+++ b/taskcluster/taskgraph/test/test_optimize.py
@@ -1,21 +1,22 @@
 # 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/.
 
 from __future__ import absolute_import, print_function, unicode_literals
 
 import unittest
 
-from ..optimize import optimize_task_graph, resolve_task_references, optimization
-from ..optimize import annotate_task_graph, get_subgraph
-from ..taskgraph import TaskGraph
-from .. import graph
-from ..task import Task
+from taskgraph.optimize import optimize_task_graph, resolve_task_references, optimization
+from taskgraph.optimize import annotate_task_graph, get_subgraph
+from taskgraph.taskgraph import TaskGraph
+from taskgraph import graph
+from taskgraph.task import Task
+from mozunit import main
 
 
 class TestResolveTaskReferences(unittest.TestCase):
 
     def do(self, input, output):
         taskid_for_edge_name = {'edge%d' % n: 'tid%d' % n for n in range(1, 4)}
         self.assertEqual(resolve_task_references('subject', input, taskid_for_edge_name), output)
 
@@ -237,8 +238,12 @@ class TestOptimize(unittest.TestCase):
             self.make_task('task3', ['no-optimize']),
             ('task2', 'task1', 'build'),
             ('task2', 'task3', 'image'),
         )
         opt, label_to_taskid = optimize_task_graph(input, {}, set())
         self.assertEqual(opt.graph, graph.Graph(
             {label_to_taskid['task2'], label_to_taskid['task3']},
             {(label_to_taskid['task2'], label_to_taskid['task3'], 'image')}))
+
+
+if __name__ == '__main__':
+    main()
--- a/taskcluster/taskgraph/test/test_parameters.py
+++ b/taskcluster/taskgraph/test/test_parameters.py
@@ -1,17 +1,17 @@
 # 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/.
 
 from __future__ import absolute_import, print_function, unicode_literals
 
 import unittest
 
-from ..parameters import Parameters, load_parameters_file, PARAMETER_NAMES
+from taskgraph.parameters import Parameters, load_parameters_file, PARAMETER_NAMES
 from mozunit import main, MockedOpen
 
 
 class TestParameters(unittest.TestCase):
 
     vals = {n: n for n in PARAMETER_NAMES}
 
     def test_Parameters_immutable(self):
--- a/taskcluster/taskgraph/test/test_target_tasks.py
+++ b/taskcluster/taskgraph/test/test_target_tasks.py
@@ -1,21 +1,21 @@
 # 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/.
 
 from __future__ import absolute_import, print_function, unicode_literals
 
 import unittest
 
-from .. import target_tasks
-from .. import try_option_syntax
-from ..graph import Graph
-from ..taskgraph import TaskGraph
-from ..task import Task
+from taskgraph import target_tasks
+from taskgraph import try_option_syntax
+from taskgraph.graph import Graph
+from taskgraph.taskgraph import TaskGraph
+from taskgraph.task import Task
 from mozunit import main
 
 
 class FakeTryOptionSyntax(object):
 
     def __init__(self, message, task_graph):
         self.trigger_tests = 0
         self.talos_trigger_tests = 0
--- a/taskcluster/taskgraph/test/test_taskgraph.py
+++ b/taskcluster/taskgraph/test/test_taskgraph.py
@@ -1,19 +1,19 @@
 # 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/.
 
 from __future__ import absolute_import, print_function, unicode_literals
 
 import unittest
 
-from ..graph import Graph
-from ..task import Task
-from ..taskgraph import TaskGraph
+from taskgraph.graph import Graph
+from taskgraph.task import Task
+from taskgraph.taskgraph import TaskGraph
 from mozunit import main
 
 
 class TestTaskGraph(unittest.TestCase):
 
     maxDiff = None
 
     def test_taskgraph_to_json(self):
--- a/taskcluster/taskgraph/test/test_try_option_syntax.py
+++ b/taskcluster/taskgraph/test/test_try_option_syntax.py
@@ -1,21 +1,21 @@
 # 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/.
 
 from __future__ import absolute_import, print_function, unicode_literals
 
 import unittest
 
-from ..try_option_syntax import TryOptionSyntax
-from ..try_option_syntax import RIDEALONG_BUILDS
-from ..graph import Graph
-from ..taskgraph import TaskGraph
-from ..task import Task
+from taskgraph.try_option_syntax import TryOptionSyntax
+from taskgraph.try_option_syntax import RIDEALONG_BUILDS
+from taskgraph.graph import Graph
+from taskgraph.taskgraph import TaskGraph
+from taskgraph.task import Task
 from mozunit import main
 
 
 def unittest_task(n, tp, bt='opt'):
     return (n, Task('test', n, {
         'unittest_try_name': n,
         'test_platform': tp.split('/')[0],
         'build_type': bt,
--- a/taskcluster/taskgraph/test/test_util_attributes.py
+++ b/taskcluster/taskgraph/test/test_util_attributes.py
@@ -4,16 +4,17 @@
 # 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 unittest
 from taskgraph.util.attributes import (
     attrmatch,
     match_run_on_projects,
 )
+from mozunit import main
 
 
 class Attrmatch(unittest.TestCase):
 
     def test_trivial_match(self):
         """Given no conditions, anything matches"""
         self.assertTrue(attrmatch({}))
 
@@ -84,8 +85,12 @@ class MatchRunOnProjects(unittest.TestCa
         self.assertTrue(match_run_on_projects('try', ['release', 'try', 'date']))
         self.assertFalse(match_run_on_projects('larch', ['release', 'try', 'date']))
         self.assertTrue(match_run_on_projects('date', ['release', 'try', 'date']))
         self.assertFalse(match_run_on_projects('autoland', ['release', 'try', 'date']))
         self.assertFalse(match_run_on_projects('mozilla-inbound', ['release', 'try', 'date']))
         self.assertTrue(match_run_on_projects('mozilla-central', ['release', 'try', 'date']))
         self.assertTrue(match_run_on_projects('mozilla-beta', ['release', 'try', 'date']))
         self.assertTrue(match_run_on_projects('mozilla-release', ['release', 'try', 'date']))
+
+
+if __name__ == '__main__':
+    main()
--- a/taskcluster/taskgraph/test/test_util_docker.py
+++ b/taskcluster/taskgraph/test/test_util_docker.py
@@ -6,18 +6,18 @@ from __future__ import absolute_import, 
 
 import os
 import shutil
 import stat
 import tarfile
 import tempfile
 import unittest
 
-from ..util import docker
-from mozunit import MockedOpen
+from taskgraph.util import docker
+from mozunit import main, MockedOpen
 
 
 MODE_STANDARD = stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH
 
 
 class TestDocker(unittest.TestCase):
 
     def test_generate_context_hash(self):
@@ -205,8 +205,12 @@ class TestDocker(unittest.TestCase):
                     'my_image/Dockerfile',
                     'my_image/topsrcdir/extra/file0',
                     'my_image/topsrcdir/extra/file1',
                     'my_image/topsrcdir/extra/file2',
                     'my_image/topsrcdir/file0',
                 ])
         finally:
             shutil.rmtree(tmp)
+
+
+if __name__ == '__main__':
+    main()
--- a/taskcluster/taskgraph/test/test_util_python_path.py
+++ b/taskcluster/taskgraph/test/test_util_python_path.py
@@ -1,16 +1,17 @@
 # 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/.
 
 from __future__ import absolute_import, print_function, unicode_literals
 
 import unittest
-from ..util import python_path
+from taskgraph.util import python_path
+from mozunit import main
 
 
 class TestObject(object):
 
     testClassProperty = object()
 
 
 class TestPythonPath(unittest.TestCase):
@@ -21,11 +22,16 @@ class TestPythonPath(unittest.TestCase):
 
     def test_find_object_no_such_object(self):
         """find_object raises AttributeError for a nonexistent object"""
         self.assertRaises(AttributeError, python_path.find_object,
                           "taskgraph.test.test_util_python_path:NoSuchObject")
 
     def test_find_object_exists(self):
         """find_object finds an existing object"""
+        from taskgraph.test.test_util_python_path import TestObject
         obj = python_path.find_object(
             "taskgraph.test.test_util_python_path:TestObject.testClassProperty")
         self.assertIs(obj, TestObject.testClassProperty)
+
+
+if __name__ == '__main__':
+    main()
--- a/taskcluster/taskgraph/test/test_util_treeherder.py
+++ b/taskcluster/taskgraph/test/test_util_treeherder.py
@@ -1,23 +1,28 @@
 # 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/.
 
 from __future__ import absolute_import, print_function, unicode_literals
 
 import unittest
 from taskgraph.util.treeherder import split_symbol, join_symbol
+from mozunit import main
 
 
 class TestSymbols(unittest.TestCase):
 
     def test_split_no_group(self):
         self.assertEqual(split_symbol('xy'), ('?', 'xy'))
 
     def test_split_with_group(self):
         self.assertEqual(split_symbol('ab(xy)'), ('ab', 'xy'))
 
     def test_join_no_group(self):
         self.assertEqual(join_symbol('?', 'xy'), 'xy')
 
     def test_join_with_group(self):
         self.assertEqual(join_symbol('ab', 'xy'), 'ab(xy)')
+
+
+if __name__ == '__main__':
+    main()
--- a/taskcluster/taskgraph/test/test_util_yaml.py
+++ b/taskcluster/taskgraph/test/test_util_yaml.py
@@ -1,23 +1,27 @@
 # 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/.
 
 from __future__ import absolute_import, print_function, unicode_literals
 
 import unittest
 
-from ..util import yaml
-from mozunit import MockedOpen
+from taskgraph.util import yaml
+from mozunit import main, MockedOpen
 
 FOO_YML = """\
 prop:
     - val1
 """
 
 
 class TestYaml(unittest.TestCase):
 
     def test_load(self):
         with MockedOpen({'/dir1/dir2/foo.yml': FOO_YML}):
             self.assertEqual(yaml.load_yaml("/dir1/dir2", "foo.yml"),
                              {'prop': ['val1']})
+
+
+if __name__ == '__main__':
+    main()