tests/run-tests.py
branchstable
changeset 1000 cc9cdab213e1
parent 999 f89e9c528b38
child 1001 21b3c555b6f4
equal deleted inserted replaced
999:f89e9c528b38 1000:cc9cdab213e1
   523 
   523 
   524 def tsttest(test, wd, options, replacements):
   524 def tsttest(test, wd, options, replacements):
   525     t = open(test)
   525     t = open(test)
   526     out = []
   526     out = []
   527     script = []
   527     script = []
       
   528 
       
   529     # We generate a shell script which outputs unique markers to line
       
   530     # up script results with our source. These markers include input
       
   531     # line number and the last return code
   528     salt = "SALT" + str(time.time())
   532     salt = "SALT" + str(time.time())
   529 
   533     def addsalt(line):
       
   534         script.append('echo %s %s $?\n' % (salt, line))
       
   535 
       
   536     # After we run the shell script, we re-unify the script output
       
   537     # with non-active parts of the source, with synchronization by our
       
   538     # SALT line number markers. The after table contains the
       
   539     # non-active components, ordered by line number
       
   540     after = {}
   530     pos = prepos = -1
   541     pos = prepos = -1
   531     after = {}
   542 
       
   543     # Expected shellscript output
   532     expected = {}
   544     expected = {}
       
   545 
       
   546     # We keep track of whether or not we're in a Python block so we
       
   547     # can generate the surrounding doctest magic
   533     inpython = False
   548     inpython = False
       
   549 
   534     for n, l in enumerate(t):
   550     for n, l in enumerate(t):
   535         if not l.endswith('\n'):
   551         if not l.endswith('\n'):
   536             l += '\n'
   552             l += '\n'
   537         if l.startswith('  >>> '):
   553         if l.startswith('  >>> '): # python inlines
   538             if not inpython:
   554             if not inpython:
   539                 # we've just entered a Python block, add the header
   555                 # we've just entered a Python block, add the header
   540                 inpython = True
   556                 inpython = True
   541                 script.append('echo %s %s $?\n' % (salt, n))
   557                 addsalt(n)
   542                 script.append('%s -m heredoctest <<EOF\n' % PYTHON)
   558                 script.append('%s -m heredoctest <<EOF\n' % PYTHON)
   543                 prepos = pos
   559                 prepos = pos
   544                 pos = n
   560                 pos = n
   545             after.setdefault(prepos, []).append(l)
   561             after.setdefault(prepos, []).append(l)
   546             script.append(l[2:])
   562             script.append(l[2:])
   549                 script.append("EOF\n")
   565                 script.append("EOF\n")
   550                 inpython = False
   566                 inpython = False
   551             after.setdefault(pos, []).append(l)
   567             after.setdefault(pos, []).append(l)
   552             prepos = pos
   568             prepos = pos
   553             pos = n
   569             pos = n
   554             script.append('echo %s %s $?\n' % (salt, n))
   570             addsalt(n)
   555             script.append(l[4:])
   571             script.append(l[4:])
   556         elif l.startswith('  > '): # continuations
   572         elif l.startswith('  > '): # continuations
   557             after.setdefault(prepos, []).append(l)
   573             after.setdefault(prepos, []).append(l)
   558             script.append(l[4:])
   574             script.append(l[4:])
   559         elif l.startswith('  '): # results
   575         elif l.startswith('  '): # results
   568                 script.append("EOF\n")
   584                 script.append("EOF\n")
   569                 inpython = False
   585                 inpython = False
   570             # non-command/result - queue up for merged output
   586             # non-command/result - queue up for merged output
   571             after.setdefault(pos, []).append(l)
   587             after.setdefault(pos, []).append(l)
   572 
   588 
       
   589     t.close()
       
   590 
   573     if inpython:
   591     if inpython:
   574         script.append("EOF\n")
   592         script.append("EOF\n")
   575 
   593     addsalt(n + 1)
   576     t.close()
       
   577 
       
   578     script.append('echo %s %s $?\n' % (salt, n + 1))
       
   579 
   594 
   580     fd, name = tempfile.mkstemp(suffix='hg-tst')
   595     fd, name = tempfile.mkstemp(suffix='hg-tst')
   581 
       
   582     try:
   596     try:
   583         for l in script:
   597         for l in script:
   584             os.write(fd, l)
   598             os.write(fd, l)
   585         os.close(fd)
   599         os.close(fd)
   586 
   600 
   619                 res += '.'
   633                 res += '.'
   620             else:
   634             else:
   621                 res += re.escape(c)
   635                 res += re.escape(c)
   622         return rematch(res, l)
   636         return rematch(res, l)
   623 
   637 
       
   638     # Merge the script output back into a unified test
       
   639 
   624     pos = -1
   640     pos = -1
   625     postout = []
   641     postout = []
   626     ret = 0
   642     ret = 0
   627     for n, l in enumerate(output):
   643     for n, l in enumerate(output):
   628         lout, lcmd = l, None
   644         lout, lcmd = l, None
   629         if salt in l:
   645         if salt in l:
   630             lout, lcmd = l.split(salt, 1)
   646             lout, lcmd = l.split(salt, 1)
   631 
   647 
   632         if lout:
   648         if lout:
   633             if lcmd:
   649             if lcmd:
       
   650                 # output block had no trailing newline, clean up
   634                 lout += ' (no-eol)\n'
   651                 lout += ' (no-eol)\n'
   635 
   652 
       
   653             # find the expected output at the current position
   636             el = None
   654             el = None
   637             if pos in expected and expected[pos]:
   655             if pos in expected and expected[pos]:
   638                 el = expected[pos].pop(0)
   656                 el = expected[pos].pop(0)
   639 
   657 
   640             if el == lout: # perfect match (fast)
   658             if el == lout: # perfect match (fast)
   654             # add on last return code
   672             # add on last return code
   655             ret = int(lcmd.split()[1])
   673             ret = int(lcmd.split()[1])
   656             if ret != 0:
   674             if ret != 0:
   657                 postout.append("  [%s]\n" % ret)
   675                 postout.append("  [%s]\n" % ret)
   658             if pos in after:
   676             if pos in after:
       
   677                 # merge in non-active test bits
   659                 postout += after.pop(pos)
   678                 postout += after.pop(pos)
   660             pos = int(lcmd.split()[0])
   679             pos = int(lcmd.split()[0])
   661 
   680 
   662     if pos in after:
   681     if pos in after:
   663         postout += after.pop(pos)
   682         postout += after.pop(pos)