#!/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 unittest
import six
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