Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / testing / variations / PRESUBMIT.py
blob003e611755c8ece41f1a635c30ed3ccb0875d13a
1 # Copyright 2015 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 """Presubmit script validating field trial configs.
6 See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
7 for more details on the presubmit API built into depot_tools.
8 """
10 import json
11 import sys
14 def PrettyPrint(contents):
15 """Pretty prints a fieldtrial configuration.
17 Args:
18 contents: File contents as a string.
20 Returns:
21 Pretty printed file contents.
22 """
23 return json.dumps(json.loads(contents),
24 sort_keys=True, indent=4,
25 separators=(',', ': ')) + '\n'
27 def ValidateData(json_data, file_path, message_type):
28 """Validates the format of a fieldtrial configuration.
30 Args:
31 json_data: Parsed JSON object representing the fieldtrial config.
32 file_path: String representing the path to the JSON file.
33 message_type: Type of message from |output_api| to return in the case of
34 errors/warnings.
36 Returns:
37 A list of |message_type| messages. In the case of all tests passing with no
38 warnings/errors, this will return [].
39 """
40 if not isinstance(json_data, dict):
41 return [message_type(
42 'Malformed config file %s: Expecting dict' % file_path)]
43 for (study, groups) in json_data.iteritems():
44 if not isinstance(study, unicode):
45 return [message_type(
46 'Malformed config file %s: Expecting keys to be string, got %s'
47 % (file_path, type(study)))]
48 if not isinstance(groups, list):
49 return [message_type(
50 'Malformed config file %s: Expecting list for study %s'
51 % (file_path, study))]
52 for group in groups:
53 if not isinstance(group, dict):
54 return [message_type(
55 'Malformed config file %s: Expecting dict for group in '
56 'Study[%s]' % (file_path, study))]
57 if not 'group_name' in group or not isinstance(group['group_name'],
58 unicode):
59 return [message_type(
60 'Malformed config file %s: Missing valid group_name for group'
61 ' in Study[%s]' % (file_path, study))]
62 if 'params' in group:
63 params = group['params']
64 if not isinstance(params, dict):
65 return [message_type(
66 'Malformed config file %s: Invalid params for Group[%s]'
67 ' in Study[%s]' % (file_path, group['group_name'],
68 study))]
69 for (key, value) in params.iteritems():
70 if not isinstance(key, unicode) or not isinstance(value,
71 unicode):
72 return [message_type(
73 'Malformed config file %s: Invalid params for Group[%s]'
74 ' in Study[%s]' % (file_path, group['group_name'],
75 study))]
76 return []
78 def CheckPretty(contents, file_path, message_type):
79 """Validates the pretty printing of fieldtrial configuration.
81 Args:
82 contents: File contents as a string.
83 file_path: String representing the path to the JSON file.
84 message_type: Type of message from |output_api| to return in the case of
85 errors/warnings.
87 Returns:
88 A list of |message_type| messages. In the case of all tests passing with no
89 warnings/errors, this will return [].
90 """
91 pretty = PrettyPrint(contents)
92 if contents != pretty:
93 return [message_type(
94 'Pretty printing error: Run '
95 'python testing/variations/PRESUBMIT.py %s' % file_path)]
96 return []
98 def CommonChecks(input_api, output_api):
99 affected_files = input_api.AffectedFiles(
100 include_deletes=False,
101 file_filter=lambda x: x.LocalPath().endswith('.json'))
102 for f in affected_files:
103 contents = input_api.ReadFile(f)
104 try:
105 json_data = input_api.json.loads(contents)
106 result = CheckPretty(contents, f.LocalPath(), output_api.PresubmitError)
107 if len(result):
108 return result
109 result = ValidateData(json_data, f.LocalPath(),
110 output_api.PresubmitError)
111 if len(result):
112 return result
113 except ValueError:
114 return [output_api.PresubmitError(
115 'Malformed JSON file: %s' % f.LocalPath())]
116 return []
118 def CheckChangeOnUpload(input_api, output_api):
119 return CommonChecks(input_api, output_api)
121 def CheckChangeOnCommit(input_api, output_api):
122 return CommonChecks(input_api, output_api)
125 def main(argv):
126 content = open(argv[1]).read()
127 pretty = PrettyPrint(content)
128 open(argv[1],'w').write(pretty)
130 if __name__ == "__main__":
131 sys.exit(main(sys.argv))