/tools/disable_tests/expectations.py
https://github.com/chromium/chromium · Python · 127 lines · 82 code · 30 blank · 15 comment · 18 complexity · 4d4922b6ea31277caff2b19f5e9270e4 MD5 · raw file
- # Copyright 2021 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.
- """Code specific to disabling tests using test expectations files"""
- import collections
- import os
- import sys
- from typing import Optional, List
- import conditions
- from conditions import Condition
- import errors
- sys.path.append(
- os.path.join(os.path.dirname(__file__), '..', '..', 'third_party',
- 'catapult', 'third_party', 'typ'))
- from typ.expectations_parser import ( # type: ignore
- Expectation, TaggedTestListParser)
- sys.path.pop()
- def search_for_expectations(filename: str, test_name: str) -> str:
- # Web test have "virtual test suites", where the same set of tests is run with
- # different parameters. These are specified by "VirtualTestSuites" files, but
- # generally the way it works is that a test a/b/c.html will have a virtual
- # test in virtual/foo/a/b/c.html. So we handle this by stripping parts of the
- # path off until the filename and test name match.
- while not filename.endswith(test_name) and '/' in test_name:
- test_name = test_name[test_name.index('/') + 1:]
- # TODO: Is this ever not the case? If so we might need to just keep searching
- # upwards, directory by directory until we find a test expectations file
- # referencing this test.
- assert filename.endswith(test_name)
- expectations_dir = filename[:-len(test_name)]
- # TODO: I think ASan and some other conditions are handled via different
- # files.
- expectations_path = os.path.join(expectations_dir, 'TestExpectations')
- if os.path.exists(expectations_path):
- return expectations_path
- raise errors.InternalError("Couldn't find TestExpectations file for test " +
- f"{test_name} " +
- f"(expected to find it at {expectations_path})")
- def disabler(full_test_name: str, source_file: str, new_cond: Condition,
- message: Optional[str]) -> str:
- comment = None
- if message:
- comment = f"# {message}"
- existing_expectation: Optional[Expectation] = None
- condition = conditions.NEVER
- for expectation in TaggedTestListParser(source_file).expectations:
- if expectation.test == full_test_name:
- existing_expectation = expectation
- if set(expectation.results) & {'SKIP', 'FAIL'}:
- tags = set(expectation.tags)
- if not tags:
- condition = conditions.ALWAYS
- break
- merged = conditions.merge(condition, new_cond)
- if existing_expectation is None:
- ex = Expectation(test=full_test_name,
- results=['SKIP'],
- tags=condition_to_tags(merged))
- while not source_file.endswith('\n\n'):
- source_file += '\n'
- if comment:
- source_file += f"{comment}\n"
- source_file += ex.to_string()
- return source_file
- new_expectation = Expectation(
- reason=existing_expectation.reason,
- test=existing_expectation.test,
- trailing_comments=existing_expectation.trailing_comments,
- results=['SKIP'],
- tags=condition_to_tags(merged),
- )
- lines = source_file.split('\n')
- # Minus 1 as 'lineno' is 1-based.
- lines[existing_expectation.lineno - 1] = new_expectation.to_string()
- if comment:
- lines.insert(existing_expectation.lineno - 1, comment)
- return '\n'.join(lines)
- ExpectationsInfo = collections.namedtuple('ExpectationsInfo', 'tag')
- for t_name, t_tag in [
- ('android', 'Android'),
- ('fuchsia', 'Fuchsia'),
- ('linux', 'Linux'),
- ('mac', 'Mac'),
- ('win', 'Win'),
- ]:
- conditions.get_term(t_name).expectations_info = ExpectationsInfo(tag=t_tag)
- def condition_to_tags(cond: Condition) -> List[str]:
- if cond is conditions.ALWAYS:
- return []
- assert not isinstance(cond, conditions.BaseCondition)
- if isinstance(cond, conditions.Terminal):
- return [conditions.get_term(cond.name).expectations_info.tag]
- op, args = cond
- if op == 'or':
- return [tag for arg in args for tag in condition_to_tags(arg)]
- raise errors.InternalError(
- f"Unable to express condition in test expectations format: {cond}")