#!/usr/bin/env python3 # Step to run: # 1. run . build/envsetup.sh; lunch ... # 2. Run this script from inside a terminal in sysui studio, as it needs JAVA_HOME to be setup. import argparse, itertools, os, re, subprocess from collections.abc import Generator from modules_config import Config, ModuleConfig, TestModuleMapping def runGradleCommand(outputFile: str, cfg: Config, mc: ModuleConfig) -> int: gradlew_dir: String = os.path.join(cfg.build_top, mc.gradlew_location) with open(os.path.expanduser(outputFile), "w") as of: ret = subprocess.run([os.path.join(gradlew_dir, "gradlew"), f"{mc.gradlew_target}"], stdout=of, stderr=of, cwd=gradlew_dir) return ret.returncode def check_java(): expected_versions = ['17.0', '1.7', '21.0'] java_home = os.environ.get('JAVA_HOME') if not java_home: print('JAVA_HOME is not set, exiting ...') exit (-2) java_binary = os.path.join(java_home, 'bin/java') print('Checking version for java binary:', java_binary) out = subprocess.check_output([java_binary, '-version'], stderr=subprocess.STDOUT).decode('utf-8') version = re.search(' version \"(\d+\.\d+).*\"', out).groups()[0] if not version in expected_versions: print('Your java version, version', version, ' does not match any of the expected versions', expected_versions) exit (-3) def walkDir(dirname: str) -> Generator[str, None, None]: print("Processing dir:", dirname) for root, _, files in os.walk(dirname, topdown=False): for name in files: if not (name.endswith('.java') or name.endswith('.kt')): continue yield os.path.join(root, name) def processFile(filename: str, cfg: Config, mc: ModuleConfig) -> None: print("Attempting roboify on: " , filename) # Move to multivalentTests new_filename = filename.replace("/tests/", "/tests/multivalentTests/") dirname = os.path.dirname(new_filename) basename = os.path.basename(new_filename) outputFile = f"{cfg.output_dir}/{basename}.err" os.makedirs(dirname, exist_ok=True) os.rename(filename, new_filename) # Attempt run exitValue = runGradleCommand(outputFile, cfg, mc) # Log and restore state if needed print("Test run ", "succeeded" if exitValue == 0 else "failed", " with exitValue: ", exitValue) if exitValue != 0 : os.rename(new_filename, filename) return exitValue == 0 def init(): parser = argparse.ArgumentParser( description='This script attempts to convert device based unit tests to deviceless.') parser.add_argument('-m', '--module_pattern', required=True) check_java() return parser.parse_args() def process(cfg: Config, successful: list[str], failed: list[str]): for mc in cfg.module_configs: for d in mc.dirs: for f in walkDir(os.path.join(cfg.build_top, d)): if any(excl in f for excl in mc.excludes): print("Ignore file:", f) continue ret = processFile(f, cfg, mc) (successful if ret else failed).append(f) def main(): args = init() successful: list[str] = [] failed: list[str] = [] module_configs = [] for k, mc in TestModuleMapping.items(): if not (args.module_pattern in k): continue print(f"Processing module:{k}, module_config:{mc}") module_configs.append(mc) if not module_configs: print(f"Could not match any modules that match: [{args.module_pattern}], exiting ...") exit(-5) cfg = Config(module_configs) if not cfg.build_top: print("ANDROID_BUILD_TOP env variable is not set, plase run lunch before invoking this script") exit(-1) process(cfg, successful, failed) print(f"Successes:\n{successful[:3]} ...") print(f"Failures:\n{failed}") return 0 if __name__ == "__main__": ret = main() exit(ret)