#!/usr/bin/env vpython3
# Copyright 2021 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# pylint: disable=protected-access
import datetime
import os
import unittest
import unittest.mock as mock
from flake_suppressor_common import common_typing as ct
from flake_suppressor_common import data_types
from flake_suppressor_common import tag_utils as common_tag_utils
from flake_suppressor_common import unittest_utils as uu
GENERIC_EXPECTATION_FILE_CONTENTS = """\
# tags: [ win ]
# results: [ Failure ]
crbug.com/1111 [ win ] foo_test [ Failure ]
"""
GPU_EXPECTATION_FILE_CONTENTS = """\
# tags: [ win ]
# tags: [ amd nvidia ]
# results: [ Failure ]
crbug.com/1111 [ win nvidia ] conformance/textures/misc/video-rotation.html [ Failure ]
"""
class BaseResultsUnittest(unittest.TestCase):
def setUp(self) -> None:
common_tag_utils.SetTagUtilsImplementation(uu.UnitTestTagUtils)
expectations_processor = uu.UnitTestExpectationProcessor()
self._results = uu.UnitTestResultProcessor(expectations_processor)
self._local_patcher = mock.patch(
'flake_suppressor_common.results.expectations.'
'ExpectationProcessor.GetLocalCheckoutExpectationFileContents')
self._local_mock = self._local_patcher.start()
self._local_mock.return_value = {}
self.addCleanup(self._local_patcher.stop)
self._expectation_file_patcher = mock.patch.object(
uu.UnitTestExpectationProcessor, 'GetExpectationFileForSuite')
self._expectation_file_mock = self._expectation_file_patcher.start()
self.addCleanup(self._expectation_file_patcher.stop)
class AggregateResultsUnittest(BaseResultsUnittest):
def testBasic(self) -> None:
"""Basic functionality test."""
query_results = [
{
'name': ('gpu_tests.webgl_conformance_integration_test.'
'WebGLConformanceIntegrationTest.'
'conformance/textures/misc/video-rotation.html'),
'id':
'build-1111',
# The win-laptop tag is ignored, and thus should be removed in the
# output.
'typ_tags': ['win', 'nvidia', 'win-laptop'],
},
{
'name': ('gpu_tests.webgl_conformance_integration_test.'
'WebGLConformanceIntegrationTest.'
'conformance/textures/misc/video-rotation.html'),
'id':
'build-2222',
'typ_tags': ['win', 'nvidia'],
},
{
'name': ('gpu_tests.webgl_conformance_integration_test.'
'WebGLConformanceIntegrationTest.'
'conformance/textures/misc/video-rotation.html'),
'id':
'build-3333',
'typ_tags': ['win', 'amd'],
},
{
'name': ('gpu_tests.webgl_conformance_integration_test.'
'WebGLConformanceIntegrationTest.'
'conformance/textures/misc/texture-npot-video.html'),
'id':
'build-4444',
'typ_tags': ['win', 'nvidia'],
},
{
'name': ('gpu_tests.pixel_integration_test.PixelIntegrationTest.'
'Pixel_CSS3DBlueBox'),
'id':
'build-5555',
'typ_tags': ['win', 'nvidia'],
},
]
expected_output = {
'webgl_conformance_integration_test': {
'conformance/textures/misc/video-rotation.html': {
('nvidia', 'win'): [
'http://ci.chromium.org/b/1111',
'http://ci.chromium.org/b/2222',
],
('amd', 'win'): ['http://ci.chromium.org/b/3333'],
},
'conformance/textures/misc/texture-npot-video.html': {
('nvidia', 'win'): ['http://ci.chromium.org/b/4444'],
},
},
'pixel_integration_test': {
'Pixel_CSS3DBlueBox': {
('nvidia', 'win'): ['http://ci.chromium.org/b/5555'],
},
},
}
self.assertEqual(self._results.AggregateResults(query_results),
expected_output)
class AggregateTestStatusResultsUnittest(BaseResultsUnittest):
def testBasic(self) -> None:
"""Basic functionality test."""
query_results = [
{
'name': ('gpu_tests.webgl_conformance_integration_test.'
'WebGLConformanceIntegrationTest.'
'conformance/textures/misc/video-rotation.html'),
'id':
'build-1111',
# The win-laptop tag is ignored, and thus should be removed in the
# output.
'typ_tags': ['win', 'nvidia', 'win-laptop'],
'status':
ct.ResultStatus.FAIL,
'date':
'2023-03-01',
'is_slow':
False,
'typ_expectations': ['Pass'],
},
{
'name': ('gpu_tests.webgl_conformance_integration_test.'
'WebGLConformanceIntegrationTest.'
'conformance/textures/misc/video-rotation.html'),
'id':
'build-2222',
'typ_tags': ['win', 'nvidia'],
'status':
ct.ResultStatus.CRASH,
'date':
'2023-03-02',
'is_slow':
False,
'typ_expectations': ['Pass'],
},
{
'name': ('gpu_tests.webgl_conformance_integration_test.'
'WebGLConformanceIntegrationTest.'
'conformance/textures/misc/video-rotation.html'),
'id':
'build-3333',
'typ_tags': ['win', 'amd'],
'status':
ct.ResultStatus.FAIL,
'date':
'2023-03-03',
'is_slow':
True,
'typ_expectations': ['Pass', 'Slow'],
},
{
'name': ('gpu_tests.webgl_conformance_integration_test.'
'WebGLConformanceIntegrationTest.'
'conformance/textures/misc/texture-npot-video.html'),
'id':
'build-4444',
'typ_tags': ['win', 'nvidia'],
'status':
ct.ResultStatus.FAIL,
'date':
'2023-03-04',
'is_slow':
True,
'typ_expectations': ['Pass', 'Slow'],
},
{
'name': ('gpu_tests.pixel_integration_test.PixelIntegrationTest.'
'Pixel_CSS3DBlueBox'),
'id':
'build-5555',
'typ_tags': ['win', 'nvidia'],
'status':
ct.ResultStatus.FAIL,
'date':
'2023-03-05',
'is_slow':
False,
'typ_expectations': ['Pass'],
},
]
expected_output = {
'webgl_conformance_integration_test': {
'conformance/textures/misc/video-rotation.html': {
('nvidia', 'win'): [
(ct.ResultStatus.FAIL, 'http://ci.chromium.org/b/1111',
datetime.date.fromisoformat('2023-03-01'), False, ['Pass'
]),
(ct.ResultStatus.CRASH, 'http://ci.chromium.org/b/2222',
datetime.date.fromisoformat('2023-03-02'), False, ['Pass'
]),
],
('amd', 'win'): [
(ct.ResultStatus.FAIL, 'http://ci.chromium.org/b/3333',
datetime.date.fromisoformat('2023-03-03'), True,
['Pass', 'Slow']),
],
},
'conformance/textures/misc/texture-npot-video.html': {
('nvidia', 'win'):
[(ct.ResultStatus.FAIL, 'http://ci.chromium.org/b/4444',
datetime.date.fromisoformat('2023-03-04'), True,
['Pass', 'Slow'])],
},
},
'pixel_integration_test': {
'Pixel_CSS3DBlueBox': {
('nvidia', 'win'):
[(ct.ResultStatus.FAIL, 'http://ci.chromium.org/b/5555',
datetime.date.fromisoformat('2023-03-05'), False, ['Pass'])],
},
},
}
self.assertEqual(self._results.AggregateTestStatusResults(query_results),
expected_output)
class ConvertJsonResultsToResultObjectsUnittest(BaseResultsUnittest):
def testBasic(self) -> None:
"""Basic functionality test."""
r = [
{
'name': ('gpu_tests.webgl_conformance_integration_test.'
'WebGLConformanceIntegrationTest.'
'conformance/textures/misc/video-rotation.html'),
'id':
'build-1111',
# The win-laptop tag is ignored, and thus should be removed in the
# output.
'typ_tags': ['win', 'nvidia', 'win-laptop'],
},
{
'name': ('gpu_tests.webgl_conformance_integration_test.'
'WebGLConformanceIntegrationTest.'
'conformance/textures/misc/video-rotation.html'),
'id':
'build-2222',
'typ_tags': ['nvidia', 'win'],
},
]
expected_results = [
data_types.Result('webgl_conformance_integration_test',
'conformance/textures/misc/video-rotation.html',
('nvidia', 'win'), '1111'),
data_types.Result(
'webgl_conformance_integration_test',
'conformance/textures/misc/video-rotation.html',
('nvidia', 'win'),
'2222',
),
]
self.assertEqual(self._results._ConvertJsonResultsToResultObjects(r),
expected_results)
def testOnQueryResultWithOptionalAttributes(self) -> None:
"""Functionality test on query result with optional attributes."""
r = [
{
'name': ('gpu_tests.webgl_conformance_integration_test.'
'WebGLConformanceIntegrationTest.'
'conformance/textures/misc/video-rotation.html'),
'id':
'build-1111',
# The win-laptop tag is ignored, and thus should be removed in the
# output.
'typ_tags': ['win', 'nvidia', 'win-laptop'],
'status':
ct.ResultStatus.FAIL,
'date':
'2023-03-01',
'is_slow':
False,
'typ_expectations': ['Pass'],
},
{
'name': ('gpu_tests.webgl_conformance_integration_test.'
'WebGLConformanceIntegrationTest.'
'conformance/textures/misc/video-rotation.html'),
'id':
'build-2222',
'typ_tags': ['nvidia', 'win'],
'status':
ct.ResultStatus.CRASH,
'date':
'2023-03-02',
'is_slow':
True,
'typ_expectations': ['Pass', 'Slow'],
},
]
expected_results = [
data_types.Result('webgl_conformance_integration_test',
'conformance/textures/misc/video-rotation.html',
('nvidia', 'win'), '1111', ct.ResultStatus.FAIL,
datetime.date.fromisoformat('2023-03-01'), False,
['Pass']),
data_types.Result('webgl_conformance_integration_test',
'conformance/textures/misc/video-rotation.html',
('nvidia', 'win'), '2222', ct.ResultStatus.CRASH,
datetime.date.fromisoformat('2023-03-02'), True,
['Pass', 'Slow']),
]
self.assertEqual(self._results._ConvertJsonResultsToResultObjects(r),
expected_results)
class FilterOutSuppressedResultsUnittest(BaseResultsUnittest):
def testNoSuppressedResults(self) -> None:
"""Tests functionality when no expectations apply to the given results."""
self._local_mock.return_value = {
'foo_expectations.txt': GENERIC_EXPECTATION_FILE_CONTENTS,
}
r = [
data_types.Result('foo_integration_test', 'foo_test', tuple(['linux']),
'id'),
data_types.Result('foo_integration_test', 'bar_test', tuple(['win']),
'id'),
data_types.Result('bar_integration_test', 'foo_test', tuple(['win']),
'id')
]
self.assertEqual(self._results._FilterOutSuppressedResults(r), r)
def testSuppressedResults(self) -> None:
"""Tests functionality when expectations apply to the given results."""
self._local_mock.return_value = {
'foo_expectations.txt': GENERIC_EXPECTATION_FILE_CONTENTS,
}
self._expectation_file_mock.return_value = os.path.join(
uu.ABSOLUTE_EXPECTATION_FILE_DIRECTORY, 'foo_expectations.txt')
r = [
data_types.Result('foo_integration_test', 'foo_test', ('win', 'nvidia'),
'id'),
data_types.Result('foo_integration_test', 'foo_test', tuple(['win']),
'id'),
data_types.Result('foo_integration_test', 'bar_test', tuple(['win']),
'id'),
]
expected_filtered_results = [
data_types.Result('foo_integration_test', 'bar_test', tuple(['win']),
'id'),
]
self.assertEqual(self._results._FilterOutSuppressedResults(r),
expected_filtered_results)
if __name__ == '__main__':
unittest.main(verbosity=2)