15 from benchmark_builder.benchmark_builder_factory import BenchmarkBuilderFactory
16 from benchmark_results import BenchmarkResults
17 from browser_driver.browser_driver_factory import BrowserDriverFactory
18 from http_server_driver.http_server_driver_factory import HTTPServerDriverFactory
19 from utils import loadModule, getPathFromProjectRoot
20 from utils import timeout
23 _log = logging.getLogger(__name__)
26 class BenchmarkRunner(object):
28 def __init__(self, planFile, localCopy, countOverride, buildDir, outputFile, platform, browser, httpServerDriverOverride=None, deviceID=None):
30 planFile = self._findPlanFile(planFile)
31 with open(planFile, 'r') as fp:
32 self.planName = os.path.split(os.path.splitext(planFile)[0])[1]
33 self.plan = json.load(fp)
35 self.plan['local_copy'] = localCopy
37 self.plan['count'] = countOverride
38 if httpServerDriverOverride:
39 self.plan['http_server_driver'] = httpServerDriverOverride
40 self.browserDriver = BrowserDriverFactory.create([platform, browser])
41 self.httpServerDriver = HTTPServerDriverFactory.create([self.plan['http_server_driver']])
42 self.httpServerDriver.setDeviceID(deviceID)
43 self.buildDir = os.path.abspath(buildDir) if buildDir else None
44 self.outputFile = outputFile
45 self.deviceID = deviceID
46 except IOError as error:
47 _log.error('Can not open plan file: %s - Error %s' % (planFile, error))
49 except ValueError as error:
50 _log.error('Plan file: %s may not follow JSON format - Error %s' % (planFile, error))
53 def _findPlanFile(self, planFile):
54 if not os.path.exists(planFile):
55 absPath = os.path.join(os.path.dirname(__file__), 'data/plans', planFile)
56 if os.path.exists(absPath):
58 if not absPath.endswith('.plan'):
60 if os.path.exists(absPath):
65 _log.info('Start to execute the plan')
66 _log.info('Start a new benchmark')
68 self.benchmarkBuilder = BenchmarkBuilderFactory.create([self.plan['benchmark_builder']])
70 webRoot = self.benchmarkBuilder.prepare(self.planName, self.plan)
71 for x in xrange(int(self.plan['count'])):
72 _log.info('Start the iteration %d of current benchmark' % (x + 1))
73 self.httpServerDriver.serve(webRoot)
74 self.browserDriver.prepareEnv(self.deviceID)
75 url = urlparse.urljoin(self.httpServerDriver.baseUrl(), self.planName + '/' + self.plan['entry_point'])
76 self.browserDriver.launchUrl(url, self.buildDir)
79 with timeout(self.plan['timeout']):
80 result = self.httpServerDriver.fetchResult()
81 assert(not self.httpServerDriver.getReturnCode())
83 results.append(json.loads(result))
84 except Exception as error:
85 _log.error('No result or the server crashed. Something went wrong. Will skip current benchmark.\nError: %s, Server return code: %d, result: %s' % (error, not self.httpServerDriver.getReturnCode(), result))
89 self.browserDriver.closeBrowsers()
90 _log.info('End of %d iteration of current benchmark' % (x + 1))
91 results = self.wrap(results)
92 self.dump(results, self.outputFile if self.outputFile else self.plan['output_file'])
93 self.show_results(results)
94 self.benchmarkBuilder.clean()
98 if self.browserDriver:
99 self.browserDriver.closeBrowsers()
100 if self.httpServerDriver:
101 self.httpServerDriver.killServer()
102 if self.benchmarkBuilder:
103 self.benchmarkBuilder.clean()
106 def dump(cls, results, outputFile):
107 _log.info('Dumping the results to file')
109 with open(outputFile, 'w') as fp:
110 json.dump(results, fp)
111 except IOError as error:
112 _log.error('Cannot open output file: %s - Error: %s' % (outputFile, error))
113 _log.error('Results are:\n %s', json.dumps(results))
116 def wrap(cls, dicts):
117 _log.debug('Merging following results:\n%s', json.dumps(dicts))
122 ret = cls.merge(ret, dic)
123 _log.debug('Results after merging:\n%s', json.dumps(ret))
127 def merge(cls, a, b):
128 assert(isinstance(a, type(b)))
130 # special handle for list type, and should be handle before equal check
131 if argType == types.ListType and len(a) and (type(a[0]) == types.StringType or type(a[0]) == types.UnicodeType):
133 if argType == types.DictType:
135 for key, value in a.items():
137 result[key] = cls.merge(value, b[key])
140 for key, value in b.items():
141 if key not in result:
148 def show_results(cls, results):
149 results = BenchmarkResults(results)
150 print results.format()