test: make test runner multi-arch/mode compatible
authorBen Noordhuis <info@bnoordhuis.nl>
Thu, 16 Oct 2014 16:43:13 +0000 (18:43 +0200)
committerBen Noordhuis <info@bnoordhuis.nl>
Thu, 16 Oct 2014 20:39:34 +0000 (22:39 +0200)
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>
test/message/testcfg.py
test/simple/test-executable-path.js [deleted file]
test/testpy/__init__.py
test/timers/testcfg.py
tools/test.py

index 105fac6..60e64e2 100644 (file)
@@ -34,11 +34,12 @@ FLAGS_PATTERN = re.compile(r"//\s+Flags:(.*)")
 
 class MessageTestCase(test.TestCase):
 
-  def __init__(self, path, file, expected, mode, context, config):
-    super(MessageTestCase, self).__init__(context, path, mode)
+  def __init__(self, path, file, expected, arch, mode, context, config):
+    super(MessageTestCase, self).__init__(context, path, arch, mode)
     self.file = file
     self.expected = expected
     self.config = config
+    self.arch = arch
     self.mode = mode
 
   def IgnoreLine(self, str):
@@ -92,7 +93,7 @@ class MessageTestCase(test.TestCase):
     return self.path[-1]
 
   def GetCommand(self):
-    result = [self.config.context.GetVm(self.mode)]
+    result = [self.config.context.GetVm(self.arch, self.mode)]
     source = open(self.file).read()
     flags_match = FLAGS_PATTERN.search(source)
     if flags_match:
@@ -117,7 +118,7 @@ class MessageTestConfiguration(test.TestConfiguration):
     else:
         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)]
     result = []
     for test in all_tests:
@@ -128,8 +129,8 @@ class MessageTestConfiguration(test.TestConfiguration):
         if not exists(output_path):
           print "Could not find %s" % output_path
           continue
-        result.append(MessageTestCase(test, file_path, output_path, mode,
-                                      self.context, self))
+        result.append(MessageTestCase(test, file_path, output_path,
+                                      arch, mode, self.context, self))
     return result
 
   def GetBuildRequirements(self):
diff --git a/test/simple/test-executable-path.js b/test/simple/test-executable-path.js
deleted file mode 100644 (file)
index 57205af..0000000
+++ /dev/null
@@ -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);
index 9593a1f..cf64ba1 100644 (file)
@@ -41,10 +41,11 @@ FILES_PATTERN = re.compile(r"//\s+Files:(.*)")
 
 class SimpleTestCase(test.TestCase):
 
-  def __init__(self, path, file, mode, context, config, additional=[]):
-    super(SimpleTestCase, self).__init__(context, path, mode)
+  def __init__(self, path, file, arch, mode, context, config, additional=[]):
+    super(SimpleTestCase, self).__init__(context, path, arch, mode)
     self.file = file
     self.config = config
+    self.arch = arch
     self.mode = mode
     self.tmpdir = join(dirname(self.config.root), 'tmp')
     self.additional_flags = additional
@@ -82,7 +83,7 @@ class SimpleTestCase(test.TestCase):
     return self.path[-1]
 
   def GetCommand(self):
-    result = [self.config.context.GetVm(self.mode)]
+    result = [self.config.context.GetVm(self.arch, self.mode)]
     source = open(self.file).read()
     flags_match = FLAGS_PATTERN.search(source)
     if flags_match:
@@ -117,14 +118,14 @@ class SimpleTestConfiguration(test.TestConfiguration):
       return name.startswith('test-') and name.endswith('.js')
     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))]
     result = []
     for test in all_tests:
       if self.Contains(path, test):
         file_path = join(self.root, reduce(join, test[1:], "") + ".js")
-        result.append(SimpleTestCase(test, file_path, mode, self.context, self,
-          self.additional_flags))
+        result.append(SimpleTestCase(test, file_path, arch, mode, self.context,
+                                     self, self.additional_flags))
     return result
 
   def GetBuildRequirements(self):
@@ -151,7 +152,7 @@ class AddonTestConfiguration(SimpleTestConfiguration):
             result.append([subpath, f[:-3]])
     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))]
     result = []
     for test in all_tests:
index 98653e4..a7c248f 100644 (file)
@@ -40,10 +40,11 @@ FAKETIME_BIN_PATH = os.path.join("tools", "faketime", "src", "faketime")
 
 class TimersTestCase(test.TestCase):
 
-  def __init__(self, path, file, mode, context, config):
-    super(TimersTestCase, self).__init__(context, path, mode)
+  def __init__(self, path, file, arch, mode, context, config):
+    super(TimersTestCase, self).__init__(context, path, arch, mode)
     self.file = file
     self.config = config
+    self.arch = arch
     self.mode = mode
 
   def GetLabel(self):
@@ -60,7 +61,7 @@ class TimersTestCase(test.TestCase):
     if faketime_flags_match:
       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]
 
     return result
@@ -79,13 +80,14 @@ class TimersTestConfiguration(test.TestConfiguration):
       return name.startswith('test-') and name.endswith('.js')
     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))]
     result = []
     for test in all_tests:
       if self.Contains(path, test):
         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
 
   def GetBuildRequirements(self):
index 0772f9a..08cf4d1 100755 (executable)
@@ -368,10 +368,11 @@ class CommandOutput(object):
 
 class TestCase(object):
 
-  def __init__(self, context, path, mode):
+  def __init__(self, context, path, arch, mode):
     self.path = path
     self.context = context
     self.duration = None
+    self.arch = arch
     self.mode = mode
 
   def IsNegative(self):
@@ -644,9 +645,10 @@ class TestRepository(TestSuite):
   def GetBuildRequirements(self, path, context):
     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:
-      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
       result += tests
 
@@ -669,14 +671,14 @@ class LiteralTestSuite(TestSuite):
         result += test.GetBuildRequirements(rest, context)
     return result
 
-  def ListTests(self, current_path, path, context, mode):
+  def ListTests(self, current_path, path, context, arch, mode):
     (name, rest) = CarCdr(path)
     result = [ ]
     for test in self.tests:
       test_name = test.GetName()
       if not name or name.match(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()))
     return result
 
@@ -708,11 +710,11 @@ class Context(object):
     self.suppress_dialogs = suppress_dialogs
     self.store_unexpected_output = store_unexpected_output
 
-  def GetVm(self, mode):
-    if mode == 'debug':
-      name = 'out/Debug/node'
+  def GetVm(self, arch, mode):
+    if arch == 'none':
+      name = 'out/Debug/node' if mode == 'debug' else 'out/Release/node'
     else:
-      name = 'out/Release/node'
+      name = 'out/%s.%s/node' % (arch, mode)
 
     # Currently GYP does not support output_dir for MSVS.
     # http://code.google.com/p/gyp/issues/detail?id=40
@@ -729,9 +731,6 @@ class Context(object):
 
     return name
 
-  def GetVmCommand(self, testcase, mode):
-    return [self.GetVm(mode)] + self.GetVmFlags(testcase, mode)
-
   def GetVmFlags(self, testcase, mode):
     return testcase.variant_flags + FLAGS[mode]
 
@@ -1203,8 +1202,6 @@ def BuildOptions():
       default='none')
   result.add_option("--snapshot", help="Run the tests with snapshot turned on",
       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("--use-http1", help="Pass --use-http1 switch to node",
       default=False, action="store_true")
@@ -1235,29 +1232,8 @@ def BuildOptions():
 def ProcessOptions(options):
   global VERBOSE
   VERBOSE = options.verbose
+  options.arch = options.arch.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
 
 
@@ -1415,25 +1391,28 @@ def Main():
   unclassified_tests = [ ]
   globally_unused_rules = None
   for path in paths:
-    for mode in options.mode:
-      if not exists(context.GetVm(mode)):
-        print "Can't find shell executable: '%s'" % context.GetVm(mode)
-        continue
-      env = {
-        'mode': mode,
-        'system': utils.GuessOS(),
-        'arch': options.arch,
-        'simulator': options.simulator
-      }
-      test_list = root.ListTests([], path, context, mode)
-      unclassified_tests += test_list
-      (cases, unused_rules, all_outcomes) = config.ClassifyTests(test_list, env)
-      if globally_unused_rules is None:
-        globally_unused_rules = set(unused_rules)
-      else:
-        globally_unused_rules = globally_unused_rules.intersection(unused_rules)
-      all_cases += cases
-      all_unused.append(unused_rules)
+    for arch in options.arch:
+      for mode in options.mode:
+        vm = context.GetVm(arch, mode)
+        if not exists(vm):
+          print "Can't find shell executable: '%s'" % vm
+          continue
+        env = {
+          'mode': mode,
+          'system': utils.GuessOS(),
+          'arch': arch,
+        }
+        test_list = root.ListTests([], path, context, arch, mode)
+        unclassified_tests += test_list
+        (cases, unused_rules, all_outcomes) = (
+            config.ClassifyTests(test_list, env))
+        if globally_unused_rules is None:
+          globally_unused_rules = set(unused_rules)
+        else:
+          globally_unused_rules = (
+              globally_unused_rules.intersection(unused_rules))
+        all_cases += cases
+        all_unused.append(unused_rules)
 
   if options.cat:
     visited = set()