tests/run-tests.py
author Greg Ward <greg@gerg.ca>
Thu, 05 Jun 2014 22:11:04 -0400
changeset 978 8328337d23b2
parent 530 6ee7add34f8b
permissions -rwxr-xr-x
docs: add new user guide This has also been reviewed to death on evolve-testers. There are still a couple of short sections to write (clearly marked "TODO"), and one example to add. But (if I may be so bold) this is a gigantic improvement over the current docs, so it really should get merged. Incidentally, the figures are all SVG files created with Inkscape. They're not perfect, but they're pretty nice. Anyone who knows a better way to create technical diagrams is welcome to contribute. One wart: there's a test script that accompanies the document and largely duplicates it, but I haven't unified them. I've been concentrating on writing the best possible content, not on fiddling with tools. I suspect that unifying them will be non-trivial, but definitely worth doing.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
     1
#!/usr/bin/env python
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
     2
#
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
     3
# run-tests.py - Run a set of tests on Mercurial
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
     4
#
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
     5
# Copyright 2006 Matt Mackall <mpm@selenic.com>
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
     6
#
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
     7
# This software may be used and distributed according to the terms of the
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
     8
# GNU General Public License version 2 or any later version.
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
     9
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    10
# Modifying this script is tricky because it has many modes:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    11
#   - serial (default) vs parallel (-jN, N > 1)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    12
#   - no coverage (default) vs coverage (-c, -C, -s)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    13
#   - temp install (default) vs specific hg script (--with-hg, --local)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    14
#   - tests are a mix of shell scripts and Python scripts
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    15
#
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    16
# If you change this script, it is recommended that you ensure you
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    17
# haven't broken it by running it in various modes with a representative
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    18
# sample of test scripts.  For example:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    19
#
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    20
#  1) serial, no coverage, temp install:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    21
#      ./run-tests.py test-s*
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    22
#  2) serial, no coverage, local hg:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    23
#      ./run-tests.py --local test-s*
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    24
#  3) serial, coverage, temp install:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    25
#      ./run-tests.py -c test-s*
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    26
#  4) serial, coverage, local hg:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    27
#      ./run-tests.py -c --local test-s*      # unsupported
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    28
#  5) parallel, no coverage, temp install:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    29
#      ./run-tests.py -j2 test-s*
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    30
#  6) parallel, no coverage, local hg:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    31
#      ./run-tests.py -j2 --local test-s*
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    32
#  7) parallel, coverage, temp install:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    33
#      ./run-tests.py -j2 -c test-s*          # currently broken
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    34
#  8) parallel, coverage, local install:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    35
#      ./run-tests.py -j2 -c --local test-s*  # unsupported (and broken)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    36
#  9) parallel, custom tmp dir:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    37
#      ./run-tests.py -j2 --tmpdir /tmp/myhgtests
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    38
#
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    39
# (You could use any subset of the tests: test-s* happens to match
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    40
# enough that it's worth doing parallel runs, few enough that it
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    41
# completes fairly quickly, includes both shell and Python scripts, and
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    42
# includes some scripts that run daemon processes.)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    43
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    44
from distutils import version
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    45
import difflib
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    46
import errno
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    47
import optparse
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    48
import os
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    49
import shutil
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    50
import subprocess
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    51
import signal
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    52
import sys
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    53
import tempfile
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    54
import time
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    55
import re
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    56
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    57
closefds = os.name == 'posix'
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    58
def Popen4(cmd, bufsize=-1):
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    59
    p = subprocess.Popen(cmd, shell=True, bufsize=bufsize,
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    60
                         close_fds=closefds,
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    61
                         stdin=subprocess.PIPE, stdout=subprocess.PIPE,
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    62
                         stderr=subprocess.STDOUT)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    63
    p.fromchild = p.stdout
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    64
    p.tochild = p.stdin
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    65
    p.childerr = p.stderr
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    66
    return p
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    67
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    68
# reserved exit code to skip test (used by hghave)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    69
SKIPPED_STATUS = 80
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    70
SKIPPED_PREFIX = 'skipped: '
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    71
FAILED_PREFIX  = 'hghave check failed: '
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    72
PYTHON = sys.executable
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    73
IMPL_PATH = 'PYTHONPATH'
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    74
if 'java' in sys.platform:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    75
    IMPL_PATH = 'JYTHONPATH'
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    76
530
6ee7add34f8b tests: remove unused required tools
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 21
diff changeset
    77
requiredtools = ["python", "diff", "grep", "sed"]
0
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    78
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    79
defaults = {
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    80
    'jobs': ('HGTEST_JOBS', 1),
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    81
    'timeout': ('HGTEST_TIMEOUT', 180),
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    82
    'port': ('HGTEST_PORT', 20059),
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    83
}
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    84
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    85
def parseargs():
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    86
    parser = optparse.OptionParser("%prog [options] [tests]")
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    87
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    88
    # keep these sorted
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    89
    parser.add_option("--blacklist", action="append",
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    90
        help="skip tests listed in the specified blacklist file")
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    91
    parser.add_option("-C", "--annotate", action="store_true",
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    92
        help="output files annotated with coverage")
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    93
    parser.add_option("--child", type="int",
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    94
        help="run as child process, summary to given fd")
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    95
    parser.add_option("-c", "--cover", action="store_true",
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    96
        help="print a test coverage report")
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    97
    parser.add_option("-d", "--debug", action="store_true",
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    98
        help="debug mode: write output of test scripts to console"
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    99
             " rather than capturing and diff'ing it (disables timeout)")
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   100
    parser.add_option("-f", "--first", action="store_true",
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   101
        help="exit on the first test failure")
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   102
    parser.add_option("--inotify", action="store_true",
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   103
        help="enable inotify extension when running tests")
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   104
    parser.add_option("-i", "--interactive", action="store_true",
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   105
        help="prompt to accept changed output")
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   106
    parser.add_option("-j", "--jobs", type="int",
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   107
        help="number of jobs to run in parallel"
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   108
             " (default: $%s or %d)" % defaults['jobs'])
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   109
    parser.add_option("--keep-tmpdir", action="store_true",
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   110
        help="keep temporary directory after running tests")
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   111
    parser.add_option("-k", "--keywords",
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   112
        help="run tests matching keywords")
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   113
    parser.add_option("-l", "--local", action="store_true",
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   114
        help="shortcut for --with-hg=<testdir>/../hg")
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   115
    parser.add_option("-n", "--nodiff", action="store_true",
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   116
        help="skip showing test changes")
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   117
    parser.add_option("-p", "--port", type="int",
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   118
        help="port on which servers should listen"
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   119
             " (default: $%s or %d)" % defaults['port'])
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   120
    parser.add_option("--pure", action="store_true",
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   121
        help="use pure Python code instead of C extensions")
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   122
    parser.add_option("-R", "--restart", action="store_true",
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   123
        help="restart at last error")
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   124
    parser.add_option("-r", "--retest", action="store_true",
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   125
        help="retest failed tests")
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   126
    parser.add_option("-S", "--noskips", action="store_true",
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   127
        help="don't report skip tests verbosely")
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   128
    parser.add_option("-t", "--timeout", type="int",
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   129
        help="kill errant tests after TIMEOUT seconds"
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   130
             " (default: $%s or %d)" % defaults['timeout'])
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   131
    parser.add_option("--tmpdir", type="string",
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   132
        help="run tests in the given temporary directory"
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   133
             " (implies --keep-tmpdir)")
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   134
    parser.add_option("-v", "--verbose", action="store_true",
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   135
        help="output verbose messages")
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   136
    parser.add_option("--view", type="string",
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   137
        help="external diff viewer")
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   138
    parser.add_option("--with-hg", type="string",
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   139
        metavar="HG",
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   140
        help="test using specified hg script rather than a "
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   141
             "temporary installation")
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   142
    parser.add_option("-3", "--py3k-warnings", action="store_true",
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   143
        help="enable Py3k warnings on Python 2.6+")
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   144
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   145
    for option, default in defaults.items():
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   146
        defaults[option] = int(os.environ.get(*default))
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   147
    parser.set_defaults(**defaults)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   148
    (options, args) = parser.parse_args()
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   149
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   150
    # jython is always pure
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   151
    if 'java' in sys.platform or '__pypy__' in sys.modules:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   152
        options.pure = True
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   153
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   154
    if options.with_hg:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   155
        if not (os.path.isfile(options.with_hg) and
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   156
                os.access(options.with_hg, os.X_OK)):
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   157
            parser.error('--with-hg must specify an executable hg script')
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   158
        if not os.path.basename(options.with_hg) == 'hg':
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   159
            sys.stderr.write('warning: --with-hg should specify an hg script')
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   160
    if options.local:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   161
        testdir = os.path.dirname(os.path.realpath(sys.argv[0]))
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   162
        hgbin = os.path.join(os.path.dirname(testdir), 'hg')
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   163
        if not os.access(hgbin, os.X_OK):
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   164
            parser.error('--local specified, but %r not found or not executable'
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   165
                         % hgbin)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   166
        options.with_hg = hgbin
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   167
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   168
    options.anycoverage = options.cover or options.annotate
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   169
    if options.anycoverage:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   170
        try:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   171
            import coverage
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   172
            covver = version.StrictVersion(coverage.__version__).version
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   173
            if covver < (3, 3):
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   174
                parser.error('coverage options require coverage 3.3 or later')
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   175
        except ImportError:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   176
            parser.error('coverage options now require the coverage package')
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   177
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   178
    if options.anycoverage and options.local:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   179
        # this needs some path mangling somewhere, I guess
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   180
        parser.error("sorry, coverage options do not work when --local "
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   181
                     "is specified")
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   182
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   183
    global vlog
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   184
    if options.verbose:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   185
        if options.jobs > 1 or options.child is not None:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   186
            pid = "[%d]" % os.getpid()
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   187
        else:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   188
            pid = None
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   189
        def vlog(*msg):
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   190
            if pid:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   191
                print pid,
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   192
            for m in msg:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   193
                print m,
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   194
            print
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   195
            sys.stdout.flush()
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   196
    else:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   197
        vlog = lambda *msg: None
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   198
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   199
    if options.tmpdir:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   200
        options.tmpdir = os.path.expanduser(options.tmpdir)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   201
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   202
    if options.jobs < 1:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   203
        parser.error('--jobs must be positive')
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   204
    if options.interactive and options.jobs > 1:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   205
        print '(--interactive overrides --jobs)'
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   206
        options.jobs = 1
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   207
    if options.interactive and options.debug:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   208
        parser.error("-i/--interactive and -d/--debug are incompatible")
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   209
    if options.debug:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   210
        if options.timeout != defaults['timeout']:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   211
            sys.stderr.write(
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   212
                'warning: --timeout option ignored with --debug\n')
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   213
        options.timeout = 0
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   214
    if options.py3k_warnings:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   215
        if sys.version_info[:2] < (2, 6) or sys.version_info[:2] >= (3, 0):
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   216
            parser.error('--py3k-warnings can only be used on Python 2.6+')
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   217
    if options.blacklist:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   218
        blacklist = dict()
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   219
        for filename in options.blacklist:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   220
            try:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   221
                path = os.path.expanduser(os.path.expandvars(filename))
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   222
                f = open(path, "r")
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   223
            except IOError, err:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   224
                if err.errno != errno.ENOENT:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   225
                    raise
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   226
                print "warning: no such blacklist file: %s" % filename
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   227
                continue
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   228
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   229
            for line in f.readlines():
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   230
                line = line.strip()
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   231
                if line and not line.startswith('#'):
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   232
                    blacklist[line] = filename
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   233
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   234
            f.close()
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   235
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   236
        options.blacklist = blacklist
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   237
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   238
    return (options, args)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   239
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   240
def rename(src, dst):
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   241
    """Like os.rename(), trade atomicity and opened files friendliness
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   242
    for existing destination support.
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   243
    """
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   244
    shutil.copy(src, dst)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   245
    os.remove(src)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   246
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   247
def splitnewlines(text):
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   248
    '''like str.splitlines, but only split on newlines.
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   249
    keep line endings.'''
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   250
    i = 0
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   251
    lines = []
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   252
    while True:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   253
        n = text.find('\n', i)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   254
        if n == -1:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   255
            last = text[i:]
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   256
            if last:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   257
                lines.append(last)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   258
            return lines
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   259
        lines.append(text[i:n + 1])
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   260
        i = n + 1
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   261
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   262
def parsehghaveoutput(lines):
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   263
    '''Parse hghave log lines.
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   264
    Return tuple of lists (missing, failed):
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   265
      * the missing/unknown features
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   266
      * the features for which existence check failed'''
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   267
    missing = []
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   268
    failed = []
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   269
    for line in lines:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   270
        if line.startswith(SKIPPED_PREFIX):
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   271
            line = line.splitlines()[0]
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   272
            missing.append(line[len(SKIPPED_PREFIX):])
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   273
        elif line.startswith(FAILED_PREFIX):
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   274
            line = line.splitlines()[0]
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   275
            failed.append(line[len(FAILED_PREFIX):])
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   276
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   277
    return missing, failed
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   278
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   279
def showdiff(expected, output, ref, err):
21
aa0870d093b8 Add pull and push support for relevant heads.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 0
diff changeset
   280
    try:
aa0870d093b8 Add pull and push support for relevant heads.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 0
diff changeset
   281
        for line in difflib.unified_diff(expected, output, ref, err):
aa0870d093b8 Add pull and push support for relevant heads.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 0
diff changeset
   282
            sys.stdout.write(line)
aa0870d093b8 Add pull and push support for relevant heads.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 0
diff changeset
   283
    except IOError, ex:
aa0870d093b8 Add pull and push support for relevant heads.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 0
diff changeset
   284
        print >>sys.stderr, 'BORKEN PIPE', ex.errno
aa0870d093b8 Add pull and push support for relevant heads.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 0
diff changeset
   285
        pass
0
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   286
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   287
def findprogram(program):
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   288
    """Search PATH for a executable program"""
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   289
    for p in os.environ.get('PATH', os.defpath).split(os.pathsep):
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   290
        name = os.path.join(p, program)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   291
        if os.access(name, os.X_OK):
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   292
            return name
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   293
    return None
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   294
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   295
def checktools():
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   296
    # Before we go any further, check for pre-requisite tools
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   297
    # stuff from coreutils (cat, rm, etc) are not tested
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   298
    for p in requiredtools:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   299
        if os.name == 'nt':
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   300
            p += '.exe'
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   301
        found = findprogram(p)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   302
        if found:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   303
            vlog("# Found prerequisite", p, "at", found)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   304
        else:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   305
            print "WARNING: Did not find prerequisite tool: "+p
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   306
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   307
def killdaemons():
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   308
    # Kill off any leftover daemon processes
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   309
    try:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   310
        fp = open(DAEMON_PIDS)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   311
        for line in fp:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   312
            try:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   313
                pid = int(line)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   314
            except ValueError:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   315
                continue
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   316
            try:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   317
                os.kill(pid, 0)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   318
                vlog('# Killing daemon process %d' % pid)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   319
                os.kill(pid, signal.SIGTERM)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   320
                time.sleep(0.25)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   321
                os.kill(pid, 0)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   322
                vlog('# Daemon process %d is stuck - really killing it' % pid)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   323
                os.kill(pid, signal.SIGKILL)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   324
            except OSError, err:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   325
                if err.errno != errno.ESRCH:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   326
                    raise
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   327
        fp.close()
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   328
        os.unlink(DAEMON_PIDS)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   329
    except IOError:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   330
        pass
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   331
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   332
def cleanup(options):
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   333
    if not options.keep_tmpdir:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   334
        vlog("# Cleaning up HGTMP", HGTMP)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   335
        shutil.rmtree(HGTMP, True)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   336
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   337
def usecorrectpython():
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   338
    # some tests run python interpreter. they must use same
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   339
    # interpreter we use or bad things will happen.
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   340
    exedir, exename = os.path.split(sys.executable)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   341
    if exename == 'python':
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   342
        path = findprogram('python')
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   343
        if os.path.dirname(path) == exedir:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   344
            return
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   345
    vlog('# Making python executable in test path use correct Python')
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   346
    mypython = os.path.join(BINDIR, 'python')
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   347
    try:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   348
        os.symlink(sys.executable, mypython)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   349
    except AttributeError:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   350
        # windows fallback
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   351
        shutil.copyfile(sys.executable, mypython)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   352
        shutil.copymode(sys.executable, mypython)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   353
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   354
def installhg(options):
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   355
    vlog("# Performing temporary installation of HG")
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   356
    installerrs = os.path.join("tests", "install.err")
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   357
    pure = options.pure and "--pure" or ""
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   358
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   359
    # Run installer in hg root
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   360
    script = os.path.realpath(sys.argv[0])
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   361
    hgroot = os.path.dirname(os.path.dirname(script))
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   362
    os.chdir(hgroot)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   363
    nohome = '--home=""'
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   364
    if os.name == 'nt':
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   365
        # The --home="" trick works only on OS where os.sep == '/'
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   366
        # because of a distutils convert_path() fast-path. Avoid it at
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   367
        # least on Windows for now, deal with .pydistutils.cfg bugs
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   368
        # when they happen.
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   369
        nohome = ''
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   370
    cmd = ('%s setup.py %s clean --all'
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   371
           ' build --build-base="%s"'
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   372
           ' install --force --prefix="%s" --install-lib="%s"'
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   373
           ' --install-scripts="%s" %s >%s 2>&1'
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   374
           % (sys.executable, pure, os.path.join(HGTMP, "build"),
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   375
              INST, PYTHONDIR, BINDIR, nohome, installerrs))
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   376
    vlog("# Running", cmd)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   377
    if os.system(cmd) == 0:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   378
        if not options.verbose:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   379
            os.remove(installerrs)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   380
    else:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   381
        f = open(installerrs)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   382
        for line in f:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   383
            print line,
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   384
        f.close()
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   385
        sys.exit(1)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   386
    os.chdir(TESTDIR)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   387
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   388
    usecorrectpython()
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   389
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   390
    vlog("# Installing dummy diffstat")
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   391
    f = open(os.path.join(BINDIR, 'diffstat'), 'w')
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   392
    f.write('#!' + sys.executable + '\n'
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   393
            'import sys\n'
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   394
            'files = 0\n'
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   395
            'for line in sys.stdin:\n'
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   396
            '    if line.startswith("diff "):\n'
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   397
            '        files += 1\n'
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   398
            'sys.stdout.write("files patched: %d\\n" % files)\n')
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   399
    f.close()
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   400
    os.chmod(os.path.join(BINDIR, 'diffstat'), 0700)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   401
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   402
    if options.py3k_warnings and not options.anycoverage:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   403
        vlog("# Updating hg command to enable Py3k Warnings switch")
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   404
        f = open(os.path.join(BINDIR, 'hg'), 'r')
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   405
        lines = [line.rstrip() for line in f]
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   406
        lines[0] += ' -3'
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   407
        f.close()
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   408
        f = open(os.path.join(BINDIR, 'hg'), 'w')
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   409
        for line in lines:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   410
            f.write(line + '\n')
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   411
        f.close()
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   412
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   413
    if options.anycoverage:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   414
        custom = os.path.join(TESTDIR, 'sitecustomize.py')
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   415
        target = os.path.join(PYTHONDIR, 'sitecustomize.py')
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   416
        vlog('# Installing coverage trigger to %s' % target)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   417
        shutil.copyfile(custom, target)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   418
        rc = os.path.join(TESTDIR, '.coveragerc')
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   419
        vlog('# Installing coverage rc to %s' % rc)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   420
        os.environ['COVERAGE_PROCESS_START'] = rc
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   421
        fn = os.path.join(INST, '..', '.coverage')
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   422
        os.environ['COVERAGE_FILE'] = fn
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   423
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   424
def outputcoverage(options):
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   425
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   426
    vlog('# Producing coverage report')
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   427
    os.chdir(PYTHONDIR)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   428
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   429
    def covrun(*args):
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   430
        cmd = 'coverage %s' % ' '.join(args)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   431
        vlog('# Running: %s' % cmd)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   432
        os.system(cmd)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   433
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   434
    if options.child:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   435
        return
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   436
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   437
    covrun('-c')
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   438
    omit = ','.join([BINDIR, TESTDIR])
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   439
    covrun('-i', '-r', '"--omit=%s"' % omit) # report
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   440
    if options.annotate:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   441
        adir = os.path.join(TESTDIR, 'annotated')
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   442
        if not os.path.isdir(adir):
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   443
            os.mkdir(adir)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   444
        covrun('-i', '-a', '"--directory=%s"' % adir, '"--omit=%s"' % omit)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   445
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   446
class Timeout(Exception):
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   447
    pass
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   448
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   449
def alarmed(signum, frame):
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   450
    raise Timeout
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   451
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   452
def pytest(test, options, replacements):
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   453
    py3kswitch = options.py3k_warnings and ' -3' or ''
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   454
    cmd = '%s%s "%s"' % (PYTHON, py3kswitch, test)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   455
    vlog("# Running", cmd)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   456
    return run(cmd, options, replacements)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   457
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   458
def shtest(test, options, replacements):
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   459
    cmd = '"%s"' % test
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   460
    vlog("# Running", cmd)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   461
    return run(cmd, options, replacements)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   462
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   463
needescape = re.compile(r'[\x00-\x08\x0b-\x1f\x7f-\xff]').search
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   464
escapesub = re.compile(r'[\x00-\x08\x0b-\x1f\\\x7f-\xff]').sub
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   465
escapemap = dict((chr(i), r'\x%02x' % i) for i in range(256))
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   466
escapemap.update({'\\': '\\\\', '\r': r'\r'})
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   467
def escapef(m):
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   468
    return escapemap[m.group(0)]
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   469
def stringescape(s):
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   470
    return escapesub(escapef, s)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   471
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   472
def tsttest(test, options, replacements):
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   473
    t = open(test)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   474
    out = []
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   475
    script = []
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   476
    salt = "SALT" + str(time.time())
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   477
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   478
    pos = prepos = -1
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   479
    after = {}
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   480
    expected = {}
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   481
    for n, l in enumerate(t):
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   482
        if not l.endswith('\n'):
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   483
            l += '\n'
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   484
        if l.startswith('  $ '): # commands
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   485
            after.setdefault(pos, []).append(l)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   486
            prepos = pos
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   487
            pos = n
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   488
            script.append('echo %s %s $?\n' % (salt, n))
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   489
            script.append(l[4:])
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   490
        elif l.startswith('  > '): # continuations
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   491
            after.setdefault(prepos, []).append(l)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   492
            script.append(l[4:])
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   493
        elif l.startswith('  '): # results
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   494
            # queue up a list of expected results
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   495
            expected.setdefault(pos, []).append(l[2:])
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   496
        else:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   497
            # non-command/result - queue up for merged output
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   498
            after.setdefault(pos, []).append(l)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   499
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   500
    t.close()
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   501
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   502
    script.append('echo %s %s $?\n' % (salt, n + 1))
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   503
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   504
    fd, name = tempfile.mkstemp(suffix='hg-tst')
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   505
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   506
    try:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   507
        for l in script:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   508
            os.write(fd, l)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   509
        os.close(fd)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   510
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   511
        cmd = '/bin/sh "%s"' % name
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   512
        vlog("# Running", cmd)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   513
        exitcode, output = run(cmd, options, replacements)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   514
        # do not merge output if skipped, return hghave message instead
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   515
        # similarly, with --debug, output is None
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   516
        if exitcode == SKIPPED_STATUS or output is None:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   517
            return exitcode, output
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   518
    finally:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   519
        os.remove(name)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   520
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   521
    def rematch(el, l):
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   522
        try:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   523
            # ensure that the regex matches to the end of the string
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   524
            return re.match(el + r'\Z', l)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   525
        except re.error:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   526
            # el is an invalid regex
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   527
            return False
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   528
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   529
    def globmatch(el, l):
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   530
        # The only supported special characters are * and ?. Escaping is
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   531
        # supported.
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   532
        i, n = 0, len(el)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   533
        res = ''
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   534
        while i < n:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   535
            c = el[i]
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   536
            i += 1
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   537
            if c == '\\' and el[i] in '*?\\':
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   538
                res += el[i - 1:i + 1]
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   539
                i += 1
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   540
            elif c == '*':
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   541
                res += '.*'
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   542
            elif c == '?':
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   543
                res += '.'
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   544
            else:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   545
                res += re.escape(c)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   546
        return rematch(res, l)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   547
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   548
    pos = -1
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   549
    postout = []
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   550
    ret = 0
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   551
    for n, l in enumerate(output):
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   552
        lout, lcmd = l, None
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   553
        if salt in l:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   554
            lout, lcmd = l.split(salt, 1)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   555
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   556
        if lout:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   557
            if lcmd:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   558
                lout += ' (no-eol)\n'
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   559
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   560
            el = None
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   561
            if pos in expected and expected[pos]:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   562
                el = expected[pos].pop(0)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   563
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   564
            if el == lout: # perfect match (fast)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   565
                postout.append("  " + lout)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   566
            elif (el and
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   567
                  (el.endswith(" (re)\n") and rematch(el[:-6] + '\n', lout) or
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   568
                   el.endswith(" (glob)\n") and globmatch(el[:-8] + '\n', lout)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   569
                   or el.endswith(" (esc)\n") and
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   570
                      el.decode('string-escape') == l)):
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   571
                postout.append("  " + el) # fallback regex/glob/esc match
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   572
            else:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   573
                if needescape(lout):
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   574
                    lout = stringescape(lout.rstrip('\n')) + " (esc)\n"
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   575
                postout.append("  " + lout) # let diff deal with it
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   576
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   577
        if lcmd:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   578
            # add on last return code
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   579
            ret = int(lcmd.split()[1])
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   580
            if ret != 0:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   581
                postout.append("  [%s]\n" % ret)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   582
            if pos in after:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   583
                postout += after.pop(pos)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   584
            pos = int(lcmd.split()[0])
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   585
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   586
    if pos in after:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   587
        postout += after.pop(pos)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   588
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   589
    return exitcode, postout
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   590
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   591
wifexited = getattr(os, "WIFEXITED", lambda x: False)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   592
def run(cmd, options, replacements):
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   593
    """Run command in a sub-process, capturing the output (stdout and stderr).
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   594
    Return a tuple (exitcode, output).  output is None in debug mode."""
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   595
    # TODO: Use subprocess.Popen if we're running on Python 2.4
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   596
    if options.debug:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   597
        proc = subprocess.Popen(cmd, shell=True)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   598
        ret = proc.wait()
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   599
        return (ret, None)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   600
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   601
    if os.name == 'nt' or sys.platform.startswith('java'):
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   602
        tochild, fromchild = os.popen4(cmd)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   603
        tochild.close()
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   604
        output = fromchild.read()
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   605
        ret = fromchild.close()
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   606
        if ret is None:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   607
            ret = 0
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   608
    else:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   609
        proc = Popen4(cmd)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   610
        def cleanup():
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   611
            os.kill(proc.pid, signal.SIGTERM)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   612
            ret = proc.wait()
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   613
            if ret == 0:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   614
                ret = signal.SIGTERM << 8
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   615
            killdaemons()
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   616
            return ret
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   617
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   618
        try:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   619
            output = ''
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   620
            proc.tochild.close()
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   621
            output = proc.fromchild.read()
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   622
            ret = proc.wait()
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   623
            if wifexited(ret):
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   624
                ret = os.WEXITSTATUS(ret)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   625
        except Timeout:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   626
            vlog('# Process %d timed out - killing it' % proc.pid)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   627
            ret = cleanup()
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   628
            output += ("\n### Abort: timeout after %d seconds.\n"
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   629
                       % options.timeout)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   630
        except KeyboardInterrupt:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   631
            vlog('# Handling keyboard interrupt')
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   632
            cleanup()
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   633
            raise
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   634
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   635
    for s, r in replacements:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   636
        output = re.sub(s, r, output)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   637
    return ret, splitnewlines(output)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   638
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   639
def runone(options, test, skips, fails):
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   640
    '''tristate output:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   641
    None -> skipped
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   642
    True -> passed
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   643
    False -> failed'''
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   644
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   645
    def skip(msg):
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   646
        if not options.verbose:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   647
            skips.append((test, msg))
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   648
        else:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   649
            print "\nSkipping %s: %s" % (testpath, msg)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   650
        return None
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   651
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   652
    def fail(msg):
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   653
        fails.append((test, msg))
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   654
        if not options.nodiff:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   655
            print "\nERROR: %s %s" % (testpath, msg)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   656
        return None
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   657
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   658
    vlog("# Test", test)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   659
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   660
    # create a fresh hgrc
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   661
    hgrc = open(HGRCPATH, 'w+')
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   662
    hgrc.write('[ui]\n')
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   663
    hgrc.write('slash = True\n')
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   664
    hgrc.write('[defaults]\n')
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   665
    hgrc.write('backout = -d "0 0"\n')
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   666
    hgrc.write('commit = -d "0 0"\n')
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   667
    hgrc.write('tag = -d "0 0"\n')
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   668
    if options.inotify:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   669
        hgrc.write('[extensions]\n')
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   670
        hgrc.write('inotify=\n')
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   671
        hgrc.write('[inotify]\n')
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   672
        hgrc.write('pidfile=%s\n' % DAEMON_PIDS)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   673
        hgrc.write('appendpid=True\n')
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   674
    hgrc.close()
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   675
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   676
    testpath = os.path.join(TESTDIR, test)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   677
    ref = os.path.join(TESTDIR, test+".out")
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   678
    err = os.path.join(TESTDIR, test+".err")
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   679
    if os.path.exists(err):
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   680
        os.remove(err)       # Remove any previous output files
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   681
    try:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   682
        tf = open(testpath)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   683
        firstline = tf.readline().rstrip()
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   684
        tf.close()
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   685
    except:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   686
        firstline = ''
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   687
    lctest = test.lower()
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   688
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   689
    if lctest.endswith('.py') or firstline == '#!/usr/bin/env python':
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   690
        runner = pytest
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   691
    elif lctest.endswith('.t'):
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   692
        runner = tsttest
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   693
        ref = testpath
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   694
    else:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   695
        # do not try to run non-executable programs
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   696
        if not os.access(testpath, os.X_OK):
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   697
            return skip("not executable")
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   698
        runner = shtest
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   699
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   700
    # Make a tmp subdirectory to work in
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   701
    testtmp = os.environ["TESTTMP"] = os.path.join(HGTMP, test)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   702
    os.mkdir(testtmp)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   703
    os.chdir(testtmp)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   704
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   705
    if options.timeout > 0:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   706
        signal.alarm(options.timeout)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   707
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   708
    ret, out = runner(testpath, options, [
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   709
        (re.escape(testtmp), '$TESTTMP'),
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   710
        (r':%s\b' % options.port, ':$HGPORT'),
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   711
        (r':%s\b' % (options.port + 1), ':$HGPORT1'),
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   712
        (r':%s\b' % (options.port + 2), ':$HGPORT2'),
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   713
        ])
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   714
    vlog("# Ret was:", ret)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   715
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   716
    if options.timeout > 0:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   717
        signal.alarm(0)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   718
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   719
    mark = '.'
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   720
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   721
    skipped = (ret == SKIPPED_STATUS)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   722
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   723
    # If we're not in --debug mode and reference output file exists,
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   724
    # check test output against it.
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   725
    if options.debug:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   726
        refout = None                   # to match "out is None"
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   727
    elif os.path.exists(ref):
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   728
        f = open(ref, "r")
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   729
        refout = splitnewlines(f.read())
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   730
        f.close()
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   731
    else:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   732
        refout = []
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   733
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   734
    if (ret != 0 or out != refout) and not skipped and not options.debug:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   735
        # Save errors to a file for diagnosis
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   736
        f = open(err, "wb")
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   737
        for line in out:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   738
            f.write(line)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   739
        f.close()
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   740
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   741
    if skipped:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   742
        mark = 's'
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   743
        if out is None:                 # debug mode: nothing to parse
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   744
            missing = ['unknown']
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   745
            failed = None
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   746
        else:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   747
            missing, failed = parsehghaveoutput(out)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   748
        if not missing:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   749
            missing = ['irrelevant']
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   750
        if failed:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   751
            fail("hghave failed checking for %s" % failed[-1])
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   752
            skipped = False
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   753
        else:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   754
            skip(missing[-1])
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   755
    elif out != refout:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   756
        mark = '!'
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   757
        if ret:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   758
            fail("output changed and returned error code %d" % ret)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   759
        else:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   760
            fail("output changed")
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   761
        if not options.nodiff:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   762
            if options.view:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   763
                os.system("%s %s %s" % (options.view, ref, err))
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   764
            else:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   765
                showdiff(refout, out, ref, err)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   766
        ret = 1
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   767
    elif ret:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   768
        mark = '!'
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   769
        fail("returned error code %d" % ret)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   770
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   771
    if not options.verbose:
21
aa0870d093b8 Add pull and push support for relevant heads.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 0
diff changeset
   772
        try:
aa0870d093b8 Add pull and push support for relevant heads.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 0
diff changeset
   773
            sys.stdout.write(mark)
aa0870d093b8 Add pull and push support for relevant heads.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 0
diff changeset
   774
            sys.stdout.flush()
aa0870d093b8 Add pull and push support for relevant heads.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 0
diff changeset
   775
        except IOError, ex:
aa0870d093b8 Add pull and push support for relevant heads.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 0
diff changeset
   776
            print >>sys.stderr, 'BORKEN PIPE', ex.errno
aa0870d093b8 Add pull and push support for relevant heads.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 0
diff changeset
   777
            pass
0
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   778
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   779
    killdaemons()
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   780
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   781
    os.chdir(TESTDIR)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   782
    if not options.keep_tmpdir:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   783
        shutil.rmtree(testtmp, True)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   784
    if skipped:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   785
        return None
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   786
    return ret == 0
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   787
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   788
_hgpath = None
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   789
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   790
def _gethgpath():
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   791
    """Return the path to the mercurial package that is actually found by
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   792
    the current Python interpreter."""
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   793
    global _hgpath
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   794
    if _hgpath is not None:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   795
        return _hgpath
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   796
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   797
    cmd = '%s -c "import mercurial; print mercurial.__path__[0]"'
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   798
    pipe = os.popen(cmd % PYTHON)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   799
    try:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   800
        _hgpath = pipe.read().strip()
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   801
    finally:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   802
        pipe.close()
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   803
    return _hgpath
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   804
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   805
def _checkhglib(verb):
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   806
    """Ensure that the 'mercurial' package imported by python is
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   807
    the one we expect it to be.  If not, print a warning to stderr."""
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   808
    expecthg = os.path.join(PYTHONDIR, 'mercurial')
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   809
    actualhg = _gethgpath()
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   810
    if actualhg != expecthg:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   811
        sys.stderr.write('warning: %s with unexpected mercurial lib: %s\n'
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   812
                         '         (expected %s)\n'
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   813
                         % (verb, actualhg, expecthg))
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   814
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   815
def runchildren(options, tests):
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   816
    if INST:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   817
        installhg(options)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   818
        _checkhglib("Testing")
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   819
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   820
    optcopy = dict(options.__dict__)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   821
    optcopy['jobs'] = 1
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   822
    del optcopy['blacklist']
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   823
    if optcopy['with_hg'] is None:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   824
        optcopy['with_hg'] = os.path.join(BINDIR, "hg")
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   825
    optcopy.pop('anycoverage', None)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   826
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   827
    opts = []
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   828
    for opt, value in optcopy.iteritems():
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   829
        name = '--' + opt.replace('_', '-')
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   830
        if value is True:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   831
            opts.append(name)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   832
        elif value is not None:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   833
            opts.append(name + '=' + str(value))
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   834
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   835
    tests.reverse()
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   836
    jobs = [[] for j in xrange(options.jobs)]
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   837
    while tests:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   838
        for job in jobs:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   839
            if not tests:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   840
                break
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   841
            job.append(tests.pop())
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   842
    fps = {}
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   843
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   844
    for j, job in enumerate(jobs):
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   845
        if not job:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   846
            continue
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   847
        rfd, wfd = os.pipe()
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   848
        childopts = ['--child=%d' % wfd, '--port=%d' % (options.port + j * 3)]
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   849
        childtmp = os.path.join(HGTMP, 'child%d' % j)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   850
        childopts += ['--tmpdir', childtmp]
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   851
        cmdline = [PYTHON, sys.argv[0]] + opts + childopts + job
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   852
        vlog(' '.join(cmdline))
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   853
        fps[os.spawnvp(os.P_NOWAIT, cmdline[0], cmdline)] = os.fdopen(rfd, 'r')
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   854
        os.close(wfd)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   855
    signal.signal(signal.SIGINT, signal.SIG_IGN)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   856
    failures = 0
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   857
    tested, skipped, failed = 0, 0, 0
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   858
    skips = []
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   859
    fails = []
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   860
    while fps:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   861
        pid, status = os.wait()
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   862
        fp = fps.pop(pid)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   863
        l = fp.read().splitlines()
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   864
        try:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   865
            test, skip, fail = map(int, l[:3])
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   866
        except ValueError:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   867
            test, skip, fail = 0, 0, 0
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   868
        split = -fail or len(l)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   869
        for s in l[3:split]:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   870
            skips.append(s.split(" ", 1))
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   871
        for s in l[split:]:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   872
            fails.append(s.split(" ", 1))
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   873
        tested += test
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   874
        skipped += skip
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   875
        failed += fail
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   876
        vlog('pid %d exited, status %d' % (pid, status))
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   877
        failures |= status
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   878
    print
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   879
    if not options.noskips:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   880
        for s in skips:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   881
            print "Skipped %s: %s" % (s[0], s[1])
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   882
    for s in fails:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   883
        print "Failed %s: %s" % (s[0], s[1])
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   884
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   885
    _checkhglib("Tested")
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   886
    print "# Ran %d tests, %d skipped, %d failed." % (
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   887
        tested, skipped, failed)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   888
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   889
    if options.anycoverage:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   890
        outputcoverage(options)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   891
    sys.exit(failures != 0)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   892
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   893
def runtests(options, tests):
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   894
    global DAEMON_PIDS, HGRCPATH
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   895
    DAEMON_PIDS = os.environ["DAEMON_PIDS"] = os.path.join(HGTMP, 'daemon.pids')
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   896
    HGRCPATH = os.environ["HGRCPATH"] = os.path.join(HGTMP, '.hgrc')
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   897
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   898
    try:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   899
        if INST:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   900
            installhg(options)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   901
            _checkhglib("Testing")
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   902
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   903
        if options.timeout > 0:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   904
            try:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   905
                signal.signal(signal.SIGALRM, alarmed)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   906
                vlog('# Running each test with %d second timeout' %
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   907
                     options.timeout)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   908
            except AttributeError:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   909
                print 'WARNING: cannot run tests with timeouts'
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   910
                options.timeout = 0
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   911
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   912
        tested = 0
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   913
        failed = 0
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   914
        skipped = 0
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   915
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   916
        if options.restart:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   917
            orig = list(tests)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   918
            while tests:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   919
                if os.path.exists(tests[0] + ".err"):
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   920
                    break
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   921
                tests.pop(0)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   922
            if not tests:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   923
                print "running all tests"
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   924
                tests = orig
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   925
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   926
        skips = []
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   927
        fails = []
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   928
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   929
        for test in tests:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   930
            if options.blacklist:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   931
                filename = options.blacklist.get(test)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   932
                if filename is not None:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   933
                    skips.append((test, "blacklisted (%s)" % filename))
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   934
                    skipped += 1
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   935
                    continue
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   936
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   937
            if options.retest and not os.path.exists(test + ".err"):
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   938
                skipped += 1
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   939
                continue
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   940
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   941
            if options.keywords:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   942
                fp = open(test)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   943
                t = fp.read().lower() + test.lower()
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   944
                fp.close()
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   945
                for k in options.keywords.lower().split():
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   946
                    if k in t:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   947
                        break
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   948
                else:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   949
                    skipped += 1
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   950
                    continue
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   951
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   952
            ret = runone(options, test, skips, fails)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   953
            if ret is None:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   954
                skipped += 1
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   955
            elif not ret:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   956
                if options.interactive:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   957
                    print "Accept this change? [n] ",
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   958
                    answer = sys.stdin.readline().strip()
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   959
                    if answer.lower() in "y yes".split():
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   960
                        if test.endswith(".t"):
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   961
                            rename(test + ".err", test)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   962
                        else:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   963
                            rename(test + ".err", test + ".out")
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   964
                        tested += 1
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   965
                        fails.pop()
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   966
                        continue
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   967
                failed += 1
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   968
                if options.first:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   969
                    break
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   970
            tested += 1
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   971
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   972
        if options.child:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   973
            fp = os.fdopen(options.child, 'w')
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   974
            fp.write('%d\n%d\n%d\n' % (tested, skipped, failed))
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   975
            for s in skips:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   976
                fp.write("%s %s\n" % s)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   977
            for s in fails:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   978
                fp.write("%s %s\n" % s)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   979
            fp.close()
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   980
        else:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   981
            print
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   982
            for s in skips:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   983
                print "Skipped %s: %s" % s
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   984
            for s in fails:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   985
                print "Failed %s: %s" % s
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   986
            _checkhglib("Tested")
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   987
            print "# Ran %d tests, %d skipped, %d failed." % (
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   988
                tested, skipped, failed)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   989
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   990
        if options.anycoverage:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   991
            outputcoverage(options)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   992
    except KeyboardInterrupt:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   993
        failed = True
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   994
        print "\ninterrupted!"
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   995
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   996
    if failed:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   997
        sys.exit(1)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   998
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
   999
def main():
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1000
    (options, args) = parseargs()
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1001
    if not options.child:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1002
        os.umask(022)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1003
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1004
        checktools()
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1005
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1006
    if len(args) == 0:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1007
        args = os.listdir(".")
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1008
    args.sort()
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1009
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1010
    tests = []
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1011
    skipped = []
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1012
    for test in args:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1013
        if (test.startswith("test-") and '~' not in test and
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1014
            ('.' not in test or test.endswith('.py') or
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1015
             test.endswith('.bat') or test.endswith('.t'))):
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1016
            if not os.path.exists(test):
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1017
                skipped.append(test)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1018
            else:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1019
                tests.append(test)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1020
    if not tests:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1021
        for test in skipped:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1022
            print 'Skipped %s: does not exist' % test
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1023
        print "# Ran 0 tests, %d skipped, 0 failed." % len(skipped)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1024
        return
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1025
    tests = tests + skipped
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1026
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1027
    # Reset some environment variables to well-known values so that
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1028
    # the tests produce repeatable output.
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1029
    os.environ['LANG'] = os.environ['LC_ALL'] = os.environ['LANGUAGE'] = 'C'
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1030
    os.environ['TZ'] = 'GMT'
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1031
    os.environ["EMAIL"] = "Foo Bar <foo.bar@example.com>"
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1032
    os.environ['CDPATH'] = ''
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1033
    os.environ['COLUMNS'] = '80'
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1034
    os.environ['GREP_OPTIONS'] = ''
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1035
    os.environ['http_proxy'] = ''
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1036
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1037
    # unset env related to hooks
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1038
    for k in os.environ.keys():
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1039
        if k.startswith('HG_'):
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1040
            # can't remove on solaris
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1041
            os.environ[k] = ''
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1042
            del os.environ[k]
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1043
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1044
    global TESTDIR, HGTMP, INST, BINDIR, PYTHONDIR, COVERAGE_FILE
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1045
    TESTDIR = os.environ["TESTDIR"] = os.getcwd()
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1046
    if options.tmpdir:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1047
        options.keep_tmpdir = True
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1048
        tmpdir = options.tmpdir
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1049
        if os.path.exists(tmpdir):
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1050
            # Meaning of tmpdir has changed since 1.3: we used to create
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1051
            # HGTMP inside tmpdir; now HGTMP is tmpdir.  So fail if
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1052
            # tmpdir already exists.
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1053
            sys.exit("error: temp dir %r already exists" % tmpdir)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1054
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1055
            # Automatically removing tmpdir sounds convenient, but could
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1056
            # really annoy anyone in the habit of using "--tmpdir=/tmp"
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1057
            # or "--tmpdir=$HOME".
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1058
            #vlog("# Removing temp dir", tmpdir)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1059
            #shutil.rmtree(tmpdir)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1060
        os.makedirs(tmpdir)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1061
    else:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1062
        tmpdir = tempfile.mkdtemp('', 'hgtests.')
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1063
    HGTMP = os.environ['HGTMP'] = os.path.realpath(tmpdir)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1064
    DAEMON_PIDS = None
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1065
    HGRCPATH = None
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1066
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1067
    os.environ["HGEDITOR"] = sys.executable + ' -c "import sys; sys.exit(0)"'
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1068
    os.environ["HGMERGE"] = "internal:merge"
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1069
    os.environ["HGUSER"]   = "test"
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1070
    os.environ["HGENCODING"] = "ascii"
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1071
    os.environ["HGENCODINGMODE"] = "strict"
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1072
    os.environ["HGPORT"] = str(options.port)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1073
    os.environ["HGPORT1"] = str(options.port + 1)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1074
    os.environ["HGPORT2"] = str(options.port + 2)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1075
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1076
    if options.with_hg:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1077
        INST = None
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1078
        BINDIR = os.path.dirname(os.path.realpath(options.with_hg))
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1079
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1080
        # This looks redundant with how Python initializes sys.path from
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1081
        # the location of the script being executed.  Needed because the
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1082
        # "hg" specified by --with-hg is not the only Python script
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1083
        # executed in the test suite that needs to import 'mercurial'
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1084
        # ... which means it's not really redundant at all.
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1085
        PYTHONDIR = BINDIR
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1086
    else:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1087
        INST = os.path.join(HGTMP, "install")
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1088
        BINDIR = os.environ["BINDIR"] = os.path.join(INST, "bin")
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1089
        PYTHONDIR = os.path.join(INST, "lib", "python")
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1090
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1091
    os.environ["BINDIR"] = BINDIR
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1092
    os.environ["PYTHON"] = PYTHON
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1093
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1094
    if not options.child:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1095
        path = [BINDIR] + os.environ["PATH"].split(os.pathsep)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1096
        os.environ["PATH"] = os.pathsep.join(path)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1097
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1098
        # Include TESTDIR in PYTHONPATH so that out-of-tree extensions
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1099
        # can run .../tests/run-tests.py test-foo where test-foo
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1100
        # adds an extension to HGRC
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1101
        pypath = [PYTHONDIR, TESTDIR]
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1102
        # We have to augment PYTHONPATH, rather than simply replacing
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1103
        # it, in case external libraries are only available via current
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1104
        # PYTHONPATH.  (In particular, the Subversion bindings on OS X
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1105
        # are in /opt/subversion.)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1106
        oldpypath = os.environ.get(IMPL_PATH)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1107
        if oldpypath:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1108
            pypath.append(oldpypath)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1109
        os.environ[IMPL_PATH] = os.pathsep.join(pypath)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1110
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1111
    COVERAGE_FILE = os.path.join(TESTDIR, ".coverage")
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1112
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1113
    vlog("# Using TESTDIR", TESTDIR)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1114
    vlog("# Using HGTMP", HGTMP)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1115
    vlog("# Using PATH", os.environ["PATH"])
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1116
    vlog("# Using", IMPL_PATH, os.environ[IMPL_PATH])
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1117
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1118
    try:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1119
        if len(tests) > 1 and options.jobs > 1:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1120
            runchildren(options, tests)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1121
        else:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1122
            runtests(options, tests)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1123
    finally:
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1124
        time.sleep(1)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1125
        cleanup(options)
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1126
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1127
if __name__ == '__main__':
bbeef801409c minimalistic state concept.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
  1128
    main()