1# Copyright (c) 2012 The Chromium Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5# If this presubmit check fails or misbehaves, please complain to 6# mnissler@chromium.org, pastarmovj@chromium.org or joaodasilva@chromium.org. 7 8import itertools 9import sys 10import xml.dom.minidom 11 12def _GetPolicyTemplates(template_path): 13 # Read list of policies in the template. eval() is used instead of a JSON 14 # parser because policy_templates.json is not quite JSON, and uses some 15 # python features such as #-comments and '''strings'''. policy_templates.json 16 # is actually maintained as a python dictionary. 17 with open(template_path) as f: 18 template_data = eval(f.read(), {}) 19 policies = ( policy 20 for policy in template_data['policy_definitions'] 21 if policy['type'] != 'group' ) 22 groups = ( policy['policies'] 23 for policy in template_data['policy_definitions'] 24 if policy['type'] == 'group' ) 25 subpolicies = ( policy for group in groups for policy in group ) 26 return list(itertools.chain(policies, subpolicies)) 27 28def _CheckPolicyTemplatesSyntax(input_api, output_api): 29 local_path = input_api.PresubmitLocalPath() 30 filepath = input_api.os_path.join(local_path, 'policy_templates.json') 31 if any(f.AbsoluteLocalPath() == filepath 32 for f in input_api.AffectedFiles()): 33 old_sys_path = sys.path 34 try: 35 tools_path = input_api.os_path.normpath( 36 input_api.os_path.join(local_path, input_api.os_path.pardir, 'tools')) 37 sys.path = [ tools_path ] + sys.path 38 # Optimization: only load this when it's needed. 39 import syntax_check_policy_template_json 40 checker = syntax_check_policy_template_json.PolicyTemplateChecker() 41 if checker.Run([], filepath) > 0: 42 return [output_api.PresubmitError('Syntax error(s) in file:', 43 [filepath])] 44 finally: 45 sys.path = old_sys_path 46 return [] 47 48 49def _CheckPolicyTestCases(input_api, output_api, policies): 50 # Read list of policies in chrome/test/data/policy/policy_test_cases.json. 51 root = input_api.change.RepositoryRoot() 52 policy_test_cases_file = input_api.os_path.join( 53 root, 'chrome', 'test', 'data', 'policy', 'policy_test_cases.json') 54 test_names = input_api.json.load(open(policy_test_cases_file)).keys() 55 tested_policies = frozenset(name.partition('.')[0] 56 for name in test_names 57 if name[:2] != '--') 58 policy_names = frozenset(policy['name'] for policy in policies) 59 60 # Finally check if any policies are missing. 61 missing = policy_names - tested_policies 62 extra = tested_policies - policy_names 63 error_missing = ('Policy \'%s\' was added to policy_templates.json but not ' 64 'to src/chrome/test/data/policy/policy_test_cases.json. ' 65 'Please update both files.') 66 error_extra = ('Policy \'%s\' is tested by ' 67 'src/chrome/test/data/policy/policy_test_cases.json but is not' 68 ' defined in policy_templates.json. Please update both files.') 69 results = [] 70 for policy in missing: 71 results.append(output_api.PresubmitError(error_missing % policy)) 72 for policy in extra: 73 results.append(output_api.PresubmitError(error_extra % policy)) 74 return results 75 76 77def _CheckPolicyHistograms(input_api, output_api, policies): 78 root = input_api.change.RepositoryRoot() 79 histograms = input_api.os_path.join( 80 root, 'tools', 'metrics', 'histograms', 'histograms.xml') 81 with open(histograms) as f: 82 tree = xml.dom.minidom.parseString(f.read()) 83 enums = (tree.getElementsByTagName('histogram-configuration')[0] 84 .getElementsByTagName('enums')[0] 85 .getElementsByTagName('enum')) 86 policy_enum = [e for e in enums 87 if e.getAttribute('name') == 'EnterprisePolicies'][0] 88 policy_ids = frozenset([int(e.getAttribute('value')) 89 for e in policy_enum.getElementsByTagName('int')]) 90 91 error_missing = ('Policy \'%s\' was added to policy_templates.json but not ' 92 'to src/tools/metrics/histograms/histograms.xml. ' 93 'Please update both files.') 94 results = [] 95 for policy in policies: 96 if policy['id'] not in policy_ids: 97 results.append(output_api.PresubmitError(error_missing % policy['name'])) 98 return results 99 100 101def _CommonChecks(input_api, output_api): 102 results = [] 103 results.extend(_CheckPolicyTemplatesSyntax(input_api, output_api)) 104 105 os_path = input_api.os_path 106 local_path = input_api.PresubmitLocalPath() 107 template_path = os_path.join(local_path, 'policy_templates.json') 108 affected_files = input_api.AffectedFiles() 109 if any(f.AbsoluteLocalPath() == template_path for f in affected_files): 110 try: 111 policies = _GetPolicyTemplates(template_path) 112 except: 113 results.append(output_api.PresubmitError('Invalid Python/JSON syntax.')) 114 return results 115 results.extend(_CheckPolicyTestCases(input_api, output_api, policies)) 116 results.extend(_CheckPolicyHistograms(input_api, output_api, policies)) 117 118 return results 119 120 121def CheckChangeOnUpload(input_api, output_api): 122 return _CommonChecks(input_api, output_api) 123 124 125def CheckChangeOnCommit(input_api, output_api): 126 return _CommonChecks(input_api, output_api) 127