|  | #!/usr/bin/python | 
|  | # Copyright 2017 The Chromium Authors. All rights reserved. | 
|  | # Use of this source code is governed by a BSD-style license that can be | 
|  | # found in the LICENSE file. | 
|  |  | 
|  | """Tests for generate_buildbot_json.py.""" | 
|  |  | 
|  | import argparse | 
|  | import os | 
|  | import unittest | 
|  |  | 
|  | import generate_buildbot_json | 
|  |  | 
|  |  | 
|  | class FakeBBGen(generate_buildbot_json.BBJSONGenerator): | 
|  | def __init__(self, waterfalls, test_suites, exceptions, luci_milo_cfg): | 
|  | super(FakeBBGen, self).__init__() | 
|  | self.files = { | 
|  | 'waterfalls.pyl': waterfalls, | 
|  | 'test_suites.pyl': test_suites, | 
|  | 'test_suite_exceptions.pyl': exceptions, | 
|  | os.path.join( '..', '..', 'infra', 'config', 'global', 'luci-milo.cfg'): | 
|  | luci_milo_cfg, | 
|  | } | 
|  |  | 
|  | def read_file(self, relative_path): | 
|  | return self.files[relative_path] | 
|  |  | 
|  | def write_file(self, relative_path, contents): | 
|  | self.files[relative_path] = contents | 
|  |  | 
|  |  | 
|  | FOO_GTESTS_WATERFALL = """\ | 
|  | [ | 
|  | { | 
|  | 'name': 'chromium.test', | 
|  | 'machines': { | 
|  | 'Fake Tester': { | 
|  | 'swarming': { | 
|  | 'dimension_sets': [ | 
|  | { | 
|  | 'kvm': '1', | 
|  | }, | 
|  | ], | 
|  | }, | 
|  | 'test_suites': { | 
|  | 'gtest_tests': 'foo_tests', | 
|  | }, | 
|  | }, | 
|  | }, | 
|  | }, | 
|  | ] | 
|  | """ | 
|  |  | 
|  | FOO_GTESTS_WITH_ENABLE_FEATURES_WATERFALL = """\ | 
|  | [ | 
|  | { | 
|  | 'name': 'chromium.test', | 
|  | 'machines': { | 
|  | 'Fake Tester': { | 
|  | 'test_suites': { | 
|  | 'gtest_tests': 'foo_tests', | 
|  | }, | 
|  | 'args': [ | 
|  | '--enable-features=Baz', | 
|  | ], | 
|  | }, | 
|  | }, | 
|  | }, | 
|  | ] | 
|  | """ | 
|  |  | 
|  | FOO_GTESTS_MULTI_DIMENSION_WATERFALL = """\ | 
|  | [ | 
|  | { | 
|  | 'name': 'chromium.test', | 
|  | 'machines': { | 
|  | 'Fake Tester': { | 
|  | 'swarming': { | 
|  | 'dimension_sets': [ | 
|  | { | 
|  | "gpu": "none", | 
|  | "os": "1", | 
|  | }, | 
|  | ], | 
|  | }, | 
|  | 'use_multi_dimension_trigger_script': True, | 
|  | 'alternate_swarming_dimensions': [ | 
|  | { | 
|  | "gpu": "none", | 
|  | "os": "2", | 
|  | }, | 
|  | ], | 
|  | 'test_suites': { | 
|  | 'gtest_tests': 'foo_tests', | 
|  | }, | 
|  | }, | 
|  | }, | 
|  | }, | 
|  | ] | 
|  | """ | 
|  |  | 
|  | COMPOSITION_GTEST_SUITE_WATERFALL = """\ | 
|  | [ | 
|  | { | 
|  | 'name': 'chromium.test', | 
|  | 'machines': { | 
|  | 'Fake Tester': { | 
|  | 'test_suites': { | 
|  | 'gtest_tests': 'composition_tests', | 
|  | }, | 
|  | }, | 
|  | }, | 
|  | }, | 
|  | ] | 
|  | """ | 
|  |  | 
|  | COMPOSITION_GTEST_SUITE_WITH_ARGS_WATERFALL = """\ | 
|  | [ | 
|  | { | 
|  | 'name': 'chromium.test', | 
|  | 'machines': { | 
|  | 'Fake Tester': { | 
|  | 'test_suites': { | 
|  | 'gtest_tests': 'composition_tests', | 
|  | }, | 
|  | 'args': [ | 
|  | '--this-is-an-argument', | 
|  | ], | 
|  | }, | 
|  | }, | 
|  | }, | 
|  | ] | 
|  | """ | 
|  |  | 
|  | FOO_ISOLATED_SCRIPTS_WATERFALL = """\ | 
|  | [ | 
|  | { | 
|  | 'name': 'chromium.test', | 
|  | 'machines': { | 
|  | 'Fake Tester': { | 
|  | 'test_suites': { | 
|  | 'isolated_scripts': 'composition_tests', | 
|  | }, | 
|  | }, | 
|  | }, | 
|  | }, | 
|  | ] | 
|  | """ | 
|  |  | 
|  | FOO_SCRIPT_WATERFALL = """\ | 
|  | [ | 
|  | { | 
|  | 'name': 'chromium.test', | 
|  | 'machines': { | 
|  | 'Fake Tester': { | 
|  | 'test_suites': { | 
|  | 'scripts': 'foo_scripts', | 
|  | }, | 
|  | }, | 
|  | }, | 
|  | }, | 
|  | ] | 
|  | """ | 
|  |  | 
|  | FOO_JUNIT_WATERFALL = """\ | 
|  | [ | 
|  | { | 
|  | 'name': 'chromium.test', | 
|  | 'machines': { | 
|  | 'Fake Tester': { | 
|  | 'test_suites': { | 
|  | 'junit_tests': 'composition_tests', | 
|  | }, | 
|  | }, | 
|  | }, | 
|  | }, | 
|  | ] | 
|  | """ | 
|  |  | 
|  | FOO_CTS_WATERFALL = """\ | 
|  | [ | 
|  | { | 
|  | 'name': 'chromium.test', | 
|  | 'machines': { | 
|  | 'Fake Tester': { | 
|  | 'test_suites': { | 
|  | 'cts_tests': 'foo_cts_tests', | 
|  | }, | 
|  | }, | 
|  | }, | 
|  | }, | 
|  | ] | 
|  | """ | 
|  |  | 
|  | FOO_INSTRUMENTATION_TEST_WATERFALL = """\ | 
|  | [ | 
|  | { | 
|  | 'name': 'chromium.test', | 
|  | 'machines': { | 
|  | 'Fake Tester': { | 
|  | 'test_suites': { | 
|  | 'instrumentation_tests': 'composition_tests', | 
|  | }, | 
|  | }, | 
|  | }, | 
|  | }, | 
|  | ] | 
|  | """ | 
|  |  | 
|  | UNKNOWN_TEST_SUITE_WATERFALL = """\ | 
|  | [ | 
|  | { | 
|  | 'name': 'chromium.test', | 
|  | 'machines': { | 
|  | 'Fake Tester': { | 
|  | 'test_suites': { | 
|  | 'gtest_tests': 'baz_tests', | 
|  | }, | 
|  | }, | 
|  | }, | 
|  | }, | 
|  | ] | 
|  | """ | 
|  |  | 
|  | UNKNOWN_TEST_SUITE_TYPE_WATERFALL = """\ | 
|  | [ | 
|  | { | 
|  | 'name': 'chromium.test', | 
|  | 'machines': { | 
|  | 'Fake Tester': { | 
|  | 'test_suites': { | 
|  | 'gtest_tests': 'foo_tests', | 
|  | 'foo_test_type': 'foo_tests', | 
|  | }, | 
|  | }, | 
|  | }, | 
|  | }, | 
|  | ] | 
|  | """ | 
|  |  | 
|  | ANDROID_WATERFALL = """\ | 
|  | [ | 
|  | { | 
|  | 'name': 'chromium.test', | 
|  | 'machines': { | 
|  | 'Android Builder': { | 
|  | 'additional_compile_targets': [ | 
|  | 'bar_test', | 
|  | ], | 
|  | }, | 
|  | 'Fake Android K Tester': { | 
|  | 'additional_compile_targets': [ | 
|  | 'bar_test', | 
|  | ], | 
|  | 'swarming': { | 
|  | 'dimension_sets': [ | 
|  | { | 
|  | 'device_os': 'KTU84P', | 
|  | 'device_type': 'hammerhead', | 
|  | }, | 
|  | ], | 
|  | }, | 
|  | 'os_type': 'android', | 
|  | 'skip_device_recovery': True, | 
|  | 'test_suites': { | 
|  | 'gtest_tests': 'foo_tests', | 
|  | }, | 
|  | }, | 
|  | 'Fake Android L Tester': { | 
|  | 'swarming': { | 
|  | 'dimension_sets': [ | 
|  | { | 
|  | 'device_os': 'KTU84P', | 
|  | 'device_type': 'hammerhead', | 
|  | }, | 
|  | ], | 
|  | }, | 
|  | 'os_type': 'android', | 
|  | 'skip_merge_script': True, | 
|  | 'skip_output_links': True, | 
|  | 'test_suites': { | 
|  | 'gtest_tests': 'foo_tests', | 
|  | }, | 
|  | }, | 
|  | 'Fake Android M Tester': { | 
|  | 'swarming': { | 
|  | 'dimension_sets': [ | 
|  | { | 
|  | 'device_os': 'MMB29Q', | 
|  | 'device_type': 'bullhead', | 
|  | }, | 
|  | ], | 
|  | }, | 
|  | 'os_type': 'android', | 
|  | 'use_swarming': False, | 
|  | 'test_suites': { | 
|  | 'gtest_tests': 'foo_tests', | 
|  | }, | 
|  | }, | 
|  | }, | 
|  | }, | 
|  | ] | 
|  | """ | 
|  |  | 
|  | UNKNOWN_BOT_GTESTS_WATERFALL = """\ | 
|  | [ | 
|  | { | 
|  | 'name': 'chromium.test', | 
|  | 'machines': { | 
|  | 'Unknown Bot': { | 
|  | 'test_suites': { | 
|  | 'gtest_tests': 'foo_tests', | 
|  | }, | 
|  | }, | 
|  | }, | 
|  | }, | 
|  | ] | 
|  | """ | 
|  |  | 
|  | FOO_TEST_SUITE = """\ | 
|  | { | 
|  | 'foo_tests': { | 
|  | 'foo_test': { | 
|  | 'swarming': { | 
|  | 'dimension_sets': [ | 
|  | { | 
|  | 'integrity': 'high', | 
|  | } | 
|  | ], | 
|  | 'expiration': 120, | 
|  | }, | 
|  | }, | 
|  | }, | 
|  | } | 
|  | """ | 
|  |  | 
|  | FOO_TEST_SUITE_WITH_ARGS = """\ | 
|  | { | 
|  | 'foo_tests': { | 
|  | 'foo_test': { | 
|  | 'args': [ | 
|  | '--c_arg', | 
|  | ], | 
|  | }, | 
|  | }, | 
|  | } | 
|  | """ | 
|  |  | 
|  | FOO_TEST_SUITE_WITH_ENABLE_FEATURES = """\ | 
|  | { | 
|  | 'foo_tests': { | 
|  | 'foo_test': { | 
|  | 'args': [ | 
|  | '--enable-features=Foo,Bar', | 
|  | ], | 
|  | }, | 
|  | }, | 
|  | } | 
|  | """ | 
|  |  | 
|  | FOO_SCRIPT_SUITE = """\ | 
|  | { | 
|  | 'foo_scripts': { | 
|  | 'foo_test': { | 
|  | 'script': 'foo.py', | 
|  | }, | 
|  | 'bar_test': { | 
|  | 'script': 'bar.py', | 
|  | }, | 
|  | }, | 
|  | } | 
|  | """ | 
|  |  | 
|  | FOO_CTS_SUITE = """\ | 
|  | { | 
|  | 'foo_cts_tests': { | 
|  | 'arch': 'arm64', | 
|  | 'platform': 'L', | 
|  | }, | 
|  | } | 
|  | """ | 
|  |  | 
|  | GOOD_COMPOSITION_TEST_SUITES = """\ | 
|  | { | 
|  | 'foo_tests': { | 
|  | 'foo_test': {}, | 
|  | }, | 
|  | 'bar_tests': { | 
|  | 'bar_test': {}, | 
|  | }, | 
|  | 'composition_tests': [ | 
|  | 'foo_tests', | 
|  | 'bar_tests', | 
|  | ], | 
|  | } | 
|  | """ | 
|  |  | 
|  | BAD_COMPOSITION_TEST_SUITES = """\ | 
|  | { | 
|  | 'foo_tests': {}, | 
|  | 'bar_tests': {}, | 
|  | 'buggy_composition_tests': [ | 
|  | 'bar_tests', | 
|  | ], | 
|  | 'composition_tests': [ | 
|  | 'foo_tests', | 
|  | 'buggy_composition_tests', | 
|  | ], | 
|  | } | 
|  | """ | 
|  |  | 
|  | INSTRUMENTATION_TESTS_WITH_DIFFERENT_NAMES = """\ | 
|  | { | 
|  | 'composition_tests': { | 
|  | 'foo_tests': { | 
|  | 'test': 'foo_test', | 
|  | }, | 
|  | 'bar_tests': { | 
|  | 'test': 'foo_test', | 
|  | }, | 
|  | }, | 
|  | } | 
|  | """ | 
|  |  | 
|  | SCRIPT_SUITE = """\ | 
|  | { | 
|  | 'foo_scripts': { | 
|  | 'foo_test': { | 
|  | 'script': 'foo.py', | 
|  | }, | 
|  | }, | 
|  | } | 
|  | """ | 
|  |  | 
|  | UNREFED_TEST_SUITE = """\ | 
|  | { | 
|  | 'foo_tests': {}, | 
|  | 'bar_tests': {}, | 
|  | } | 
|  | """ | 
|  |  | 
|  | REUSING_TEST_WITH_DIFFERENT_NAME = """\ | 
|  | { | 
|  | 'foo_tests': { | 
|  | 'foo_test': {}, | 
|  | 'variation_test': { | 
|  | 'args': [ | 
|  | '--variation', | 
|  | ], | 
|  | 'test': 'foo_test', | 
|  | }, | 
|  | }, | 
|  | } | 
|  | """ | 
|  |  | 
|  | EMPTY_EXCEPTIONS = """\ | 
|  | { | 
|  | } | 
|  | """ | 
|  |  | 
|  | SCRIPT_WITH_ARGS_EXCEPTIONS = """\ | 
|  | { | 
|  | 'foo_test': { | 
|  | 'modifications': { | 
|  | 'Fake Tester': { | 
|  | 'args': ['--fake-arg'], | 
|  | }, | 
|  | }, | 
|  | }, | 
|  | } | 
|  | """ | 
|  |  | 
|  | NO_BAR_TEST_EXCEPTIONS = """\ | 
|  | { | 
|  | 'bar_test': { | 
|  | 'remove_from': [ | 
|  | 'Fake Tester', | 
|  | ] | 
|  | } | 
|  | } | 
|  | """ | 
|  |  | 
|  | EMPTY_BAR_TEST_EXCEPTIONS = """\ | 
|  | { | 
|  | 'bar_test': { | 
|  | } | 
|  | } | 
|  | """ | 
|  |  | 
|  | FOO_TEST_MODIFICATIONS = """\ | 
|  | { | 
|  | 'foo_test': { | 
|  | 'modifications': { | 
|  | 'Fake Tester': { | 
|  | 'args': [ | 
|  | '--bar', | 
|  | ], | 
|  | 'swarming': { | 
|  | 'hard_timeout': 600, | 
|  | }, | 
|  | }, | 
|  | }, | 
|  | } | 
|  | } | 
|  | """ | 
|  |  | 
|  | ANDROID_TEST_EXCEPTIONS = """\ | 
|  | { | 
|  | 'foo_test': { | 
|  | 'key_removals': { | 
|  | 'Fake Android K Tester': [ | 
|  | 'merge', | 
|  | ], | 
|  | }, | 
|  | }, | 
|  | } | 
|  | """ | 
|  |  | 
|  | NONEXISTENT_REMOVAL = """\ | 
|  | { | 
|  | 'foo_test': { | 
|  | 'remove_from': [ | 
|  | 'Nonexistent Tester', | 
|  | ] | 
|  | } | 
|  | } | 
|  | """ | 
|  |  | 
|  | NONEXISTENT_MODIFICATION = """\ | 
|  | { | 
|  | 'foo_test': { | 
|  | 'modifications': { | 
|  | 'Nonexistent Tester': { | 
|  | 'args': [], | 
|  | }, | 
|  | }, | 
|  | } | 
|  | } | 
|  | """ | 
|  |  | 
|  | NONEXISTENT_KEY_REMOVAL = """ | 
|  | { | 
|  | 'foo_test': { | 
|  | 'key_removals': { | 
|  | 'Fake Tester': [ | 
|  | 'args', | 
|  | ], | 
|  | } | 
|  | }, | 
|  | } | 
|  | """ | 
|  |  | 
|  | COMPOSITION_WATERFALL_OUTPUT = """\ | 
|  | { | 
|  | "AAAAA1 AUTOGENERATED FILE DO NOT EDIT": {}, | 
|  | "AAAAA2 See generate_buildbot_json.py to make changes": {}, | 
|  | "Fake Tester": { | 
|  | "gtest_tests": [ | 
|  | { | 
|  | "swarming": { | 
|  | "can_use_on_swarming_builders": true | 
|  | }, | 
|  | "test": "bar_test" | 
|  | }, | 
|  | { | 
|  | "swarming": { | 
|  | "can_use_on_swarming_builders": true | 
|  | }, | 
|  | "test": "foo_test" | 
|  | } | 
|  | ] | 
|  | } | 
|  | } | 
|  | """ | 
|  |  | 
|  | COMPOSITION_WATERFALL_WITH_ARGS_OUTPUT = """\ | 
|  | { | 
|  | "AAAAA1 AUTOGENERATED FILE DO NOT EDIT": {}, | 
|  | "AAAAA2 See generate_buildbot_json.py to make changes": {}, | 
|  | "Fake Tester": { | 
|  | "gtest_tests": [ | 
|  | { | 
|  | "args": [ | 
|  | "--this-is-an-argument" | 
|  | ], | 
|  | "swarming": { | 
|  | "can_use_on_swarming_builders": true | 
|  | }, | 
|  | "test": "bar_test" | 
|  | }, | 
|  | { | 
|  | "args": [ | 
|  | "--this-is-an-argument" | 
|  | ], | 
|  | "swarming": { | 
|  | "can_use_on_swarming_builders": true | 
|  | }, | 
|  | "test": "foo_test" | 
|  | } | 
|  | ] | 
|  | } | 
|  | } | 
|  | """ | 
|  |  | 
|  | VARIATION_GTEST_OUTPUT = """\ | 
|  | { | 
|  | "AAAAA1 AUTOGENERATED FILE DO NOT EDIT": {}, | 
|  | "AAAAA2 See generate_buildbot_json.py to make changes": {}, | 
|  | "Fake Tester": { | 
|  | "gtest_tests": [ | 
|  | { | 
|  | "swarming": { | 
|  | "can_use_on_swarming_builders": true, | 
|  | "dimension_sets": [ | 
|  | { | 
|  | "kvm": "1" | 
|  | } | 
|  | ] | 
|  | }, | 
|  | "test": "foo_test" | 
|  | }, | 
|  | { | 
|  | "args": [ | 
|  | "--variation" | 
|  | ], | 
|  | "name": "variation_test", | 
|  | "swarming": { | 
|  | "can_use_on_swarming_builders": true, | 
|  | "dimension_sets": [ | 
|  | { | 
|  | "kvm": "1" | 
|  | } | 
|  | ] | 
|  | }, | 
|  | "test": "foo_test" | 
|  | } | 
|  | ] | 
|  | } | 
|  | } | 
|  | """ | 
|  |  | 
|  | COMPOSITION_WATERFALL_FILTERED_OUTPUT = """\ | 
|  | { | 
|  | "AAAAA1 AUTOGENERATED FILE DO NOT EDIT": {}, | 
|  | "AAAAA2 See generate_buildbot_json.py to make changes": {}, | 
|  | "Fake Tester": { | 
|  | "gtest_tests": [ | 
|  | { | 
|  | "swarming": { | 
|  | "can_use_on_swarming_builders": true | 
|  | }, | 
|  | "test": "foo_test" | 
|  | } | 
|  | ] | 
|  | } | 
|  | } | 
|  | """ | 
|  |  | 
|  | MERGED_ARGS_OUTPUT = """\ | 
|  | { | 
|  | "AAAAA1 AUTOGENERATED FILE DO NOT EDIT": {}, | 
|  | "AAAAA2 See generate_buildbot_json.py to make changes": {}, | 
|  | "Fake Tester": { | 
|  | "gtest_tests": [ | 
|  | { | 
|  | "args": [ | 
|  | "--c_arg", | 
|  | "--bar" | 
|  | ], | 
|  | "swarming": { | 
|  | "can_use_on_swarming_builders": true, | 
|  | "dimension_sets": [ | 
|  | { | 
|  | "kvm": "1" | 
|  | } | 
|  | ], | 
|  | "hard_timeout": 600 | 
|  | }, | 
|  | "test": "foo_test" | 
|  | } | 
|  | ] | 
|  | } | 
|  | } | 
|  | """ | 
|  |  | 
|  | MERGED_ENABLE_FEATURES_OUTPUT = """\ | 
|  | { | 
|  | "AAAAA1 AUTOGENERATED FILE DO NOT EDIT": {}, | 
|  | "AAAAA2 See generate_buildbot_json.py to make changes": {}, | 
|  | "Fake Tester": { | 
|  | "gtest_tests": [ | 
|  | { | 
|  | "args": [ | 
|  | "--enable-features=Foo,Bar,Baz" | 
|  | ], | 
|  | "swarming": { | 
|  | "can_use_on_swarming_builders": true | 
|  | }, | 
|  | "test": "foo_test" | 
|  | } | 
|  | ] | 
|  | } | 
|  | } | 
|  | """ | 
|  |  | 
|  | MODIFIED_OUTPUT = """\ | 
|  | { | 
|  | "AAAAA1 AUTOGENERATED FILE DO NOT EDIT": {}, | 
|  | "AAAAA2 See generate_buildbot_json.py to make changes": {}, | 
|  | "Fake Tester": { | 
|  | "gtest_tests": [ | 
|  | { | 
|  | "args": [ | 
|  | "--bar" | 
|  | ], | 
|  | "swarming": { | 
|  | "can_use_on_swarming_builders": true, | 
|  | "dimension_sets": [ | 
|  | { | 
|  | "integrity": "high", | 
|  | "kvm": "1" | 
|  | } | 
|  | ], | 
|  | "expiration": 120, | 
|  | "hard_timeout": 600 | 
|  | }, | 
|  | "test": "foo_test" | 
|  | } | 
|  | ] | 
|  | } | 
|  | } | 
|  | """ | 
|  |  | 
|  | ISOLATED_SCRIPT_OUTPUT = """\ | 
|  | { | 
|  | "AAAAA1 AUTOGENERATED FILE DO NOT EDIT": {}, | 
|  | "AAAAA2 See generate_buildbot_json.py to make changes": {}, | 
|  | "Fake Tester": { | 
|  | "isolated_scripts": [ | 
|  | { | 
|  | "isolate_name": "foo_test", | 
|  | "name": "foo_test", | 
|  | "swarming": { | 
|  | "can_use_on_swarming_builders": true | 
|  | } | 
|  | } | 
|  | ] | 
|  | } | 
|  | } | 
|  | """ | 
|  |  | 
|  | SCRIPT_OUTPUT = """\ | 
|  | { | 
|  | "AAAAA1 AUTOGENERATED FILE DO NOT EDIT": {}, | 
|  | "AAAAA2 See generate_buildbot_json.py to make changes": {}, | 
|  | "Fake Tester": { | 
|  | "scripts": [ | 
|  | { | 
|  | "name": "foo_test", | 
|  | "script": "foo.py" | 
|  | } | 
|  | ] | 
|  | } | 
|  | } | 
|  | """ | 
|  |  | 
|  | SCRIPT_WITH_ARGS_OUTPUT = """\ | 
|  | { | 
|  | "AAAAA1 AUTOGENERATED FILE DO NOT EDIT": {}, | 
|  | "AAAAA2 See generate_buildbot_json.py to make changes": {}, | 
|  | "Fake Tester": { | 
|  | "scripts": [ | 
|  | { | 
|  | "args": [ | 
|  | "--fake-arg" | 
|  | ], | 
|  | "name": "foo_test", | 
|  | "script": "foo.py" | 
|  | } | 
|  | ] | 
|  | } | 
|  | } | 
|  | """ | 
|  |  | 
|  | JUNIT_OUTPUT = """\ | 
|  | { | 
|  | "AAAAA1 AUTOGENERATED FILE DO NOT EDIT": {}, | 
|  | "AAAAA2 See generate_buildbot_json.py to make changes": {}, | 
|  | "Fake Tester": { | 
|  | "junit_tests": [ | 
|  | { | 
|  | "test": "foo_test" | 
|  | } | 
|  | ] | 
|  | } | 
|  | } | 
|  | """ | 
|  |  | 
|  | CTS_OUTPUT = """\ | 
|  | { | 
|  | "AAAAA1 AUTOGENERATED FILE DO NOT EDIT": {}, | 
|  | "AAAAA2 See generate_buildbot_json.py to make changes": {}, | 
|  | "Fake Tester": { | 
|  | "cts_tests": [ | 
|  | { | 
|  | "arch": "arm64", | 
|  | "platform": "L" | 
|  | } | 
|  | ] | 
|  | } | 
|  | } | 
|  | """ | 
|  |  | 
|  | INSTRUMENTATION_TEST_OUTPUT = """\ | 
|  | { | 
|  | "AAAAA1 AUTOGENERATED FILE DO NOT EDIT": {}, | 
|  | "AAAAA2 See generate_buildbot_json.py to make changes": {}, | 
|  | "Fake Tester": { | 
|  | "instrumentation_tests": [ | 
|  | { | 
|  | "test": "foo_test" | 
|  | } | 
|  | ] | 
|  | } | 
|  | } | 
|  | """ | 
|  |  | 
|  | INSTRUMENTATION_TEST_DIFFERENT_NAMES_OUTPUT = """\ | 
|  | { | 
|  | "AAAAA1 AUTOGENERATED FILE DO NOT EDIT": {}, | 
|  | "AAAAA2 See generate_buildbot_json.py to make changes": {}, | 
|  | "Fake Tester": { | 
|  | "instrumentation_tests": [ | 
|  | { | 
|  | "name": "bar_tests", | 
|  | "test": "foo_test" | 
|  | }, | 
|  | { | 
|  | "name": "foo_tests", | 
|  | "test": "foo_test" | 
|  | } | 
|  | ] | 
|  | } | 
|  | } | 
|  | """ | 
|  |  | 
|  | ANDROID_WATERFALL_OUTPUT = """\ | 
|  | { | 
|  | "AAAAA1 AUTOGENERATED FILE DO NOT EDIT": {}, | 
|  | "AAAAA2 See generate_buildbot_json.py to make changes": {}, | 
|  | "Android Builder": { | 
|  | "additional_compile_targets": [ | 
|  | "bar_test" | 
|  | ] | 
|  | }, | 
|  | "Fake Android K Tester": { | 
|  | "additional_compile_targets": [ | 
|  | "bar_test" | 
|  | ], | 
|  | "gtest_tests": [ | 
|  | { | 
|  | "args": [ | 
|  | "--gs-results-bucket=chromium-result-details" | 
|  | ], | 
|  | "swarming": { | 
|  | "can_use_on_swarming_builders": true, | 
|  | "cipd_packages": [ | 
|  | { | 
|  | "cipd_package": "infra/tools/luci/logdog/butler/${platform}", | 
|  | "location": "bin", | 
|  | "revision": \ | 
|  | "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" | 
|  | } | 
|  | ], | 
|  | "dimension_sets": [ | 
|  | { | 
|  | "device_os": "KTU84P", | 
|  | "device_type": "hammerhead", | 
|  | "integrity": "high" | 
|  | } | 
|  | ], | 
|  | "expiration": 120, | 
|  | "output_links": [ | 
|  | { | 
|  | "link": [ | 
|  | "https://luci-logdog.appspot.com/v/?s", | 
|  | "=android%2Fswarming%2Flogcats%2F", | 
|  | "${TASK_ID}%2F%2B%2Funified_logcats" | 
|  | ], | 
|  | "name": "shard #${SHARD_INDEX} logcats" | 
|  | } | 
|  | ] | 
|  | }, | 
|  | "test": "foo_test" | 
|  | } | 
|  | ] | 
|  | }, | 
|  | "Fake Android L Tester": { | 
|  | "gtest_tests": [ | 
|  | { | 
|  | "args": [ | 
|  | "--gs-results-bucket=chromium-result-details", | 
|  | "--recover-devices" | 
|  | ], | 
|  | "swarming": { | 
|  | "can_use_on_swarming_builders": true, | 
|  | "cipd_packages": [ | 
|  | { | 
|  | "cipd_package": "infra/tools/luci/logdog/butler/${platform}", | 
|  | "location": "bin", | 
|  | "revision": \ | 
|  | "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" | 
|  | } | 
|  | ], | 
|  | "dimension_sets": [ | 
|  | { | 
|  | "device_os": "KTU84P", | 
|  | "device_type": "hammerhead", | 
|  | "integrity": "high" | 
|  | } | 
|  | ], | 
|  | "expiration": 120 | 
|  | }, | 
|  | "test": "foo_test" | 
|  | } | 
|  | ] | 
|  | }, | 
|  | "Fake Android M Tester": { | 
|  | "gtest_tests": [ | 
|  | { | 
|  | "swarming": { | 
|  | "can_use_on_swarming_builders": false | 
|  | }, | 
|  | "test": "foo_test" | 
|  | } | 
|  | ] | 
|  | } | 
|  | } | 
|  | """ | 
|  |  | 
|  | MULTI_DIMENSION_OUTPUT = """\ | 
|  | { | 
|  | "AAAAA1 AUTOGENERATED FILE DO NOT EDIT": {}, | 
|  | "AAAAA2 See generate_buildbot_json.py to make changes": {}, | 
|  | "Fake Tester": { | 
|  | "gtest_tests": [ | 
|  | { | 
|  | "swarming": { | 
|  | "can_use_on_swarming_builders": true, | 
|  | "dimension_sets": [ | 
|  | { | 
|  | "gpu": "none", | 
|  | "integrity": "high", | 
|  | "os": "1" | 
|  | } | 
|  | ], | 
|  | "expiration": 120 | 
|  | }, | 
|  | "test": "foo_test", | 
|  | "trigger_script": { | 
|  | "args": [ | 
|  | "--multiple-trigger-configs", | 
|  | "[{\\"gpu\\": \\"none\\", \\"os\\": \\"1\\"}, \ | 
|  | {\\"gpu\\": \\"none\\", \\"os\\": \\"2\\"}]", | 
|  | "--multiple-dimension-script-verbose", | 
|  | "True" | 
|  | ], | 
|  | "script": "//testing/trigger_scripts/trigger_multiple_dimensions.py" | 
|  | } | 
|  | } | 
|  | ] | 
|  | } | 
|  | } | 
|  | """ | 
|  |  | 
|  | LUCI_MILO_CFG = """\ | 
|  | consoles { | 
|  | builders { | 
|  | name: "buildbucket/luci.chromium.ci/Fake Tester" | 
|  | } | 
|  | } | 
|  | """ | 
|  |  | 
|  | class UnitTest(unittest.TestCase): | 
|  | def test_base_generator(self): | 
|  | # Only needed for complete code coverage. | 
|  | self.assertRaises(NotImplementedError, | 
|  | generate_buildbot_json.BaseGenerator(None).generate, | 
|  | None, None, None, None) | 
|  | self.assertRaises(NotImplementedError, | 
|  | generate_buildbot_json.BaseGenerator(None).sort, | 
|  | None) | 
|  |  | 
|  | def test_good_test_suites_are_ok(self): | 
|  | fbb = FakeBBGen(FOO_GTESTS_WATERFALL, | 
|  | FOO_TEST_SUITE, | 
|  | EMPTY_EXCEPTIONS, | 
|  | LUCI_MILO_CFG) | 
|  | fbb.check_input_file_consistency() | 
|  |  | 
|  | def test_good_multi_dimension_test_suites_are_ok(self): | 
|  | fbb = FakeBBGen(FOO_GTESTS_MULTI_DIMENSION_WATERFALL, | 
|  | FOO_TEST_SUITE, | 
|  | EMPTY_EXCEPTIONS, | 
|  | LUCI_MILO_CFG) | 
|  | fbb.check_input_file_consistency() | 
|  |  | 
|  | def test_good_composition_test_suites_are_ok(self): | 
|  | fbb = FakeBBGen(COMPOSITION_GTEST_SUITE_WATERFALL, | 
|  | GOOD_COMPOSITION_TEST_SUITES, | 
|  | EMPTY_EXCEPTIONS, | 
|  | LUCI_MILO_CFG) | 
|  | fbb.check_input_file_consistency() | 
|  |  | 
|  | def test_bad_composition_test_suites_are_caught(self): | 
|  | fbb = FakeBBGen(COMPOSITION_GTEST_SUITE_WATERFALL, | 
|  | BAD_COMPOSITION_TEST_SUITES, | 
|  | EMPTY_EXCEPTIONS, | 
|  | LUCI_MILO_CFG) | 
|  | self.assertRaisesRegexp(generate_buildbot_json.BBGenErr, | 
|  | 'Composition test suites may not refer to.*', | 
|  | fbb.check_input_file_consistency) | 
|  |  | 
|  | def test_unknown_test_suites_are_caught(self): | 
|  | fbb = FakeBBGen(UNKNOWN_TEST_SUITE_WATERFALL, | 
|  | FOO_TEST_SUITE, | 
|  | EMPTY_EXCEPTIONS, | 
|  | LUCI_MILO_CFG) | 
|  | self.assertRaisesRegexp(generate_buildbot_json.BBGenErr, | 
|  | 'Test suite baz_tests from machine.*', | 
|  | fbb.check_input_file_consistency) | 
|  |  | 
|  | def test_unknown_test_suite_types_are_caught(self): | 
|  | fbb = FakeBBGen(UNKNOWN_TEST_SUITE_TYPE_WATERFALL, | 
|  | FOO_TEST_SUITE, | 
|  | EMPTY_EXCEPTIONS, | 
|  | LUCI_MILO_CFG) | 
|  | self.assertRaisesRegexp(generate_buildbot_json.BBGenErr, | 
|  | 'Unknown test suite type foo_test_type.*', | 
|  | fbb.check_input_file_consistency) | 
|  |  | 
|  | def test_unrefed_test_suite_caught(self): | 
|  | fbb = FakeBBGen(FOO_GTESTS_WATERFALL, | 
|  | UNREFED_TEST_SUITE, | 
|  | EMPTY_EXCEPTIONS, | 
|  | LUCI_MILO_CFG) | 
|  | self.assertRaisesRegexp(generate_buildbot_json.BBGenErr, | 
|  | '.*unreferenced.*bar_tests.*', | 
|  | fbb.check_input_file_consistency) | 
|  |  | 
|  | def test_good_waterfall_output(self): | 
|  | fbb = FakeBBGen(COMPOSITION_GTEST_SUITE_WATERFALL, | 
|  | GOOD_COMPOSITION_TEST_SUITES, | 
|  | EMPTY_EXCEPTIONS, | 
|  | LUCI_MILO_CFG) | 
|  | fbb.files['chromium.test.json'] = COMPOSITION_WATERFALL_OUTPUT | 
|  | fbb.check_output_file_consistency(verbose=True) | 
|  |  | 
|  | def test_reusing_gtest_targets(self): | 
|  | fbb = FakeBBGen(FOO_GTESTS_WATERFALL, | 
|  | REUSING_TEST_WITH_DIFFERENT_NAME, | 
|  | EMPTY_EXCEPTIONS, | 
|  | LUCI_MILO_CFG) | 
|  | fbb.files['chromium.test.json'] = VARIATION_GTEST_OUTPUT | 
|  | fbb.check_output_file_consistency(verbose=True) | 
|  |  | 
|  | def test_noop_exception_does_nothing(self): | 
|  | fbb = FakeBBGen(COMPOSITION_GTEST_SUITE_WATERFALL, | 
|  | GOOD_COMPOSITION_TEST_SUITES, | 
|  | EMPTY_BAR_TEST_EXCEPTIONS, | 
|  | LUCI_MILO_CFG) | 
|  | fbb.files['chromium.test.json'] = COMPOSITION_WATERFALL_OUTPUT | 
|  | fbb.check_output_file_consistency(verbose=True) | 
|  |  | 
|  | def test_test_arg_merges(self): | 
|  | fbb = FakeBBGen(FOO_GTESTS_WATERFALL, | 
|  | FOO_TEST_SUITE_WITH_ARGS, | 
|  | FOO_TEST_MODIFICATIONS, | 
|  | LUCI_MILO_CFG) | 
|  | fbb.files['chromium.test.json'] = MERGED_ARGS_OUTPUT | 
|  | fbb.check_output_file_consistency(verbose=True) | 
|  |  | 
|  | def test_enable_features_arg_merges(self): | 
|  | fbb = FakeBBGen(FOO_GTESTS_WITH_ENABLE_FEATURES_WATERFALL, | 
|  | FOO_TEST_SUITE_WITH_ENABLE_FEATURES, | 
|  | EMPTY_EXCEPTIONS, | 
|  | LUCI_MILO_CFG) | 
|  | fbb.files['chromium.test.json'] = MERGED_ENABLE_FEATURES_OUTPUT | 
|  | fbb.check_output_file_consistency(verbose=True) | 
|  |  | 
|  | def test_test_filtering(self): | 
|  | fbb = FakeBBGen(COMPOSITION_GTEST_SUITE_WATERFALL, | 
|  | GOOD_COMPOSITION_TEST_SUITES, | 
|  | NO_BAR_TEST_EXCEPTIONS, | 
|  | LUCI_MILO_CFG) | 
|  | fbb.files['chromium.test.json'] = COMPOSITION_WATERFALL_FILTERED_OUTPUT | 
|  | fbb.check_output_file_consistency(verbose=True) | 
|  |  | 
|  | def test_test_modifications(self): | 
|  | fbb = FakeBBGen(FOO_GTESTS_WATERFALL, | 
|  | FOO_TEST_SUITE, | 
|  | FOO_TEST_MODIFICATIONS, | 
|  | LUCI_MILO_CFG) | 
|  | fbb.files['chromium.test.json'] = MODIFIED_OUTPUT | 
|  | fbb.check_output_file_consistency(verbose=True) | 
|  |  | 
|  | def test_isolated_script_tests(self): | 
|  | fbb = FakeBBGen(FOO_ISOLATED_SCRIPTS_WATERFALL, | 
|  | GOOD_COMPOSITION_TEST_SUITES, | 
|  | NO_BAR_TEST_EXCEPTIONS, | 
|  | LUCI_MILO_CFG) | 
|  | fbb.files['chromium.test.json'] = ISOLATED_SCRIPT_OUTPUT | 
|  | fbb.check_output_file_consistency(verbose=True) | 
|  |  | 
|  | def test_script_with_args(self): | 
|  | fbb = FakeBBGen(FOO_SCRIPT_WATERFALL, | 
|  | SCRIPT_SUITE, | 
|  | SCRIPT_WITH_ARGS_EXCEPTIONS, | 
|  | LUCI_MILO_CFG) | 
|  | fbb.files['chromium.test.json'] = SCRIPT_WITH_ARGS_OUTPUT | 
|  | fbb.check_output_file_consistency(verbose=True) | 
|  |  | 
|  | def test_script(self): | 
|  | fbb = FakeBBGen(FOO_SCRIPT_WATERFALL, | 
|  | FOO_SCRIPT_SUITE, | 
|  | NO_BAR_TEST_EXCEPTIONS, | 
|  | LUCI_MILO_CFG) | 
|  | fbb.files['chromium.test.json'] = SCRIPT_OUTPUT | 
|  | fbb.check_output_file_consistency(verbose=True) | 
|  |  | 
|  | def test_junit_tests(self): | 
|  | fbb = FakeBBGen(FOO_JUNIT_WATERFALL, | 
|  | GOOD_COMPOSITION_TEST_SUITES, | 
|  | NO_BAR_TEST_EXCEPTIONS, | 
|  | LUCI_MILO_CFG) | 
|  | fbb.files['chromium.test.json'] = JUNIT_OUTPUT | 
|  | fbb.check_output_file_consistency(verbose=True) | 
|  |  | 
|  | def test_cts_tests(self): | 
|  | fbb = FakeBBGen(FOO_CTS_WATERFALL, | 
|  | FOO_CTS_SUITE, | 
|  | EMPTY_EXCEPTIONS, | 
|  | LUCI_MILO_CFG) | 
|  | fbb.files['chromium.test.json'] = CTS_OUTPUT | 
|  | fbb.check_output_file_consistency(verbose=True) | 
|  |  | 
|  | def test_instrumentation_tests(self): | 
|  | fbb = FakeBBGen(FOO_INSTRUMENTATION_TEST_WATERFALL, | 
|  | GOOD_COMPOSITION_TEST_SUITES, | 
|  | NO_BAR_TEST_EXCEPTIONS, | 
|  | LUCI_MILO_CFG) | 
|  | fbb.files['chromium.test.json'] = INSTRUMENTATION_TEST_OUTPUT | 
|  | fbb.check_output_file_consistency(verbose=True) | 
|  |  | 
|  | def test_instrumentation_tests_with_different_names(self): | 
|  | fbb = FakeBBGen(FOO_INSTRUMENTATION_TEST_WATERFALL, | 
|  | INSTRUMENTATION_TESTS_WITH_DIFFERENT_NAMES, | 
|  | EMPTY_EXCEPTIONS, | 
|  | LUCI_MILO_CFG) | 
|  | fbb.files['chromium.test.json'] = \ | 
|  | INSTRUMENTATION_TEST_DIFFERENT_NAMES_OUTPUT | 
|  | fbb.check_output_file_consistency(verbose=True) | 
|  |  | 
|  | def test_ungenerated_output_files_are_caught(self): | 
|  | fbb = FakeBBGen(COMPOSITION_GTEST_SUITE_WATERFALL, | 
|  | GOOD_COMPOSITION_TEST_SUITES, | 
|  | NO_BAR_TEST_EXCEPTIONS, | 
|  | LUCI_MILO_CFG) | 
|  | fbb.files['chromium.test.json'] = ( | 
|  | '\n' + COMPOSITION_WATERFALL_FILTERED_OUTPUT) | 
|  | self.assertRaises(generate_buildbot_json.BBGenErr, | 
|  | fbb.check_output_file_consistency) | 
|  |  | 
|  | def test_android_output_options(self): | 
|  | fbb = FakeBBGen(ANDROID_WATERFALL, | 
|  | FOO_TEST_SUITE, | 
|  | ANDROID_TEST_EXCEPTIONS, | 
|  | LUCI_MILO_CFG) | 
|  | fbb.files['chromium.test.json'] = ANDROID_WATERFALL_OUTPUT | 
|  | fbb.check_output_file_consistency(verbose=True) | 
|  |  | 
|  | def test_nonexistent_removal_raises(self): | 
|  | fbb = FakeBBGen(FOO_GTESTS_WATERFALL, | 
|  | FOO_TEST_SUITE, | 
|  | NONEXISTENT_REMOVAL, | 
|  | LUCI_MILO_CFG) | 
|  | self.assertRaisesRegexp(generate_buildbot_json.BBGenErr, | 
|  | 'The following nonexistent machines.*', | 
|  | fbb.check_input_file_consistency) | 
|  |  | 
|  | def test_nonexistent_modification_raises(self): | 
|  | fbb = FakeBBGen(FOO_GTESTS_WATERFALL, | 
|  | FOO_TEST_SUITE, | 
|  | NONEXISTENT_MODIFICATION, | 
|  | LUCI_MILO_CFG) | 
|  | self.assertRaisesRegexp(generate_buildbot_json.BBGenErr, | 
|  | 'The following nonexistent machines.*', | 
|  | fbb.check_input_file_consistency) | 
|  |  | 
|  | def test_nonexistent_key_removal_raises(self): | 
|  | fbb = FakeBBGen(FOO_GTESTS_WATERFALL, | 
|  | FOO_TEST_SUITE, | 
|  | NONEXISTENT_KEY_REMOVAL, | 
|  | LUCI_MILO_CFG) | 
|  | with self.assertRaises(generate_buildbot_json.BBGenErr): | 
|  | fbb.check_output_file_consistency(verbose=True) | 
|  |  | 
|  | def test_waterfall_args(self): | 
|  | fbb = FakeBBGen(COMPOSITION_GTEST_SUITE_WITH_ARGS_WATERFALL, | 
|  | GOOD_COMPOSITION_TEST_SUITES, | 
|  | EMPTY_EXCEPTIONS, | 
|  | LUCI_MILO_CFG) | 
|  | fbb.files['chromium.test.json'] = COMPOSITION_WATERFALL_WITH_ARGS_OUTPUT | 
|  | fbb.check_output_file_consistency(verbose=True) | 
|  |  | 
|  | def test_multi_dimension_output(self): | 
|  | fbb = FakeBBGen(FOO_GTESTS_MULTI_DIMENSION_WATERFALL, | 
|  | FOO_TEST_SUITE, | 
|  | EMPTY_EXCEPTIONS, | 
|  | LUCI_MILO_CFG) | 
|  | fbb.files['chromium.test.json'] = MULTI_DIMENSION_OUTPUT | 
|  | fbb.check_output_file_consistency(verbose=True) | 
|  |  | 
|  | def test_relative_pyl_file_dir(self): | 
|  | fbb = FakeBBGen(FOO_GTESTS_WATERFALL, | 
|  | REUSING_TEST_WITH_DIFFERENT_NAME, | 
|  | EMPTY_EXCEPTIONS, | 
|  | LUCI_MILO_CFG) | 
|  | fbb.args = argparse.Namespace(pyl_files_dir='relative/path/') | 
|  | for file_name in list(fbb.files): | 
|  | if not 'luci-milo.cfg' in file_name: | 
|  | fbb.files[os.path.join('relative/path/', file_name)] = ( | 
|  | fbb.files.pop(file_name)) | 
|  | fbb.check_input_file_consistency() | 
|  | fbb.files['relative/path/chromium.test.json'] = VARIATION_GTEST_OUTPUT | 
|  | fbb.check_output_file_consistency(verbose=True) | 
|  |  | 
|  | def test_nonexistent_bot_raises(self): | 
|  | fbb = FakeBBGen(UNKNOWN_BOT_GTESTS_WATERFALL, | 
|  | FOO_TEST_SUITE, | 
|  | NONEXISTENT_KEY_REMOVAL, | 
|  | LUCI_MILO_CFG) | 
|  | with self.assertRaises(generate_buildbot_json.BBGenErr): | 
|  | fbb.check_input_file_consistency() | 
|  |  | 
|  |  | 
|  | if __name__ == '__main__': | 
|  | unittest.main() |