1#!/usr/bin/env python3 2 3# Copyright (C) 2020 The Android Open Source Project 4 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16 17import os 18import unittest 19from xml.etree import ElementTree 20import subprocess 21import sys 22 23VERBOSE = True 24TEST_CONFIG = os.path.join(os.path.dirname(__file__), "test_igt_gpu_tools.xml") 25 26""" Extracts tests from AndroidTest.xml compatible file 27 param: xmlfile str containing path to AndroidTest.xml compatible xml file 28""" 29def extract_tests_from_xml(xmlfile): 30 tree = ElementTree.parse(xmlfile) 31 root = tree.getroot() 32 return [(o.attrib['key'], o.attrib['value']) 33 for o in root.findall("./target_preparer/option") 34 if o.attrib['name'] == "push-file"] 35 36def run_command(command): 37 serial_number = os.environ.get("ANDROID_SERIAL", "") 38 if not serial_number: 39 raise "$ANDROID_SERIAL is empty, device must be specified" 40 full_command = ["adb", "-s", serial_number, "shell"] + command 41 if VERBOSE: 42 print("+" + " ".join(full_command)) 43 ret = subprocess.run(full_command, capture_output=True, universal_newlines=True) 44 if VERBOSE: 45 print(ret.stdout) 46 return ret.stdout 47 48class IGTGpuToolsBinary(): 49 """Harness object for a specific IGT GPU test binary. """ 50 51 """ param: ondevice_test_path The IGT binary path on device """ 52 def __init__(self, ondevice_test_path): 53 self._path = ondevice_test_path 54 subtests = run_command([self._path, "--list-subtests"]) 55 self._subtests = list(filter(lambda x: x != "", subtests.split("\n"))) 56 57 """lists subtests detected in tests. 58 return: list of strings indicating subtests found in binary. 59 """ 60 def subtests(self): 61 return self._subtests; 62 63 """Runs a subtest. 64 65 param: subtest_name One of the subtests listed by self.subtest() 66 return: a subprocess.CompletedProcess 67 """ 68 def run_subtest(self, subtest_name): 69 if subtest_name not in self._subtests: 70 error 71 return run_command([self._path, "--run-subtest", subtest_name]) 72 73class IGTGpuToolsTest(unittest.TestCase): 74 """Tests for DRM/KMS using Intel Graphics Tests suite""" 75 76 """ param: subtest A valid subtest for the binary 77 param: the IGT binary to run as a unit test. 78 """ 79 def __init__(self, subtest, binary): 80 self._subtest_name = subtest 81 self._test_binary = binary 82 setattr(self, self._subtest_name, self.runTest) 83 super(IGTGpuToolsTest, self).__init__(methodName=self._subtest_name) 84 85 """ Runs the test set in the constructor """ 86 def runTest(self): 87 output = self._test_binary.run_subtest(self._subtest_name) 88 for line in output.split("\n"): 89 if "Subtest" not in line: 90 continue; 91 if "SKIP" in line: 92 self.skipTest("{} - skipped".format(self._subtest_name)) 93 break 94 if "SUCCESS" in line: 95 break 96 if "FAIL" in line: 97 self.fail(output) 98 break 99 self.fail("could not parse test output; test runner failure") 100 101ANDROID_RUNNER_REQUIRED_VERBOSITY = 2 102 103def main(): 104 """main entrypoint for test runner""" 105 106 runner = unittest.TextTestRunner(stream=sys.stderr, verbosity=ANDROID_RUNNER_REQUIRED_VERBOSITY) 107 suite = unittest.TestSuite() 108 for test, test_path in extract_tests_from_xml(TEST_CONFIG): 109 print("Found IGT-GPU-tools test {}".format(test)) 110 subsuite = unittest.TestSuite() 111 binary = IGTGpuToolsBinary(test_path) 112 for subtest in binary.subtests(): 113 print("\tFound subtest {}".format(subtest)) 114 subsuite.addTest(IGTGpuToolsTest(subtest, binary)) 115 suite.addTest(subsuite) 116 runner.run(suite) 117 118if __name__=="__main__": 119 main() 120