| #! /usr/bin/env python |
| # |
| # Copyright (C) 2017 Apple Inc. All rights reserved. |
| # |
| # Redistribution and use in source and binary forms, with or without |
| # modification, are permitted provided that the following conditions |
| # are met: |
| # |
| # 1. Redistributions of source code must retain the above copyright |
| # notice, this list of conditions and the following disclaimer. |
| # 2. Redistributions in binary form must reproduce the above copyright |
| # notice, this list of conditions and the following disclaimer in the |
| # documentation and/or other materials provided with the distribution. |
| # |
| # THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY |
| # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| # DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY |
| # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
| # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| |
| import argparse |
| import glob |
| import json |
| import os.path |
| import shutil |
| import subprocess |
| import sys |
| import tarfile |
| |
| if sys.version_info > (3, 0): |
| from urllib.request import urlopen |
| else: |
| from urllib2 import urlopen |
| |
| LKGR_URL = 'https://storage.googleapis.com/wasm-llvm/builds/%s/lkgr.json' |
| TORTURE_FILE = 'wasm-torture-emwasm-%s.tbz2' |
| TORTURE_URL = 'https://storage.googleapis.com/wasm-llvm/builds/%s/%s/%s' |
| TORTURE_DIR = 'emwasm-torture-out' |
| WATERFALL_DIR = 'waterfall' |
| WATERFALL_GIT = 'https://github.com/WebAssembly/waterfall.git' |
| WATERFALL_KNOWN_FAILURES = 'src/test/run_known_gcc_test_failures.txt' |
| |
| DESCRIPTION = """GCC torture test packager for jsc testing |
| |
| Obtain the GCC torture tests as compiled for WebAssembly by the waterfall, using |
| Emscripten with its embedded libc. Create a yaml file which can be executed with |
| run-jsc-stress-tests.""" |
| |
| |
| def parse_args(): |
| parser = argparse.ArgumentParser( |
| description=DESCRIPTION, |
| formatter_class=argparse.RawDescriptionHelpFormatter, |
| epilog='See http://wasm-stat.us for current waterfall status') |
| parser.add_argument('--lkgr', default=None, help='LKGR value to use') |
| parser.add_argument('--platform', default='mac', help='Waterfall platform to sync to') |
| parser.add_argument('--nountar', default=False, action='store_true', help='If set, torture tests are assumed to already be in their destination folder') |
| parser.add_argument('--waterfall_hash', default=None, help='git hash to use for the waterfall repo') |
| parser.add_argument('--yaml', default='gcc-torture.yaml', help='yaml test file to generate') |
| return parser.parse_args() |
| |
| |
| def update_lkgr(args): |
| lkgr_url = LKGR_URL % args.platform |
| if not args.lkgr: |
| print('Downloading: %s' % lkgr_url) |
| args.lkgr = json.loads(urlopen(lkgr_url).read())['build'] |
| print('lkgr: %s' % args.lkgr) |
| |
| |
| def untar_torture(args): |
| torture_file = TORTURE_FILE % args.lkgr |
| torture_url = TORTURE_URL % (args.platform, args.lkgr, torture_file) |
| if not os.path.exists(torture_file): |
| print('Downloading: %s' % torture_url) |
| torture_download = urlopen(torture_url) |
| with open(torture_file, 'wb') as f: |
| f.write(torture_download.read()) |
| if not args.nountar: |
| if os.path.isdir(TORTURE_DIR): |
| shutil.rmtree(TORTURE_DIR) |
| with tarfile.open(torture_file, 'r') as torture_tar: |
| print('Extracting: %s -> %s' % (torture_file, TORTURE_DIR)) |
| torture_tar.extractall() |
| assert os.path.isdir(TORTURE_DIR) |
| |
| |
| def list_js_files(args): |
| js_files = sorted([os.path.basename(f) for f in glob.glob(os.path.join(TORTURE_DIR, '*.js'))]) |
| print('Found %s JavaScript tests' % len(js_files)) |
| assert len(js_files) > 1200 |
| return js_files |
| |
| |
| def waterfall_known_failures(args): |
| if not os.path.isdir(WATERFALL_DIR): |
| subprocess.check_call(['git', 'clone', WATERFALL_GIT, WATERFALL_DIR]) |
| else: |
| subprocess.check_call(['git', 'pull'], cwd=WATERFALL_DIR) |
| if args.waterfall_hash: |
| subprocess.check_call(['git', 'checkout', args.waterfall_hash], cwd=WATERFALL_DIR) |
| else: |
| args.waterfall_hash = subprocess.check_output(['git', 'log', '-n1', '--pretty=format:%H'], cwd=WATERFALL_DIR).strip() |
| print('Waterfall at: %s' % args.waterfall_hash) |
| known_failures = [] |
| with open(os.path.join(WATERFALL_DIR, WATERFALL_KNOWN_FAILURES)) as failures_file: |
| for line in failures_file: |
| line = line.strip() |
| if '#' in line: |
| line = line[:line.index('#')].strip() |
| tokens = line.split() |
| if not tokens: |
| continue |
| test_file = tokens[0] |
| if len(tokens) > 1: |
| attributes = set(tokens[1].split(',')) |
| if 'emwasm' not in attributes: |
| continue |
| if os.path.splitext(test_file)[-1] != '.js': |
| continue |
| known_failures.append(test_file) |
| assert known_failures |
| return set(known_failures) |
| |
| |
| def create_yaml(args, js_files, known_failures): |
| with open(args.yaml, 'w+') as yaml: |
| yaml.write('# GCC torture tests\n') |
| yaml.write('# Auto-generated by: %s\n' % sys.argv[0]) |
| yaml.write('# lkgr: %s\n' % args.lkgr) |
| yaml.write('# Waterfall hash: %s\n' % args.waterfall_hash) |
| for js in js_files: |
| yaml.write('\n- path: %s/%s\n' % (TORTURE_DIR, js)) |
| yaml.write(' cmd: runWebAssemblyEmscripten :%s\n' % ('normal' if js not in known_failures else 'skip')) |
| |
| |
| def main(): |
| args = parse_args() |
| update_lkgr(args) |
| untar_torture(args) |
| js_files = list_js_files(args) |
| known_failures = waterfall_known_failures(args) |
| create_yaml(args, js_files, known_failures) |
| |
| |
| if __name__ == '__main__': |
| sys.exit(main()) |