• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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