1*dd0948b3SAndroid Build Coastguard Worker#!/usr/bin/env python3 2*dd0948b3SAndroid Build Coastguard Worker 3*dd0948b3SAndroid Build Coastguard Workerimport argparse 4*dd0948b3SAndroid Build Coastguard Workerimport os 5*dd0948b3SAndroid Build Coastguard Workerimport shutil 6*dd0948b3SAndroid Build Coastguard Worker 7*dd0948b3SAndroid Build Coastguard Worker 8*dd0948b3SAndroid Build Coastguard Workerdef parse_arguments(): 9*dd0948b3SAndroid Build Coastguard Worker """Parses command-line arguments and returns the parsed arguments object.""" 10*dd0948b3SAndroid Build Coastguard Worker parser = argparse.ArgumentParser(description="Validate directories and golden files.") 11*dd0948b3SAndroid Build Coastguard Worker parser.add_argument("--source-directory", required=True, help="Path to the source directory.") 12*dd0948b3SAndroid Build Coastguard Worker parser.add_argument("--android-build-top", required=True, 13*dd0948b3SAndroid Build Coastguard Worker help="Path to the Android build directory.") 14*dd0948b3SAndroid Build Coastguard Worker return parser.parse_args() 15*dd0948b3SAndroid Build Coastguard Worker 16*dd0948b3SAndroid Build Coastguard Worker 17*dd0948b3SAndroid Build Coastguard Workerdef validate_directories(args): 18*dd0948b3SAndroid Build Coastguard Worker """Validates the provided source and Android directory arguments and returns their paths if valid.""" 19*dd0948b3SAndroid Build Coastguard Worker if not args.source_directory or not args.android_build_top: 20*dd0948b3SAndroid Build Coastguard Worker print("Error: Both --source-directory and --android-build-top arguments are required.") 21*dd0948b3SAndroid Build Coastguard Worker return None 22*dd0948b3SAndroid Build Coastguard Worker 23*dd0948b3SAndroid Build Coastguard Worker source_dir = args.source_directory 24*dd0948b3SAndroid Build Coastguard Worker android_dir = args.android_build_top 25*dd0948b3SAndroid Build Coastguard Worker 26*dd0948b3SAndroid Build Coastguard Worker is_source_dir_valid = os.path.isdir(source_dir) 27*dd0948b3SAndroid Build Coastguard Worker is_android_dir_valid = os.path.isdir(android_dir) 28*dd0948b3SAndroid Build Coastguard Worker 29*dd0948b3SAndroid Build Coastguard Worker if not is_source_dir_valid: 30*dd0948b3SAndroid Build Coastguard Worker print(f"Error: Source directory does not exist: {source_dir}") 31*dd0948b3SAndroid Build Coastguard Worker 32*dd0948b3SAndroid Build Coastguard Worker if not is_android_dir_valid: 33*dd0948b3SAndroid Build Coastguard Worker print(f"Error: Android build directory does not exist: {android_dir}") 34*dd0948b3SAndroid Build Coastguard Worker 35*dd0948b3SAndroid Build Coastguard Worker if not is_source_dir_valid or not is_android_dir_valid: 36*dd0948b3SAndroid Build Coastguard Worker return None 37*dd0948b3SAndroid Build Coastguard Worker 38*dd0948b3SAndroid Build Coastguard Worker return [source_dir, android_dir] 39*dd0948b3SAndroid Build Coastguard Worker 40*dd0948b3SAndroid Build Coastguard Worker 41*dd0948b3SAndroid Build Coastguard Workerdef find_golden_files(source_dir): 42*dd0948b3SAndroid Build Coastguard Worker """Finds golden files within the source directory and returns their filenames or handles errors.""" 43*dd0948b3SAndroid Build Coastguard Worker golden_files = [] 44*dd0948b3SAndroid Build Coastguard Worker for root, _, files in os.walk(source_dir): 45*dd0948b3SAndroid Build Coastguard Worker for file in files: 46*dd0948b3SAndroid Build Coastguard Worker if "_goldResult_" in file and file.endswith(".textproto"): 47*dd0948b3SAndroid Build Coastguard Worker golden_files.append(file) 48*dd0948b3SAndroid Build Coastguard Worker 49*dd0948b3SAndroid Build Coastguard Worker if not golden_files: 50*dd0948b3SAndroid Build Coastguard Worker print("Error: No golden files found in the source directory.") 51*dd0948b3SAndroid Build Coastguard Worker return None 52*dd0948b3SAndroid Build Coastguard Worker 53*dd0948b3SAndroid Build Coastguard Worker return golden_files 54*dd0948b3SAndroid Build Coastguard Worker 55*dd0948b3SAndroid Build Coastguard Worker 56*dd0948b3SAndroid Build Coastguard Workerdef validate_protos(source_dir, proto_files): 57*dd0948b3SAndroid Build Coastguard Worker """Validates proto files, extracts image locations, and handles errors.""" 58*dd0948b3SAndroid Build Coastguard Worker all_image_locations = [] 59*dd0948b3SAndroid Build Coastguard Worker for filename in proto_files: 60*dd0948b3SAndroid Build Coastguard Worker required_image_locations = {"image_location_diff": False, "image_location_golden": False, 61*dd0948b3SAndroid Build Coastguard Worker "image_location_reference": False, "image_location_test": False} 62*dd0948b3SAndroid Build Coastguard Worker found_image_locations = {} 63*dd0948b3SAndroid Build Coastguard Worker 64*dd0948b3SAndroid Build Coastguard Worker with open(os.path.join(source_dir, filename), 'r') as file: 65*dd0948b3SAndroid Build Coastguard Worker for line in file: 66*dd0948b3SAndroid Build Coastguard Worker for location in required_image_locations: 67*dd0948b3SAndroid Build Coastguard Worker if line.startswith(location): 68*dd0948b3SAndroid Build Coastguard Worker if required_image_locations[location]: 69*dd0948b3SAndroid Build Coastguard Worker print(f"Error: Duplicate '{location}' entry found in {filename}.") 70*dd0948b3SAndroid Build Coastguard Worker return None 71*dd0948b3SAndroid Build Coastguard Worker required_image_locations[location] = True 72*dd0948b3SAndroid Build Coastguard Worker found_image_locations[location] = line.split(": ")[1].strip().strip('"') 73*dd0948b3SAndroid Build Coastguard Worker break 74*dd0948b3SAndroid Build Coastguard Worker 75*dd0948b3SAndroid Build Coastguard Worker if not all(required_image_locations.values()): 76*dd0948b3SAndroid Build Coastguard Worker missing_keys = [key for key, found in required_image_locations.items() if not found] 77*dd0948b3SAndroid Build Coastguard Worker print(f"Error: Missing image location(s) in {filename}: {', '.join(missing_keys)}") 78*dd0948b3SAndroid Build Coastguard Worker return None 79*dd0948b3SAndroid Build Coastguard Worker else: 80*dd0948b3SAndroid Build Coastguard Worker print(f"Proto file {filename} is valid.") 81*dd0948b3SAndroid Build Coastguard Worker all_image_locations.append(found_image_locations) 82*dd0948b3SAndroid Build Coastguard Worker return all_image_locations 83*dd0948b3SAndroid Build Coastguard Worker 84*dd0948b3SAndroid Build Coastguard Worker 85*dd0948b3SAndroid Build Coastguard Workerdef validate_test_images(source_dir, all_image_locations): 86*dd0948b3SAndroid Build Coastguard Worker """Validates if PNG files exist in the source directory based on provided image locations.""" 87*dd0948b3SAndroid Build Coastguard Worker for image_locations in all_image_locations: 88*dd0948b3SAndroid Build Coastguard Worker for location, path in image_locations.items(): 89*dd0948b3SAndroid Build Coastguard Worker if location != "image_location_golden": 90*dd0948b3SAndroid Build Coastguard Worker base_name = os.path.splitext(os.path.basename(path))[0] 91*dd0948b3SAndroid Build Coastguard Worker for root, _, files in os.walk(source_dir): 92*dd0948b3SAndroid Build Coastguard Worker for file in files: 93*dd0948b3SAndroid Build Coastguard Worker if file.startswith(base_name) and file.endswith(".png"): 94*dd0948b3SAndroid Build Coastguard Worker image_locations[location] = os.path.join(root, file) 95*dd0948b3SAndroid Build Coastguard Worker break 96*dd0948b3SAndroid Build Coastguard Worker else: 97*dd0948b3SAndroid Build Coastguard Worker print(f"Error: No PNG file found matching {path} in {source_dir}") 98*dd0948b3SAndroid Build Coastguard Worker return None 99*dd0948b3SAndroid Build Coastguard Worker filename_without_ext = \ 100*dd0948b3SAndroid Build Coastguard Worker os.path.splitext(os.path.basename(image_locations["image_location_golden"]))[0] 101*dd0948b3SAndroid Build Coastguard Worker print(f"Golden {filename_without_ext} is valid.") 102*dd0948b3SAndroid Build Coastguard Worker return all_image_locations 103*dd0948b3SAndroid Build Coastguard Worker 104*dd0948b3SAndroid Build Coastguard Worker 105*dd0948b3SAndroid Build Coastguard Workerdef update_goldens(android_dir, updated_image_locations_list): 106*dd0948b3SAndroid Build Coastguard Worker """Copies updated 'image_location_test' images to their 'image_location_golden' paths in the android_build_top directory.""" 107*dd0948b3SAndroid Build Coastguard Worker for image_locations in updated_image_locations_list: 108*dd0948b3SAndroid Build Coastguard Worker test_image_path = image_locations["image_location_test"] 109*dd0948b3SAndroid Build Coastguard Worker golden_image_path = os.path.join(android_dir, image_locations["image_location_golden"]) 110*dd0948b3SAndroid Build Coastguard Worker 111*dd0948b3SAndroid Build Coastguard Worker try: 112*dd0948b3SAndroid Build Coastguard Worker shutil.copy2(test_image_path, golden_image_path) 113*dd0948b3SAndroid Build Coastguard Worker print(f"Updated golden image: {golden_image_path}") 114*dd0948b3SAndroid Build Coastguard Worker except IOError as e: 115*dd0948b3SAndroid Build Coastguard Worker print(f"Error updating golden image: {e}") 116*dd0948b3SAndroid Build Coastguard Worker 117*dd0948b3SAndroid Build Coastguard Worker 118*dd0948b3SAndroid Build Coastguard Workerdef main(): 119*dd0948b3SAndroid Build Coastguard Worker args = parse_arguments() 120*dd0948b3SAndroid Build Coastguard Worker 121*dd0948b3SAndroid Build Coastguard Worker directories = validate_directories(args) 122*dd0948b3SAndroid Build Coastguard Worker if directories is None: 123*dd0948b3SAndroid Build Coastguard Worker return 124*dd0948b3SAndroid Build Coastguard Worker 125*dd0948b3SAndroid Build Coastguard Worker source_dir, android_dir = directories 126*dd0948b3SAndroid Build Coastguard Worker 127*dd0948b3SAndroid Build Coastguard Worker proto_files = find_golden_files(source_dir) 128*dd0948b3SAndroid Build Coastguard Worker if proto_files is None: 129*dd0948b3SAndroid Build Coastguard Worker return 130*dd0948b3SAndroid Build Coastguard Worker 131*dd0948b3SAndroid Build Coastguard Worker all_image_locations = validate_protos(source_dir, proto_files) 132*dd0948b3SAndroid Build Coastguard Worker if all_image_locations is None: 133*dd0948b3SAndroid Build Coastguard Worker return 134*dd0948b3SAndroid Build Coastguard Worker 135*dd0948b3SAndroid Build Coastguard Worker updated_image_locations_list = validate_test_images(source_dir, all_image_locations) 136*dd0948b3SAndroid Build Coastguard Worker if updated_image_locations_list is None: 137*dd0948b3SAndroid Build Coastguard Worker return 138*dd0948b3SAndroid Build Coastguard Worker 139*dd0948b3SAndroid Build Coastguard Worker update_goldens(android_dir, updated_image_locations_list) 140*dd0948b3SAndroid Build Coastguard Worker 141*dd0948b3SAndroid Build Coastguard Worker 142*dd0948b3SAndroid Build Coastguard Workerif __name__ == "__main__": 143*dd0948b3SAndroid Build Coastguard Worker main() 144