tests/run-tests.py
changeset 21312 986b8a58a6d3
parent 21311 f9a7018a35ff
child 21313 a2bd02a3b6d2
equal deleted inserted replaced
21311:f9a7018a35ff 21312:986b8a58a6d3
   745             return globmatch(el[:-8], l)
   745             return globmatch(el[:-8], l)
   746         if os.altsep and l.replace('\\', '/') == el:
   746         if os.altsep and l.replace('\\', '/') == el:
   747             return '+glob'
   747             return '+glob'
   748     return False
   748     return False
   749 
   749 
   750 def tsttest(test, wd, options, replacements, env):
   750 def tsttest(t, test, wd, options, replacements, env):
   751     # We generate a shell script which outputs unique markers to line
       
   752     # up script results with our source. These markers include input
       
   753     # line number and the last return code
       
   754     salt = "SALT" + str(time.time())
       
   755     def addsalt(line, inpython):
       
   756         if inpython:
       
   757             script.append('%s %d 0\n' % (salt, line))
       
   758         else:
       
   759             script.append('echo %s %s $?\n' % (salt, line))
       
   760 
       
   761     # After we run the shell script, we re-unify the script output
       
   762     # with non-active parts of the source, with synchronization by our
       
   763     # SALT line number markers. The after table contains the
       
   764     # non-active components, ordered by line number
       
   765     after = {}
       
   766     pos = prepos = -1
       
   767 
       
   768     # Expected shell script output
       
   769     expected = {}
       
   770 
       
   771     # We keep track of whether or not we're in a Python block so we
       
   772     # can generate the surrounding doctest magic
       
   773     inpython = False
       
   774 
       
   775     # True or False when in a true or false conditional section
       
   776     skipping = None
       
   777 
       
   778     def hghave(reqs):
       
   779         # TODO: do something smarter when all other uses of hghave is gone
       
   780         tdir = TESTDIR.replace('\\', '/')
       
   781         proc = Popen4('%s -c "%s/hghave %s"' %
       
   782                       (options.shell, tdir, ' '.join(reqs)), wd, 0)
       
   783         stdout, stderr = proc.communicate()
       
   784         ret = proc.wait()
       
   785         if wifexited(ret):
       
   786             ret = os.WEXITSTATUS(ret)
       
   787         if ret == 2:
       
   788             print stdout
       
   789             sys.exit(1)
       
   790         return ret == 0
       
   791 
       
   792     f = open(test)
   751     f = open(test)
   793     t = f.readlines()
   752     tlines = f.readlines()
   794     f.close()
   753     f.close()
   795 
   754 
   796     script = []
   755     salt, script, after, expected = t._parsetest(tlines, wd)
   797     if options.debug:
       
   798         script.append('set -x\n')
       
   799     if os.getenv('MSYSTEM'):
       
   800         script.append('alias pwd="pwd -W"\n')
       
   801     n = 0
       
   802     for n, l in enumerate(t):
       
   803         if not l.endswith('\n'):
       
   804             l += '\n'
       
   805         if l.startswith('#if'):
       
   806             lsplit = l.split()
       
   807             if len(lsplit) < 2 or lsplit[0] != '#if':
       
   808                 after.setdefault(pos, []).append('  !!! invalid #if\n')
       
   809             if skipping is not None:
       
   810                 after.setdefault(pos, []).append('  !!! nested #if\n')
       
   811             skipping = not hghave(lsplit[1:])
       
   812             after.setdefault(pos, []).append(l)
       
   813         elif l.startswith('#else'):
       
   814             if skipping is None:
       
   815                 after.setdefault(pos, []).append('  !!! missing #if\n')
       
   816             skipping = not skipping
       
   817             after.setdefault(pos, []).append(l)
       
   818         elif l.startswith('#endif'):
       
   819             if skipping is None:
       
   820                 after.setdefault(pos, []).append('  !!! missing #if\n')
       
   821             skipping = None
       
   822             after.setdefault(pos, []).append(l)
       
   823         elif skipping:
       
   824             after.setdefault(pos, []).append(l)
       
   825         elif l.startswith('  >>> '): # python inlines
       
   826             after.setdefault(pos, []).append(l)
       
   827             prepos = pos
       
   828             pos = n
       
   829             if not inpython:
       
   830                 # we've just entered a Python block, add the header
       
   831                 inpython = True
       
   832                 addsalt(prepos, False) # make sure we report the exit code
       
   833                 script.append('%s -m heredoctest <<EOF\n' % PYTHON)
       
   834             addsalt(n, True)
       
   835             script.append(l[2:])
       
   836         elif l.startswith('  ... '): # python inlines
       
   837             after.setdefault(prepos, []).append(l)
       
   838             script.append(l[2:])
       
   839         elif l.startswith('  $ '): # commands
       
   840             if inpython:
       
   841                 script.append("EOF\n")
       
   842                 inpython = False
       
   843             after.setdefault(pos, []).append(l)
       
   844             prepos = pos
       
   845             pos = n
       
   846             addsalt(n, False)
       
   847             cmd = l[4:].split()
       
   848             if len(cmd) == 2 and cmd[0] == 'cd':
       
   849                 l = '  $ cd %s || exit 1\n' % cmd[1]
       
   850             script.append(l[4:])
       
   851         elif l.startswith('  > '): # continuations
       
   852             after.setdefault(prepos, []).append(l)
       
   853             script.append(l[4:])
       
   854         elif l.startswith('  '): # results
       
   855             # queue up a list of expected results
       
   856             expected.setdefault(pos, []).append(l[2:])
       
   857         else:
       
   858             if inpython:
       
   859                 script.append("EOF\n")
       
   860                 inpython = False
       
   861             # non-command/result - queue up for merged output
       
   862             after.setdefault(pos, []).append(l)
       
   863 
       
   864     if inpython:
       
   865         script.append("EOF\n")
       
   866     if skipping is not None:
       
   867         after.setdefault(pos, []).append('  !!! missing #endif\n')
       
   868     addsalt(n + 1, False)
       
   869 
   756 
   870     # Write out the script and execute it
   757     # Write out the script and execute it
   871     name = wd + '.sh'
   758     name = wd + '.sh'
   872     f = open(name, 'w')
   759     f = open(name, 'w')
   873     for l in script:
   760     for l in script:
   944 
   831 
   945 class TTest(Test):
   832 class TTest(Test):
   946     """A "t test" is a test backed by a .t file."""
   833     """A "t test" is a test backed by a .t file."""
   947 
   834 
   948     def _run(self, testtmp, replacements, env):
   835     def _run(self, testtmp, replacements, env):
   949         return tsttest(self._path, testtmp, self._options, replacements,
   836         return tsttest(self, self._path, testtmp, self._options, replacements,
   950                        env)
   837                        env)
       
   838 
       
   839     def _hghave(self, reqs, testtmp):
       
   840         # TODO do something smarter when all other uses of hghave are gone.
       
   841         tdir = TESTDIR.replace('\\', '/')
       
   842         proc = Popen4('%s -c "%s/hghave %s"' %
       
   843                       (self._options.shell, tdir, ' '.join(reqs)),
       
   844                       testtmp, 0)
       
   845         stdout, stderr = proc.communicate()
       
   846         ret = proc.wait()
       
   847         if wifexited(ret):
       
   848             ret = os.WEXITSTATUS(ret)
       
   849         if ret == 2:
       
   850             print stdout
       
   851             sys.exit(1)
       
   852 
       
   853         return ret == 0
       
   854 
       
   855     def _parsetest(self, lines, testtmp):
       
   856         # We generate a shell script which outputs unique markers to line
       
   857         # up script results with our source. These markers include input
       
   858         # line number and the last return code.
       
   859         salt = "SALT" + str(time.time())
       
   860         def addsalt(line, inpython):
       
   861             if inpython:
       
   862                 script.append('%s %d 0\n' % (salt, line))
       
   863             else:
       
   864                 script.append('echo %s %s $?\n' % (salt, line))
       
   865 
       
   866         script = []
       
   867 
       
   868         # After we run the shell script, we re-unify the script output
       
   869         # with non-active parts of the source, with synchronization by our
       
   870         # SALT line number markers. The after table contains the non-active
       
   871         # components, ordered by line number.
       
   872         after = {}
       
   873 
       
   874         # Expected shell script output.
       
   875         expected = {}
       
   876 
       
   877         pos = prepos = -1
       
   878 
       
   879         # True or False when in a true or false conditional section
       
   880         skipping = None
       
   881 
       
   882         # We keep track of whether or not we're in a Python block so we
       
   883         # can generate the surrounding doctest magic.
       
   884         inpython = False
       
   885 
       
   886         if self._options.debug:
       
   887             script.append('set -x\n')
       
   888         if os.getenv('MSYSTEM'):
       
   889             script.append('alias pwd="pwd -W"\n')
       
   890 
       
   891         for n, l in enumerate(lines):
       
   892             if not l.endswith('\n'):
       
   893                 l += '\n'
       
   894             if l.startswith('#if'):
       
   895                 lsplit = l.split()
       
   896                 if len(lsplit) < 2 or lsplit[0] != '#if':
       
   897                     after.setdefault(pos, []).append('  !!! invalid #if\n')
       
   898                 if skipping is not None:
       
   899                     after.setdefault(pos, []).append('  !!! nested #if\n')
       
   900                 skipping = not self._hghave(lsplit[1:], testtmp)
       
   901                 after.setdefault(pos, []).append(l)
       
   902             elif l.startswith('#else'):
       
   903                 if skipping is None:
       
   904                     after.setdefault(pos, []).append('  !!! missing #if\n')
       
   905                 skipping = not skipping
       
   906                 after.setdefault(pos, []).append(l)
       
   907             elif l.startswith('#endif'):
       
   908                 if skipping is None:
       
   909                     after.setdefault(pos, []).append('  !!! missing #if\n')
       
   910                 skipping = None
       
   911                 after.setdefault(pos, []).append(l)
       
   912             elif skipping:
       
   913                 after.setdefault(pos, []).append(l)
       
   914             elif l.startswith('  >>> '): # python inlines
       
   915                 after.setdefault(pos, []).append(l)
       
   916                 prepos = pos
       
   917                 pos = n
       
   918                 if not inpython:
       
   919                     # We've just entered a Python block. Add the header.
       
   920                     inpython = True
       
   921                     addsalt(prepos, False) # Make sure we report the exit code.
       
   922                     script.append('%s -m heredoctest <<EOF\n' % PYTHON)
       
   923                 addsalt(n, True)
       
   924                 script.append(l[2:])
       
   925             elif l.startswith('  ... '): # python inlines
       
   926                 after.setdefault(prepos, []).append(l)
       
   927                 script.append(l[2:])
       
   928             elif l.startswith('  $ '): # commands
       
   929                 if inpython:
       
   930                     script.append('EOF\n')
       
   931                     inpython = False
       
   932                 after.setdefault(pos, []).append(l)
       
   933                 prepos = pos
       
   934                 pos = n
       
   935                 addsalt(n, False)
       
   936                 cmd = l[4:].split()
       
   937                 if len(cmd) == 2 and cmd[0] == 'cd':
       
   938                     l = '  $ cd %s || exit 1\n' % cmd[1]
       
   939                 script.append(l[4:])
       
   940             elif l.startswith('  > '): # continuations
       
   941                 after.setdefault(prepos, []).append(l)
       
   942                 script.append(l[4:])
       
   943             elif l.startswith('  '): # results
       
   944                 # Queue up a list of expected results.
       
   945                 expected.setdefault(pos, []).append(l[2:])
       
   946             else:
       
   947                 if inpython:
       
   948                     script.append('EOF\n')
       
   949                     inpython = False
       
   950                 # Non-command/result. Queue up for merged output.
       
   951                 after.setdefault(pos, []).append(l)
       
   952 
       
   953         if inpython:
       
   954             script.append('EOF\n')
       
   955         if skipping is not None:
       
   956             after.setdefault(pos, []).append('  !!! missing #endif\n')
       
   957         addsalt(n + 1, False)
       
   958 
       
   959         return salt, script, after, expected
       
   960 
   951 
   961 
   952 wifexited = getattr(os, "WIFEXITED", lambda x: False)
   962 wifexited = getattr(os, "WIFEXITED", lambda x: False)
   953 def run(cmd, wd, options, replacements, env):
   963 def run(cmd, wd, options, replacements, env):
   954     """Run command in a sub-process, capturing the output (stdout and stderr).
   964     """Run command in a sub-process, capturing the output (stdout and stderr).
   955     Return a tuple (exitcode, output).  output is None in debug mode."""
   965     Return a tuple (exitcode, output).  output is None in debug mode."""