452 def shtest(test, options, replacements): |
452 def shtest(test, options, replacements): |
453 cmd = '"%s"' % test |
453 cmd = '"%s"' % test |
454 vlog("# Running", cmd) |
454 vlog("# Running", cmd) |
455 return run(cmd, options, replacements) |
455 return run(cmd, options, replacements) |
456 |
456 |
|
457 needescape = re.compile(r'[\x00-\x08\x0b-\x1f\x7f-\xff]').search |
|
458 escapesub = re.compile(r'[\x00-\x08\x0b-\x1f\\\x7f-\xff]').sub |
|
459 escapemap = dict((chr(i), r'\x%02x' % i) for i in range(256)) |
|
460 escapemap.update({'\\': '\\\\', '\r': r'\r'}) |
|
461 def escapef(m): |
|
462 return escapemap[m.group(0)] |
|
463 def stringescape(s): |
|
464 return escapesub(escapef, s) |
|
465 |
457 def tsttest(test, options, replacements): |
466 def tsttest(test, options, replacements): |
458 t = open(test) |
467 t = open(test) |
459 out = [] |
468 out = [] |
460 script = [] |
469 script = [] |
461 salt = "SALT" + str(time.time()) |
470 salt = "SALT" + str(time.time()) |
462 |
471 |
463 pos = prepos = -1 |
472 pos = prepos = -1 |
464 after = {} |
473 after = {} |
465 expected = {} |
474 expected = {} |
466 for n, l in enumerate(t): |
475 for n, l in enumerate(t): |
|
476 if not l.endswith('\n'): |
|
477 l += '\n' |
467 if l.startswith(' $ '): # commands |
478 if l.startswith(' $ '): # commands |
468 after.setdefault(pos, []).append(l) |
479 after.setdefault(pos, []).append(l) |
469 prepos = pos |
480 prepos = pos |
470 pos = n |
481 pos = n |
471 script.append('echo %s %s $?\n' % (salt, n)) |
482 script.append('echo %s %s $?\n' % (salt, n)) |
478 expected.setdefault(pos, []).append(l[2:]) |
489 expected.setdefault(pos, []).append(l[2:]) |
479 else: |
490 else: |
480 # non-command/result - queue up for merged output |
491 # non-command/result - queue up for merged output |
481 after.setdefault(pos, []).append(l) |
492 after.setdefault(pos, []).append(l) |
482 |
493 |
483 if script and not script[-1].endswith('\n'): |
|
484 script[-1] = script[-1] + '\n' |
|
485 script.append('echo %s %s $?\n' % (salt, n + 1)) |
494 script.append('echo %s %s $?\n' % (salt, n + 1)) |
486 |
495 |
487 fd, name = tempfile.mkstemp(suffix='hg-tst') |
496 fd, name = tempfile.mkstemp(suffix='hg-tst') |
488 |
497 |
489 try: |
498 try: |
529 |
538 |
530 pos = -1 |
539 pos = -1 |
531 postout = [] |
540 postout = [] |
532 ret = 0 |
541 ret = 0 |
533 for n, l in enumerate(output): |
542 for n, l in enumerate(output): |
534 if l.startswith(salt): |
543 lout, lcmd = l, None |
|
544 if salt in l: |
|
545 lout, lcmd = l.split(salt, 1) |
|
546 |
|
547 if lout: |
|
548 if lcmd: |
|
549 lout += ' (no-eol)\n' |
|
550 |
|
551 el = None |
|
552 if pos in expected and expected[pos]: |
|
553 el = expected[pos].pop(0) |
|
554 |
|
555 if el == lout: # perfect match (fast) |
|
556 postout.append(" " + lout) |
|
557 elif (el and |
|
558 (el.endswith(" (re)\n") and rematch(el[:-6] + '\n', lout) or |
|
559 el.endswith(" (glob)\n") and globmatch(el[:-8] + '\n', lout)) or |
|
560 el.endswith(" (esc)\n") and el.decode('string-escape') == l): |
|
561 postout.append(" " + el) # fallback regex/glob/esc match |
|
562 else: |
|
563 if needescape(lout): |
|
564 lout = stringescape(lout.rstrip('\n')) + " (esc)\n" |
|
565 postout.append(" " + lout) # let diff deal with it |
|
566 |
|
567 if lcmd: |
535 # add on last return code |
568 # add on last return code |
536 ret = int(l.split()[2]) |
569 ret = int(lcmd.split()[1]) |
537 if ret != 0: |
570 if ret != 0: |
538 postout.append(" [%s]\n" % ret) |
571 postout.append(" [%s]\n" % ret) |
539 if pos in after: |
572 if pos in after: |
540 postout += after.pop(pos) |
573 postout += after.pop(pos) |
541 pos = int(l.split()[1]) |
574 pos = int(lcmd.split()[0]) |
542 else: |
|
543 el = None |
|
544 if pos in expected and expected[pos]: |
|
545 el = expected[pos].pop(0) |
|
546 |
|
547 if el == l: # perfect match (fast) |
|
548 postout.append(" " + l) |
|
549 elif el and el.decode('string-escape') == l: |
|
550 postout.append(" " + el) # \-escape match |
|
551 elif (el and |
|
552 (el.endswith(" (re)\n") and rematch(el[:-6] + '\n', l) or |
|
553 el.endswith(" (glob)\n") and globmatch(el[:-8] + '\n', l))): |
|
554 postout.append(" " + el) # fallback regex/glob match |
|
555 else: |
|
556 postout.append(" " + l) # let diff deal with it |
|
557 |
575 |
558 if pos in after: |
576 if pos in after: |
559 postout += after.pop(pos) |
577 postout += after.pop(pos) |
560 |
578 |
561 return exitcode, postout |
579 return exitcode, postout |