lin
2025-07-30 fcd736bf35fd93b563e9bbf594f2aa7b62028cc9
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# Copyright 2018 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.
 
"""Common file shared by test_push of autotest and skylab.
 
autotest: site_utils/test_push.py
skylab: venv/skylab_staging/test_push.py
"""
 
import collections
import re
 
# Dictionary of test results keyed by test name regular expression.
EXPECTED_TEST_RESULTS = {'^SERVER_JOB$':                 'GOOD',
                         # This is related to dummy_Fail/control.dependency.
                         'dummy_Fail.dependency$':       'TEST_NA',
                         'login_LoginSuccess.*':         'GOOD',
                         'provision_AutoUpdate.double':  'GOOD',
                         'dummy_Pass.*':                 'GOOD',
                         'dummy_Fail.Fail$':             'FAIL',
                         'dummy_Fail.Error$':            'ERROR',
                         'dummy_Fail.Warn$':             'WARN',
                         'dummy_Fail.NAError$':          'TEST_NA',
                         'dummy_Fail.Crash$':            'GOOD',
                         'autotest_SyncCount$':          'GOOD',
                         }
 
EXPECTED_TEST_RESULTS_DUMMY = {'^SERVER_JOB$':       'GOOD',
                               'dummy_Pass.*':       'GOOD',
                               'dummy_Fail.Fail':    'FAIL',
                               'dummy_Fail.Warn':    'WARN',
                               'dummy_Fail.Crash':   'GOOD',
                               'dummy_Fail.Error':   'ERROR',
                               'dummy_Fail.NAError': 'TEST_NA',}
 
EXPECTED_TEST_RESULTS_POWERWASH = {'platform_Powerwash': 'GOOD',
                                   'SERVER_JOB':         'GOOD'}
 
_TestPushErrors = collections.namedtuple(
        '_TestPushErrors',
        [
                'mismatch_errors',
                'unknown_tests',
                'missing_tests',
        ]
)
 
 
def summarize_push(test_views, expected_results, ignored_tests=[]):
    """Summarize the test push errors."""
    test_push_errors = _match_test_results(test_views, expected_results,
                                           ignored_tests)
    return _generate_push_summary(test_push_errors)
 
 
def _match_test_results(test_views, expected_results, ignored_tests):
    """Match test results with expected results.
 
    @param test_views: A dictionary of test status keyed by test name, e.g.,
             {'dummy_Fail.Error': 'ERROR', 'dummy_Fail.NAError': 'TEST_NA'}
    @param expected_results: A dictionary of test name to expected test result.
 
    @return: A _TestPushErrors tuple.
    """
    mismatch_errors = []
    unknown_tests = []
    found_keys = set()
    for test_name, test_status in test_views.iteritems():
        test_found = False
        for test_name_pattern, expected_result in expected_results.items():
            if re.search(test_name_pattern, test_name):
                test_found = True
                found_keys.add(test_name_pattern)
                if (expected_result != test_status and
                    _is_significant(test_name, ignored_tests)):
                    error = ('%s Expected: [%s], Actual: [%s]' %
                             (test_name, expected_result, test_status))
                    mismatch_errors.append(error)
 
        if not test_found and _is_significant(test_name, ignored_tests):
            unknown_tests.append(test_name)
 
    missing_tests = set(expected_results.keys()) - found_keys
    missing_tests = [t for t in missing_tests
                     if _is_significant(t, ignored_tests)]
    return _TestPushErrors(mismatch_errors=mismatch_errors,
                           unknown_tests=unknown_tests,
                           missing_tests=missing_tests)
 
 
def _is_significant(test, ignored_tests_patterns):
    return all([test not in m for m in ignored_tests_patterns])
 
 
def _generate_push_summary(test_push_errors):
    """Generate a list of summary based on the test_push results."""
    summary = []
    if test_push_errors.mismatch_errors:
        summary.append(('Results of %d test(s) do not match expected '
                        'values:') % len(test_push_errors.mismatch_errors))
        summary.extend(test_push_errors.mismatch_errors)
        summary.append('\n')
 
    if test_push_errors.unknown_tests:
        summary.append('%d test(s) are not expected to be run:' %
                       len(test_push_errors.unknown_tests))
        summary.extend(test_push_errors.unknown_tests)
        summary.append('\n')
 
    if test_push_errors.missing_tests:
        summary.append('%d test(s) are missing from the results:' %
                       len(test_push_errors.missing_tests))
        summary.extend(test_push_errors.missing_tests)
        summary.append('\n')
 
    return summary