gecko-dev/taskcluster/taskgraph/test/test_generator.py

202 строки
7.3 KiB
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/.
from __future__ import absolute_import, print_function, unicode_literals
import pytest
import unittest
from mozunit import main
from taskgraph.generator import TaskGraphGenerator, Kind
from taskgraph.optimize import OptimizationStrategy
from taskgraph.util.templates import merge
from taskgraph import (
generator,
graph,
optimize as optimize_mod,
target_tasks as target_tasks_mod,
)
def fake_loader(kind, path, config, parameters, loaded_tasks):
for i in range(3):
dependencies = {}
if i >= 1:
dependencies['prev'] = '{}-t-{}'.format(kind, i-1)
task = {
'kind': kind,
'label': '{}-t-{}'.format(kind, i),
'attributes': {'_tasknum': str(i)},
'task': {'i': i},
'dependencies': dependencies,
}
if 'job-defaults' in config:
task = merge(config['job-defaults'], task)
yield task
class FakeKind(Kind):
def _get_loader(self):
return fake_loader
def load_tasks(self, parameters, loaded_tasks):
FakeKind.loaded_kinds.append(self.name)
return super(FakeKind, self).load_tasks(parameters, loaded_tasks)
class WithFakeKind(TaskGraphGenerator):
def _load_kinds(self, graph_config):
for kind_name, cfg in self.parameters['_kinds']:
config = {
'transforms': [],
}
if cfg:
config.update(cfg)
yield FakeKind(kind_name, '/fake', config, graph_config)
def fake_load_graph_config(root_dir):
return {}
class FakeParameters(dict):
strict = True
class FakeOptimization(OptimizationStrategy):
def __init__(self, mode, *args, **kwargs):
super(FakeOptimization, self).__init__(*args, **kwargs)
self.mode = mode
def should_remove_task(self, task, params, arg):
if self.mode == 'always':
return True
if self.mode == 'even':
return task.task['i'] % 2 == 0
if self.mode == 'odd':
return task.task['i'] % 2 != 0
return False
class TestGenerator(unittest.TestCase):
@pytest.fixture(autouse=True)
def patch(self, monkeypatch):
self.patch = monkeypatch
def maketgg(self, target_tasks=None, kinds=[('_fake', [])], params=None):
params = params or {}
FakeKind.loaded_kinds = []
self.target_tasks = target_tasks or []
def target_tasks_method(full_task_graph, parameters, graph_config):
return self.target_tasks
def make_fake_strategies():
return {mode: FakeOptimization(mode)
for mode in ('always', 'never', 'even', 'odd')}
target_tasks_mod._target_task_methods['test_method'] = target_tasks_method
self.patch.setattr(optimize_mod, '_make_default_strategies', make_fake_strategies)
parameters = FakeParameters({
'_kinds': kinds,
'target_tasks_method': 'test_method',
'try_mode': None,
})
parameters.update(params)
self.patch.setattr(generator, 'load_graph_config', fake_load_graph_config)
return WithFakeKind('/root', parameters)
def test_kind_ordering(self):
"When task kinds depend on each other, they are loaded in postorder"
self.tgg = self.maketgg(kinds=[
('_fake3', {'kind-dependencies': ['_fake2', '_fake1']}),
('_fake2', {'kind-dependencies': ['_fake1']}),
('_fake1', {'kind-dependencies': []}),
])
self.tgg._run_until('full_task_set')
self.assertEqual(FakeKind.loaded_kinds, ['_fake1', '_fake2', '_fake3'])
def test_full_task_set(self):
"The full_task_set property has all tasks"
self.tgg = self.maketgg()
self.assertEqual(self.tgg.full_task_set.graph,
graph.Graph({'_fake-t-0', '_fake-t-1', '_fake-t-2'}, set()))
self.assertEqual(sorted(self.tgg.full_task_set.tasks.keys()),
sorted(['_fake-t-0', '_fake-t-1', '_fake-t-2']))
def test_full_task_graph(self):
"The full_task_graph property has all tasks, and links"
self.tgg = self.maketgg()
self.assertEqual(self.tgg.full_task_graph.graph,
graph.Graph({'_fake-t-0', '_fake-t-1', '_fake-t-2'},
{
('_fake-t-1', '_fake-t-0', 'prev'),
('_fake-t-2', '_fake-t-1', 'prev'),
}))
self.assertEqual(sorted(self.tgg.full_task_graph.tasks.keys()),
sorted(['_fake-t-0', '_fake-t-1', '_fake-t-2']))
def test_target_task_set(self):
"The target_task_set property has the targeted tasks"
self.tgg = self.maketgg(['_fake-t-1'])
self.assertEqual(self.tgg.target_task_set.graph,
graph.Graph({'_fake-t-1'}, set()))
self.assertEqual(self.tgg.target_task_set.tasks.keys(),
['_fake-t-1'])
def test_target_task_graph(self):
"The target_task_graph property has the targeted tasks and deps"
self.tgg = self.maketgg(['_fake-t-1'])
self.assertEqual(self.tgg.target_task_graph.graph,
graph.Graph({'_fake-t-0', '_fake-t-1'},
{('_fake-t-1', '_fake-t-0', 'prev')}))
self.assertEqual(sorted(self.tgg.target_task_graph.tasks.keys()),
sorted(['_fake-t-0', '_fake-t-1']))
def test_always_target_tasks(self):
"The target_task_graph includes tasks with 'always_target'"
tgg_args = {
'target_tasks': ['_fake-t-0', '_fake-t-1', '_ignore-t-0', '_ignore-t-1'],
'kinds': [
('_fake', {'job-defaults': {'optimization': {'odd': None}}}),
('_ignore', {'job-defaults': {
'attributes': {'always_target': True},
'optimization': {'even': None},
}}),
],
'params': {'optimize_target_tasks': False},
}
self.tgg = self.maketgg(**tgg_args)
self.assertEqual(
sorted(self.tgg.target_task_set.tasks.keys()),
sorted(['_fake-t-0', '_fake-t-1', '_ignore-t-0', '_ignore-t-1']))
self.assertEqual(
sorted(self.tgg.target_task_graph.tasks.keys()),
sorted(['_fake-t-0', '_fake-t-1', '_ignore-t-0', '_ignore-t-1', '_ignore-t-2']))
self.assertEqual(
sorted([t.label for t in self.tgg.optimized_task_graph.tasks.values()]),
sorted(['_fake-t-0', '_fake-t-1', '_ignore-t-0', '_ignore-t-1']))
def test_optimized_task_graph(self):
"The optimized task graph contains task ids"
self.tgg = self.maketgg(['_fake-t-2'])
tid = self.tgg.label_to_taskid
self.assertEqual(
self.tgg.optimized_task_graph.graph,
graph.Graph({tid['_fake-t-0'], tid['_fake-t-1'], tid['_fake-t-2']}, {
(tid['_fake-t-1'], tid['_fake-t-0'], 'prev'),
(tid['_fake-t-2'], tid['_fake-t-1'], 'prev'),
}))
if __name__ == '__main__':
main()