blob: aa48bb7e6dda3cce1216239a5ad4f48fa86b5884 [file] [log] [blame]
# Copyright 2019 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.
DEPS = [
'recipe_engine/json',
'recipe_engine/properties',
'recipe_engine/step',
'chromium',
'chromium_tests',
'test_utils',
]
from recipe_engine.recipe_api import Property
from recipe_engine import post_process
from RECIPE_MODULES.build.chromium_tests import steps
PROPERTIES = {
# This property is a dictionary that specifies the expectations of the
# labeled known flakes of the mocked tests, and the format is from a test
# name to a list of tests.
'known_flakes_expectations': Property(default={}),
# This property is a boolean that indicates whether to create a mocked test
# that has failed tests to test that if there are no test failures, a
# request should NOT be sent to the service because it's unnecessary.
'exclude_failed_test': Property(default=False),
# This property is a boolean that indicates whether to create a mocked test
# that has a massive amount of failures to test that a request should NOT be
# sent to the service to avoid overloading it.
'has_too_many_failures': Property(default=False),
}
def RunSteps(api, known_flakes_expectations, exclude_failed_test,
has_too_many_failures):
test_specs = [
steps.MockTestSpec.create(name='succeeded_test'),
steps.MockTestSpec.create(
name='invalid_test', runs_on_swarming=True, has_valid_results=False),
]
if not exclude_failed_test:
test_specs.append(
steps.MockTestSpec.create(
name='failed_test',
runs_on_swarming=True,
per_suffix_failures={'with patch': ['testA', 'testB']},
))
if has_too_many_failures:
test_specs.append(
steps.MockTestSpec.create(
name='too_many_failures',
runs_on_swarming=True,
per_suffix_failures={
'with patch': ['test%d' % i for i in range(1000)]
}))
tests = [s.get_test() for s in test_specs]
api.test_utils.run_tests(
api.chromium_tests.m,
tests,
'with patch',
retry_failed_shards=True,
retry_invalid_shards=True)
for t in tests:
assert t.known_flaky_failures == set(
known_flakes_expectations.get(t.name, []))
def GenTests(api):
yield api.test(
'immune to infra failure of querying flaky failures',
api.chromium.generic_build(builder_group='g', builder='b'),
api.properties(**{
'$build/test_utils': {
'should_exonerate_flaky_failures': True,
},
}),
api.step_data('query known flaky failures on CQ', retcode=1),
api.post_process(post_process.MustRun,
'query known flaky failures on CQ'),
api.post_process(post_process.StepTextContains,
'query known flaky failures on CQ',
['Failed to get known flakes']),
api.post_process(post_process.StatusSuccess),
api.post_process(post_process.DropExpectation),
)
yield api.test(
'immune to ill-formed response',
api.chromium.generic_build(builder_group='g', builder='b'),
api.properties(**{
'$build/test_utils': {
'should_exonerate_flaky_failures': True,
},
}),
api.step_data(
'query known flaky failures on CQ',
api.json.output({'step_ui_name': 'browser_tests (with patch)'})),
api.post_process(post_process.StepTextContains,
'query known flaky failures on CQ',
['Response is ill-formed']),
api.post_process(post_process.StatusSuccess),
api.post_process(post_process.DropExpectation),
)
yield api.test(
'immune to another ill-formed response',
api.chromium.generic_build(builder_group='g', builder='b'),
api.properties(**{
'$build/test_utils': {
'should_exonerate_flaky_failures': True,
},
}),
api.step_data(
'query known flaky failures on CQ',
api.json.output(
{'flakes': [{
'step_ui_name': 'browser_tests (with patch)'
}]})),
api.post_process(post_process.StepTextContains,
'query known flaky failures on CQ',
['Response is ill-formed']),
api.post_process(post_process.StatusSuccess),
api.post_process(post_process.DropExpectation),
)
yield api.test(
'empty response',
api.chromium.generic_build(builder_group='g', builder='b'),
api.properties(**{
'$build/test_utils': {
'should_exonerate_flaky_failures': True,
},
}),
api.step_data('query known flaky failures on CQ', api.json.output({})),
api.post_process(post_process.StatusSuccess),
api.post_process(post_process.DropExpectation),
)
yield api.test(
'no failed tests',
api.chromium.generic_build(builder_group='g', builder='b'),
api.properties(
exclude_failed_test=True,
**{
'$build/test_utils': {
'should_exonerate_flaky_failures': True,
},
}),
api.post_process(post_process.DoesNotRun,
'query known flaky failures on CQ'),
api.post_process(post_process.StatusSuccess),
api.post_process(post_process.DropExpectation),
)
yield api.test(
'no tests are marked as known flaky',
api.chromium.generic_build(builder_group='g', builder='b'),
api.properties(
known_flakes_expectations={},
**{
'$build/test_utils': {
'should_exonerate_flaky_failures': True,
},
}),
api.step_data('query known flaky failures on CQ', api.json.output([])),
api.post_process(post_process.MustRun,
'query known flaky failures on CQ'),
api.post_process(post_process.StatusSuccess),
api.post_process(post_process.DropExpectation),
)
yield api.test(
'part of the tests are marked as known flaky',
api.chromium.generic_build(builder_group='g', builder='b'),
api.properties(
known_flakes_expectations={
'failed_test': ['testA'],
},
**{
'$build/test_utils': {
'should_exonerate_flaky_failures': True,
},
}),
api.step_data(
'query known flaky failures on CQ',
api.json.output({
'flakes': [{
'test': {
'step_ui_name': 'failed_test (with patch)',
'test_name': 'testA',
},
'affected_gerrit_changes': ['123', '234'],
'monorail_issue': '999',
}]
})),
api.post_process(post_process.MustRun,
'query known flaky failures on CQ'),
api.post_process(post_process.StatusSuccess),
api.post_process(post_process.DropExpectation),
)
yield api.test(
'all of the tests are marked as known flaky',
api.chromium.generic_build(builder_group='g', builder='b'),
api.properties(
known_flakes_expectations={
'failed_test': ['testA', 'testB'],
},
**{
'$build/test_utils': {
'should_exonerate_flaky_failures': True,
},
}),
api.step_data(
'query known flaky failures on CQ',
api.json.output({
'flakes': [
{
'test': {
'step_ui_name': 'failed_test (with patch)',
'test_name': 'testA',
},
'affected_gerrit_changes': ['123', '234'],
'monorail_issue': '999',
},
{
'test': {
'step_ui_name': 'failed_test (with patch)',
'test_name': 'testB',
},
'affected_gerrit_changes': ['567', '678'],
'monorail_issue': '998',
},
]
})),
api.post_process(post_process.MustRun,
'query known flaky failures on CQ'),
api.post_process(post_process.StatusSuccess),
api.post_process(post_process.DropExpectation),
)
yield api.test(
'skip querying if there are too many failures',
api.chromium.generic_build(builder_group='g', builder='b'),
api.properties(
exclude_failed_test=True,
has_too_many_failures=True,
**{
'$build/test_utils': {
'should_exonerate_flaky_failures': True,
},
}),
api.post_process(post_process.DoesNotRun,
'query known flaky failures on CQ'),
api.post_process(post_process.StatusSuccess),
api.post_process(post_process.DropExpectation),
)
# The difference between this test and the immediate above one is that this
# test doesn't exclude the test suite with limited number of failures, and
# this test tests that even though there are tests with too many failures, the
# recipe should still query known flaky failures for other test suites with
# limited number of failures.
yield api.test(
'keep querying if at least one test suite has limited failures',
api.chromium.generic_build(builder_group='g', builder='b'),
api.properties(
has_too_many_failures=True,
**{
'$build/test_utils': {
'should_exonerate_flaky_failures': True,
},
}),
api.post_process(post_process.LogContains,
'query known flaky failures on CQ', 'input',
['failed_test (with patch)']),
api.post_process(post_process.StatusSuccess),
api.post_process(post_process.DropExpectation),
)