#!/usr/bin/env python3 # Copyright (C) 2020 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 unittest from xml.etree import ElementTree import subprocess import sys VERBOSE = True TEST_CONFIG = os.path.join(os.path.dirname(__file__), "test_igt_gpu_tools.xml") """ Extracts tests from AndroidTest.xml compatible file param: xmlfile str containing path to AndroidTest.xml compatible xml file """ def extract_tests_from_xml(xmlfile): tree = ElementTree.parse(xmlfile) root = tree.getroot() return [(o.attrib['key'], o.attrib['value']) for o in root.findall("./target_preparer/option") if o.attrib['name'] == "push-file"] def run_command(command): serial_number = os.environ.get("ANDROID_SERIAL", "") if not serial_number: raise "$ANDROID_SERIAL is empty, device must be specified" full_command = ["adb", "-s", serial_number, "shell"] + command if VERBOSE: print("+" + " ".join(full_command)) ret = subprocess.run(full_command, capture_output=True, universal_newlines=True) if VERBOSE: print(ret.stdout) return ret.stdout class IGTGpuToolsBinary(): """Harness object for a specific IGT GPU test binary. """ """ param: ondevice_test_path The IGT binary path on device """ def __init__(self, ondevice_test_path): self._path = ondevice_test_path subtests = run_command([self._path, "--list-subtests"]) self._subtests = list(filter(lambda x: x != "", subtests.split("\n"))) """lists subtests detected in tests. return: list of strings indicating subtests found in binary. """ def subtests(self): return self._subtests; """Runs a subtest. param: subtest_name One of the subtests listed by self.subtest() return: a subprocess.CompletedProcess """ def run_subtest(self, subtest_name): if subtest_name not in self._subtests: error return run_command([self._path, "--run-subtest", subtest_name]) class IGTGpuToolsTest(unittest.TestCase): """Tests for DRM/KMS using Intel Graphics Tests suite""" """ param: subtest A valid subtest for the binary param: the IGT binary to run as a unit test. """ def __init__(self, subtest, binary): self._subtest_name = subtest self._test_binary = binary setattr(self, self._subtest_name, self.runTest) super(IGTGpuToolsTest, self).__init__(methodName=self._subtest_name) """ Runs the test set in the constructor """ def runTest(self): output = self._test_binary.run_subtest(self._subtest_name) for line in output.split("\n"): if "Subtest" not in line: continue; if "SKIP" in line: self.skipTest("{} - skipped".format(self._subtest_name)) break if "SUCCESS" in line: break if "FAIL" in line: self.fail(output) break self.fail("could not parse test output; test runner failure") ANDROID_RUNNER_REQUIRED_VERBOSITY = 2 def main(): """main entrypoint for test runner""" runner = unittest.TextTestRunner(stream=sys.stderr, verbosity=ANDROID_RUNNER_REQUIRED_VERBOSITY) suite = unittest.TestSuite() for test, test_path in extract_tests_from_xml(TEST_CONFIG): print("Found IGT-GPU-tools test {}".format(test)) subsuite = unittest.TestSuite() binary = IGTGpuToolsBinary(test_path) for subtest in binary.subtests(): print("\tFound subtest {}".format(subtest)) subsuite.addTest(IGTGpuToolsTest(subtest, binary)) suite.addTest(subsuite) runner.run(suite) if __name__=="__main__": main()