Fixes the broken run_tests_test (by Vlad Losev).


git-svn-id: http://googletest.googlecode.com/svn/trunk@272 861a406c-534a-0410-8894-cb66d6ee9925
diff --git a/run_tests.py b/run_tests.py
index 2aa3ddb..d4a2725 100755
--- a/run_tests.py
+++ b/run_tests.py
@@ -132,6 +132,7 @@
 
 IS_WINDOWS = os.name == 'nt'
 IS_MAC = os.name == 'posix' and os.uname()[0] == 'Darwin'
+IS_CYGWIN = os.name == 'posix' and 'CYGWIN' in os.uname()[0]
 
 # Definition of CONFIGS must match that of the build directory names in the
 # SConstruct script. The first list item is the default build configuration.
@@ -142,12 +143,14 @@
 else:
   CONFIGS = ('dbg', 'opt')
 
-if IS_WINDOWS:
+if IS_WINDOWS or IS_CYGWIN:
   PYTHON_TEST_REGEX = re.compile(r'_(unit)?test\.py$', re.IGNORECASE)
   BINARY_TEST_REGEX = re.compile(r'_(unit)?test(\.exe)?$', re.IGNORECASE)
+  BINARY_TEST_SEARCH_REGEX = re.compile(r'_(unit)?test\.exe$', re.IGNORECASE)
 else:
   PYTHON_TEST_REGEX = re.compile(r'_(unit)?test\.py$')
   BINARY_TEST_REGEX = re.compile(r'_(unit)?test$')
+  BINARY_TEST_SEARCH_REGEX = BINARY_TEST_REGEX
 
 GTEST_BUILD_DIR = 'GTEST_BUILD_DIR'
 
@@ -306,12 +309,13 @@
     listed_python_tests = []  # All Python tests listed on the command line.
     listed_binary_tests = []  # All binary tests listed on the command line.
 
+    test_dir = self.os.path.normpath(self.os.path.join(self.script_dir, 'test'))
+
     # Sifts through non-directory arguments fishing for any Python or binary
     # tests and detecting errors.
     for argument in sets.Set(normalized_args) - build_dirs:
       if re.search(PYTHON_TEST_REGEX, argument):
-        python_path = self.os.path.join(self.script_dir,
-                                        'test',
+        python_path = self.os.path.join(test_dir,
                                         self.os.path.basename(argument))
         if self.os.path.isfile(python_path):
           listed_python_tests.append(python_path)
@@ -335,9 +339,7 @@
     if user_has_listed_tests:
       selected_python_tests = listed_python_tests
     else:
-      selected_python_tests = self.FindFilesByRegex(
-          self.os.path.join(self.script_dir, 'test'),
-          PYTHON_TEST_REGEX)
+      selected_python_tests = self.FindFilesByRegex(test_dir, PYTHON_TEST_REGEX)
 
     # TODO(vladl@google.com): skip unbuilt Python tests when -b is specified.
     python_test_pairs = []
@@ -352,7 +354,7 @@
             [(directory, self.os.path.join(directory, test))
              for test in listed_binary_tests])
       else:
-        tests = self.FindFilesByRegex(directory, BINARY_TEST_REGEX)
+        tests = self.FindFilesByRegex(directory, BINARY_TEST_SEARCH_REGEX)
         binary_test_pairs.extend([(directory, test) for test in tests])
 
     return (python_test_pairs, binary_test_pairs)
diff --git a/test/gtest_test_utils.py b/test/gtest_test_utils.py
index 45b25cd..5b28fe4 100755
--- a/test/gtest_test_utils.py
+++ b/test/gtest_test_utils.py
@@ -53,6 +53,7 @@
 
 
 IS_WINDOWS = os.name == 'nt'
+IS_CYGWIN = os.name == 'posix' and 'CYGWIN' in os.uname()[0]
 
 # Here we expose a class from a particular module, depending on the
 # environment. The comment suppresses the 'Invalid variable name' lint
@@ -150,7 +151,7 @@
   """
 
   path = os.path.abspath(os.path.join(GetBuildDir(), executable_name))
-  if IS_WINDOWS and not path.endswith('.exe'):
+  if (IS_WINDOWS or IS_CYGWIN) and not path.endswith('.exe'):
     path += '.exe'
 
   if not os.path.exists(path):
diff --git a/test/run_tests_test.py b/test/run_tests_test.py
index b55739e..d8bbc36 100755
--- a/test/run_tests_test.py
+++ b/test/run_tests_test.py
@@ -33,12 +33,22 @@
 __author__ = 'vladl@google.com (Vlad Losev)'
 
 import os
+import re
+import sets
 import sys
 import unittest
 
 sys.path.append(os.path.join(os.path.dirname(sys.argv[0]), os.pardir))
 import run_tests
 
+def AddExeExtension(path):
+  """Appends .exe to the path on Windows or Cygwin."""
+
+  if run_tests.IS_WINDOWS or run_tests.IS_CYGWIN:
+    return path + '.exe'
+  else:
+    return path
+
 
 class FakePath(object):
   """A fake os.path module for testing."""
@@ -137,28 +147,43 @@
 class GetTestsToRunTest(unittest.TestCase):
   """Exercises TestRunner.GetTestsToRun."""
 
+  def NormalizeGetTestsToRunResults(self, results):
+    """Normalizes path data returned from GetTestsToRun for comparison."""
+
+    def NormalizePythonTestPair(pair):
+      """Normalizes path data in the (directory, python_script) pair."""
+
+      return (os.path.normpath(pair[0]), os.path.normpath(pair[1]))
+
+    def NormalizeBinaryTestPair(pair):
+      """Normalizes path data in the (directory, binary_executable) pair."""
+
+      directory, executable = map(os.path.normpath, pair)
+
+      # On Windows and Cygwin, the test file names have the .exe extension, but
+      # they can be invoked either by name or by name+extension. Our test must
+      # accommodate both situations.
+      if run_tests.IS_WINDOWS or run_tests.IS_CYGWIN:
+        executable = re.sub(r'\.exe$', '', executable)
+      return (directory, executable)
+
+    python_tests = sets.Set(map(NormalizePythonTestPair, results[0]))
+    binary_tests = sets.Set(map(NormalizeBinaryTestPair, results[1]))
+    return (python_tests, binary_tests)
+
   def AssertResultsEqual(self, results, expected):
     """Asserts results returned by GetTestsToRun equal to expected results."""
 
-    def NormalizeResultPaths(paths):
-      """Normalizes values returned by GetTestsToRun for comparison."""
-
-      def NormalizeResultPair(pair):
-        return (os.path.normpath(pair[0]), os.path.normpath(pair[1]))
-
-      return (sorted(map(NormalizeResultPair, paths[0])),
-              sorted(map(NormalizeResultPair, paths[1])))
-
-    self.assertEqual(NormalizeResultPaths(results),
-                     NormalizeResultPaths(expected),
-                     'Incorrect set of tests %s returned vs %s expected' %
+    self.assertEqual(self.NormalizeGetTestsToRunResults(results),
+                     self.NormalizeGetTestsToRunResults(expected),
+                     'Incorrect set of tests returned:\n%s\nexpected:\n%s' %
                      (results, expected))
 
   def setUp(self):
     self.fake_os = FakeOs(FakePath(
         current_dir=os.path.abspath(os.path.dirname(run_tests.__file__)),
-        known_paths=['scons/build/dbg/scons/gtest_unittest',
-                     'scons/build/opt/scons/gtest_unittest',
+        known_paths=[AddExeExtension('scons/build/dbg/scons/gtest_unittest'),
+                     AddExeExtension('scons/build/opt/scons/gtest_unittest'),
                      'test/gtest_color_test.py']))
     self.fake_configurations = ['dbg', 'opt']
     self.test_runner = run_tests.TestRunner(injected_os=self.fake_os,
@@ -390,8 +415,7 @@
 
     self.fake_os = FakeOs(FakePath(
         current_dir=os.path.abspath(os.path.dirname(run_tests.__file__)),
-        known_paths=['scons/build/dbg/scons/gtest_nontest',
-                     'scons/build/opt/scons/gtest_nontest.exe',
+        known_paths=[AddExeExtension('scons/build/dbg/scons/gtest_nontest'),
                      'test/']))
     self.test_runner = run_tests.TestRunner(injected_os=self.fake_os,
                                             injected_subprocess=None,
@@ -412,8 +436,8 @@
     self.fake_os = FakeOs(FakePath(
         current_dir=os.path.abspath('/a/b/c'),
         known_paths=['/a/b/c/',
-                     '/d/scons/build/dbg/scons/gtest_unittest',
-                     '/d/scons/build/opt/scons/gtest_unittest',
+                     AddExeExtension('/d/scons/build/dbg/scons/gtest_unittest'),
+                     AddExeExtension('/d/scons/build/opt/scons/gtest_unittest'),
                      '/d/test/gtest_color_test.py']))
     self.fake_configurations = ['dbg', 'opt']
     self.test_runner = run_tests.TestRunner(injected_os=self.fake_os,
@@ -461,6 +485,24 @@
             False,
             available_configurations=self.fake_configurations))
 
+  if run_tests.IS_WINDOWS or run_tests.IS_CYGWIN:
+    def testDoesNotPickNonExeFilesOnWindows(self):
+      """Verifies that GetTestsToRun does not find _test files on Windows."""
+
+      self.fake_os = FakeOs(FakePath(
+          current_dir=os.path.abspath(os.path.dirname(run_tests.__file__)),
+          known_paths=['scons/build/dbg/scons/gtest_test', 'test/']))
+      self.test_runner = run_tests.TestRunner(injected_os=self.fake_os,
+                                              injected_subprocess=None,
+                                              injected_script_dir='.')
+      self.AssertResultsEqual(
+          self.test_runner.GetTestsToRun(
+              [],
+              '',
+              True,
+              available_configurations=self.fake_configurations),
+          ([], []))
+
 
 class RunTestsTest(unittest.TestCase):
   """Exercises TestRunner.RunTests."""
@@ -480,8 +522,8 @@
   def setUp(self):
     self.fake_os = FakeOs(FakePath(
         current_dir=os.path.abspath(os.path.dirname(run_tests.__file__)),
-        known_paths=['scons/build/dbg/scons/gtest_unittest',
-                     'scons/build/opt/scons/gtest_unittest',
+        known_paths=[AddExeExtension('scons/build/dbg/scons/gtest_unittest'),
+                     AddExeExtension('scons/build/opt/scons/gtest_unittest'),
                      'test/gtest_color_test.py']))
     self.fake_configurations = ['dbg', 'opt']
     self.test_runner = run_tests.TestRunner(injected_os=self.fake_os,