blob: 5d64fe997c8172ffe5ac3ba9bebaa9f363eabc2b [file] [log] [blame]
#!/usr/bin/env python3
# Copyright (C) 2023 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import os
import re
import sys
from typing import TYPE_CHECKING, Dict, List, Optional, Set, Tuple, Union
from python.generators.diff_tests.testing import (BinaryProto, Csv, DataPath,
DiffTestBlueprint, Json, Path,
Systrace, TextProto)
from python.generators.diff_tests.models import DiscoveredTests, TestCase, TestType
if TYPE_CHECKING:
from python.generators.diff_tests.testing import TestSuite
class TestLoader:
"""Discovers and loads all tests."""
def __init__(self, root_dir: os.PathLike):
self.root_dir = root_dir
def discover_and_load_tests(self, name_filter: str,
enabled_modules: Set[str]) -> DiscoveredTests:
# Import the index file to discover all the tests.
include_path = os.path.join(self.root_dir, 'test', 'trace_processor',
'diff_tests')
sys.path.append(include_path)
from include_index import fetch_all_diff_tests
sys.path.pop()
all_tests_data = fetch_all_diff_tests(include_path)
runnable: List[TestCase] = []
skipped_name_filter: List[str] = []
skipped_module_missing: List[Tuple[str, str]] = []
query_metric_pattern = re.compile(name_filter)
for name, blueprint in all_tests_data:
if not query_metric_pattern.match(os.path.basename(name)):
skipped_name_filter.append(name)
continue
should_run, reason = self._validate_test(blueprint, enabled_modules)
if not should_run:
if reason:
skipped_module_missing.append((name, reason))
continue
query_path = self._get_query_path(name, blueprint)
trace_path = self._get_trace_path(name, blueprint)
expected_path = self._get_expected_path(name, blueprint)
expected_str = self._get_expected_str(name, blueprint, expected_path)
register_files_dir = self._get_register_files_dir(name, blueprint)
test_type = self._get_test_type(blueprint)
runnable.append(
TestCase(name, blueprint, query_path, trace_path, expected_path,
expected_str, register_files_dir, test_type))
return DiscoveredTests(runnable, skipped_name_filter,
skipped_module_missing)
# Returns a bool that is true if and only if the test should run, and a string
# describing the reason the test did not run
def _validate_test(self, blueprint: DiffTestBlueprint,
enabled_modules: Set[str]) -> Tuple[bool, Optional[str]]:
if blueprint.module_dependencies:
for module in blueprint.module_dependencies:
if module not in enabled_modules:
return False, f"module '{module}' not found"
return True, None
def _get_test_type(self, blueprint: DiffTestBlueprint) -> TestType:
if blueprint.is_metric():
return TestType.METRIC
elif blueprint.is_metric_v2():
return TestType.METRIC_V2
else:
return TestType.QUERY
def _get_path(self, name: str, file_path: Union[Path, DataPath],
index_dir: str, test_data_dir: str) -> str:
if isinstance(file_path, DataPath):
path = os.path.join(test_data_dir, file_path.filename)
else:
path = os.path.abspath(os.path.join(index_dir, file_path.filename))
if not os.path.exists(path):
raise AssertionError(f"File ({path}) for test '{name}' does not exist.")
return path
def _get_query_path(self, name: str,
blueprint: DiffTestBlueprint) -> Optional[str]:
if not blueprint.is_query_file():
return None
assert isinstance(blueprint.query, (Path, DataPath))
return self._get_path(name, blueprint.query, blueprint.index_dir,
blueprint.test_data_dir)
def _get_trace_path(self, name: str,
blueprint: DiffTestBlueprint) -> Optional[str]:
if not blueprint.is_trace_file():
return None
assert isinstance(blueprint.trace, (Path, DataPath))
return self._get_path(name, blueprint.trace, blueprint.index_dir,
blueprint.test_data_dir)
def _get_expected_path(self, name: str,
blueprint: DiffTestBlueprint) -> Optional[str]:
if not blueprint.is_out_file():
return None
assert isinstance(blueprint.out, (Path, DataPath))
return self._get_path(name, blueprint.out, blueprint.index_dir,
blueprint.test_data_dir)
def _get_register_files_dir(self, name: str,
blueprint: DiffTestBlueprint) -> Optional[str]:
if not blueprint.register_files_dir:
return None
return self._get_path(name, blueprint.register_files_dir,
blueprint.index_dir, blueprint.test_data_dir)
def _get_expected_str(self, name: str, blueprint: DiffTestBlueprint,
expected_path: Optional[str]) -> str:
if blueprint.is_out_file():
assert expected_path
with open(expected_path, 'r') as expected_file:
return expected_file.read()
assert isinstance(blueprint.out, (
TextProto,
Json,
Csv,
BinaryProto,
Systrace,
))
return blueprint.out.contents