2 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
6 """Verify perf_expectations.json can be loaded using simplejson.
8 perf_expectations.json is a JSON-formatted file. This script verifies
9 that simplejson can load it correctly. It should catch most common
23 script_path
= os
.path
.dirname(sys
.argv
[0])
27 # This test script should be stored in src/tools/perf_expectations/. That
28 # directory will most commonly live in 2 locations:
30 # - a regular Chromium checkout, in which case src/third_party
31 # is where to look for simplejson
33 # - a buildbot checkout, in which case .../pylibs is where
34 # to look for simplejson
36 # Locate and install the correct path based on what we can find.
38 for path
in ('../../../third_party', '../../../../../pylibs'):
39 path
= os
.path
.join(script_path
, path
)
40 if os
.path
.exists(path
) and os
.path
.isdir(path
):
41 load_path
= os
.path
.abspath(path
)
45 msg
= "%s expects to live within a Chromium checkout" % sys
.argv
[0]
46 raise Exception, "Error locating simplejson load path (%s)" % msg
48 # Try importing simplejson once. If this succeeds, we found it and will
49 # load it again later properly. Fail if we cannot load it.
50 sys
.path
.append(load_path
)
52 import simplejson
as Simplejson
53 simplejson
= Simplejson
54 except ImportError, e
:
55 msg
= "%s expects to live within a Chromium checkout" % sys
.argv
[0]
56 raise Exception, "Error trying to import simplejson from %s (%s)" % \
62 def LoadJsonFile(filename
):
63 f
= open(filename
, 'r')
65 data
= simplejson
.load(f
)
68 print "Error reading %s:\n%s" % (filename
,
76 CONFIG_JSON
= os
.path
.join(os
.path
.dirname(sys
.argv
[0]),
77 '../chromium_perf_expectations.cfg')
78 MAKE_EXPECTATIONS
= os
.path
.join(os
.path
.dirname(sys
.argv
[0]),
79 '../make_expectations.py')
80 PERF_EXPECTATIONS
= os
.path
.join(os
.path
.dirname(sys
.argv
[0]),
81 '../perf_expectations.json')
84 class PerfExpectationsUnittest(unittest
.TestCase
):
85 def testPerfExpectations(self
):
86 # Test data is dictionary.
87 perf_data
= LoadJsonFile(PERF_EXPECTATIONS
)
88 if not isinstance(perf_data
, dict):
89 raise Exception('perf expectations is not a dict')
91 # Test the 'load' key.
92 if not 'load' in perf_data
:
93 raise Exception("perf expectations is missing a load key")
94 if not isinstance(perf_data
['load'], bool):
95 raise Exception("perf expectations load key has non-bool value")
97 # Test all key values are dictionaries.
102 if not isinstance(perf_data
[key
], dict):
104 if len(bad_keys
) > 0:
105 msg
= "perf expectations keys have non-dict values"
106 raise Exception("%s: %s" % (msg
, bad_keys
))
108 # Test all key values have delta and var keys.
109 for key
in perf_data
:
113 # First check if regress/improve is in the key's data.
114 if 'regress' in perf_data
[key
]:
115 if 'improve' not in perf_data
[key
]:
117 if (not isinstance(perf_data
[key
]['regress'], int) and
118 not isinstance(perf_data
[key
]['regress'], float)):
120 if (not isinstance(perf_data
[key
]['improve'], int) and
121 not isinstance(perf_data
[key
]['improve'], float)):
124 # Otherwise check if delta/var is in the key's data.
125 if 'delta' not in perf_data
[key
] or 'var' not in perf_data
[key
]:
127 if (not isinstance(perf_data
[key
]['delta'], int) and
128 not isinstance(perf_data
[key
]['delta'], float)):
130 if (not isinstance(perf_data
[key
]['var'], int) and
131 not isinstance(perf_data
[key
]['var'], float)):
134 if len(bad_keys
) > 0:
135 msg
= "perf expectations key values missing or invalid delta/var"
136 raise Exception("%s: %s" % (msg
, bad_keys
))
138 # Test all keys have the correct format.
139 for key
in perf_data
:
142 # tools/buildbot/scripts/master/log_parser.py should have a matching
143 # regular expression.
144 if not re
.match(r
"^([\w\.-]+)/([\w\.-]+)/([\w\.-]+)/([\w\.-]+)$", key
):
146 if len(bad_keys
) > 0:
147 msg
= "perf expectations keys in bad format, expected a/b/c/d"
148 raise Exception("%s: %s" % (msg
, bad_keys
))
150 def testNoUpdatesNeeded(self
):
151 p
= subprocess
.Popen([MAKE_EXPECTATIONS
, '-s'], stdout
=subprocess
.PIPE
)
153 self
.assertEqual(p
.returncode
, 0,
154 msg
='Update expectations first by running ./make_expectations.py')
156 def testConfigFile(self
):
157 # Test that the config file can be parsed as JSON.
158 config
= LoadJsonFile(CONFIG_JSON
)
159 # Require the following keys.
160 if 'base_url' not in config
:
161 raise Exception('base_url not specified in config file')
162 if 'perf_file' not in config
:
163 raise Exception('perf_file not specified in config file')
166 if __name__
== '__main__':