subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From pbu...@apache.org
Subject svn commit: r1071809 - in /subversion/trunk: build/run_tests.py subversion/tests/cmdline/svntest/main.py win-tests.py
Date Thu, 17 Feb 2011 22:09:03 GMT
Author: pburba
Date: Thu Feb 17 22:09:02 2011
New Revision: 1071809

URL: http://svn.apache.org/viewvc?rev=1071809&view=rev
Log:
Add an option (--milestone-filter=REGEX) to the Python tests so we can list a
subset of the tests based on their associated issues' target milestone.

This option is currently only available to win-tests.py and
subversion/tests/cmdline/svntest/main.py.  So it isn't quite as useful
on non-Windows platforms just yet.

Now we can easily answer questions like, "What xfailing merge tests need to
be fixed before we can release 1.7?"

  C:\SVN\src-trunk>win-tests.py --list --milestone-filter="(1.7.*)|(---)"
  --mode-filter xfail --log-to-stdout --test merge
  Listing Debug configuration on local repository.
  LISTING: merge_tests.py
  Test #  Mode   Test Description
  ------  -----  ----------------
    64    XFAIL  merge target with non inheritable mergeinfo
  [#2970(blue-sky),#3642(1.7.0)]
    75    XFAIL  merge added subtree [#1962(1.7-consider)]

* build/run_tests.py

  (TestHarness.__init__): Add mode_filter argument.

  (TestHarness._run_c_test): Issue warning that --milestone-filter doesn't
   work when listing C tests.

  (TestHarness._run_py_test): Accept --milestone-filter option.

* subversion/tests/cmdline/svntest/main.py

  (global): Import xml and urllib.

  (TestSpawningThread.run_one): Support --milestone-filter option.

  (TestRunner.list): Add optional argument mapping issues to target
   milestones.

  (TestRunner.get_issues): New.

  (_create_parser): Handle --milestone-filter.

  (get_target_milestones_for_issues): New.

  (execute_tests): Handle --milestone-filter.

* win-tests.py

  (_usage_exit): Add --milestone-filter to usage text.

  (milestone_filter): New global variable.

  (global): Accept --milestone-filter as a valid option, pass it to
   run_tests.TestHarness().


Modified:
    subversion/trunk/build/run_tests.py
    subversion/trunk/subversion/tests/cmdline/svntest/main.py
    subversion/trunk/win-tests.py

Modified: subversion/trunk/build/run_tests.py
URL: http://svn.apache.org/viewvc/subversion/trunk/build/run_tests.py?rev=1071809&r1=1071808&r2=1071809&view=diff
==============================================================================
--- subversion/trunk/build/run_tests.py (original)
+++ subversion/trunk/build/run_tests.py Thu Feb 17 22:09:02 2011
@@ -79,7 +79,8 @@ class TestHarness:
                server_minor_version=None, verbose=None,
                cleanup=None, enable_sasl=None, parallel=None, config_file=None,
                fsfs_sharding=None, fsfs_packing=None,
-               list_tests=None, svn_bin=None, mode_filter=None):
+               list_tests=None, svn_bin=None, mode_filter=None,
+               milestone_filter=None):
     '''Construct a TestHarness instance.
 
     ABS_SRCDIR and ABS_BUILDDIR are the source and build directories.
@@ -91,8 +92,12 @@ class TestHarness:
     HTTP_LIBRARY is the HTTP library for DAV-based communications.
     SERVER_MINOR_VERSION is the minor version of the server being tested.
     SVN_BIN is the path where the svn binaries are installed.
-    mode_filter restricts the TestHarness to tests with the expected mode
-    XFail, Skip, Pass, or All tests (default).
+    MODE_FILTER restricts the TestHarness to tests with the expected mode
+    XFail, Skip, Pass, or All tests (default).  MILESTONE_FILTER is a
+    string representation of a valid regular expression pattern; when used
+    in conjunction with LIST_TESTS, the only tests that are listed are
+    those with an associated issue in the tracker which has a target
+    milestone that matches the regex.
     '''
     self.srcdir = abs_srcdir
     self.builddir = abs_builddir
@@ -114,6 +119,7 @@ class TestHarness:
     if config_file is not None:
       self.config_file = os.path.abspath(config_file)
     self.list_tests = list_tests
+    self.milestone_filter = milestone_filter
     self.svn_bin = svn_bin
     self.mode_filter = mode_filter
     self.log = None
@@ -280,6 +286,8 @@ class TestHarness:
     if not self.list_tests:
       sys.stdout.write('.' * dot_count)
       sys.stdout.flush()
+    elif self.milestone_filter:
+      print 'WARNING: --milestone-filter option does not currently work with C tests'
 
     if os.access(progbase, os.X_OK):
       progname = './' + progbase
@@ -349,6 +357,8 @@ class TestHarness:
       svntest.main.options.server_minor_version = self.server_minor_version
     if self.list_tests is not None:
       svntest.main.options.list_tests = True
+    if self.milestone_filter is not None:
+      svntest.main.options.milestone_filter = self.milestone_filter
     if self.svn_bin is not None:
       svntest.main.options.svn_bin = self.svn_bin
     if self.fsfs_sharding is not None:

Modified: subversion/trunk/subversion/tests/cmdline/svntest/main.py
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/svntest/main.py?rev=1071809&r1=1071808&r2=1071809&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/svntest/main.py (original)
+++ subversion/trunk/subversion/tests/cmdline/svntest/main.py Thu Feb 17 22:09:02 2011
@@ -34,6 +34,8 @@ import time    # for time()
 import traceback # for print_exc()
 import threading
 import optparse # for argument parsing
+import xml
+import urllib
 
 try:
   # Python >=3.0
@@ -1132,6 +1134,8 @@ class TestSpawningThread(threading.Threa
       args.append('--server-minor-version=' + str(options.server_minor_version))
     if options.mode_filter:
       args.append('--mode-filter=' + options.mode_filter)
+    if options.milestone_filter:
+      args.append('--milestone-filter=' + options.milestone_filter)
 
     result, stdout_lines, stderr_lines = spawn_process(command, 0, 0, None,
                                                        *args)
@@ -1152,26 +1156,61 @@ class TestRunner:
     self.pred = svntest.testcase.create_test_case(func)
     self.index = index
 
-  def list(self):
+  def list(self, milestones_dict=None):
+    """Print test doc strings.  MILESTONES_DICT is an optional mapping
+    of issue numbers to target milestones."""
     if options.mode_filter.upper() == 'ALL' \
        or options.mode_filter.upper() == self.pred.list_mode().upper() \
        or (options.mode_filter.upper() == 'PASS' \
            and self.pred.list_mode() == ''):
+      issues = []
       tail = ''
       if self.pred.issues:
-        tail += " [%s]" % ','.join(['#%d' % i for i in self.pred.issues])
-      if options.verbose and self.pred.inprogress:
-        tail += " [[%s]]" % self.pred.inprogress
-      else:
-        print(" %3d    %-5s  %s%s" % (self.index,
-                                      self.pred.list_mode(),
-                                      self.pred.description,
-                                      tail))
+        if not options.milestone_filter or milestones_dict is None:
+          issues = self.pred.issues
+        else: # Limit listing by requested target milestone(s).
+          filter_issues = []
+          matches_filter = False
+
+          # Get the milestones for all the issues associated with this test.
+          # If any one of them matches the MILESTONE_FILTER then we'll print
+          # them all.
+          for issue in self.pred.issues:
+            # A safe starting assumption.
+            milestone = 'unknown'
+            if milestones_dict:
+              if milestones_dict.has_key(str(issue)):
+                milestone = milestones_dict[str(issue)]
+
+            filter_issues.append(str(issue) + '(' + milestone + ')')
+            pattern = re.compile(options.milestone_filter)
+            if pattern.match(milestone):
+              matches_filter = True
+
+          # Did at least one of the associated issues meet our filter?
+          if matches_filter:
+            issues = filter_issues
+
+        tail += " [%s]" % ','.join(['#%s' % str(i) for i in issues])
+
+      # If there is no filter or this test made if through
+      # the filter then print it!
+      if options.milestone_filter is None or len(issues):
+        if options.verbose and self.pred.inprogress:
+          tail += " [[%s]]" % self.pred.inprogress
+        else:
+          print(" %3d    %-5s  %s%s" % (self.index,
+                                        self.pred.list_mode(),
+                                        self.pred.description,
+                                        tail))
     sys.stdout.flush()
 
   def get_mode(self):
     return self.pred.list_mode()
 
+  def get_issues(self):
+    return self.pred.issues
+
   def get_function_name(self):
     return self.pred.get_function_name()
 
@@ -1376,6 +1415,8 @@ def _create_parser():
   parser = optparse.OptionParser(usage=usage)
   parser.add_option('-l', '--list', action='store_true', dest='list_tests',
                     help='Print test doc strings instead of running them')
+  parser.add_option('--milestone-filter', action='store', dest='milestone_filter',
+                    help='Limit --list to those with target milestone specified')
   parser.add_option('-v', '--verbose', action='store_true', dest='verbose',
                     help='Print binary command-lines (not with --quiet)')
   parser.add_option('-q', '--quiet', action='store_true',
@@ -1470,6 +1511,47 @@ def run_tests(test_list, serial_only = F
 
   sys.exit(execute_tests(test_list, serial_only))
 
+def get_target_milestones_for_issues(issue_numbers):
+  xml_url = "http://subversion.tigris.org/issues/xml.cgi?id="
+  issue_dict = {}
+
+  if isinstance(issue_numbers, int):
+    issue_numbers = [str(issue_numbers)]
+  elif isinstance(issue_numbers, str):
+    issue_numbers = [issue_numbers]
+
+  if issue_numbers is None or len(issue_numbers) == 0:
+    return issue_dict
+
+  for num in issue_numbers:
+    xml_url += str(num) + ','
+    issue_dict[str(num)] = 'unknown'
+
+  try:
+    # Parse the xml for ISSUE_NO from the issue tracker into a Document.
+    issue_xml_f = urllib.urlopen(xml_url)
+  except:
+    print "WARNING: Unable to contact issue tracker; " \
+          "milestones defaulting to 'unknown'."
+    return issue_dict
+
+  try:
+    xmldoc = xml.dom.minidom.parse(issue_xml_f)
+    issue_xml_f.close()
+  
+    # Get the target milestone for each issue.
+    issue_element = xmldoc.getElementsByTagName('issue')
+    for i in issue_element:
+      issue_id_element = i.getElementsByTagName('issue_id')
+      issue_id = issue_id_element[0].childNodes[0].nodeValue
+      milestone_element = i.getElementsByTagName('target_milestone')
+      milestone = milestone_element[0].childNodes[0].nodeValue
+      issue_dict[issue_id] = milestone
+  except:
+    print "ERROR: Unable to parse target milestones from issue tracker"
+    raise
+
+  return issue_dict
 
 # Main func.  This is the "entry point" that all the test scripts call
 # to run their list of tests.
@@ -1586,6 +1668,23 @@ def execute_tests(test_list, serial_only
     testnums = list(range(1, len(test_list)))
 
   if options.list_tests:
+
+    # If we want to list the target milestones, then get all the issues
+    # associated with all the individual tests.
+    milestones_dict = None
+    if options.milestone_filter:
+      issues_dict = {}
+      for testnum in testnums:
+        issues = TestRunner(test_list[testnum], testnum).get_issues()
+        test_mode = TestRunner(test_list[testnum], testnum).get_mode().upper()
+        if issues:
+          for issue in issues:
+            if (options.mode_filter.upper() == 'ALL' or
+                options.mode_filter.upper() == test_mode or
+                (options.mode_filter.upper() == 'PASS' and test_mode == '')):
+              issues_dict[issue]=issue
+      milestones_dict = get_target_milestones_for_issues(issues_dict.keys())
+
     header = "Test #  Mode   Test Description\n" \
              "------  -----  ----------------"
     printed_header = False
@@ -1597,7 +1696,7 @@ def execute_tests(test_list, serial_only
         if not printed_header:
           print header
           printed_header = True
-        TestRunner(test_list[testnum], testnum).list()
+        TestRunner(test_list[testnum], testnum).list(milestones_dict)
     # We are simply listing the tests so always exit with success.
     return 0
 

Modified: subversion/trunk/win-tests.py
URL: http://svn.apache.org/viewvc/subversion/trunk/win-tests.py?rev=1071809&r1=1071808&r2=1071809&view=diff
==============================================================================
--- subversion/trunk/win-tests.py (original)
+++ subversion/trunk/win-tests.py Thu Feb 17 22:09:02 2011
@@ -79,6 +79,10 @@ def _usage_exit():
   print("  --http-library         : dav library to use, neon (default) or serf")
   print("  --javahl               : Run the javahl tests instead of the normal tests")
   print("  --list                 : print test doc strings only")
+  print("  --milestone-filter=RE  : RE is a regular expression pattern that (when")
+  print("                           used with --list) limits the tests listed to")
+  print("                           those with an associated issue in the tracker")
+  print("                           which has a target milestone that matches RE.")
   print("  --mode-filter=TYPE     : limit tests to expected TYPE = XFAIL, SKIP, PASS,")
   print("                           or 'ALL' (default)")
   print("  --enable-sasl          : enable Cyrus SASL authentication for")
@@ -123,7 +127,7 @@ opts, args = my_getopt(sys.argv[1:], 'hr
                         'fsfs-packing', 'fsfs-sharding=', 'javahl',
                         'list', 'enable-sasl', 'bin=', 'parallel',
                         'config-file=', 'server-minor-version=',
-                        'log-to-stdout', 'mode-filter='])
+                        'log-to-stdout', 'mode-filter=', 'milestone-filter='])
 if len(args) > 1:
   print('Warning: non-option arguments after the first one will be ignored')
 
@@ -140,6 +144,7 @@ httpd_port = None
 httpd_service = None
 http_library = 'neon'
 list_tests = None
+milestone_filter = None
 test_javahl = None
 enable_sasl = None
 svn_bin = None
@@ -195,6 +200,8 @@ for opt, val in opts:
     test_javahl = 1
   elif opt == '--list':
     list_tests = 1
+  elif opt == '--milestone-filter':
+    milestone_filter = val
   elif opt == '--mode-filter':
     mode_filter = val
   elif opt == '--enable-sasl':
@@ -688,7 +695,8 @@ if not test_javahl:
                              server_minor_version, not quiet,
                              cleanup, enable_sasl, parallel, config_file,
                              fsfs_sharding, fsfs_packing,
-                             list_tests, svn_bin, mode_filter)
+                             list_tests, svn_bin, mode_filter,
+                             milestone_filter)
   old_cwd = os.getcwd()
   try:
     os.chdir(abs_builddir)



Mime
View raw message