1#!/usr/bin/env python3 2 3# 4# Copyright 2024, The Android Open Source Project 5# 6# Licensed under the Apache License, Version 2.0 (the "License"); 7# you may not use this file except in compliance with the License. 8# You may obtain a copy of the License at 9# 10# http://www.apache.org/licenses/LICENSE-2.0 11# 12# Unless required by applicable law or agreed to in writing, software 13# distributed under the License is distributed on an "AS IS" BASIS, 14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15# See the License for the specific language governing permissions and 16# limitations under the License. 17# 18 19"""This program validates pixel thermal configuration strings 20against a predefined list of fields. 21""" 22 23from __future__ import print_function 24 25import argparse 26import errno 27import json 28import os 29import shutil 30import subprocess 31import sys 32import gitlint.git as git 33 34from pixel_config_checker import PixelJSONFieldNameChecker 35 36def get_thermal_modified_files(commit): 37 """Getter for finding which thermal json files were modified 38 in the commit. 39 40 Args: Commit sha 41 42 Returns: 43 modified_files: List of thermal config files modified if any. 44 """ 45 root = git.repository_root() 46 modified_files = git.modified_files(root, True, commit) 47 modified_files = {f: modified_files[f] for f 48 in modified_files if f.endswith('.json') and 'thermal' in f} 49 50 return modified_files 51 52def validate_sensor_config(sensors): 53 """Validates configuration fields sensors in thermal config 54 55 Args: Json object for sensors 56 57 Returns: 58 Tuple of Success and error message. 59 """ 60 for sensor in sensors: 61 sensor_name = sensor["Name"] 62 combination_size = 0 63 coefficients_size = 0 64 combination_type_size = 0 65 coefficients_type_size = 0 66 message = sensor_name + ": " 67 68 if "Combination" in sensor.keys(): 69 combination_size = len(sensor["Combination"]) 70 71 if "Coefficient" in sensor.keys(): 72 coefficients_size = len(sensor["Coefficient"]) 73 74 if combination_size != coefficients_size: 75 message += "Combination size does not match with Coefficient size" 76 return False, message 77 78 if "CombinationType" in sensor.keys(): 79 combination_type_size = len(sensor["CombinationType"]) 80 81 if combination_size != combination_type_size: 82 message += "Combination size does not match with CombinationType size" 83 return False, message 84 85 if "CoefficientType" in sensor.keys(): 86 coefficients_type_size = len(sensor["CoefficientType"]) 87 88 if coefficients_size != coefficients_type_size: 89 message += "Coefficient size does not match with CoefficientType size" 90 return False, message 91 92 return True, None 93 94def check_thermal_config(file_path, json_file): 95 """Validates configuration fields in thermal config 96 97 Args: Json object for thermal config 98 99 Returns: 100 Tuple of Success and error message. 101 """ 102 if "Sensors" in json_file.keys(): 103 status, message = validate_sensor_config(json_file["Sensors"]) 104 if not status: 105 return False, file_path + ": " + message 106 107 return True, None 108 109def main(args=None): 110 """Main function for checking thermal configs. 111 112 Args: 113 commit: The change commit's SHA. 114 field_names: The path to known field names. 115 116 Returns: 117 Exits with error if unsuccessful. 118 """ 119 120 # Mapping of form (json path, json object) 121 json_files = dict() 122 123 # Load arguments provided from repo hooks. 124 parser = argparse.ArgumentParser() 125 parser.add_argument('--commit', '-c') 126 parser.add_argument('--field_names', '-l') 127 args = parser.parse_args() 128 if not args.commit: 129 return "Invalid commit provided" 130 131 if not args.field_names: 132 return "No field names path provided" 133 134 if not git.repository_root(): 135 return "Not inside a git repository" 136 137 # Gets modified and added json files in current commit. 138 thermal_check_file_paths = get_thermal_modified_files(args.commit) 139 if not list(thermal_check_file_paths.keys()): 140 return 0 141 142 # Populate and validate (json path, json object) maps to test. 143 for file_name in thermal_check_file_paths.keys(): 144 rel_path = os.path.relpath(file_name) 145 content = subprocess.check_output( 146 ["git", "show", args.commit + ":" + rel_path]) 147 try: 148 json_file = json.loads(content) 149 json_files[rel_path] = json_file 150 success, message = check_thermal_config(rel_path, json_file) 151 if not success: 152 return "Thermal config check error: " + message 153 except ValueError as e: 154 return "Malformed JSON file " + rel_path + " with message "+ str(e) 155 156 # Instantiates the common config checker and runs tests on config. 157 checker = PixelJSONFieldNameChecker(json_files, args.field_names) 158 success, message = checker.check_json_field_names() 159 if not success: 160 return "Thermal JSON field name check error: " + message 161 162if __name__ == '__main__': 163 ret = main() 164 if ret: 165 print(ret) 166 print("----------------------------------------------------") 167 print("| !! Please see go/pixel-perf-thermal-preupload !! |") 168 print("----------------------------------------------------") 169 sys.exit(1) 170 171