Subclass Benchmark Runner script for WebDriver support
[WebKit-https.git] / Tools / Scripts / webkitpy / benchmark_runner / benchmark_builder.py
1 #!/usr/bin/env python
2
3 import logging
4 import tempfile
5 import os
6 import urllib
7 import shutil
8 import subprocess
9 import tarfile
10
11 from webkitpy.benchmark_runner.utils import get_path_from_project_root, force_remove
12 from zipfile import ZipFile
13
14
15 _log = logging.getLogger(__name__)
16
17
18 class BenchmarkBuilder(object):
19     def __init__(self, name, plan, driver):
20         self._name = name
21         self._plan = plan
22         self._driver = driver
23
24     def __enter__(self):
25         self._web_root = tempfile.mkdtemp()
26         self._dest = os.path.join(self._web_root, self._name)
27         if 'local_copy' in self._plan:
28             self._copy_benchmark_to_temp_dir(self._plan['local_copy'])
29         elif 'remote_archive' in self._plan:
30             self._fetch_remote_archive(self._plan['remote_archive'])
31         elif 'svn_source' in self._plan:
32             self._checkout_with_subversion(self._plan['svn_source'])
33         else:
34             raise Exception('The benchmark location was not specified')
35
36         _log.info('Copied the benchmark into: %s' % self._dest)
37         try:
38             if 'create_script' in self._plan:
39                 self._run_create_script(self._plan['create_script'])
40             patch_file_key = "{driver}_benchmark_patch".format(driver=self._driver)
41             if patch_file_key in self._plan:
42                 self._apply_patch(self._plan[patch_file_key])
43             return self._web_root
44         except Exception:
45             self._clean()
46             raise
47
48     def __exit__(self, exc_type, exc_value, traceback):
49         self._clean()
50
51     def _run_create_script(self, create_script):
52         old_working_directory = os.getcwd()
53         os.chdir(self._dest)
54         _log.debug('Running %s in %s' % (create_script, self._dest))
55         error_code = subprocess.call(create_script)
56         os.chdir(old_working_directory)
57         if error_code:
58             raise Exception('Cannot create the benchmark - Error: %s' % error_code)
59
60     def _copy_benchmark_to_temp_dir(self, benchmark_path):
61         shutil.copytree(get_path_from_project_root(benchmark_path), self._dest)
62
63     def _fetch_remote_archive(self, archive_url):
64         if archive_url.endswith('.zip'):
65             archive_type = 'zip'
66         elif archive_url.endswith('tar.gz'):
67             archive_type = 'tar.gz'
68         else:
69             raise Exception('Could not infer the file extention from URL: %s' % archive_url)
70
71         archive_path = os.path.join(self._web_root, 'archive.' + archive_type)
72         _log.info('Downloading %s to %s' % (archive_url, archive_path))
73         urllib.urlretrieve(archive_url, archive_path)
74
75         if archive_type == 'zip':
76             with ZipFile(archive_path, 'r') as archive:
77                 archive.extractall(self._dest)
78         elif archive_type == 'tar.gz':
79             with tarfile.open(archive_path, 'r:gz') as archive:
80                 archive.extractall(self._dest)
81
82         unarchived_files = filter(lambda name: not name.startswith('.'), os.listdir(self._dest))
83         if len(unarchived_files) == 1:
84             first_file = os.path.join(self._dest, unarchived_files[0])
85             if os.path.isdir(first_file):
86                 shutil.move(first_file, self._web_root)
87                 os.rename(os.path.join(self._web_root, unarchived_files[0]), self._dest)
88
89     def _checkout_with_subversion(self, subversion_url):
90         _log.info('Checking out %s to %s' % (subversion_url, self._dest))
91         error_code = subprocess.call(['svn', 'checkout', '--trust-server-cert', '--non-interactive', subversion_url, self._dest])
92         if error_code:
93             raise Exception('Cannot checkout the benchmark - Error: %s' % error_code)
94
95     def _apply_patch(self, patch):
96         old_working_directory = os.getcwd()
97         os.chdir(self._dest)
98         error_code = subprocess.call(['patch', '-p1', '-f', '-i', get_path_from_project_root(patch)])
99         os.chdir(old_working_directory)
100         if error_code:
101             raise Exception('Cannot apply patch, will skip current benchmark_path - Error: %s' % error_code)
102
103     def _clean(self):
104         _log.info('Cleaning Benchmark')
105         if self._web_root:
106             force_remove(self._web_root)