#!/usr/bin/env vpython3 # Copyright 2016 The Chromium Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. import copy import os import six import sys import unittest THIS_DIR = os.path.dirname(os.path.abspath(__file__)) # For results_merger. sys.path.insert(0, os.path.join(THIS_DIR, '..', 'resources')) import results_merger GOOD_JSON_TEST_RESULT_0 = { 'tests': { 'car': { 'honda': { 'expected': 'PASS', 'actual': 'PASS' }, 'toyota': { 'expected': 'FAIL', 'actual': 'FAIL' } }, 'computer': { 'dell': { 'expected': 'PASS', 'actual': 'PASS' } }, }, 'interrupted': False, 'version': 3, 'seconds_since_epoch': 1406662289.76, 'num_failures_by_type': { 'FAIL': 0, 'PASS': 2 }, 'layout_tests_dir': 'abc' } GOOD_JSON_TEST_RESULT_1 = { 'tests': { 'car': { 'tesla': { 'expected': 'PASS', 'actual': 'PASS' }, }, 'burger': { 'mcdonald': { 'expected': 'PASS', 'actual': 'PASS' } }, }, 'interrupted': False, 'version': 3, 'seconds_since_epoch': 1406662283.11, 'num_failures_by_type': { 'FAIL': 0, 'PASS': 2 }, 'layout_tests_dir': '123' } GOOD_JSON_TEST_RESULT_2 = { 'tests': { 'car': { 'mercedes': { 'expected': 'PASS', 'actual': 'FAIL' }, }, 'burger': { 'in n out': { 'expected': 'PASS', 'actual': 'PASS' } }, }, 'interrupted': True, 'version': 3, 'seconds_since_epoch': 1406662200.01, 'num_failures_by_type': { 'FAIL': 1, 'PASS': 1 } } GOOD_JSON_TEST_RESULT_MERGED = { 'tests': { 'car': { 'tesla': { 'expected': 'PASS', 'actual': 'PASS' }, 'mercedes': { 'expected': 'PASS', 'actual': 'FAIL' }, 'honda': { 'expected': 'PASS', 'actual': 'PASS' }, 'toyota': { 'expected': 'FAIL', 'actual': 'FAIL' } }, 'computer': { 'dell': { 'expected': 'PASS', 'actual': 'PASS' } }, 'burger': { 'mcdonald': { 'expected': 'PASS', 'actual': 'PASS' }, 'in n out': { 'expected': 'PASS', 'actual': 'PASS' } } }, 'interrupted': True, 'version': 3, 'seconds_since_epoch': 1406662200.01, 'num_failures_by_type': { 'FAIL': 1, 'PASS': 5 }, 'layout_tests_dir': '123' } def extend(initial, add): out = copy.deepcopy(initial) out.update(add) return out def remove(initial, keys): out = copy.deepcopy(initial) for k in keys: del out[k] return out # These unittests are run in PRESUBMIT, but not by recipe_simulation_test, hence # to avoid false alert on missing coverage by recipe_simulation_test, we mark # these code as no cover. class MergingTest(unittest.TestCase): # pragma: no cover maxDiff = None # Show full diff if assertion fail def test_merge_tries(self): self.assertEqual( {'a': 'A', 'b': {'c': 'C'}}, results_merger.merge_tries( {'a': 'A', 'b': {}}, {'b': {'c': 'C'}})) def test_merge_tries_unmergable(self): with six.assertRaisesRegex(self, results_merger.MergeException, "a:b"): results_merger.merge_tries( {'a': {'b': 'A'}}, {'a': {'b': 'C'}}) def test_merge_metadata(self): metadata1 = {'metadata': {'tags': ['foo', 'bar']}} metadata2 = {'metadata': {'tags': ['foo', 'bat']}} merged_results = results_merger.merge_test_results( [extend(GOOD_JSON_TEST_RESULT_0, metadata1), extend(GOOD_JSON_TEST_RESULT_1, metadata2)]) self.assertEqual( merged_results['metadata']['tags'], ['foo', 'bat']) def test_merge_json_test_results_nop(self): good_json_results = ( GOOD_JSON_TEST_RESULT_0, GOOD_JSON_TEST_RESULT_1, GOOD_JSON_TEST_RESULT_2, GOOD_JSON_TEST_RESULT_MERGED) for j in good_json_results: # Clone so we can check the input dictionaries are not modified a = copy.deepcopy(j) self.assertEqual(results_merger.merge_test_results([a]), j) self.assertEqual(a, j) def test_merge_json_test_results_invalid_version(self): with self.assertRaises(results_merger.MergeException): results_merger.merge_test_results([ extend(GOOD_JSON_TEST_RESULT_0, {'version': 5}), ]) with self.assertRaises(results_merger.MergeException): results_merger.merge_test_results([ GOOD_JSON_TEST_RESULT_0, extend(GOOD_JSON_TEST_RESULT_1, {'version': 5}), ]) def test_merge_json_test_results_missing_version(self): with self.assertRaises(results_merger.MergeException): results_merger.merge_test_results([ remove(GOOD_JSON_TEST_RESULT_0, ['version']), ]) with self.assertRaises(results_merger.MergeException): results_merger.merge_test_results([ GOOD_JSON_TEST_RESULT_0, remove(GOOD_JSON_TEST_RESULT_1, ['version']), ]) def test_merge_json_test_results_invalid_extra(self): with self.assertRaises(results_merger.MergeException): results_merger.merge_test_results([ extend(GOOD_JSON_TEST_RESULT_0, {'extra': True}), ]) with self.assertRaises(results_merger.MergeException): results_merger.merge_test_results([ GOOD_JSON_TEST_RESULT_0, extend(GOOD_JSON_TEST_RESULT_1, {'extra': True}), ]) def test_merge_json_test_results_missing_required(self): with self.assertRaises(results_merger.MergeException): results_merger.merge_test_results([ remove(GOOD_JSON_TEST_RESULT_0, ['interrupted']), ]) with self.assertRaises(results_merger.MergeException): results_merger.merge_test_results([ GOOD_JSON_TEST_RESULT_0, remove(GOOD_JSON_TEST_RESULT_1, ['interrupted']), ]) def test_merge_json_test_results_multiple(self): self.assertEqual( results_merger.merge_test_results([ GOOD_JSON_TEST_RESULT_0, GOOD_JSON_TEST_RESULT_1, GOOD_JSON_TEST_RESULT_2, ]), GOOD_JSON_TEST_RESULT_MERGED) def test_merge_json_test_results_optional_matches(self): self.assertEqual( results_merger.merge_test_results([ extend(GOOD_JSON_TEST_RESULT_0, {'path_delimiter': '.'}), extend(GOOD_JSON_TEST_RESULT_1, {'path_delimiter': '.'}), extend(GOOD_JSON_TEST_RESULT_2, {'path_delimiter': '.'}), ]), extend(GOOD_JSON_TEST_RESULT_MERGED, {'path_delimiter': '.'})) def test_merge_json_test_results_optional_differs(self): with self.assertRaises(results_merger.MergeException): results_merger.merge_test_results([ extend(GOOD_JSON_TEST_RESULT_0, {'path_delimiter': '.'}), extend(GOOD_JSON_TEST_RESULT_1, {'path_delimiter': '.'}), extend(GOOD_JSON_TEST_RESULT_2, {'path_delimiter': '/'}), ]) def test_merge_json_test_results_optional_count(self): self.assertEqual( results_merger.merge_test_results([ extend(GOOD_JSON_TEST_RESULT_0, {'fixable': 1}), extend(GOOD_JSON_TEST_RESULT_1, {'fixable': 2}), extend(GOOD_JSON_TEST_RESULT_2, {'fixable': 3}), ]), extend(GOOD_JSON_TEST_RESULT_MERGED, {'fixable': 6})) def test_merge_nothing(self): self.assertEqual( results_merger.merge_test_results([]), {}) # TODO(tansell): Make this test fail properly, currently fails with an # AttributeError. # def test_merge_test_name_conflict(self): # self.maxDiff = None # Show full diff if assertion fail # with self.assertRaises(results_merger.MergeException): # results_merger.merge_test_results( # [GOOD_JSON_TEST_RESULT_0, GOOD_JSON_TEST_RESULT_0]) if __name__ == '__main__': unittest.main() # pragma: no cover