tests/run-tests.py
author Augie Fackler <raf@durin42.com>
Wed, 30 Sep 2015 18:05:27 -0400
changeset 1863 29fc43f24948
parent 1839 1bc5e62fc0c7
permissions -rwxr-xr-x
topic: fix missing error import
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
1839
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
     1
#!/usr/bin/env python
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
     2
#
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
     3
# run-tests.py - Run a set of tests on Mercurial
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
     4
#
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
     5
# Copyright 2006 Matt Mackall <mpm@selenic.com>
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
     6
#
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
     7
# This software may be used and distributed according to the terms of the
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
     8
# GNU General Public License version 2 or any later version.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
     9
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    10
# Modifying this script is tricky because it has many modes:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    11
#   - serial (default) vs parallel (-jN, N > 1)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    12
#   - no coverage (default) vs coverage (-c, -C, -s)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    13
#   - temp install (default) vs specific hg script (--with-hg, --local)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    14
#   - tests are a mix of shell scripts and Python scripts
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    15
#
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    16
# If you change this script, it is recommended that you ensure you
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    17
# haven't broken it by running it in various modes with a representative
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    18
# sample of test scripts.  For example:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    19
#
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    20
#  1) serial, no coverage, temp install:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    21
#      ./run-tests.py test-s*
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    22
#  2) serial, no coverage, local hg:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    23
#      ./run-tests.py --local test-s*
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    24
#  3) serial, coverage, temp install:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    25
#      ./run-tests.py -c test-s*
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    26
#  4) serial, coverage, local hg:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    27
#      ./run-tests.py -c --local test-s*      # unsupported
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    28
#  5) parallel, no coverage, temp install:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    29
#      ./run-tests.py -j2 test-s*
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    30
#  6) parallel, no coverage, local hg:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    31
#      ./run-tests.py -j2 --local test-s*
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    32
#  7) parallel, coverage, temp install:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    33
#      ./run-tests.py -j2 -c test-s*          # currently broken
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    34
#  8) parallel, coverage, local install:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    35
#      ./run-tests.py -j2 -c --local test-s*  # unsupported (and broken)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    36
#  9) parallel, custom tmp dir:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    37
#      ./run-tests.py -j2 --tmpdir /tmp/myhgtests
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    38
#
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    39
# (You could use any subset of the tests: test-s* happens to match
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    40
# enough that it's worth doing parallel runs, few enough that it
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    41
# completes fairly quickly, includes both shell and Python scripts, and
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    42
# includes some scripts that run daemon processes.)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    43
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    44
from __future__ import print_function
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    45
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    46
from distutils import version
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    47
import difflib
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    48
import errno
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    49
import optparse
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    50
import os
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    51
import shutil
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    52
import subprocess
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    53
import signal
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    54
import socket
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    55
import sys
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    56
import tempfile
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    57
import time
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    58
import random
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    59
import re
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    60
import threading
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    61
import killdaemons as killmod
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    62
try:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    63
    import Queue as queue
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    64
except ImportError:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    65
    import queue
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    66
from xml.dom import minidom
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    67
import unittest
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    68
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    69
osenvironb = getattr(os, 'environb', os.environ)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    70
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    71
try:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    72
    import json
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    73
except ImportError:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    74
    try:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    75
        import simplejson as json
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    76
    except ImportError:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    77
        json = None
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    78
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    79
processlock = threading.Lock()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    80
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    81
if sys.version_info > (3, 5, 0):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    82
    PYTHON3 = True
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    83
    xrange = range # we use xrange in one place, and we'd rather not use range
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    84
    def _bytespath(p):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    85
        return p.encode('utf-8')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    86
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    87
    def _strpath(p):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    88
        return p.decode('utf-8')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    89
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    90
elif sys.version_info >= (3, 0, 0):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    91
    print('%s is only supported on Python 3.5+ and 2.6-2.7, not %s' %
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    92
          (sys.argv[0], '.'.join(str(v) for v in sys.version_info[:3])))
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    93
    sys.exit(70) # EX_SOFTWARE from `man 3 sysexit`
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    94
else:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    95
    PYTHON3 = False
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    96
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    97
    # In python 2.x, path operations are generally done using
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    98
    # bytestrings by default, so we don't have to do any extra
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
    99
    # fiddling there. We define the wrapper functions anyway just to
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   100
    # help keep code consistent between platforms.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   101
    def _bytespath(p):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   102
        return p
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   103
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   104
    _strpath = _bytespath
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   105
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   106
# For Windows support
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   107
wifexited = getattr(os, "WIFEXITED", lambda x: False)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   108
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   109
def checkportisavailable(port):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   110
    """return true if a port seems free to bind on localhost"""
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   111
    try:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   112
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   113
        s.bind(('localhost', port))
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   114
        s.close()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   115
        return True
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   116
    except socket.error as exc:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   117
        if not exc.errno == errno.EADDRINUSE:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   118
            raise
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   119
        return False
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   120
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   121
closefds = os.name == 'posix'
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   122
def Popen4(cmd, wd, timeout, env=None):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   123
    processlock.acquire()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   124
    p = subprocess.Popen(cmd, shell=True, bufsize=-1, cwd=wd, env=env,
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   125
                         close_fds=closefds,
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   126
                         stdin=subprocess.PIPE, stdout=subprocess.PIPE,
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   127
                         stderr=subprocess.STDOUT)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   128
    processlock.release()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   129
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   130
    p.fromchild = p.stdout
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   131
    p.tochild = p.stdin
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   132
    p.childerr = p.stderr
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   133
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   134
    p.timeout = False
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   135
    if timeout:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   136
        def t():
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   137
            start = time.time()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   138
            while time.time() - start < timeout and p.returncode is None:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   139
                time.sleep(.1)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   140
            p.timeout = True
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   141
            if p.returncode is None:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   142
                terminate(p)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   143
        threading.Thread(target=t).start()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   144
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   145
    return p
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   146
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   147
PYTHON = _bytespath(sys.executable.replace('\\', '/'))
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   148
IMPL_PATH = b'PYTHONPATH'
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   149
if 'java' in sys.platform:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   150
    IMPL_PATH = b'JYTHONPATH'
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   151
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   152
defaults = {
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   153
    'jobs': ('HGTEST_JOBS', 1),
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   154
    'timeout': ('HGTEST_TIMEOUT', 180),
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   155
    'port': ('HGTEST_PORT', 20059),
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   156
    'shell': ('HGTEST_SHELL', 'sh'),
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   157
}
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   158
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   159
def parselistfiles(files, listtype, warn=True):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   160
    entries = dict()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   161
    for filename in files:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   162
        try:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   163
            path = os.path.expanduser(os.path.expandvars(filename))
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   164
            f = open(path, "rb")
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   165
        except IOError as err:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   166
            if err.errno != errno.ENOENT:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   167
                raise
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   168
            if warn:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   169
                print("warning: no such %s file: %s" % (listtype, filename))
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   170
            continue
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   171
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   172
        for line in f.readlines():
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   173
            line = line.split(b'#', 1)[0].strip()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   174
            if line:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   175
                entries[line] = filename
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   176
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   177
        f.close()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   178
    return entries
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   179
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   180
def getparser():
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   181
    """Obtain the OptionParser used by the CLI."""
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   182
    parser = optparse.OptionParser("%prog [options] [tests]")
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   183
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   184
    # keep these sorted
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   185
    parser.add_option("--blacklist", action="append",
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   186
        help="skip tests listed in the specified blacklist file")
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   187
    parser.add_option("--whitelist", action="append",
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   188
        help="always run tests listed in the specified whitelist file")
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   189
    parser.add_option("--changed", type="string",
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   190
        help="run tests that are changed in parent rev or working directory")
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   191
    parser.add_option("-C", "--annotate", action="store_true",
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   192
        help="output files annotated with coverage")
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   193
    parser.add_option("-c", "--cover", action="store_true",
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   194
        help="print a test coverage report")
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   195
    parser.add_option("-d", "--debug", action="store_true",
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   196
        help="debug mode: write output of test scripts to console"
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   197
             " rather than capturing and diffing it (disables timeout)")
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   198
    parser.add_option("-f", "--first", action="store_true",
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   199
        help="exit on the first test failure")
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   200
    parser.add_option("-H", "--htmlcov", action="store_true",
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   201
        help="create an HTML report of the coverage of the files")
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   202
    parser.add_option("-i", "--interactive", action="store_true",
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   203
        help="prompt to accept changed output")
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   204
    parser.add_option("-j", "--jobs", type="int",
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   205
        help="number of jobs to run in parallel"
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   206
             " (default: $%s or %d)" % defaults['jobs'])
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   207
    parser.add_option("--keep-tmpdir", action="store_true",
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   208
        help="keep temporary directory after running tests")
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   209
    parser.add_option("-k", "--keywords",
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   210
        help="run tests matching keywords")
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   211
    parser.add_option("-l", "--local", action="store_true",
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   212
        help="shortcut for --with-hg=<testdir>/../hg")
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   213
    parser.add_option("--loop", action="store_true",
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   214
        help="loop tests repeatedly")
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   215
    parser.add_option("--runs-per-test", type="int", dest="runs_per_test",
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   216
        help="run each test N times (default=1)", default=1)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   217
    parser.add_option("-n", "--nodiff", action="store_true",
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   218
        help="skip showing test changes")
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   219
    parser.add_option("-p", "--port", type="int",
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   220
        help="port on which servers should listen"
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   221
             " (default: $%s or %d)" % defaults['port'])
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   222
    parser.add_option("--compiler", type="string",
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   223
        help="compiler to build with")
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   224
    parser.add_option("--pure", action="store_true",
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   225
        help="use pure Python code instead of C extensions")
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   226
    parser.add_option("-R", "--restart", action="store_true",
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   227
        help="restart at last error")
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   228
    parser.add_option("-r", "--retest", action="store_true",
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   229
        help="retest failed tests")
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   230
    parser.add_option("-S", "--noskips", action="store_true",
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   231
        help="don't report skip tests verbosely")
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   232
    parser.add_option("--shell", type="string",
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   233
        help="shell to use (default: $%s or %s)" % defaults['shell'])
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   234
    parser.add_option("-t", "--timeout", type="int",
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   235
        help="kill errant tests after TIMEOUT seconds"
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   236
             " (default: $%s or %d)" % defaults['timeout'])
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   237
    parser.add_option("--time", action="store_true",
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   238
        help="time how long each test takes")
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   239
    parser.add_option("--json", action="store_true",
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   240
                      help="store test result data in 'report.json' file")
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   241
    parser.add_option("--tmpdir", type="string",
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   242
        help="run tests in the given temporary directory"
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   243
             " (implies --keep-tmpdir)")
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   244
    parser.add_option("-v", "--verbose", action="store_true",
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   245
        help="output verbose messages")
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   246
    parser.add_option("--xunit", type="string",
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   247
                      help="record xunit results at specified path")
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   248
    parser.add_option("--view", type="string",
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   249
        help="external diff viewer")
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   250
    parser.add_option("--with-hg", type="string",
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   251
        metavar="HG",
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   252
        help="test using specified hg script rather than a "
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   253
             "temporary installation")
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   254
    parser.add_option("-3", "--py3k-warnings", action="store_true",
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   255
        help="enable Py3k warnings on Python 2.6+")
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   256
    parser.add_option('--extra-config-opt', action="append",
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   257
                      help='set the given config opt in the test hgrc')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   258
    parser.add_option('--random', action="store_true",
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   259
                      help='run tests in random order')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   260
    parser.add_option('--profile-runner', action='store_true',
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   261
                      help='run statprof on run-tests')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   262
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   263
    for option, (envvar, default) in defaults.items():
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   264
        defaults[option] = type(default)(os.environ.get(envvar, default))
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   265
    parser.set_defaults(**defaults)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   266
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   267
    return parser
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   268
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   269
def parseargs(args, parser):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   270
    """Parse arguments with our OptionParser and validate results."""
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   271
    (options, args) = parser.parse_args(args)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   272
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   273
    # jython is always pure
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   274
    if 'java' in sys.platform or '__pypy__' in sys.modules:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   275
        options.pure = True
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   276
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   277
    if options.with_hg:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   278
        options.with_hg = os.path.expanduser(options.with_hg)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   279
        if not (os.path.isfile(options.with_hg) and
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   280
                os.access(options.with_hg, os.X_OK)):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   281
            parser.error('--with-hg must specify an executable hg script')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   282
        if not os.path.basename(options.with_hg) == 'hg':
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   283
            sys.stderr.write('warning: --with-hg should specify an hg script\n')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   284
    if options.local:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   285
        testdir = os.path.dirname(_bytespath(os.path.realpath(sys.argv[0])))
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   286
        hgbin = os.path.join(os.path.dirname(testdir), b'hg')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   287
        if os.name != 'nt' and not os.access(hgbin, os.X_OK):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   288
            parser.error('--local specified, but %r not found or not executable'
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   289
                         % hgbin)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   290
        options.with_hg = hgbin
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   291
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   292
    options.anycoverage = options.cover or options.annotate or options.htmlcov
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   293
    if options.anycoverage:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   294
        try:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   295
            import coverage
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   296
            covver = version.StrictVersion(coverage.__version__).version
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   297
            if covver < (3, 3):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   298
                parser.error('coverage options require coverage 3.3 or later')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   299
        except ImportError:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   300
            parser.error('coverage options now require the coverage package')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   301
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   302
    if options.anycoverage and options.local:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   303
        # this needs some path mangling somewhere, I guess
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   304
        parser.error("sorry, coverage options do not work when --local "
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   305
                     "is specified")
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   306
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   307
    if options.anycoverage and options.with_hg:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   308
        parser.error("sorry, coverage options do not work when --with-hg "
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   309
                     "is specified")
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   310
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   311
    global verbose
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   312
    if options.verbose:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   313
        verbose = ''
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   314
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   315
    if options.tmpdir:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   316
        options.tmpdir = os.path.expanduser(options.tmpdir)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   317
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   318
    if options.jobs < 1:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   319
        parser.error('--jobs must be positive')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   320
    if options.interactive and options.debug:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   321
        parser.error("-i/--interactive and -d/--debug are incompatible")
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   322
    if options.debug:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   323
        if options.timeout != defaults['timeout']:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   324
            sys.stderr.write(
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   325
                'warning: --timeout option ignored with --debug\n')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   326
        options.timeout = 0
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   327
    if options.py3k_warnings:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   328
        if PYTHON3:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   329
            parser.error(
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   330
                '--py3k-warnings can only be used on Python 2.6 and 2.7')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   331
    if options.blacklist:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   332
        options.blacklist = parselistfiles(options.blacklist, 'blacklist')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   333
    if options.whitelist:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   334
        options.whitelisted = parselistfiles(options.whitelist, 'whitelist')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   335
    else:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   336
        options.whitelisted = {}
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   337
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   338
    return (options, args)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   339
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   340
def rename(src, dst):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   341
    """Like os.rename(), trade atomicity and opened files friendliness
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   342
    for existing destination support.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   343
    """
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   344
    shutil.copy(src, dst)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   345
    os.remove(src)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   346
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   347
_unified_diff = difflib.unified_diff
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   348
if PYTHON3:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   349
    import functools
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   350
    _unified_diff = functools.partial(difflib.diff_bytes, difflib.unified_diff)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   351
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   352
def getdiff(expected, output, ref, err):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   353
    servefail = False
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   354
    lines = []
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   355
    for line in _unified_diff(expected, output, ref, err):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   356
        if line.startswith(b'+++') or line.startswith(b'---'):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   357
            line = line.replace(b'\\', b'/')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   358
            if line.endswith(b' \n'):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   359
                line = line[:-2] + b'\n'
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   360
        lines.append(line)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   361
        if not servefail and line.startswith(
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   362
                             b'+  abort: child process failed to start'):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   363
            servefail = True
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   364
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   365
    return servefail, lines
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   366
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   367
verbose = False
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   368
def vlog(*msg):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   369
    """Log only when in verbose mode."""
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   370
    if verbose is False:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   371
        return
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   372
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   373
    return log(*msg)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   374
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   375
# Bytes that break XML even in a CDATA block: control characters 0-31
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   376
# sans \t, \n and \r
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   377
CDATA_EVIL = re.compile(br"[\000-\010\013\014\016-\037]")
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   378
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   379
def cdatasafe(data):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   380
    """Make a string safe to include in a CDATA block.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   381
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   382
    Certain control characters are illegal in a CDATA block, and
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   383
    there's no way to include a ]]> in a CDATA either. This function
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   384
    replaces illegal bytes with ? and adds a space between the ]] so
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   385
    that it won't break the CDATA block.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   386
    """
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   387
    return CDATA_EVIL.sub(b'?', data).replace(b']]>', b'] ]>')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   388
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   389
def log(*msg):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   390
    """Log something to stdout.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   391
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   392
    Arguments are strings to print.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   393
    """
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   394
    with iolock:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   395
        if verbose:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   396
            print(verbose, end=' ')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   397
        for m in msg:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   398
            print(m, end=' ')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   399
        print()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   400
        sys.stdout.flush()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   401
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   402
def terminate(proc):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   403
    """Terminate subprocess (with fallback for Python versions < 2.6)"""
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   404
    vlog('# Terminating process %d' % proc.pid)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   405
    try:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   406
        getattr(proc, 'terminate', lambda : os.kill(proc.pid, signal.SIGTERM))()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   407
    except OSError:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   408
        pass
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   409
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   410
def killdaemons(pidfile):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   411
    return killmod.killdaemons(pidfile, tryhard=False, remove=True,
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   412
                               logfn=vlog)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   413
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   414
class Test(unittest.TestCase):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   415
    """Encapsulates a single, runnable test.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   416
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   417
    While this class conforms to the unittest.TestCase API, it differs in that
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   418
    instances need to be instantiated manually. (Typically, unittest.TestCase
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   419
    classes are instantiated automatically by scanning modules.)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   420
    """
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   421
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   422
    # Status code reserved for skipped tests (used by hghave).
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   423
    SKIPPED_STATUS = 80
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   424
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   425
    def __init__(self, path, tmpdir, keeptmpdir=False,
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   426
                 debug=False,
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   427
                 timeout=defaults['timeout'],
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   428
                 startport=defaults['port'], extraconfigopts=None,
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   429
                 py3kwarnings=False, shell=None):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   430
        """Create a test from parameters.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   431
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   432
        path is the full path to the file defining the test.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   433
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   434
        tmpdir is the main temporary directory to use for this test.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   435
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   436
        keeptmpdir determines whether to keep the test's temporary directory
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   437
        after execution. It defaults to removal (False).
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   438
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   439
        debug mode will make the test execute verbosely, with unfiltered
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   440
        output.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   441
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   442
        timeout controls the maximum run time of the test. It is ignored when
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   443
        debug is True.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   444
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   445
        startport controls the starting port number to use for this test. Each
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   446
        test will reserve 3 port numbers for execution. It is the caller's
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   447
        responsibility to allocate a non-overlapping port range to Test
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   448
        instances.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   449
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   450
        extraconfigopts is an iterable of extra hgrc config options. Values
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   451
        must have the form "key=value" (something understood by hgrc). Values
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   452
        of the form "foo.key=value" will result in "[foo] key=value".
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   453
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   454
        py3kwarnings enables Py3k warnings.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   455
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   456
        shell is the shell to execute tests in.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   457
        """
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   458
        self.path = path
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   459
        self.bname = os.path.basename(path)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   460
        self.name = _strpath(self.bname)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   461
        self._testdir = os.path.dirname(path)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   462
        self.errpath = os.path.join(self._testdir, b'%s.err' % self.bname)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   463
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   464
        self._threadtmp = tmpdir
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   465
        self._keeptmpdir = keeptmpdir
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   466
        self._debug = debug
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   467
        self._timeout = timeout
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   468
        self._startport = startport
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   469
        self._extraconfigopts = extraconfigopts or []
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   470
        self._py3kwarnings = py3kwarnings
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   471
        self._shell = _bytespath(shell)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   472
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   473
        self._aborted = False
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   474
        self._daemonpids = []
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   475
        self._finished = None
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   476
        self._ret = None
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   477
        self._out = None
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   478
        self._skipped = None
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   479
        self._testtmp = None
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   480
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   481
        # If we're not in --debug mode and reference output file exists,
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   482
        # check test output against it.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   483
        if debug:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   484
            self._refout = None # to match "out is None"
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   485
        elif os.path.exists(self.refpath):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   486
            f = open(self.refpath, 'rb')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   487
            self._refout = f.read().splitlines(True)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   488
            f.close()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   489
        else:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   490
            self._refout = []
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   491
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   492
    # needed to get base class __repr__ running
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   493
    @property
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   494
    def _testMethodName(self):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   495
        return self.name
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   496
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   497
    def __str__(self):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   498
        return self.name
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   499
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   500
    def shortDescription(self):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   501
        return self.name
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   502
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   503
    def setUp(self):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   504
        """Tasks to perform before run()."""
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   505
        self._finished = False
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   506
        self._ret = None
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   507
        self._out = None
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   508
        self._skipped = None
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   509
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   510
        try:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   511
            os.mkdir(self._threadtmp)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   512
        except OSError as e:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   513
            if e.errno != errno.EEXIST:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   514
                raise
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   515
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   516
        self._testtmp = os.path.join(self._threadtmp,
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   517
                                     os.path.basename(self.path))
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   518
        os.mkdir(self._testtmp)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   519
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   520
        # Remove any previous output files.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   521
        if os.path.exists(self.errpath):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   522
            try:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   523
                os.remove(self.errpath)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   524
            except OSError as e:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   525
                # We might have raced another test to clean up a .err
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   526
                # file, so ignore ENOENT when removing a previous .err
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   527
                # file.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   528
                if e.errno != errno.ENOENT:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   529
                    raise
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   530
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   531
    def run(self, result):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   532
        """Run this test and report results against a TestResult instance."""
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   533
        # This function is extremely similar to unittest.TestCase.run(). Once
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   534
        # we require Python 2.7 (or at least its version of unittest), this
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   535
        # function can largely go away.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   536
        self._result = result
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   537
        result.startTest(self)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   538
        try:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   539
            try:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   540
                self.setUp()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   541
            except (KeyboardInterrupt, SystemExit):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   542
                self._aborted = True
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   543
                raise
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   544
            except Exception:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   545
                result.addError(self, sys.exc_info())
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   546
                return
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   547
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   548
            success = False
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   549
            try:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   550
                self.runTest()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   551
            except KeyboardInterrupt:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   552
                self._aborted = True
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   553
                raise
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   554
            except SkipTest as e:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   555
                result.addSkip(self, str(e))
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   556
                # The base class will have already counted this as a
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   557
                # test we "ran", but we want to exclude skipped tests
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   558
                # from those we count towards those run.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   559
                result.testsRun -= 1
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   560
            except IgnoreTest as e:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   561
                result.addIgnore(self, str(e))
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   562
                # As with skips, ignores also should be excluded from
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   563
                # the number of tests executed.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   564
                result.testsRun -= 1
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   565
            except WarnTest as e:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   566
                result.addWarn(self, str(e))
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   567
            except self.failureException as e:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   568
                # This differs from unittest in that we don't capture
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   569
                # the stack trace. This is for historical reasons and
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   570
                # this decision could be revisited in the future,
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   571
                # especially for PythonTest instances.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   572
                if result.addFailure(self, str(e)):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   573
                    success = True
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   574
            except Exception:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   575
                result.addError(self, sys.exc_info())
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   576
            else:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   577
                success = True
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   578
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   579
            try:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   580
                self.tearDown()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   581
            except (KeyboardInterrupt, SystemExit):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   582
                self._aborted = True
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   583
                raise
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   584
            except Exception:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   585
                result.addError(self, sys.exc_info())
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   586
                success = False
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   587
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   588
            if success:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   589
                result.addSuccess(self)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   590
        finally:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   591
            result.stopTest(self, interrupted=self._aborted)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   592
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   593
    def runTest(self):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   594
        """Run this test instance.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   595
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   596
        This will return a tuple describing the result of the test.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   597
        """
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   598
        env = self._getenv()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   599
        self._daemonpids.append(env['DAEMON_PIDS'])
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   600
        self._createhgrc(env['HGRCPATH'])
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   601
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   602
        vlog('# Test', self.name)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   603
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   604
        ret, out = self._run(env)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   605
        self._finished = True
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   606
        self._ret = ret
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   607
        self._out = out
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   608
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   609
        def describe(ret):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   610
            if ret < 0:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   611
                return 'killed by signal: %d' % -ret
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   612
            return 'returned error code %d' % ret
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   613
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   614
        self._skipped = False
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   615
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   616
        if ret == self.SKIPPED_STATUS:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   617
            if out is None: # Debug mode, nothing to parse.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   618
                missing = ['unknown']
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   619
                failed = None
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   620
            else:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   621
                missing, failed = TTest.parsehghaveoutput(out)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   622
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   623
            if not missing:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   624
                missing = ['skipped']
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   625
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   626
            if failed:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   627
                self.fail('hg have failed checking for %s' % failed[-1])
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   628
            else:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   629
                self._skipped = True
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   630
                raise SkipTest(missing[-1])
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   631
        elif ret == 'timeout':
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   632
            self.fail('timed out')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   633
        elif ret is False:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   634
            raise WarnTest('no result code from test')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   635
        elif out != self._refout:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   636
            # Diff generation may rely on written .err file.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   637
            if (ret != 0 or out != self._refout) and not self._skipped \
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   638
                and not self._debug:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   639
                f = open(self.errpath, 'wb')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   640
                for line in out:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   641
                    f.write(line)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   642
                f.close()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   643
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   644
            # The result object handles diff calculation for us.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   645
            if self._result.addOutputMismatch(self, ret, out, self._refout):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   646
                # change was accepted, skip failing
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   647
                return
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   648
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   649
            if ret:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   650
                msg = 'output changed and ' + describe(ret)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   651
            else:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   652
                msg = 'output changed'
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   653
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   654
            self.fail(msg)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   655
        elif ret:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   656
            self.fail(describe(ret))
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   657
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   658
    def tearDown(self):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   659
        """Tasks to perform after run()."""
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   660
        for entry in self._daemonpids:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   661
            killdaemons(entry)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   662
        self._daemonpids = []
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   663
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   664
        if not self._keeptmpdir:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   665
            shutil.rmtree(self._testtmp, True)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   666
            shutil.rmtree(self._threadtmp, True)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   667
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   668
        if (self._ret != 0 or self._out != self._refout) and not self._skipped \
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   669
            and not self._debug and self._out:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   670
            f = open(self.errpath, 'wb')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   671
            for line in self._out:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   672
                f.write(line)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   673
            f.close()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   674
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   675
        vlog("# Ret was:", self._ret, '(%s)' % self.name)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   676
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   677
    def _run(self, env):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   678
        # This should be implemented in child classes to run tests.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   679
        raise SkipTest('unknown test type')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   680
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   681
    def abort(self):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   682
        """Terminate execution of this test."""
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   683
        self._aborted = True
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   684
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   685
    def _getreplacements(self):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   686
        """Obtain a mapping of text replacements to apply to test output.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   687
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   688
        Test output needs to be normalized so it can be compared to expected
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   689
        output. This function defines how some of that normalization will
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   690
        occur.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   691
        """
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   692
        r = [
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   693
            (br':%d\b' % self._startport, b':$HGPORT'),
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   694
            (br':%d\b' % (self._startport + 1), b':$HGPORT1'),
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   695
            (br':%d\b' % (self._startport + 2), b':$HGPORT2'),
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   696
            (br'(?m)^(saved backup bundle to .*\.hg)( \(glob\))?$',
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   697
             br'\1 (glob)'),
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   698
            ]
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   699
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   700
        if os.name == 'nt':
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   701
            r.append(
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   702
                (b''.join(c.isalpha() and b'[%s%s]' % (c.lower(), c.upper()) or
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   703
                    c in b'/\\' and br'[/\\]' or c.isdigit() and c or b'\\' + c
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   704
                    for c in self._testtmp), b'$TESTTMP'))
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   705
        else:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   706
            r.append((re.escape(self._testtmp), b'$TESTTMP'))
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   707
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   708
        return r
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   709
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   710
    def _getenv(self):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   711
        """Obtain environment variables to use during test execution."""
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   712
        env = os.environ.copy()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   713
        env['TESTTMP'] = self._testtmp
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   714
        env['HOME'] = self._testtmp
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   715
        env["HGPORT"] = str(self._startport)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   716
        env["HGPORT1"] = str(self._startport + 1)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   717
        env["HGPORT2"] = str(self._startport + 2)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   718
        env["HGRCPATH"] = os.path.join(self._threadtmp, b'.hgrc')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   719
        env["DAEMON_PIDS"] = os.path.join(self._threadtmp, b'daemon.pids')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   720
        env["HGEDITOR"] = ('"' + sys.executable + '"'
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   721
                           + ' -c "import sys; sys.exit(0)"')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   722
        env["HGMERGE"] = "internal:merge"
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   723
        env["HGUSER"]   = "test"
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   724
        env["HGENCODING"] = "ascii"
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   725
        env["HGENCODINGMODE"] = "strict"
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   726
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   727
        # Reset some environment variables to well-known values so that
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   728
        # the tests produce repeatable output.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   729
        env['LANG'] = env['LC_ALL'] = env['LANGUAGE'] = 'C'
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   730
        env['TZ'] = 'GMT'
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   731
        env["EMAIL"] = "Foo Bar <foo.bar@example.com>"
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   732
        env['COLUMNS'] = '80'
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   733
        env['TERM'] = 'xterm'
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   734
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   735
        for k in ('HG HGPROF CDPATH GREP_OPTIONS http_proxy no_proxy ' +
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   736
                  'NO_PROXY').split():
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   737
            if k in env:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   738
                del env[k]
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   739
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   740
        # unset env related to hooks
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   741
        for k in env.keys():
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   742
            if k.startswith('HG_'):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   743
                del env[k]
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   744
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   745
        return env
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   746
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   747
    def _createhgrc(self, path):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   748
        """Create an hgrc file for this test."""
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   749
        hgrc = open(path, 'wb')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   750
        hgrc.write(b'[ui]\n')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   751
        hgrc.write(b'slash = True\n')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   752
        hgrc.write(b'interactive = False\n')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   753
        hgrc.write(b'mergemarkers = detailed\n')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   754
        hgrc.write(b'promptecho = True\n')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   755
        hgrc.write(b'[defaults]\n')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   756
        hgrc.write(b'backout = -d "0 0"\n')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   757
        hgrc.write(b'commit = -d "0 0"\n')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   758
        hgrc.write(b'shelve = --date "0 0"\n')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   759
        hgrc.write(b'tag = -d "0 0"\n')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   760
        hgrc.write(b'[devel]\n')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   761
        hgrc.write(b'all = true\n')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   762
        hgrc.write(b'[largefiles]\n')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   763
        hgrc.write(b'usercache = %s\n' %
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   764
                   (os.path.join(self._testtmp, b'.cache/largefiles')))
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   765
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   766
        for opt in self._extraconfigopts:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   767
            section, key = opt.split('.', 1)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   768
            assert '=' in key, ('extra config opt %s must '
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   769
                                'have an = for assignment' % opt)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   770
            hgrc.write(b'[%s]\n%s\n' % (section, key))
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   771
        hgrc.close()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   772
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   773
    def fail(self, msg):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   774
        # unittest differentiates between errored and failed.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   775
        # Failed is denoted by AssertionError (by default at least).
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   776
        raise AssertionError(msg)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   777
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   778
    def _runcommand(self, cmd, env, normalizenewlines=False):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   779
        """Run command in a sub-process, capturing the output (stdout and
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   780
        stderr).
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   781
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   782
        Return a tuple (exitcode, output). output is None in debug mode.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   783
        """
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   784
        if self._debug:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   785
            proc = subprocess.Popen(cmd, shell=True, cwd=self._testtmp,
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   786
                                    env=env)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   787
            ret = proc.wait()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   788
            return (ret, None)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   789
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   790
        proc = Popen4(cmd, self._testtmp, self._timeout, env)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   791
        def cleanup():
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   792
            terminate(proc)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   793
            ret = proc.wait()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   794
            if ret == 0:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   795
                ret = signal.SIGTERM << 8
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   796
            killdaemons(env['DAEMON_PIDS'])
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   797
            return ret
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   798
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   799
        output = ''
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   800
        proc.tochild.close()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   801
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   802
        try:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   803
            output = proc.fromchild.read()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   804
        except KeyboardInterrupt:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   805
            vlog('# Handling keyboard interrupt')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   806
            cleanup()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   807
            raise
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   808
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   809
        ret = proc.wait()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   810
        if wifexited(ret):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   811
            ret = os.WEXITSTATUS(ret)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   812
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   813
        if proc.timeout:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   814
            ret = 'timeout'
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   815
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   816
        if ret:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   817
            killdaemons(env['DAEMON_PIDS'])
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   818
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   819
        for s, r in self._getreplacements():
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   820
            output = re.sub(s, r, output)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   821
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   822
        if normalizenewlines:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   823
            output = output.replace('\r\n', '\n')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   824
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   825
        return ret, output.splitlines(True)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   826
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   827
class PythonTest(Test):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   828
    """A Python-based test."""
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   829
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   830
    @property
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   831
    def refpath(self):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   832
        return os.path.join(self._testdir, b'%s.out' % self.bname)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   833
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   834
    def _run(self, env):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   835
        py3kswitch = self._py3kwarnings and b' -3' or b''
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   836
        cmd = b'%s%s "%s"' % (PYTHON, py3kswitch, self.path)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   837
        vlog("# Running", cmd)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   838
        normalizenewlines = os.name == 'nt'
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   839
        result = self._runcommand(cmd, env,
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   840
                                  normalizenewlines=normalizenewlines)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   841
        if self._aborted:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   842
            raise KeyboardInterrupt()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   843
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   844
        return result
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   845
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   846
# This script may want to drop globs from lines matching these patterns on
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   847
# Windows, but check-code.py wants a glob on these lines unconditionally.  Don't
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   848
# warn if that is the case for anything matching these lines.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   849
checkcodeglobpats = [
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   850
    re.compile(br'^pushing to \$TESTTMP/.*[^)]$'),
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   851
    re.compile(br'^moving \S+/.*[^)]$'),
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   852
    re.compile(br'^pulling from \$TESTTMP/.*[^)]$')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   853
]
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   854
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   855
bchr = chr
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   856
if PYTHON3:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   857
    bchr = lambda x: bytes([x])
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   858
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   859
class TTest(Test):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   860
    """A "t test" is a test backed by a .t file."""
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   861
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   862
    SKIPPED_PREFIX = 'skipped: '
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   863
    FAILED_PREFIX = 'hghave check failed: '
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   864
    NEEDESCAPE = re.compile(br'[\x00-\x08\x0b-\x1f\x7f-\xff]').search
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   865
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   866
    ESCAPESUB = re.compile(br'[\x00-\x08\x0b-\x1f\\\x7f-\xff]').sub
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   867
    ESCAPEMAP = dict((bchr(i), br'\x%02x' % i) for i in range(256))
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   868
    ESCAPEMAP.update({b'\\': b'\\\\', b'\r': br'\r'})
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   869
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   870
    @property
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   871
    def refpath(self):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   872
        return os.path.join(self._testdir, self.bname)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   873
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   874
    def _run(self, env):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   875
        f = open(self.path, 'rb')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   876
        lines = f.readlines()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   877
        f.close()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   878
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   879
        salt, script, after, expected = self._parsetest(lines)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   880
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   881
        # Write out the generated script.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   882
        fname = b'%s.sh' % self._testtmp
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   883
        f = open(fname, 'wb')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   884
        for l in script:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   885
            f.write(l)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   886
        f.close()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   887
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   888
        cmd = b'%s "%s"' % (self._shell, fname)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   889
        vlog("# Running", cmd)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   890
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   891
        exitcode, output = self._runcommand(cmd, env)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   892
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   893
        if self._aborted:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   894
            raise KeyboardInterrupt()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   895
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   896
        # Do not merge output if skipped. Return hghave message instead.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   897
        # Similarly, with --debug, output is None.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   898
        if exitcode == self.SKIPPED_STATUS or output is None:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   899
            return exitcode, output
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   900
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   901
        return self._processoutput(exitcode, output, salt, after, expected)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   902
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   903
    def _hghave(self, reqs):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   904
        # TODO do something smarter when all other uses of hghave are gone.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   905
        tdir = self._testdir.replace(b'\\', b'/')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   906
        proc = Popen4(b'%s -c "%s/hghave %s"' %
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   907
                      (self._shell, tdir, b' '.join(reqs)),
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   908
                      self._testtmp, 0, self._getenv())
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   909
        stdout, stderr = proc.communicate()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   910
        ret = proc.wait()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   911
        if wifexited(ret):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   912
            ret = os.WEXITSTATUS(ret)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   913
        if ret == 2:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   914
            print(stdout)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   915
            sys.exit(1)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   916
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   917
        return ret == 0
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   918
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   919
    def _parsetest(self, lines):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   920
        # We generate a shell script which outputs unique markers to line
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   921
        # up script results with our source. These markers include input
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   922
        # line number and the last return code.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   923
        salt = b"SALT%d" % time.time()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   924
        def addsalt(line, inpython):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   925
            if inpython:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   926
                script.append(b'%s %d 0\n' % (salt, line))
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   927
            else:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   928
                script.append(b'echo %s %d $?\n' % (salt, line))
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   929
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   930
        script = []
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   931
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   932
        # After we run the shell script, we re-unify the script output
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   933
        # with non-active parts of the source, with synchronization by our
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   934
        # SALT line number markers. The after table contains the non-active
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   935
        # components, ordered by line number.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   936
        after = {}
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   937
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   938
        # Expected shell script output.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   939
        expected = {}
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   940
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   941
        pos = prepos = -1
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   942
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   943
        # True or False when in a true or false conditional section
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   944
        skipping = None
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   945
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   946
        # We keep track of whether or not we're in a Python block so we
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   947
        # can generate the surrounding doctest magic.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   948
        inpython = False
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   949
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   950
        if self._debug:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   951
            script.append(b'set -x\n')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   952
        if os.getenv('MSYSTEM'):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   953
            script.append(b'alias pwd="pwd -W"\n')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   954
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   955
        for n, l in enumerate(lines):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   956
            if not l.endswith(b'\n'):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   957
                l += b'\n'
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   958
            if l.startswith(b'#require'):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   959
                lsplit = l.split()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   960
                if len(lsplit) < 2 or lsplit[0] != b'#require':
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   961
                    after.setdefault(pos, []).append('  !!! invalid #require\n')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   962
                if not self._hghave(lsplit[1:]):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   963
                    script = [b"exit 80\n"]
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   964
                    break
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   965
                after.setdefault(pos, []).append(l)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   966
            elif l.startswith(b'#if'):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   967
                lsplit = l.split()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   968
                if len(lsplit) < 2 or lsplit[0] != b'#if':
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   969
                    after.setdefault(pos, []).append('  !!! invalid #if\n')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   970
                if skipping is not None:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   971
                    after.setdefault(pos, []).append('  !!! nested #if\n')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   972
                skipping = not self._hghave(lsplit[1:])
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   973
                after.setdefault(pos, []).append(l)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   974
            elif l.startswith(b'#else'):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   975
                if skipping is None:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   976
                    after.setdefault(pos, []).append('  !!! missing #if\n')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   977
                skipping = not skipping
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   978
                after.setdefault(pos, []).append(l)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   979
            elif l.startswith(b'#endif'):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   980
                if skipping is None:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   981
                    after.setdefault(pos, []).append('  !!! missing #if\n')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   982
                skipping = None
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   983
                after.setdefault(pos, []).append(l)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   984
            elif skipping:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   985
                after.setdefault(pos, []).append(l)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   986
            elif l.startswith(b'  >>> '): # python inlines
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   987
                after.setdefault(pos, []).append(l)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   988
                prepos = pos
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   989
                pos = n
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   990
                if not inpython:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   991
                    # We've just entered a Python block. Add the header.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   992
                    inpython = True
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   993
                    addsalt(prepos, False) # Make sure we report the exit code.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   994
                    script.append(b'%s -m heredoctest <<EOF\n' % PYTHON)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   995
                addsalt(n, True)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   996
                script.append(l[2:])
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   997
            elif l.startswith(b'  ... '): # python inlines
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   998
                after.setdefault(prepos, []).append(l)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
   999
                script.append(l[2:])
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1000
            elif l.startswith(b'  $ '): # commands
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1001
                if inpython:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1002
                    script.append(b'EOF\n')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1003
                    inpython = False
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1004
                after.setdefault(pos, []).append(l)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1005
                prepos = pos
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1006
                pos = n
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1007
                addsalt(n, False)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1008
                cmd = l[4:].split()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1009
                if len(cmd) == 2 and cmd[0] == b'cd':
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1010
                    l = b'  $ cd %s || exit 1\n' % cmd[1]
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1011
                script.append(l[4:])
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1012
            elif l.startswith(b'  > '): # continuations
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1013
                after.setdefault(prepos, []).append(l)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1014
                script.append(l[4:])
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1015
            elif l.startswith(b'  '): # results
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1016
                # Queue up a list of expected results.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1017
                expected.setdefault(pos, []).append(l[2:])
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1018
            else:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1019
                if inpython:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1020
                    script.append(b'EOF\n')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1021
                    inpython = False
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1022
                # Non-command/result. Queue up for merged output.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1023
                after.setdefault(pos, []).append(l)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1024
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1025
        if inpython:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1026
            script.append(b'EOF\n')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1027
        if skipping is not None:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1028
            after.setdefault(pos, []).append('  !!! missing #endif\n')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1029
        addsalt(n + 1, False)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1030
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1031
        return salt, script, after, expected
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1032
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1033
    def _processoutput(self, exitcode, output, salt, after, expected):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1034
        # Merge the script output back into a unified test.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1035
        warnonly = 1 # 1: not yet; 2: yes; 3: for sure not
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1036
        if exitcode != 0:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1037
            warnonly = 3
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1038
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1039
        pos = -1
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1040
        postout = []
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1041
        for l in output:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1042
            lout, lcmd = l, None
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1043
            if salt in l:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1044
                lout, lcmd = l.split(salt, 1)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1045
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1046
            if lout:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1047
                if not lout.endswith(b'\n'):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1048
                    lout += b' (no-eol)\n'
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1049
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1050
                # Find the expected output at the current position.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1051
                el = None
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1052
                if expected.get(pos, None):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1053
                    el = expected[pos].pop(0)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1054
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1055
                r = TTest.linematch(el, lout)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1056
                if isinstance(r, str):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1057
                    if r == '+glob':
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1058
                        lout = el[:-1] + ' (glob)\n'
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1059
                        r = '' # Warn only this line.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1060
                    elif r == '-glob':
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1061
                        lout = ''.join(el.rsplit(' (glob)', 1))
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1062
                        r = '' # Warn only this line.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1063
                    else:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1064
                        log('\ninfo, unknown linematch result: %r\n' % r)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1065
                        r = False
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1066
                if r:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1067
                    postout.append(b'  ' + el)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1068
                else:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1069
                    if self.NEEDESCAPE(lout):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1070
                        lout = TTest._stringescape(b'%s (esc)\n' %
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1071
                                                   lout.rstrip(b'\n'))
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1072
                    postout.append(b'  ' + lout) # Let diff deal with it.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1073
                    if r != '': # If line failed.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1074
                        warnonly = 3 # for sure not
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1075
                    elif warnonly == 1: # Is "not yet" and line is warn only.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1076
                        warnonly = 2 # Yes do warn.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1077
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1078
            if lcmd:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1079
                # Add on last return code.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1080
                ret = int(lcmd.split()[1])
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1081
                if ret != 0:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1082
                    postout.append(b'  [%d]\n' % ret)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1083
                if pos in after:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1084
                    # Merge in non-active test bits.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1085
                    postout += after.pop(pos)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1086
                pos = int(lcmd.split()[0])
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1087
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1088
        if pos in after:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1089
            postout += after.pop(pos)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1090
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1091
        if warnonly == 2:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1092
            exitcode = False # Set exitcode to warned.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1093
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1094
        return exitcode, postout
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1095
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1096
    @staticmethod
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1097
    def rematch(el, l):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1098
        try:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1099
            # use \Z to ensure that the regex matches to the end of the string
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1100
            if os.name == 'nt':
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1101
                return re.match(el + br'\r?\n\Z', l)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1102
            return re.match(el + br'\n\Z', l)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1103
        except re.error:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1104
            # el is an invalid regex
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1105
            return False
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1106
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1107
    @staticmethod
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1108
    def globmatch(el, l):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1109
        # The only supported special characters are * and ? plus / which also
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1110
        # matches \ on windows. Escaping of these characters is supported.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1111
        if el + b'\n' == l:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1112
            if os.altsep:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1113
                # matching on "/" is not needed for this line
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1114
                for pat in checkcodeglobpats:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1115
                    if pat.match(el):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1116
                        return True
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1117
                return b'-glob'
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1118
            return True
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1119
        i, n = 0, len(el)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1120
        res = b''
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1121
        while i < n:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1122
            c = el[i:i + 1]
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1123
            i += 1
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1124
            if c == b'\\' and i < n and el[i:i + 1] in b'*?\\/':
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1125
                res += el[i - 1:i + 1]
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1126
                i += 1
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1127
            elif c == b'*':
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1128
                res += b'.*'
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1129
            elif c == b'?':
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1130
                res += b'.'
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1131
            elif c == b'/' and os.altsep:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1132
                res += b'[/\\\\]'
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1133
            else:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1134
                res += re.escape(c)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1135
        return TTest.rematch(res, l)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1136
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1137
    @staticmethod
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1138
    def linematch(el, l):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1139
        if el == l: # perfect match (fast)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1140
            return True
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1141
        if el:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1142
            if el.endswith(b" (esc)\n"):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1143
                if PYTHON3:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1144
                    el = el[:-7].decode('unicode_escape') + '\n'
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1145
                    el = el.encode('utf-8')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1146
                else:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1147
                    el = el[:-7].decode('string-escape') + '\n'
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1148
            if el == l or os.name == 'nt' and el[:-1] + b'\r\n' == l:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1149
                return True
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1150
            if el.endswith(b" (re)\n"):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1151
                return TTest.rematch(el[:-6], l)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1152
            if el.endswith(b" (glob)\n"):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1153
                # ignore '(glob)' added to l by 'replacements'
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1154
                if l.endswith(b" (glob)\n"):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1155
                    l = l[:-8] + b"\n"
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1156
                return TTest.globmatch(el[:-8], l)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1157
            if os.altsep and l.replace(b'\\', b'/') == el:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1158
                return b'+glob'
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1159
        return False
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1160
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1161
    @staticmethod
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1162
    def parsehghaveoutput(lines):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1163
        '''Parse hghave log lines.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1164
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1165
        Return tuple of lists (missing, failed):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1166
          * the missing/unknown features
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1167
          * the features for which existence check failed'''
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1168
        missing = []
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1169
        failed = []
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1170
        for line in lines:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1171
            if line.startswith(TTest.SKIPPED_PREFIX):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1172
                line = line.splitlines()[0]
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1173
                missing.append(line[len(TTest.SKIPPED_PREFIX):])
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1174
            elif line.startswith(TTest.FAILED_PREFIX):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1175
                line = line.splitlines()[0]
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1176
                failed.append(line[len(TTest.FAILED_PREFIX):])
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1177
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1178
        return missing, failed
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1179
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1180
    @staticmethod
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1181
    def _escapef(m):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1182
        return TTest.ESCAPEMAP[m.group(0)]
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1183
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1184
    @staticmethod
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1185
    def _stringescape(s):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1186
        return TTest.ESCAPESUB(TTest._escapef, s)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1187
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1188
iolock = threading.RLock()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1189
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1190
class SkipTest(Exception):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1191
    """Raised to indicate that a test is to be skipped."""
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1192
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1193
class IgnoreTest(Exception):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1194
    """Raised to indicate that a test is to be ignored."""
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1195
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1196
class WarnTest(Exception):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1197
    """Raised to indicate that a test warned."""
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1198
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1199
class TestResult(unittest._TextTestResult):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1200
    """Holds results when executing via unittest."""
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1201
    # Don't worry too much about accessing the non-public _TextTestResult.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1202
    # It is relatively common in Python testing tools.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1203
    def __init__(self, options, *args, **kwargs):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1204
        super(TestResult, self).__init__(*args, **kwargs)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1205
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1206
        self._options = options
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1207
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1208
        # unittest.TestResult didn't have skipped until 2.7. We need to
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1209
        # polyfill it.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1210
        self.skipped = []
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1211
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1212
        # We have a custom "ignored" result that isn't present in any Python
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1213
        # unittest implementation. It is very similar to skipped. It may make
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1214
        # sense to map it into skip some day.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1215
        self.ignored = []
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1216
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1217
        # We have a custom "warned" result that isn't present in any Python
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1218
        # unittest implementation. It is very similar to failed. It may make
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1219
        # sense to map it into fail some day.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1220
        self.warned = []
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1221
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1222
        self.times = []
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1223
        self._firststarttime =  None
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1224
        # Data stored for the benefit of generating xunit reports.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1225
        self.successes = []
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1226
        self.faildata = {}
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1227
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1228
    def addFailure(self, test, reason):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1229
        self.failures.append((test, reason))
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1230
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1231
        if self._options.first:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1232
            self.stop()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1233
        else:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1234
            with iolock:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1235
                if not self._options.nodiff:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1236
                    self.stream.write('\nERROR: %s output changed\n' % test)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1237
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1238
                self.stream.write('!')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1239
                self.stream.flush()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1240
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1241
    def addSuccess(self, test):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1242
        with iolock:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1243
            super(TestResult, self).addSuccess(test)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1244
        self.successes.append(test)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1245
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1246
    def addError(self, test, err):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1247
        super(TestResult, self).addError(test, err)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1248
        if self._options.first:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1249
            self.stop()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1250
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1251
    # Polyfill.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1252
    def addSkip(self, test, reason):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1253
        self.skipped.append((test, reason))
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1254
        with iolock:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1255
            if self.showAll:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1256
                self.stream.writeln('skipped %s' % reason)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1257
            else:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1258
                self.stream.write('s')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1259
                self.stream.flush()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1260
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1261
    def addIgnore(self, test, reason):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1262
        self.ignored.append((test, reason))
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1263
        with iolock:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1264
            if self.showAll:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1265
                self.stream.writeln('ignored %s' % reason)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1266
            else:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1267
                if reason not in ('not retesting', "doesn't match keyword"):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1268
                    self.stream.write('i')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1269
                else:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1270
                    self.testsRun += 1
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1271
                self.stream.flush()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1272
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1273
    def addWarn(self, test, reason):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1274
        self.warned.append((test, reason))
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1275
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1276
        if self._options.first:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1277
            self.stop()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1278
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1279
        with iolock:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1280
            if self.showAll:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1281
                self.stream.writeln('warned %s' % reason)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1282
            else:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1283
                self.stream.write('~')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1284
                self.stream.flush()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1285
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1286
    def addOutputMismatch(self, test, ret, got, expected):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1287
        """Record a mismatch in test output for a particular test."""
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1288
        if self.shouldStop:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1289
            # don't print, some other test case already failed and
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1290
            # printed, we're just stale and probably failed due to our
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1291
            # temp dir getting cleaned up.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1292
            return
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1293
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1294
        accepted = False
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1295
        failed = False
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1296
        lines = []
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1297
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1298
        with iolock:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1299
            if self._options.nodiff:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1300
                pass
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1301
            elif self._options.view:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1302
                v = self._options.view
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1303
                if PYTHON3:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1304
                    v = _bytespath(v)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1305
                os.system(b"%s %s %s" %
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1306
                          (v, test.refpath, test.errpath))
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1307
            else:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1308
                servefail, lines = getdiff(expected, got,
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1309
                                           test.refpath, test.errpath)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1310
                if servefail:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1311
                    self.addFailure(
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1312
                        test,
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1313
                        'server failed to start (HGPORT=%s)' % test._startport)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1314
                else:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1315
                    self.stream.write('\n')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1316
                    for line in lines:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1317
                        if PYTHON3:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1318
                            self.stream.flush()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1319
                            self.stream.buffer.write(line)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1320
                            self.stream.buffer.flush()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1321
                        else:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1322
                            self.stream.write(line)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1323
                            self.stream.flush()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1324
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1325
            # handle interactive prompt without releasing iolock
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1326
            if self._options.interactive:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1327
                self.stream.write('Accept this change? [n] ')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1328
                answer = sys.stdin.readline().strip()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1329
                if answer.lower() in ('y', 'yes'):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1330
                    if test.name.endswith('.t'):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1331
                        rename(test.errpath, test.path)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1332
                    else:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1333
                        rename(test.errpath, '%s.out' % test.path)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1334
                    accepted = True
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1335
            if not accepted and not failed:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1336
                self.faildata[test.name] = b''.join(lines)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1337
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1338
        return accepted
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1339
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1340
    def startTest(self, test):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1341
        super(TestResult, self).startTest(test)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1342
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1343
        # os.times module computes the user time and system time spent by
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1344
        # child's processes along with real elapsed time taken by a process.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1345
        # This module has one limitation. It can only work for Linux user
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1346
        # and not for Windows.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1347
        test.started = os.times()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1348
        if self._firststarttime is None: # thread racy but irrelevant
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1349
            self._firststarttime = test.started[4]
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1350
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1351
    def stopTest(self, test, interrupted=False):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1352
        super(TestResult, self).stopTest(test)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1353
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1354
        test.stopped = os.times()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1355
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1356
        starttime = test.started
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1357
        endtime = test.stopped
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1358
        origin = self._firststarttime
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1359
        self.times.append((test.name,
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1360
                           endtime[2] - starttime[2], # user space CPU time
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1361
                           endtime[3] - starttime[3], # sys  space CPU time
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1362
                           endtime[4] - starttime[4], # real time
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1363
                           starttime[4] - origin, # start date in run context
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1364
                           endtime[4] - origin, # end date in run context
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1365
                           ))
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1366
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1367
        if interrupted:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1368
            with iolock:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1369
                self.stream.writeln('INTERRUPTED: %s (after %d seconds)' % (
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1370
                    test.name, self.times[-1][3]))
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1371
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1372
class TestSuite(unittest.TestSuite):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1373
    """Custom unittest TestSuite that knows how to execute Mercurial tests."""
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1374
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1375
    def __init__(self, testdir, jobs=1, whitelist=None, blacklist=None,
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1376
                 retest=False, keywords=None, loop=False, runs_per_test=1,
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1377
                 loadtest=None,
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1378
                 *args, **kwargs):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1379
        """Create a new instance that can run tests with a configuration.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1380
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1381
        testdir specifies the directory where tests are executed from. This
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1382
        is typically the ``tests`` directory from Mercurial's source
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1383
        repository.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1384
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1385
        jobs specifies the number of jobs to run concurrently. Each test
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1386
        executes on its own thread. Tests actually spawn new processes, so
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1387
        state mutation should not be an issue.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1388
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1389
        whitelist and blacklist denote tests that have been whitelisted and
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1390
        blacklisted, respectively. These arguments don't belong in TestSuite.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1391
        Instead, whitelist and blacklist should be handled by the thing that
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1392
        populates the TestSuite with tests. They are present to preserve
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1393
        backwards compatible behavior which reports skipped tests as part
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1394
        of the results.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1395
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1396
        retest denotes whether to retest failed tests. This arguably belongs
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1397
        outside of TestSuite.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1398
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1399
        keywords denotes key words that will be used to filter which tests
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1400
        to execute. This arguably belongs outside of TestSuite.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1401
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1402
        loop denotes whether to loop over tests forever.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1403
        """
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1404
        super(TestSuite, self).__init__(*args, **kwargs)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1405
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1406
        self._jobs = jobs
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1407
        self._whitelist = whitelist
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1408
        self._blacklist = blacklist
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1409
        self._retest = retest
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1410
        self._keywords = keywords
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1411
        self._loop = loop
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1412
        self._runs_per_test = runs_per_test
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1413
        self._loadtest = loadtest
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1414
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1415
    def run(self, result):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1416
        # We have a number of filters that need to be applied. We do this
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1417
        # here instead of inside Test because it makes the running logic for
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1418
        # Test simpler.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1419
        tests = []
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1420
        num_tests = [0]
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1421
        for test in self._tests:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1422
            def get():
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1423
                num_tests[0] += 1
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1424
                if getattr(test, 'should_reload', False):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1425
                    return self._loadtest(test.bname, num_tests[0])
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1426
                return test
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1427
            if not os.path.exists(test.path):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1428
                result.addSkip(test, "Doesn't exist")
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1429
                continue
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1430
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1431
            if not (self._whitelist and test.name in self._whitelist):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1432
                if self._blacklist and test.bname in self._blacklist:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1433
                    result.addSkip(test, 'blacklisted')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1434
                    continue
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1435
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1436
                if self._retest and not os.path.exists(test.errpath):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1437
                    result.addIgnore(test, 'not retesting')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1438
                    continue
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1439
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1440
                if self._keywords:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1441
                    f = open(test.path, 'rb')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1442
                    t = f.read().lower() + test.bname.lower()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1443
                    f.close()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1444
                    ignored = False
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1445
                    for k in self._keywords.lower().split():
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1446
                        if k not in t:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1447
                            result.addIgnore(test, "doesn't match keyword")
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1448
                            ignored = True
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1449
                            break
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1450
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1451
                    if ignored:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1452
                        continue
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1453
            for _ in xrange(self._runs_per_test):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1454
                tests.append(get())
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1455
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1456
        runtests = list(tests)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1457
        done = queue.Queue()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1458
        running = 0
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1459
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1460
        def job(test, result):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1461
            try:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1462
                test(result)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1463
                done.put(None)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1464
            except KeyboardInterrupt:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1465
                pass
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1466
            except: # re-raises
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1467
                done.put(('!', test, 'run-test raised an error, see traceback'))
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1468
                raise
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1469
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1470
        stoppedearly = False
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1471
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1472
        try:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1473
            while tests or running:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1474
                if not done.empty() or running == self._jobs or not tests:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1475
                    try:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1476
                        done.get(True, 1)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1477
                        running -= 1
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1478
                        if result and result.shouldStop:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1479
                            stoppedearly = True
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1480
                            break
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1481
                    except queue.Empty:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1482
                        continue
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1483
                if tests and not running == self._jobs:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1484
                    test = tests.pop(0)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1485
                    if self._loop:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1486
                        if getattr(test, 'should_reload', False):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1487
                            num_tests[0] += 1
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1488
                            tests.append(
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1489
                                self._loadtest(test.name, num_tests[0]))
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1490
                        else:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1491
                            tests.append(test)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1492
                    t = threading.Thread(target=job, name=test.name,
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1493
                                         args=(test, result))
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1494
                    t.start()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1495
                    running += 1
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1496
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1497
            # If we stop early we still need to wait on started tests to
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1498
            # finish. Otherwise, there is a race between the test completing
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1499
            # and the test's cleanup code running. This could result in the
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1500
            # test reporting incorrect.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1501
            if stoppedearly:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1502
                while running:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1503
                    try:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1504
                        done.get(True, 1)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1505
                        running -= 1
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1506
                    except queue.Empty:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1507
                        continue
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1508
        except KeyboardInterrupt:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1509
            for test in runtests:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1510
                test.abort()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1511
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1512
        return result
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1513
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1514
class TextTestRunner(unittest.TextTestRunner):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1515
    """Custom unittest test runner that uses appropriate settings."""
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1516
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1517
    def __init__(self, runner, *args, **kwargs):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1518
        super(TextTestRunner, self).__init__(*args, **kwargs)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1519
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1520
        self._runner = runner
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1521
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1522
    def run(self, test):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1523
        result = TestResult(self._runner.options, self.stream,
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1524
                            self.descriptions, self.verbosity)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1525
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1526
        test(result)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1527
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1528
        failed = len(result.failures)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1529
        warned = len(result.warned)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1530
        skipped = len(result.skipped)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1531
        ignored = len(result.ignored)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1532
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1533
        with iolock:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1534
            self.stream.writeln('')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1535
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1536
            if not self._runner.options.noskips:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1537
                for test, msg in result.skipped:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1538
                    self.stream.writeln('Skipped %s: %s' % (test.name, msg))
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1539
            for test, msg in result.warned:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1540
                self.stream.writeln('Warned %s: %s' % (test.name, msg))
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1541
            for test, msg in result.failures:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1542
                self.stream.writeln('Failed %s: %s' % (test.name, msg))
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1543
            for test, msg in result.errors:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1544
                self.stream.writeln('Errored %s: %s' % (test.name, msg))
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1545
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1546
            if self._runner.options.xunit:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1547
                xuf = open(self._runner.options.xunit, 'wb')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1548
                try:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1549
                    timesd = dict((t[0], t[3]) for t in result.times)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1550
                    doc = minidom.Document()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1551
                    s = doc.createElement('testsuite')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1552
                    s.setAttribute('name', 'run-tests')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1553
                    s.setAttribute('tests', str(result.testsRun))
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1554
                    s.setAttribute('errors', "0") # TODO
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1555
                    s.setAttribute('failures', str(failed))
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1556
                    s.setAttribute('skipped', str(skipped + ignored))
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1557
                    doc.appendChild(s)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1558
                    for tc in result.successes:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1559
                        t = doc.createElement('testcase')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1560
                        t.setAttribute('name', tc.name)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1561
                        t.setAttribute('time', '%.3f' % timesd[tc.name])
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1562
                        s.appendChild(t)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1563
                    for tc, err in sorted(result.faildata.items()):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1564
                        t = doc.createElement('testcase')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1565
                        t.setAttribute('name', tc)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1566
                        t.setAttribute('time', '%.3f' % timesd[tc])
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1567
                        # createCDATASection expects a unicode or it will
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1568
                        # convert using default conversion rules, which will
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1569
                        # fail if string isn't ASCII.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1570
                        err = cdatasafe(err).decode('utf-8', 'replace')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1571
                        cd = doc.createCDATASection(err)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1572
                        t.appendChild(cd)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1573
                        s.appendChild(t)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1574
                    xuf.write(doc.toprettyxml(indent='  ', encoding='utf-8'))
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1575
                finally:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1576
                    xuf.close()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1577
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1578
            if self._runner.options.json:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1579
                if json is None:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1580
                    raise ImportError("json module not installed")
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1581
                jsonpath = os.path.join(self._runner._testdir, 'report.json')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1582
                fp = open(jsonpath, 'w')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1583
                try:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1584
                    timesd = {}
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1585
                    for tdata in result.times:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1586
                        test = tdata[0]
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1587
                        timesd[test] = tdata[1:]
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1588
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1589
                    outcome = {}
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1590
                    groups = [('success', ((tc, None)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1591
                               for tc in result.successes)),
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1592
                              ('failure', result.failures),
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1593
                              ('skip', result.skipped)]
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1594
                    for res, testcases in groups:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1595
                        for tc, __ in testcases:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1596
                            tres = {'result': res,
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1597
                                    'time': ('%0.3f' % timesd[tc.name][2]),
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1598
                                    'cuser': ('%0.3f' % timesd[tc.name][0]),
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1599
                                    'csys': ('%0.3f' % timesd[tc.name][1]),
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1600
                                    'start': ('%0.3f' % timesd[tc.name][3]),
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1601
                                    'end': ('%0.3f' % timesd[tc.name][4])}
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1602
                            outcome[tc.name] = tres
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1603
                    jsonout = json.dumps(outcome, sort_keys=True, indent=4)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1604
                    fp.writelines(("testreport =", jsonout))
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1605
                finally:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1606
                    fp.close()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1607
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1608
            self._runner._checkhglib('Tested')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1609
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1610
            self.stream.writeln(
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1611
                '# Ran %d tests, %d skipped, %d warned, %d failed.'
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1612
                % (result.testsRun,
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1613
                   skipped + ignored, warned, failed))
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1614
            if failed:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1615
                self.stream.writeln('python hash seed: %s' %
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1616
                    os.environ['PYTHONHASHSEED'])
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1617
            if self._runner.options.time:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1618
                self.printtimes(result.times)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1619
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1620
        return result
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1621
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1622
    def printtimes(self, times):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1623
        # iolock held by run
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1624
        self.stream.writeln('# Producing time report')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1625
        times.sort(key=lambda t: (t[3]))
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1626
        cols = '%7.3f %7.3f %7.3f %7.3f %7.3f   %s'
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1627
        self.stream.writeln('%-7s %-7s %-7s %-7s %-7s   %s' %
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1628
                            ('start', 'end', 'cuser', 'csys', 'real', 'Test'))
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1629
        for tdata in times:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1630
            test = tdata[0]
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1631
            cuser, csys, real, start, end = tdata[1:6]
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1632
            self.stream.writeln(cols % (start, end, cuser, csys, real, test))
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1633
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1634
class TestRunner(object):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1635
    """Holds context for executing tests.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1636
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1637
    Tests rely on a lot of state. This object holds it for them.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1638
    """
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1639
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1640
    # Programs required to run tests.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1641
    REQUIREDTOOLS = [
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1642
        os.path.basename(_bytespath(sys.executable)),
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1643
        b'diff',
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1644
        b'grep',
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1645
        b'unzip',
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1646
        b'gunzip',
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1647
        b'bunzip2',
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1648
        b'sed',
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1649
    ]
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1650
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1651
    # Maps file extensions to test class.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1652
    TESTTYPES = [
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1653
        (b'.py', PythonTest),
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1654
        (b'.t', TTest),
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1655
    ]
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1656
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1657
    def __init__(self):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1658
        self.options = None
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1659
        self._hgroot = None
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1660
        self._testdir = None
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1661
        self._hgtmp = None
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1662
        self._installdir = None
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1663
        self._bindir = None
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1664
        self._tmpbinddir = None
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1665
        self._pythondir = None
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1666
        self._coveragefile = None
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1667
        self._createdfiles = []
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1668
        self._hgpath = None
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1669
        self._portoffset = 0
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1670
        self._ports = {}
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1671
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1672
    def run(self, args, parser=None):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1673
        """Run the test suite."""
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1674
        oldmask = os.umask(0o22)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1675
        try:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1676
            parser = parser or getparser()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1677
            options, args = parseargs(args, parser)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1678
            # positional arguments are paths to test files to run, so
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1679
            # we make sure they're all bytestrings
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1680
            args = [_bytespath(a) for a in args]
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1681
            self.options = options
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1682
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1683
            self._checktools()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1684
            tests = self.findtests(args)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1685
            if options.profile_runner:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1686
                import statprof
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1687
                statprof.start()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1688
            result = self._run(tests)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1689
            if options.profile_runner:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1690
                statprof.stop()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1691
                statprof.display()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1692
            return result
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1693
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1694
        finally:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1695
            os.umask(oldmask)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1696
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1697
    def _run(self, tests):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1698
        if self.options.random:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1699
            random.shuffle(tests)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1700
        else:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1701
            # keywords for slow tests
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1702
            slow = {b'svn': 10,
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1703
                    b'gendoc': 10,
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1704
                    b'check-code-hg': 100,
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1705
                   }
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1706
            def sortkey(f):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1707
                # run largest tests first, as they tend to take the longest
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1708
                try:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1709
                    val = -os.stat(f).st_size
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1710
                except OSError as e:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1711
                    if e.errno != errno.ENOENT:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1712
                        raise
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1713
                    return -1e9 # file does not exist, tell early
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1714
                for kw, mul in slow.iteritems():
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1715
                    if kw in f:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1716
                        val *= mul
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1717
                return val
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1718
            tests.sort(key=sortkey)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1719
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1720
        self._testdir = osenvironb[b'TESTDIR'] = getattr(
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1721
            os, 'getcwdb', os.getcwd)()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1722
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1723
        if 'PYTHONHASHSEED' not in os.environ:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1724
            # use a random python hash seed all the time
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1725
            # we do the randomness ourself to know what seed is used
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1726
            os.environ['PYTHONHASHSEED'] = str(random.getrandbits(32))
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1727
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1728
        if self.options.tmpdir:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1729
            self.options.keep_tmpdir = True
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1730
            tmpdir = _bytespath(self.options.tmpdir)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1731
            if os.path.exists(tmpdir):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1732
                # Meaning of tmpdir has changed since 1.3: we used to create
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1733
                # HGTMP inside tmpdir; now HGTMP is tmpdir.  So fail if
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1734
                # tmpdir already exists.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1735
                print("error: temp dir %r already exists" % tmpdir)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1736
                return 1
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1737
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1738
                # Automatically removing tmpdir sounds convenient, but could
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1739
                # really annoy anyone in the habit of using "--tmpdir=/tmp"
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1740
                # or "--tmpdir=$HOME".
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1741
                #vlog("# Removing temp dir", tmpdir)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1742
                #shutil.rmtree(tmpdir)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1743
            os.makedirs(tmpdir)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1744
        else:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1745
            d = None
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1746
            if os.name == 'nt':
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1747
                # without this, we get the default temp dir location, but
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1748
                # in all lowercase, which causes troubles with paths (issue3490)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1749
                d = osenvironb.get(b'TMP', None)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1750
            # FILE BUG: mkdtemp works only on unicode in Python 3
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1751
            tmpdir = tempfile.mkdtemp('', 'hgtests.', d and _strpath(d))
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1752
            tmpdir = _bytespath(tmpdir)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1753
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1754
        self._hgtmp = osenvironb[b'HGTMP'] = (
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1755
            os.path.realpath(tmpdir))
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1756
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1757
        if self.options.with_hg:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1758
            self._installdir = None
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1759
            whg = self.options.with_hg
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1760
            # If --with-hg is not specified, we have bytes already,
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1761
            # but if it was specified in python3 we get a str, so we
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1762
            # have to encode it back into a bytes.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1763
            if PYTHON3:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1764
                if not isinstance(whg, bytes):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1765
                    whg = _bytespath(whg)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1766
            self._bindir = os.path.dirname(os.path.realpath(whg))
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1767
            assert isinstance(self._bindir, bytes)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1768
            self._tmpbindir = os.path.join(self._hgtmp, b'install', b'bin')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1769
            os.makedirs(self._tmpbindir)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1770
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1771
            # This looks redundant with how Python initializes sys.path from
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1772
            # the location of the script being executed.  Needed because the
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1773
            # "hg" specified by --with-hg is not the only Python script
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1774
            # executed in the test suite that needs to import 'mercurial'
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1775
            # ... which means it's not really redundant at all.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1776
            self._pythondir = self._bindir
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1777
        else:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1778
            self._installdir = os.path.join(self._hgtmp, b"install")
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1779
            self._bindir = osenvironb[b"BINDIR"] = \
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1780
                os.path.join(self._installdir, b"bin")
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1781
            self._tmpbindir = self._bindir
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1782
            self._pythondir = os.path.join(self._installdir, b"lib", b"python")
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1783
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1784
        osenvironb[b"BINDIR"] = self._bindir
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1785
        osenvironb[b"PYTHON"] = PYTHON
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1786
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1787
        fileb = _bytespath(__file__)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1788
        runtestdir = os.path.abspath(os.path.dirname(fileb))
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1789
        if PYTHON3:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1790
            sepb = _bytespath(os.pathsep)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1791
        else:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1792
            sepb = os.pathsep
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1793
        path = [self._bindir, runtestdir] + osenvironb[b"PATH"].split(sepb)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1794
        if os.path.islink(__file__):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1795
            # test helper will likely be at the end of the symlink
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1796
            realfile = os.path.realpath(fileb)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1797
            realdir = os.path.abspath(os.path.dirname(realfile))
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1798
            path.insert(2, realdir)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1799
        if self._tmpbindir != self._bindir:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1800
            path = [self._tmpbindir] + path
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1801
        osenvironb[b"PATH"] = sepb.join(path)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1802
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1803
        # Include TESTDIR in PYTHONPATH so that out-of-tree extensions
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1804
        # can run .../tests/run-tests.py test-foo where test-foo
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1805
        # adds an extension to HGRC. Also include run-test.py directory to
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1806
        # import modules like heredoctest.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1807
        pypath = [self._pythondir, self._testdir, runtestdir]
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1808
        # We have to augment PYTHONPATH, rather than simply replacing
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1809
        # it, in case external libraries are only available via current
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1810
        # PYTHONPATH.  (In particular, the Subversion bindings on OS X
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1811
        # are in /opt/subversion.)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1812
        oldpypath = osenvironb.get(IMPL_PATH)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1813
        if oldpypath:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1814
            pypath.append(oldpypath)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1815
        osenvironb[IMPL_PATH] = sepb.join(pypath)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1816
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1817
        if self.options.pure:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1818
            os.environ["HGTEST_RUN_TESTS_PURE"] = "--pure"
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1819
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1820
        self._coveragefile = os.path.join(self._testdir, b'.coverage')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1821
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1822
        vlog("# Using TESTDIR", self._testdir)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1823
        vlog("# Using HGTMP", self._hgtmp)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1824
        vlog("# Using PATH", os.environ["PATH"])
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1825
        vlog("# Using", IMPL_PATH, osenvironb[IMPL_PATH])
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1826
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1827
        try:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1828
            return self._runtests(tests) or 0
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1829
        finally:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1830
            time.sleep(.1)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1831
            self._cleanup()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1832
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1833
    def findtests(self, args):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1834
        """Finds possible test files from arguments.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1835
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1836
        If you wish to inject custom tests into the test harness, this would
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1837
        be a good function to monkeypatch or override in a derived class.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1838
        """
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1839
        if not args:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1840
            if self.options.changed:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1841
                proc = Popen4('hg st --rev "%s" -man0 .' %
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1842
                              self.options.changed, None, 0)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1843
                stdout, stderr = proc.communicate()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1844
                args = stdout.strip(b'\0').split(b'\0')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1845
            else:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1846
                args = os.listdir(b'.')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1847
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1848
        return [t for t in args
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1849
                if os.path.basename(t).startswith(b'test-')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1850
                    and (t.endswith(b'.py') or t.endswith(b'.t'))]
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1851
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1852
    def _runtests(self, tests):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1853
        try:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1854
            if self._installdir:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1855
                self._installhg()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1856
                self._checkhglib("Testing")
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1857
            else:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1858
                self._usecorrectpython()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1859
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1860
            if self.options.restart:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1861
                orig = list(tests)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1862
                while tests:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1863
                    if os.path.exists(tests[0] + ".err"):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1864
                        break
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1865
                    tests.pop(0)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1866
                if not tests:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1867
                    print("running all tests")
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1868
                    tests = orig
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1869
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1870
            tests = [self._gettest(t, i) for i, t in enumerate(tests)]
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1871
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1872
            failed = False
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1873
            warned = False
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1874
            kws = self.options.keywords
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1875
            if kws is not None and PYTHON3:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1876
                kws = kws.encode('utf-8')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1877
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1878
            suite = TestSuite(self._testdir,
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1879
                              jobs=self.options.jobs,
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1880
                              whitelist=self.options.whitelisted,
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1881
                              blacklist=self.options.blacklist,
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1882
                              retest=self.options.retest,
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1883
                              keywords=kws,
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1884
                              loop=self.options.loop,
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1885
                              runs_per_test=self.options.runs_per_test,
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1886
                              tests=tests, loadtest=self._gettest)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1887
            verbosity = 1
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1888
            if self.options.verbose:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1889
                verbosity = 2
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1890
            runner = TextTestRunner(self, verbosity=verbosity)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1891
            result = runner.run(suite)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1892
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1893
            if result.failures:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1894
                failed = True
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1895
            if result.warned:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1896
                warned = True
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1897
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1898
            if self.options.anycoverage:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1899
                self._outputcoverage()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1900
        except KeyboardInterrupt:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1901
            failed = True
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1902
            print("\ninterrupted!")
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1903
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1904
        if failed:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1905
            return 1
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1906
        if warned:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1907
            return 80
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1908
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1909
    def _getport(self, count):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1910
        port = self._ports.get(count) # do we have a cached entry?
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1911
        if port is None:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1912
            port = self.options.port + self._portoffset
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1913
            portneeded = 3
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1914
            # above 100 tries we just give up and let test reports failure
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1915
            for tries in xrange(100):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1916
                allfree = True
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1917
                for idx in xrange(portneeded):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1918
                    if not checkportisavailable(port + idx):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1919
                        allfree = False
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1920
                        break
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1921
                self._portoffset += portneeded
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1922
                if allfree:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1923
                    break
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1924
            self._ports[count] = port
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1925
        return port
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1926
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1927
    def _gettest(self, test, count):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1928
        """Obtain a Test by looking at its filename.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1929
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1930
        Returns a Test instance. The Test may not be runnable if it doesn't
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1931
        map to a known type.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1932
        """
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1933
        lctest = test.lower()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1934
        testcls = Test
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1935
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1936
        for ext, cls in self.TESTTYPES:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1937
            if lctest.endswith(ext):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1938
                testcls = cls
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1939
                break
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1940
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1941
        refpath = os.path.join(self._testdir, test)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1942
        tmpdir = os.path.join(self._hgtmp, b'child%d' % count)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1943
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1944
        t = testcls(refpath, tmpdir,
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1945
                    keeptmpdir=self.options.keep_tmpdir,
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1946
                    debug=self.options.debug,
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1947
                    timeout=self.options.timeout,
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1948
                    startport=self._getport(count),
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1949
                    extraconfigopts=self.options.extra_config_opt,
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1950
                    py3kwarnings=self.options.py3k_warnings,
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1951
                    shell=self.options.shell)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1952
        t.should_reload = True
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1953
        return t
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1954
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1955
    def _cleanup(self):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1956
        """Clean up state from this test invocation."""
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1957
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1958
        if self.options.keep_tmpdir:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1959
            return
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1960
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1961
        vlog("# Cleaning up HGTMP", self._hgtmp)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1962
        shutil.rmtree(self._hgtmp, True)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1963
        for f in self._createdfiles:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1964
            try:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1965
                os.remove(f)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1966
            except OSError:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1967
                pass
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1968
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1969
    def _usecorrectpython(self):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1970
        """Configure the environment to use the appropriate Python in tests."""
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1971
        # Tests must use the same interpreter as us or bad things will happen.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1972
        pyexename = sys.platform == 'win32' and b'python.exe' or b'python'
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1973
        if getattr(os, 'symlink', None):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1974
            vlog("# Making python executable in test path a symlink to '%s'" %
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1975
                 sys.executable)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1976
            mypython = os.path.join(self._tmpbindir, pyexename)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1977
            try:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1978
                if os.readlink(mypython) == sys.executable:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1979
                    return
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1980
                os.unlink(mypython)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1981
            except OSError as err:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1982
                if err.errno != errno.ENOENT:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1983
                    raise
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1984
            if self._findprogram(pyexename) != sys.executable:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1985
                try:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1986
                    os.symlink(sys.executable, mypython)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1987
                    self._createdfiles.append(mypython)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1988
                except OSError as err:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1989
                    # child processes may race, which is harmless
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1990
                    if err.errno != errno.EEXIST:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1991
                        raise
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1992
        else:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1993
            exedir, exename = os.path.split(sys.executable)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1994
            vlog("# Modifying search path to find %s as %s in '%s'" %
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1995
                 (exename, pyexename, exedir))
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1996
            path = os.environ['PATH'].split(os.pathsep)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1997
            while exedir in path:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1998
                path.remove(exedir)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  1999
            os.environ['PATH'] = os.pathsep.join([exedir] + path)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2000
            if not self._findprogram(pyexename):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2001
                print("WARNING: Cannot find %s in search path" % pyexename)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2002
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2003
    def _installhg(self):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2004
        """Install hg into the test environment.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2005
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2006
        This will also configure hg with the appropriate testing settings.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2007
        """
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2008
        vlog("# Performing temporary installation of HG")
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2009
        installerrs = os.path.join(b"tests", b"install.err")
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2010
        compiler = ''
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2011
        if self.options.compiler:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2012
            compiler = '--compiler ' + self.options.compiler
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2013
        if self.options.pure:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2014
            pure = b"--pure"
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2015
        else:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2016
            pure = b""
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2017
        py3 = ''
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2018
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2019
        # Run installer in hg root
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2020
        script = os.path.realpath(sys.argv[0])
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2021
        exe = sys.executable
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2022
        if PYTHON3:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2023
            py3 = b'--c2to3'
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2024
            compiler = _bytespath(compiler)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2025
            script = _bytespath(script)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2026
            exe = _bytespath(exe)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2027
        hgroot = os.path.dirname(os.path.dirname(script))
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2028
        self._hgroot = hgroot
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2029
        os.chdir(hgroot)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2030
        nohome = b'--home=""'
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2031
        if os.name == 'nt':
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2032
            # The --home="" trick works only on OS where os.sep == '/'
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2033
            # because of a distutils convert_path() fast-path. Avoid it at
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2034
            # least on Windows for now, deal with .pydistutils.cfg bugs
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2035
            # when they happen.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2036
            nohome = b''
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2037
        cmd = (b'%(exe)s setup.py %(py3)s %(pure)s clean --all'
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2038
               b' build %(compiler)s --build-base="%(base)s"'
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2039
               b' install --force --prefix="%(prefix)s"'
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2040
               b' --install-lib="%(libdir)s"'
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2041
               b' --install-scripts="%(bindir)s" %(nohome)s >%(logfile)s 2>&1'
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2042
               % {b'exe': exe, b'py3': py3, b'pure': pure,
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2043
                  b'compiler': compiler,
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2044
                  b'base': os.path.join(self._hgtmp, b"build"),
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2045
                  b'prefix': self._installdir, b'libdir': self._pythondir,
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2046
                  b'bindir': self._bindir,
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2047
                  b'nohome': nohome, b'logfile': installerrs})
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2048
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2049
        # setuptools requires install directories to exist.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2050
        def makedirs(p):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2051
            try:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2052
                os.makedirs(p)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2053
            except OSError as e:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2054
                if e.errno != errno.EEXIST:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2055
                    raise
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2056
        makedirs(self._pythondir)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2057
        makedirs(self._bindir)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2058
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2059
        vlog("# Running", cmd)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2060
        if os.system(cmd) == 0:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2061
            if not self.options.verbose:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2062
                os.remove(installerrs)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2063
        else:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2064
            f = open(installerrs, 'rb')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2065
            for line in f:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2066
                if PYTHON3:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2067
                    sys.stdout.buffer.write(line)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2068
                else:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2069
                    sys.stdout.write(line)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2070
            f.close()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2071
            sys.exit(1)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2072
        os.chdir(self._testdir)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2073
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2074
        self._usecorrectpython()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2075
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2076
        if self.options.py3k_warnings and not self.options.anycoverage:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2077
            vlog("# Updating hg command to enable Py3k Warnings switch")
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2078
            f = open(os.path.join(self._bindir, 'hg'), 'rb')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2079
            lines = [line.rstrip() for line in f]
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2080
            lines[0] += ' -3'
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2081
            f.close()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2082
            f = open(os.path.join(self._bindir, 'hg'), 'wb')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2083
            for line in lines:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2084
                f.write(line + '\n')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2085
            f.close()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2086
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2087
        hgbat = os.path.join(self._bindir, b'hg.bat')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2088
        if os.path.isfile(hgbat):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2089
            # hg.bat expects to be put in bin/scripts while run-tests.py
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2090
            # installation layout put it in bin/ directly. Fix it
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2091
            f = open(hgbat, 'rb')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2092
            data = f.read()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2093
            f.close()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2094
            if b'"%~dp0..\python" "%~dp0hg" %*' in data:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2095
                data = data.replace(b'"%~dp0..\python" "%~dp0hg" %*',
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2096
                                    b'"%~dp0python" "%~dp0hg" %*')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2097
                f = open(hgbat, 'wb')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2098
                f.write(data)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2099
                f.close()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2100
            else:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2101
                print('WARNING: cannot fix hg.bat reference to python.exe')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2102
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2103
        if self.options.anycoverage:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2104
            custom = os.path.join(self._testdir, 'sitecustomize.py')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2105
            target = os.path.join(self._pythondir, 'sitecustomize.py')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2106
            vlog('# Installing coverage trigger to %s' % target)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2107
            shutil.copyfile(custom, target)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2108
            rc = os.path.join(self._testdir, '.coveragerc')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2109
            vlog('# Installing coverage rc to %s' % rc)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2110
            os.environ['COVERAGE_PROCESS_START'] = rc
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2111
            covdir = os.path.join(self._installdir, '..', 'coverage')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2112
            try:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2113
                os.mkdir(covdir)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2114
            except OSError as e:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2115
                if e.errno != errno.EEXIST:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2116
                    raise
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2117
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2118
            os.environ['COVERAGE_DIR'] = covdir
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2119
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2120
    def _checkhglib(self, verb):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2121
        """Ensure that the 'mercurial' package imported by python is
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2122
        the one we expect it to be.  If not, print a warning to stderr."""
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2123
        if ((self._bindir == self._pythondir) and
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2124
            (self._bindir != self._tmpbindir)):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2125
            # The pythondir has been inferred from --with-hg flag.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2126
            # We cannot expect anything sensible here.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2127
            return
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2128
        expecthg = os.path.join(self._pythondir, b'mercurial')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2129
        actualhg = self._gethgpath()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2130
        if os.path.abspath(actualhg) != os.path.abspath(expecthg):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2131
            sys.stderr.write('warning: %s with unexpected mercurial lib: %s\n'
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2132
                             '         (expected %s)\n'
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2133
                             % (verb, actualhg, expecthg))
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2134
    def _gethgpath(self):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2135
        """Return the path to the mercurial package that is actually found by
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2136
        the current Python interpreter."""
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2137
        if self._hgpath is not None:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2138
            return self._hgpath
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2139
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2140
        cmd = b'%s -c "import mercurial; print (mercurial.__path__[0])"'
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2141
        cmd = cmd % PYTHON
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2142
        if PYTHON3:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2143
            cmd = _strpath(cmd)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2144
        pipe = os.popen(cmd)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2145
        try:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2146
            self._hgpath = _bytespath(pipe.read().strip())
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2147
        finally:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2148
            pipe.close()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2149
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2150
        return self._hgpath
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2151
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2152
    def _outputcoverage(self):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2153
        """Produce code coverage output."""
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2154
        from coverage import coverage
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2155
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2156
        vlog('# Producing coverage report')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2157
        # chdir is the easiest way to get short, relative paths in the
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2158
        # output.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2159
        os.chdir(self._hgroot)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2160
        covdir = os.path.join(self._installdir, '..', 'coverage')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2161
        cov = coverage(data_file=os.path.join(covdir, 'cov'))
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2162
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2163
        # Map install directory paths back to source directory.
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2164
        cov.config.paths['srcdir'] = ['.', self._pythondir]
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2165
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2166
        cov.combine()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2167
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2168
        omit = [os.path.join(x, '*') for x in [self._bindir, self._testdir]]
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2169
        cov.report(ignore_errors=True, omit=omit)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2170
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2171
        if self.options.htmlcov:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2172
            htmldir = os.path.join(self._testdir, 'htmlcov')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2173
            cov.html_report(directory=htmldir, omit=omit)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2174
        if self.options.annotate:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2175
            adir = os.path.join(self._testdir, 'annotated')
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2176
            if not os.path.isdir(adir):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2177
                os.mkdir(adir)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2178
            cov.annotate(directory=adir, omit=omit)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2179
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2180
    def _findprogram(self, program):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2181
        """Search PATH for a executable program"""
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2182
        dpb = _bytespath(os.defpath)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2183
        sepb = _bytespath(os.pathsep)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2184
        for p in osenvironb.get(b'PATH', dpb).split(sepb):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2185
            name = os.path.join(p, program)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2186
            if os.name == 'nt' or os.access(name, os.X_OK):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2187
                return name
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2188
        return None
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2189
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2190
    def _checktools(self):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2191
        """Ensure tools required to run tests are present."""
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2192
        for p in self.REQUIREDTOOLS:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2193
            if os.name == 'nt' and not p.endswith('.exe'):
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2194
                p += '.exe'
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2195
            found = self._findprogram(p)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2196
            if found:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2197
                vlog("# Found prerequisite", p, "at", found)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2198
            else:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2199
                print("WARNING: Did not find prerequisite tool: %s " % p)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2200
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2201
if __name__ == '__main__':
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2202
    runner = TestRunner()
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2203
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2204
    try:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2205
        import msvcrt
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2206
        msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2207
        msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2208
        msvcrt.setmode(sys.stderr.fileno(), os.O_BINARY)
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2209
    except ImportError:
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2210
        pass
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2211
1bc5e62fc0c7 Initial dumb version of topics.
Augie Fackler <augie@google.com>
parents:
diff changeset
  2212
    sys.exit(runner.run(sys.argv[1:]))