test: make test runner multi-arch/mode compatible
Make `python tools/test.py --arch=ia32,x64 --mode=debug,release` work. The test runner looks for the `node` binary in `out/${arch}.${mode}/`. Running tools/test.py without --arch makes it use `out/Release/node` or `out/Debug/node` like before. This commit removes `test/simple/test-executable-path.js` because the assumptions it makes about the locations of the debug and release binaries are now outdated. PR-URL: https://github.com/node-forward/node/pull/24 Reviewed-By: Fedor Indutny <fedor@indutny.com>
This commit is contained in:
parent
5ec2b3fc3d
commit
edaf7af30b
@ -34,11 +34,12 @@ FLAGS_PATTERN = re.compile(r"//\s+Flags:(.*)")
|
|||||||
|
|
||||||
class MessageTestCase(test.TestCase):
|
class MessageTestCase(test.TestCase):
|
||||||
|
|
||||||
def __init__(self, path, file, expected, mode, context, config):
|
def __init__(self, path, file, expected, arch, mode, context, config):
|
||||||
super(MessageTestCase, self).__init__(context, path, mode)
|
super(MessageTestCase, self).__init__(context, path, arch, mode)
|
||||||
self.file = file
|
self.file = file
|
||||||
self.expected = expected
|
self.expected = expected
|
||||||
self.config = config
|
self.config = config
|
||||||
|
self.arch = arch
|
||||||
self.mode = mode
|
self.mode = mode
|
||||||
|
|
||||||
def IgnoreLine(self, str):
|
def IgnoreLine(self, str):
|
||||||
@ -92,7 +93,7 @@ class MessageTestCase(test.TestCase):
|
|||||||
return self.path[-1]
|
return self.path[-1]
|
||||||
|
|
||||||
def GetCommand(self):
|
def GetCommand(self):
|
||||||
result = [self.config.context.GetVm(self.mode)]
|
result = [self.config.context.GetVm(self.arch, self.mode)]
|
||||||
source = open(self.file).read()
|
source = open(self.file).read()
|
||||||
flags_match = FLAGS_PATTERN.search(source)
|
flags_match = FLAGS_PATTERN.search(source)
|
||||||
if flags_match:
|
if flags_match:
|
||||||
@ -117,7 +118,7 @@ class MessageTestConfiguration(test.TestConfiguration):
|
|||||||
else:
|
else:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def ListTests(self, current_path, path, mode):
|
def ListTests(self, current_path, path, arch, mode):
|
||||||
all_tests = [current_path + [t] for t in self.Ls(self.root)]
|
all_tests = [current_path + [t] for t in self.Ls(self.root)]
|
||||||
result = []
|
result = []
|
||||||
for test in all_tests:
|
for test in all_tests:
|
||||||
@ -128,8 +129,8 @@ class MessageTestConfiguration(test.TestConfiguration):
|
|||||||
if not exists(output_path):
|
if not exists(output_path):
|
||||||
print "Could not find %s" % output_path
|
print "Could not find %s" % output_path
|
||||||
continue
|
continue
|
||||||
result.append(MessageTestCase(test, file_path, output_path, mode,
|
result.append(MessageTestCase(test, file_path, output_path,
|
||||||
self.context, self))
|
arch, mode, self.context, self))
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def GetBuildRequirements(self):
|
def GetBuildRequirements(self):
|
||||||
|
@ -1,61 +0,0 @@
|
|||||||
// Copyright Joyent, Inc. and other Node contributors.
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the
|
|
||||||
// "Software"), to deal in the Software without restriction, including
|
|
||||||
// without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
|
||||||
// persons to whom the Software is furnished to do so, subject to the
|
|
||||||
// following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included
|
|
||||||
// in all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
|
||||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
||||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
||||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|
||||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
var common = require('../common');
|
|
||||||
var assert = require('assert');
|
|
||||||
var path = require('path');
|
|
||||||
var match = false;
|
|
||||||
|
|
||||||
var isDebug = process.features.debug;
|
|
||||||
var isWindows = process.platform === 'win32';
|
|
||||||
|
|
||||||
var debugPaths = [path.normalize(path.join(__dirname, '..', '..',
|
|
||||||
'out', 'Debug', 'node')),
|
|
||||||
path.normalize(path.join(__dirname, '..', '..',
|
|
||||||
'Debug', 'node'))];
|
|
||||||
var defaultPaths = [path.normalize(path.join(__dirname, '..', '..',
|
|
||||||
'out', 'Release', 'node')),
|
|
||||||
path.normalize(path.join(__dirname, '..', '..',
|
|
||||||
'Release', 'node'))];
|
|
||||||
|
|
||||||
console.error('debugPaths: ' + debugPaths);
|
|
||||||
console.error('defaultPaths: ' + defaultPaths);
|
|
||||||
console.error('process.execPath: ' + process.execPath);
|
|
||||||
|
|
||||||
function pathStartsWith(a, b) {
|
|
||||||
if (isWindows)
|
|
||||||
return (a.toLowerCase().indexOf(b.toLowerCase()) == 0);
|
|
||||||
else
|
|
||||||
return (a.indexOf(b) == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (isDebug) {
|
|
||||||
debugPaths.forEach(function(path) {
|
|
||||||
match = match || pathStartsWith(process.execPath, path);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
defaultPaths.forEach(function(path) {
|
|
||||||
match = match || pathStartsWith(process.execPath, path);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
assert.ok(match);
|
|
@ -41,10 +41,11 @@ FILES_PATTERN = re.compile(r"//\s+Files:(.*)")
|
|||||||
|
|
||||||
class SimpleTestCase(test.TestCase):
|
class SimpleTestCase(test.TestCase):
|
||||||
|
|
||||||
def __init__(self, path, file, mode, context, config, additional=[]):
|
def __init__(self, path, file, arch, mode, context, config, additional=[]):
|
||||||
super(SimpleTestCase, self).__init__(context, path, mode)
|
super(SimpleTestCase, self).__init__(context, path, arch, mode)
|
||||||
self.file = file
|
self.file = file
|
||||||
self.config = config
|
self.config = config
|
||||||
|
self.arch = arch
|
||||||
self.mode = mode
|
self.mode = mode
|
||||||
self.tmpdir = join(dirname(self.config.root), 'tmp')
|
self.tmpdir = join(dirname(self.config.root), 'tmp')
|
||||||
self.additional_flags = additional
|
self.additional_flags = additional
|
||||||
@ -82,7 +83,7 @@ class SimpleTestCase(test.TestCase):
|
|||||||
return self.path[-1]
|
return self.path[-1]
|
||||||
|
|
||||||
def GetCommand(self):
|
def GetCommand(self):
|
||||||
result = [self.config.context.GetVm(self.mode)]
|
result = [self.config.context.GetVm(self.arch, self.mode)]
|
||||||
source = open(self.file).read()
|
source = open(self.file).read()
|
||||||
flags_match = FLAGS_PATTERN.search(source)
|
flags_match = FLAGS_PATTERN.search(source)
|
||||||
if flags_match:
|
if flags_match:
|
||||||
@ -117,14 +118,14 @@ class SimpleTestConfiguration(test.TestConfiguration):
|
|||||||
return name.startswith('test-') and name.endswith('.js')
|
return name.startswith('test-') and name.endswith('.js')
|
||||||
return [f[:-3] for f in os.listdir(path) if SelectTest(f)]
|
return [f[:-3] for f in os.listdir(path) if SelectTest(f)]
|
||||||
|
|
||||||
def ListTests(self, current_path, path, mode):
|
def ListTests(self, current_path, path, arch, mode):
|
||||||
all_tests = [current_path + [t] for t in self.Ls(join(self.root))]
|
all_tests = [current_path + [t] for t in self.Ls(join(self.root))]
|
||||||
result = []
|
result = []
|
||||||
for test in all_tests:
|
for test in all_tests:
|
||||||
if self.Contains(path, test):
|
if self.Contains(path, test):
|
||||||
file_path = join(self.root, reduce(join, test[1:], "") + ".js")
|
file_path = join(self.root, reduce(join, test[1:], "") + ".js")
|
||||||
result.append(SimpleTestCase(test, file_path, mode, self.context, self,
|
result.append(SimpleTestCase(test, file_path, arch, mode, self.context,
|
||||||
self.additional_flags))
|
self, self.additional_flags))
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def GetBuildRequirements(self):
|
def GetBuildRequirements(self):
|
||||||
@ -151,7 +152,7 @@ class AddonTestConfiguration(SimpleTestConfiguration):
|
|||||||
result.append([subpath, f[:-3]])
|
result.append([subpath, f[:-3]])
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def ListTests(self, current_path, path, mode):
|
def ListTests(self, current_path, path, arch, mode):
|
||||||
all_tests = [current_path + t for t in self.Ls(join(self.root))]
|
all_tests = [current_path + t for t in self.Ls(join(self.root))]
|
||||||
result = []
|
result = []
|
||||||
for test in all_tests:
|
for test in all_tests:
|
||||||
|
@ -40,10 +40,11 @@ FAKETIME_BIN_PATH = os.path.join("tools", "faketime", "src", "faketime")
|
|||||||
|
|
||||||
class TimersTestCase(test.TestCase):
|
class TimersTestCase(test.TestCase):
|
||||||
|
|
||||||
def __init__(self, path, file, mode, context, config):
|
def __init__(self, path, file, arch, mode, context, config):
|
||||||
super(TimersTestCase, self).__init__(context, path, mode)
|
super(TimersTestCase, self).__init__(context, path, arch, mode)
|
||||||
self.file = file
|
self.file = file
|
||||||
self.config = config
|
self.config = config
|
||||||
|
self.arch = arch
|
||||||
self.mode = mode
|
self.mode = mode
|
||||||
|
|
||||||
def GetLabel(self):
|
def GetLabel(self):
|
||||||
@ -60,7 +61,7 @@ class TimersTestCase(test.TestCase):
|
|||||||
if faketime_flags_match:
|
if faketime_flags_match:
|
||||||
result += shlex.split(faketime_flags_match.group(1).strip())
|
result += shlex.split(faketime_flags_match.group(1).strip())
|
||||||
|
|
||||||
result += [self.config.context.GetVm(self.mode)]
|
result += [self.config.context.GetVm(self.arch, self.mode)]
|
||||||
result += [self.file]
|
result += [self.file]
|
||||||
|
|
||||||
return result
|
return result
|
||||||
@ -79,13 +80,14 @@ class TimersTestConfiguration(test.TestConfiguration):
|
|||||||
return name.startswith('test-') and name.endswith('.js')
|
return name.startswith('test-') and name.endswith('.js')
|
||||||
return [f[:-3] for f in os.listdir(path) if SelectTest(f)]
|
return [f[:-3] for f in os.listdir(path) if SelectTest(f)]
|
||||||
|
|
||||||
def ListTests(self, current_path, path, mode):
|
def ListTests(self, current_path, path, arch, mode):
|
||||||
all_tests = [current_path + [t] for t in self.Ls(join(self.root))]
|
all_tests = [current_path + [t] for t in self.Ls(join(self.root))]
|
||||||
result = []
|
result = []
|
||||||
for test in all_tests:
|
for test in all_tests:
|
||||||
if self.Contains(path, test):
|
if self.Contains(path, test):
|
||||||
file_path = join(self.root, reduce(join, test[1:], "") + ".js")
|
file_path = join(self.root, reduce(join, test[1:], "") + ".js")
|
||||||
result.append(TimersTestCase(test, file_path, mode, self.context, self))
|
result.append(TimersTestCase(test, file_path, arch, mode,
|
||||||
|
self.context, self))
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def GetBuildRequirements(self):
|
def GetBuildRequirements(self):
|
||||||
|
@ -368,10 +368,11 @@ class CommandOutput(object):
|
|||||||
|
|
||||||
class TestCase(object):
|
class TestCase(object):
|
||||||
|
|
||||||
def __init__(self, context, path, mode):
|
def __init__(self, context, path, arch, mode):
|
||||||
self.path = path
|
self.path = path
|
||||||
self.context = context
|
self.context = context
|
||||||
self.duration = None
|
self.duration = None
|
||||||
|
self.arch = arch
|
||||||
self.mode = mode
|
self.mode = mode
|
||||||
|
|
||||||
def IsNegative(self):
|
def IsNegative(self):
|
||||||
@ -644,9 +645,10 @@ class TestRepository(TestSuite):
|
|||||||
def GetBuildRequirements(self, path, context):
|
def GetBuildRequirements(self, path, context):
|
||||||
return self.GetConfiguration(context).GetBuildRequirements()
|
return self.GetConfiguration(context).GetBuildRequirements()
|
||||||
|
|
||||||
def AddTestsToList(self, result, current_path, path, context, mode):
|
def AddTestsToList(self, result, current_path, path, context, arch, mode):
|
||||||
for v in VARIANT_FLAGS:
|
for v in VARIANT_FLAGS:
|
||||||
tests = self.GetConfiguration(context).ListTests(current_path, path, mode)
|
tests = self.GetConfiguration(context).ListTests(current_path, path,
|
||||||
|
arch, mode)
|
||||||
for t in tests: t.variant_flags = v
|
for t in tests: t.variant_flags = v
|
||||||
result += tests
|
result += tests
|
||||||
|
|
||||||
@ -669,14 +671,14 @@ class LiteralTestSuite(TestSuite):
|
|||||||
result += test.GetBuildRequirements(rest, context)
|
result += test.GetBuildRequirements(rest, context)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def ListTests(self, current_path, path, context, mode):
|
def ListTests(self, current_path, path, context, arch, mode):
|
||||||
(name, rest) = CarCdr(path)
|
(name, rest) = CarCdr(path)
|
||||||
result = [ ]
|
result = [ ]
|
||||||
for test in self.tests:
|
for test in self.tests:
|
||||||
test_name = test.GetName()
|
test_name = test.GetName()
|
||||||
if not name or name.match(test_name):
|
if not name or name.match(test_name):
|
||||||
full_path = current_path + [test_name]
|
full_path = current_path + [test_name]
|
||||||
test.AddTestsToList(result, full_path, path, context, mode)
|
test.AddTestsToList(result, full_path, path, context, arch, mode)
|
||||||
result.sort(cmp=lambda a, b: cmp(a.GetName(), b.GetName()))
|
result.sort(cmp=lambda a, b: cmp(a.GetName(), b.GetName()))
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@ -708,11 +710,11 @@ class Context(object):
|
|||||||
self.suppress_dialogs = suppress_dialogs
|
self.suppress_dialogs = suppress_dialogs
|
||||||
self.store_unexpected_output = store_unexpected_output
|
self.store_unexpected_output = store_unexpected_output
|
||||||
|
|
||||||
def GetVm(self, mode):
|
def GetVm(self, arch, mode):
|
||||||
if mode == 'debug':
|
if arch == 'none':
|
||||||
name = 'out/Debug/node'
|
name = 'out/Debug/node' if mode == 'debug' else 'out/Release/node'
|
||||||
else:
|
else:
|
||||||
name = 'out/Release/node'
|
name = 'out/%s.%s/node' % (arch, mode)
|
||||||
|
|
||||||
# Currently GYP does not support output_dir for MSVS.
|
# Currently GYP does not support output_dir for MSVS.
|
||||||
# http://code.google.com/p/gyp/issues/detail?id=40
|
# http://code.google.com/p/gyp/issues/detail?id=40
|
||||||
@ -729,9 +731,6 @@ class Context(object):
|
|||||||
|
|
||||||
return name
|
return name
|
||||||
|
|
||||||
def GetVmCommand(self, testcase, mode):
|
|
||||||
return [self.GetVm(mode)] + self.GetVmFlags(testcase, mode)
|
|
||||||
|
|
||||||
def GetVmFlags(self, testcase, mode):
|
def GetVmFlags(self, testcase, mode):
|
||||||
return testcase.variant_flags + FLAGS[mode]
|
return testcase.variant_flags + FLAGS[mode]
|
||||||
|
|
||||||
@ -1203,8 +1202,6 @@ def BuildOptions():
|
|||||||
default='none')
|
default='none')
|
||||||
result.add_option("--snapshot", help="Run the tests with snapshot turned on",
|
result.add_option("--snapshot", help="Run the tests with snapshot turned on",
|
||||||
default=False, action="store_true")
|
default=False, action="store_true")
|
||||||
result.add_option("--simulator", help="Run tests with architecture simulator",
|
|
||||||
default='none')
|
|
||||||
result.add_option("--special-command", default=None)
|
result.add_option("--special-command", default=None)
|
||||||
result.add_option("--use-http1", help="Pass --use-http1 switch to node",
|
result.add_option("--use-http1", help="Pass --use-http1 switch to node",
|
||||||
default=False, action="store_true")
|
default=False, action="store_true")
|
||||||
@ -1235,29 +1232,8 @@ def BuildOptions():
|
|||||||
def ProcessOptions(options):
|
def ProcessOptions(options):
|
||||||
global VERBOSE
|
global VERBOSE
|
||||||
VERBOSE = options.verbose
|
VERBOSE = options.verbose
|
||||||
|
options.arch = options.arch.split(',')
|
||||||
options.mode = options.mode.split(',')
|
options.mode = options.mode.split(',')
|
||||||
for mode in options.mode:
|
|
||||||
if not mode in ['debug', 'release']:
|
|
||||||
print "Unknown mode %s" % mode
|
|
||||||
return False
|
|
||||||
if options.simulator != 'none':
|
|
||||||
# Simulator argument was set. Make sure arch and simulator agree.
|
|
||||||
if options.simulator != options.arch:
|
|
||||||
if options.arch == 'none':
|
|
||||||
options.arch = options.simulator
|
|
||||||
else:
|
|
||||||
print "Architecture %s does not match sim %s" %(options.arch, options.simulator)
|
|
||||||
return False
|
|
||||||
# Ensure that the simulator argument is handed down to scons.
|
|
||||||
options.scons_flags.append("simulator=" + options.simulator)
|
|
||||||
else:
|
|
||||||
# If options.arch is not set by the command line and no simulator setting
|
|
||||||
# was found, set the arch to the guess.
|
|
||||||
if options.arch == 'none':
|
|
||||||
options.arch = ARCH_GUESS
|
|
||||||
options.scons_flags.append("arch=" + options.arch)
|
|
||||||
if options.snapshot:
|
|
||||||
options.scons_flags.append("snapshot=on")
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
@ -1415,25 +1391,28 @@ def Main():
|
|||||||
unclassified_tests = [ ]
|
unclassified_tests = [ ]
|
||||||
globally_unused_rules = None
|
globally_unused_rules = None
|
||||||
for path in paths:
|
for path in paths:
|
||||||
for mode in options.mode:
|
for arch in options.arch:
|
||||||
if not exists(context.GetVm(mode)):
|
for mode in options.mode:
|
||||||
print "Can't find shell executable: '%s'" % context.GetVm(mode)
|
vm = context.GetVm(arch, mode)
|
||||||
continue
|
if not exists(vm):
|
||||||
env = {
|
print "Can't find shell executable: '%s'" % vm
|
||||||
'mode': mode,
|
continue
|
||||||
'system': utils.GuessOS(),
|
env = {
|
||||||
'arch': options.arch,
|
'mode': mode,
|
||||||
'simulator': options.simulator
|
'system': utils.GuessOS(),
|
||||||
}
|
'arch': arch,
|
||||||
test_list = root.ListTests([], path, context, mode)
|
}
|
||||||
unclassified_tests += test_list
|
test_list = root.ListTests([], path, context, arch, mode)
|
||||||
(cases, unused_rules, all_outcomes) = config.ClassifyTests(test_list, env)
|
unclassified_tests += test_list
|
||||||
if globally_unused_rules is None:
|
(cases, unused_rules, all_outcomes) = (
|
||||||
globally_unused_rules = set(unused_rules)
|
config.ClassifyTests(test_list, env))
|
||||||
else:
|
if globally_unused_rules is None:
|
||||||
globally_unused_rules = globally_unused_rules.intersection(unused_rules)
|
globally_unused_rules = set(unused_rules)
|
||||||
all_cases += cases
|
else:
|
||||||
all_unused.append(unused_rules)
|
globally_unused_rules = (
|
||||||
|
globally_unused_rules.intersection(unused_rules))
|
||||||
|
all_cases += cases
|
||||||
|
all_unused.append(unused_rules)
|
||||||
|
|
||||||
if options.cat:
|
if options.cat:
|
||||||
visited = set()
|
visited = set()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user