WebAssembly: add script which can import GCC torture tests
[WebKit-https.git] / Tools / Scripts / update-wasm-gcc-torture.py
1 #! /usr/bin/env python
2 #
3 # Copyright (C) 2017 Apple Inc. All rights reserved.
4 #
5 # Redistribution and use in source and binary forms, with or without
6 # modification, are permitted provided that the following conditions
7 # are met:
8 #
9 # 1.  Redistributions of source code must retain the above copyright
10 #     notice, this list of conditions and the following disclaimer.
11 # 2.  Redistributions in binary form must reproduce the above copyright
12 #     notice, this list of conditions and the following disclaimer in the
13 #     documentation and/or other materials provided with the distribution.
14 #
15 # THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
16 # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 # DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
19 # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22 # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
26 import argparse
27 import glob
28 import json
29 import os.path
30 import shutil
31 import subprocess
32 import sys
33 import tarfile
34 import urllib2
35
36 LKGR_URL = 'https://storage.googleapis.com/wasm-llvm/builds/%s/lkgr.json'
37 TORTURE_FILE = 'wasm-torture-emwasm-%s.tbz2'
38 TORTURE_URL = 'https://storage.googleapis.com/wasm-llvm/builds/%s/%s/%s'
39 TORTURE_DIR = 'emwasm-torture-out'
40 WATERFALL_DIR = 'waterfall'
41 WATERFALL_GIT = 'https://github.com/WebAssembly/waterfall.git'
42 WATERFALL_KNOWN_FAILURES = 'src/test/run_known_gcc_test_failures.txt'
43
44 DESCRIPTION = """GCC torture test packager for jsc testing
45
46 Obtain the GCC torture tests as compiled for WebAssembly by the waterfall, using
47 Emscripten with its embedded libc. Create a yaml file which can be executed with
48 run-jsc-stress-tests."""
49
50
51 def parse_args():
52     parser = argparse.ArgumentParser(
53         description=DESCRIPTION,
54         formatter_class=argparse.RawDescriptionHelpFormatter,
55         epilog='See http://wasm-stat.us for current waterfall status')
56     parser.add_argument('--lkgr', default=None, help='LKGR value to use')
57     parser.add_argument('--platform', default='mac', help='Waterfall platform to sync to')
58     parser.add_argument('--nountar', default=False, action='store_true', help='If set, torture tests are assumed to already be in their destination folder')
59     parser.add_argument('--waterfall_hash', default=None, help='git hash to use for the waterfall repo')
60     parser.add_argument('--yaml', default='gcc-torture.yaml', help='yaml test file to generate')
61     return parser.parse_args()
62
63
64 def update_lkgr(args):
65     lkgr_url = LKGR_URL % args.platform
66     if not args.lkgr:
67         print 'Downloading: %s' % lkgr_url
68         args.lkgr = json.loads(urllib2.urlopen(lkgr_url).read())['build']
69     print 'lkgr: %s' % args.lkgr
70
71
72 def untar_torture(args):
73     torture_file = TORTURE_FILE % args.lkgr
74     torture_url = TORTURE_URL % (args.platform, args.lkgr, torture_file)
75     if not os.path.exists(torture_file):
76         print 'Downloading: %s' % torture_url
77         torture_download = urllib2.urlopen(torture_url)
78         with open(torture_file, 'wb') as f:
79             f.write(torture_download.read())
80     if not args.nountar:
81         if os.path.isdir(TORTURE_DIR):
82             shutil.rmtree(TORTURE_DIR)
83         with tarfile.open(torture_file, 'r') as torture_tar:
84             print 'Extracting: %s -> %s' % (torture_file, TORTURE_DIR)
85             torture_tar.extractall()
86     assert os.path.isdir(TORTURE_DIR)
87
88
89 def list_js_files(args):
90     js_files = sorted([os.path.basename(f) for f in glob.glob(os.path.join(TORTURE_DIR, '*.js'))])
91     print 'Found %s JavaScript tests' % len(js_files)
92     assert len(js_files) > 1200
93     return js_files
94
95
96 def waterfall_known_failures(args):
97     if not os.path.isdir(WATERFALL_DIR):
98         subprocess.check_call(['git', 'clone', WATERFALL_GIT, WATERFALL_DIR])
99     else:
100         subprocess.check_call(['git', 'pull'], cwd=WATERFALL_DIR)
101     if args.waterfall_hash:
102         subprocess.check_call(['git', 'checkout', args.waterfall_hash], cwd=WATERFALL_DIR)
103     else:
104         args.waterfall_hash = subprocess.check_output(['git', 'log', '-n1', '--pretty=format:%H'], cwd=WATERFALL_DIR).strip()
105     print 'Waterfall at: %s' % args.waterfall_hash
106     known_failures = []
107     with open(os.path.join(WATERFALL_DIR, WATERFALL_KNOWN_FAILURES)) as failures_file:
108         for line in failures_file:
109             line = line.strip()
110             if '#' in line:
111                 line = line[:line.index('#')].strip()
112             tokens = line.split()
113             if not tokens:
114                 continue
115             test_file = tokens[0]
116             if len(tokens) > 1:
117                 attributes = set(tokens[1].split(','))
118                 if 'emwasm' not in attributes:
119                     continue
120             if os.path.splitext(test_file)[-1] != '.js':
121                 continue
122             known_failures.append(test_file)
123     assert known_failures
124     return set(known_failures)
125
126
127 def create_yaml(args, js_files, known_failures):
128     with open(args.yaml, 'w+') as yaml:
129         yaml.write('# GCC torture tests\n')
130         yaml.write('# Auto-generated by: %s\n' % sys.argv[0])
131         yaml.write('# lkgr: %s\n' % args.lkgr)
132         yaml.write('# Waterfall hash: %s\n' % args.waterfall_hash)
133         for js in js_files:
134             yaml.write('\n- path: %s/%s\n' % (TORTURE_DIR, js))
135             yaml.write('  cmd: runWebAssemblyEmscripten :%s\n' % ('normal' if js not in known_failures else 'skip'))
136
137
138 def main():
139     args = parse_args()
140     update_lkgr(args)
141     untar_torture(args)
142     js_files = list_js_files(args)
143     known_failures = waterfall_known_failures(args)
144     create_yaml(args, js_files, known_failures)
145
146
147 if __name__ == '__main__':
148     sys.exit(main())