# Copyright (c) 2012 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# If this presubmit check fails or misbehaves, please complain to
# mnissler@chromium.org, pastarmovj@chromium.org or joaodasilva@chromium.org.
import itertools
import sys
import xml.dom.minidom
def _GetPolicyTemplates(template_path):
# Read list of policies in the template. eval() is used instead of a JSON
# parser because policy_templates.json is not quite JSON, and uses some
# python features such as #-comments and '''strings'''. policy_templates.json
# is actually maintained as a python dictionary.
with open(template_path) as f:
template_data = eval(f.read(), {})
policies = ( policy
for policy in template_data['policy_definitions']
if policy['type'] != 'group' )
groups = ( policy['policies']
for policy in template_data['policy_definitions']
if policy['type'] == 'group' )
subpolicies = ( policy for group in groups for policy in group )
return list(itertools.chain(policies, subpolicies))
def _CheckPolicyTemplatesSyntax(input_api, output_api):
local_path = input_api.PresubmitLocalPath()
filepath = input_api.os_path.join(local_path, 'policy_templates.json')
if any(f.AbsoluteLocalPath() == filepath
for f in input_api.AffectedFiles()):
old_sys_path = sys.path
try:
tools_path = input_api.os_path.normpath(
input_api.os_path.join(local_path, input_api.os_path.pardir, 'tools'))
sys.path = [ tools_path ] + sys.path
# Optimization: only load this when it's needed.
import syntax_check_policy_template_json
checker = syntax_check_policy_template_json.PolicyTemplateChecker()
if checker.Run([], filepath) > 0:
return [output_api.PresubmitError('Syntax error(s) in file:',
[filepath])]
finally:
sys.path = old_sys_path
return []
def _CheckPolicyTestCases(input_api, output_api, policies):
# Read list of policies in chrome/test/data/policy/policy_test_cases.json.
root = input_api.change.RepositoryRoot()
policy_test_cases_file = input_api.os_path.join(
root, 'chrome', 'test', 'data', 'policy', 'policy_test_cases.json')
test_names = input_api.json.load(open(policy_test_cases_file)).keys()
tested_policies = frozenset(name.partition('.')[0]
for name in test_names
if name[:2] != '--')
policy_names = frozenset(policy['name'] for policy in policies)
# Finally check if any policies are missing.
missing = policy_names - tested_policies
extra = tested_policies - policy_names
error_missing = ('Policy \'%s\' was added to policy_templates.json but not '
'to src/chrome/test/data/policy/policy_test_cases.json. '
'Please update both files.')
error_extra = ('Policy \'%s\' is tested by '
'src/chrome/test/data/policy/policy_test_cases.json but is not'
' defined in policy_templates.json. Please update both files.')
results = []
for policy in missing:
results.append(output_api.PresubmitError(error_missing % policy))
for policy in extra:
results.append(output_api.PresubmitError(error_extra % policy))
return results
def _CheckPolicyHistograms(input_api, output_api, policies):
root = input_api.change.RepositoryRoot()
histograms = input_api.os_path.join(
root, 'tools', 'metrics', 'histograms', 'histograms.xml')
with open(histograms) as f:
tree = xml.dom.minidom.parseString(f.read())
enums = (tree.getElementsByTagName('histogram-configuration')[0]
.getElementsByTagName('enums')[0]
.getElementsByTagName('enum'))
policy_enum = [e for e in enums
if e.getAttribute('name') == 'EnterprisePolicies'][0]
policy_ids = frozenset([int(e.getAttribute('value'))
for e in policy_enum.getElementsByTagName('int')])
error_missing = ('Policy \'%s\' was added to policy_templates.json but not '
'to src/tools/metrics/histograms/histograms.xml. '
'Please update both files.')
results = []
for policy in policies:
if policy['id'] not in policy_ids:
results.append(output_api.PresubmitError(error_missing % policy['name']))
return results
def _CommonChecks(input_api, output_api):
results = []
results.extend(_CheckPolicyTemplatesSyntax(input_api, output_api))
os_path = input_api.os_path
local_path = input_api.PresubmitLocalPath()
template_path = os_path.join(local_path, 'policy_templates.json')
affected_files = input_api.AffectedFiles()
if any(f.AbsoluteLocalPath() == template_path for f in affected_files):
try:
policies = _GetPolicyTemplates(template_path)
except:
results.append(output_api.PresubmitError('Invalid Python/JSON syntax.'))
return results
results.extend(_CheckPolicyTestCases(input_api, output_api, policies))
results.extend(_CheckPolicyHistograms(input_api, output_api, policies))
return results
def CheckChangeOnUpload(input_api, output_api):
return _CommonChecks(input_api, output_api)
def CheckChangeOnCommit(input_api, output_api):
return _CommonChecks(input_api, output_api)