"""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 (
Expectation, TaggedTestListParser)
sys.path.pop()
def search_for_expectations(filename: str, test_name: str) -> str:
while not filename.endswith(test_name) and '/' in test_name:
test_name = test_name[test_name.index('/') + 1:]
assert filename.endswith(test_name)
expectations_dir = filename[:-len(test_name)]
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')
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}")