mirror of https://github.com/lukechilds/node.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
243 lines
6.8 KiB
243 lines
6.8 KiB
#!/usr/bin/env python
|
|
# Copyright (c) 2012 Google Inc. All rights reserved.
|
|
# Use of this source code is governed by a BSD-style license that can be
|
|
# found in the LICENSE file.
|
|
|
|
"""gyptest.py -- test runner for GYP tests."""
|
|
|
|
from __future__ import print_function
|
|
|
|
import argparse
|
|
import math
|
|
import os
|
|
import platform
|
|
import subprocess
|
|
import sys
|
|
import time
|
|
|
|
|
|
def is_test_name(f):
|
|
return f.startswith('gyptest') and f.endswith('.py')
|
|
|
|
|
|
def find_all_gyptest_files(directory):
|
|
result = []
|
|
for root, dirs, files in os.walk(directory):
|
|
result.extend([ os.path.join(root, f) for f in files if is_test_name(f) ])
|
|
result.sort()
|
|
return result
|
|
|
|
|
|
def main(argv=None):
|
|
if argv is None:
|
|
argv = sys.argv
|
|
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument("-a", "--all", action="store_true",
|
|
help="run all tests")
|
|
parser.add_argument("-C", "--chdir", action="store",
|
|
help="change to directory")
|
|
parser.add_argument("-f", "--format", action="store", default='',
|
|
help="run tests with the specified formats")
|
|
parser.add_argument("-G", '--gyp_option', action="append", default=[],
|
|
help="Add -G options to the gyp command line")
|
|
parser.add_argument("-l", "--list", action="store_true",
|
|
help="list available tests and exit")
|
|
parser.add_argument("-n", "--no-exec", action="store_true",
|
|
help="no execute, just print the command line")
|
|
parser.add_argument("--path", action="append", default=[],
|
|
help="additional $PATH directory")
|
|
parser.add_argument("-q", "--quiet", action="store_true",
|
|
help="quiet, don't print anything unless there are failures")
|
|
parser.add_argument("-v", "--verbose", action="store_true",
|
|
help="print configuration info and test results.")
|
|
parser.add_argument('tests', nargs='*')
|
|
args = parser.parse_args(argv[1:])
|
|
|
|
if args.chdir:
|
|
os.chdir(args.chdir)
|
|
|
|
if args.path:
|
|
extra_path = [os.path.abspath(p) for p in opts.path]
|
|
extra_path = os.pathsep.join(extra_path)
|
|
os.environ['PATH'] = extra_path + os.pathsep + os.environ['PATH']
|
|
|
|
if not args.tests:
|
|
if not args.all:
|
|
sys.stderr.write('Specify -a to get all tests.\n')
|
|
return 1
|
|
args.tests = ['test']
|
|
|
|
tests = []
|
|
for arg in args.tests:
|
|
if os.path.isdir(arg):
|
|
tests.extend(find_all_gyptest_files(os.path.normpath(arg)))
|
|
else:
|
|
if not is_test_name(os.path.basename(arg)):
|
|
print(arg, 'is not a valid gyp test name.', file=sys.stderr)
|
|
sys.exit(1)
|
|
tests.append(arg)
|
|
|
|
if args.list:
|
|
for test in tests:
|
|
print(test)
|
|
sys.exit(0)
|
|
|
|
os.environ['PYTHONPATH'] = os.path.abspath('test/lib')
|
|
|
|
if args.verbose:
|
|
print_configuration_info()
|
|
|
|
if args.gyp_option and not args.quiet:
|
|
print('Extra Gyp options: %s\n' % args.gyp_option)
|
|
|
|
if args.format:
|
|
format_list = args.format.split(',')
|
|
else:
|
|
format_list = {
|
|
'aix5': ['make'],
|
|
'freebsd7': ['make'],
|
|
'freebsd8': ['make'],
|
|
'openbsd5': ['make'],
|
|
'cygwin': ['msvs'],
|
|
'win32': ['msvs', 'ninja'],
|
|
'linux': ['make', 'ninja'],
|
|
'linux2': ['make', 'ninja'],
|
|
'linux3': ['make', 'ninja'],
|
|
|
|
# TODO: Re-enable xcode-ninja.
|
|
# https://bugs.chromium.org/p/gyp/issues/detail?id=530
|
|
# 'darwin': ['make', 'ninja', 'xcode', 'xcode-ninja'],
|
|
'darwin': ['make', 'ninja', 'xcode'],
|
|
}[sys.platform]
|
|
|
|
gyp_options = []
|
|
for option in args.gyp_option:
|
|
gyp_options += ['-G', option]
|
|
|
|
runner = Runner(format_list, tests, gyp_options, args.verbose)
|
|
runner.run()
|
|
|
|
if not args.quiet:
|
|
runner.print_results()
|
|
|
|
if runner.failures:
|
|
return 1
|
|
else:
|
|
return 0
|
|
|
|
|
|
def print_configuration_info():
|
|
print('Test configuration:')
|
|
if sys.platform == 'darwin':
|
|
sys.path.append(os.path.abspath('test/lib'))
|
|
import TestMac
|
|
print(' Mac %s %s' % (platform.mac_ver()[0], platform.mac_ver()[2]))
|
|
print(' Xcode %s' % TestMac.Xcode.Version())
|
|
elif sys.platform == 'win32':
|
|
sys.path.append(os.path.abspath('pylib'))
|
|
import gyp.MSVSVersion
|
|
print(' Win %s %s\n' % platform.win32_ver()[0:2])
|
|
print(' MSVS %s' %
|
|
gyp.MSVSVersion.SelectVisualStudioVersion().Description())
|
|
elif sys.platform in ('linux', 'linux2'):
|
|
print(' Linux %s' % ' '.join(platform.linux_distribution()))
|
|
print(' Python %s' % platform.python_version())
|
|
print(' PYTHONPATH=%s' % os.environ['PYTHONPATH'])
|
|
print()
|
|
|
|
|
|
class Runner(object):
|
|
def __init__(self, formats, tests, gyp_options, verbose):
|
|
self.formats = formats
|
|
self.tests = tests
|
|
self.verbose = verbose
|
|
self.gyp_options = gyp_options
|
|
self.failures = []
|
|
self.num_tests = len(formats) * len(tests)
|
|
num_digits = len(str(self.num_tests))
|
|
self.fmt_str = '[%%%dd/%%%dd] (%%s) %%s' % (num_digits, num_digits)
|
|
self.isatty = sys.stdout.isatty() and not self.verbose
|
|
self.env = os.environ.copy()
|
|
self.hpos = 0
|
|
|
|
def run(self):
|
|
run_start = time.time()
|
|
|
|
i = 1
|
|
for fmt in self.formats:
|
|
for test in self.tests:
|
|
self.run_test(test, fmt, i)
|
|
i += 1
|
|
|
|
if self.isatty:
|
|
self.erase_current_line()
|
|
|
|
self.took = time.time() - run_start
|
|
|
|
def run_test(self, test, fmt, i):
|
|
if self.isatty:
|
|
self.erase_current_line()
|
|
|
|
msg = self.fmt_str % (i, self.num_tests, fmt, test)
|
|
self.print_(msg)
|
|
|
|
start = time.time()
|
|
cmd = [sys.executable, test] + self.gyp_options
|
|
self.env['TESTGYP_FORMAT'] = fmt
|
|
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE,
|
|
stderr=subprocess.STDOUT, env=self.env)
|
|
proc.wait()
|
|
took = time.time() - start
|
|
|
|
stdout = proc.stdout.read().decode('utf8')
|
|
if proc.returncode == 2:
|
|
res = 'skipped'
|
|
elif proc.returncode:
|
|
res = 'failed'
|
|
self.failures.append('(%s) %s' % (test, fmt))
|
|
else:
|
|
res = 'passed'
|
|
res_msg = ' %s %.3fs' % (res, took)
|
|
self.print_(res_msg)
|
|
|
|
if (stdout and
|
|
not stdout.endswith('PASSED\n') and
|
|
not (stdout.endswith('NO RESULT\n'))):
|
|
print()
|
|
for l in stdout.splitlines():
|
|
print(' %s' % l)
|
|
elif not self.isatty:
|
|
print()
|
|
|
|
def print_(self, msg):
|
|
print(msg, end='')
|
|
index = msg.rfind('\n')
|
|
if index == -1:
|
|
self.hpos += len(msg)
|
|
else:
|
|
self.hpos = len(msg) - index
|
|
sys.stdout.flush()
|
|
|
|
def erase_current_line(self):
|
|
print('\b' * self.hpos + ' ' * self.hpos + '\b' * self.hpos, end='')
|
|
sys.stdout.flush()
|
|
self.hpos = 0
|
|
|
|
def print_results(self):
|
|
num_failures = len(self.failures)
|
|
if num_failures:
|
|
print()
|
|
if num_failures == 1:
|
|
print("Failed the following test:")
|
|
else:
|
|
print("Failed the following %d tests:" % num_failures)
|
|
print("\t" + "\n\t".join(sorted(self.failures)))
|
|
print()
|
|
print('Ran %d tests in %.3fs, %d failed.' % (self.num_tests, self.took,
|
|
num_failures))
|
|
print()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|
|
|