blob: 4eed28dcb97cf94d82c1c9446b86cf8e1e0e5677 [file] [log] [blame]
Mingjun Yangd448be22024-10-15 05:37:00 +00001# Copyright 2024, The Android Open Source Project
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
Mingjun Yangd2cc6a62024-11-05 23:44:38 +000014"""Test discovery agent that uses TradeFed to discover test artifacts."""
15import glob
16import json
17import logging
18import os
19import subprocess
20import buildbot
21
22
Mingjun Yangd448be22024-10-15 05:37:00 +000023class TestDiscoveryAgent:
24 """Test discovery agent."""
25
Mingjun Yangd2cc6a62024-11-05 23:44:38 +000026 _TRADEFED_PREBUILT_JAR_RELATIVE_PATH = (
27 "vendor/google_tradefederation/prebuilts/filegroups/google-tradefed/"
Mingjun Yangd448be22024-10-15 05:37:00 +000028 )
29
Mingjun Yangd2cc6a62024-11-05 23:44:38 +000030 _TRADEFED_NO_POSSIBLE_TEST_DISCOVERY_KEY = "NoPossibleTestDiscovery"
31
32 _TRADEFED_TEST_ZIP_REGEXES_LIST_KEY = "TestZipRegexes"
33
34 _TRADEFED_DISCOVERY_OUTPUT_FILE_NAME = "test_discovery_agent.txt"
35
Mingjun Yangd448be22024-10-15 05:37:00 +000036 def __init__(
37 self,
38 tradefed_args: list[str],
Mingjun Yangd2cc6a62024-11-05 23:44:38 +000039 test_mapping_zip_path: str = "",
40 tradefed_jar_revelant_files_path: str = _TRADEFED_PREBUILT_JAR_RELATIVE_PATH,
Mingjun Yangd448be22024-10-15 05:37:00 +000041 ):
42 self.tradefed_args = tradefed_args
43 self.test_mapping_zip_path = test_mapping_zip_path
44 self.tradefed_jar_relevant_files_path = tradefed_jar_revelant_files_path
45
46 def discover_test_zip_regexes(self) -> list[str]:
47 """Discover test zip regexes from TradeFed.
48
49 Returns:
50 A list of test zip regexes that TF is going to try to pull files from.
51 """
Mingjun Yangd2cc6a62024-11-05 23:44:38 +000052 test_discovery_output_file_name = os.path.join(
53 buildbot.OutDir(), self._TRADEFED_DISCOVERY_OUTPUT_FILE_NAME
54 )
55 with open(
56 test_discovery_output_file_name, mode="w+t"
57 ) as test_discovery_output_file:
58 java_args = []
59 java_args.append("prebuilts/jdk/jdk21/linux-x86/bin/java")
60 java_args.append("-cp")
61 java_args.append(
62 self.create_classpath(self.tradefed_jar_relevant_files_path)
63 )
64 java_args.append(
65 "com.android.tradefed.observatory.TestZipDiscoveryExecutor"
66 )
67 java_args.extend(self.tradefed_args)
68 env = os.environ.copy()
69 env.update({"DISCOVERY_OUTPUT_FILE": test_discovery_output_file.name})
70 logging.info(f"Calling test discovery with args: {java_args}")
71 try:
72 result = subprocess.run(args=java_args, env=env, text=True, check=True)
73 logging.info(f"Test zip discovery output: {result.stdout}")
74 except subprocess.CalledProcessError as e:
75 raise TestDiscoveryError(
76 f"Failed to run test discovery, strout: {e.stdout}, strerr:"
77 f" {e.stderr}, returncode: {e.returncode}"
78 )
79 data = json.loads(test_discovery_output_file.read())
80 logging.info(f"Test discovery result file content: {data}")
81 if (
82 self._TRADEFED_NO_POSSIBLE_TEST_DISCOVERY_KEY in data
83 and data[self._TRADEFED_NO_POSSIBLE_TEST_DISCOVERY_KEY]
84 ):
85 raise TestDiscoveryError("No possible test discovery")
86 if (
87 data[self._TRADEFED_TEST_ZIP_REGEXES_LIST_KEY] is None
88 or data[self._TRADEFED_TEST_ZIP_REGEXES_LIST_KEY] is []
89 ):
90 raise TestDiscoveryError("No test zip regexes returned")
91 return data[self._TRADEFED_TEST_ZIP_REGEXES_LIST_KEY]
Mingjun Yangd448be22024-10-15 05:37:00 +000092
93 def discover_test_modules(self) -> list[str]:
94 """Discover test modules from TradeFed.
95
96 Returns:
97 A list of test modules that TradeFed is going to execute based on the
98 TradeFed test args.
99 """
100 return []
Mingjun Yangd2cc6a62024-11-05 23:44:38 +0000101
102 def create_classpath(self, directory):
103 """Creates a classpath string from all .jar files in the given directory.
104
105 Args:
106 directory: The directory to search for .jar files.
107
108 Returns:
109 A string representing the classpath, with jar files separated by the
110 OS-specific path separator (e.g., ':' on Linux/macOS, ';' on Windows).
111 """
112 jar_files = glob.glob(os.path.join(directory, "*.jar"))
113 return os.pathsep.join(jar_files)
114
115
116class TestDiscoveryError(Exception):
117 """A TestDiscoveryErrorclass."""
118
119 def __init__(self, message):
120 super().__init__(message)
121 self.message = message