~launchpad-pqm/launchpad/devel

3944.1.1 by Francis J. Lacoste
Use system version python2.4 for scripts.
1
#!/usr/bin/python2.4
1102 by Canonical.com Patch Queue Manager
Lucille had some XXXs which should have been NOTEs
2
# Copyright 2004 Canonical Ltd.  All rights reserved.
3
4
"""Tests that get run automatically on a merge."""
5
6393.2.2 by Joey Stanford
working updates since I had to change the line for pyflakes
6
import sys, time
7
import os, errno
1102 by Canonical.com Patch Queue Manager
Lucille had some XXXs which should have been NOTEs
8
import tabnanny
9
from StringIO import StringIO
5821.2.85 by James Henstridge
Add "make check_launchpad_storm_on_merge" target that runs the tests
10
import psycopg2
3308.1.2 by Stuart Bishop
Make test_on_merge.py do incremental output
11
from subprocess import Popen, PIPE, STDOUT
2083 by Canonical.com Patch Queue Manager
[r=jamesh] testrunner improvements (?)
12
from signal import SIGKILL, SIGTERM
13
from select import select
14
6393.2.1 by Joey Stanford
change the rather long timeout setting to something more reasonable and cleanup the explaination
15
# The TIMEOUT setting (expressed in seconds) affects how long a test will run
16
# before it is deemed to be hung, and then appropriately terminated.
17
# It's principal use is preventing a PQM job from hanging indefinitely and
18
# backing up the queue.
19
# e.g. Usage: TIMEOUT = 60 * 15
20
# This will set the timeout to 15 minutes.
21
TIMEOUT = 60 * 15
1102 by Canonical.com Patch Queue Manager
Lucille had some XXXs which should have been NOTEs
22
23
def main():
24
    """Call test.py with whatever arguments this script was run with.
25
26
    If the tests ran ok (last line of stderr is 'OK<return>') then suppress
27
    output and exit(0).
28
29
    Otherwise, print output and exit(1).
30
    """
31
    here = os.path.dirname(os.path.realpath(__file__))
32
33
    # Tabnanny
6393.2.2 by Joey Stanford
working updates since I had to change the line for pyflakes
34
    # NB. If tabnanny raises an exception, run
2976.10.114 by Stuart Bishop
Test tweaks
35
    # python /usr/lib/python2.4/tabnanny.py -vv lib/canonical
36
    # for more detailed output.
1102 by Canonical.com Patch Queue Manager
Lucille had some XXXs which should have been NOTEs
37
    org_stdout = sys.stdout
38
    sys.stdout = StringIO()
39
    tabnanny.check(os.path.join(here, 'lib', 'canonical'))
40
    tabnanny_results = sys.stdout.getvalue()
41
    sys.stdout = org_stdout
42
    if len(tabnanny_results) > 0:
43
        print '---- tabnanny bitching ----'
44
        print tabnanny_results
45
        print '---- end tabnanny bitching ----'
46
        return 1
47
1064.1.3 by James Henstridge
merge from marius
48
    # Sanity check PostgreSQL version. No point in trying to create a test
49
    # database when PostgreSQL is too old.
5821.2.85 by James Henstridge
Add "make check_launchpad_storm_on_merge" target that runs the tests
50
    con = psycopg2.connect('dbname=template1')
1064.1.3 by James Henstridge
merge from marius
51
    cur = con.cursor()
52
    cur.execute('show server_version')
53
    server_version = cur.fetchone()[0]
54
    try:
55
        numeric_server_version = tuple(map(int, server_version.split('.')))
56
    except ValueError:
57
        # Skip this check if the version number is more complicated than
58
        # we expected.
59
        pass
60
    else:
3257.1.1 by Stuart Bishop
PostgreSQL 8.0+ required
61
        if numeric_server_version < (8, 0):
62
            print 'Your PostgreSQL version is too old.  You need 8.x.x'
1064.1.3 by James Henstridge
merge from marius
63
            print 'You have %s' % server_version
64
            return 1
65
1102 by Canonical.com Patch Queue Manager
Lucille had some XXXs which should have been NOTEs
66
    # Drop the template database if it exists - the Makefile does this
67
    # too, but we can explicity check for errors here
5821.2.85 by James Henstridge
Add "make check_launchpad_storm_on_merge" target that runs the tests
68
    con = psycopg2.connect('dbname=template1')
2083 by Canonical.com Patch Queue Manager
[r=jamesh] testrunner improvements (?)
69
    con.set_isolation_level(0)
1102 by Canonical.com Patch Queue Manager
Lucille had some XXXs which should have been NOTEs
70
    cur = con.cursor()
1064.1.3 by James Henstridge
merge from marius
71
    try:
2083 by Canonical.com Patch Queue Manager
[r=jamesh] testrunner improvements (?)
72
        cur.execute('drop database launchpad_ftest_template')
5821.2.85 by James Henstridge
Add "make check_launchpad_storm_on_merge" target that runs the tests
73
    except psycopg2.ProgrammingError, x:
1520 by Canonical.com Patch Queue Manager
Review and fix database security update code
74
        if 'does not exist' not in str(x):
75
            raise
2083 by Canonical.com Patch Queue Manager
[r=jamesh] testrunner improvements (?)
76
    cur.execute("""
77
        select count(*) from pg_stat_activity
78
        where datname in ('launchpad_dev',
79
            'launchpad_ftest_template', 'launchpad_ftest')
80
        """)
81
    existing_connections = cur.fetchone()[0]
82
    if existing_connections > 0:
83
        print 'Cannot rebuild database. There are %d open connections.' % (
84
                existing_connections,
85
                )
86
        return 1
1102 by Canonical.com Patch Queue Manager
Lucille had some XXXs which should have been NOTEs
87
    cur.close()
88
    con.close()
89
90
    # Build the template database. Tests duplicate this.
91
    here = os.path.dirname(os.path.realpath(__file__))
92
    schema_dir = os.path.join(here, 'database', 'schema')
1297 by Canonical.com Patch Queue Manager
Merge in database security branch
93
    if os.system('cd %s; make test PYTHON=%s > /dev/null' % (
1155 by Canonical.com Patch Queue Manager
More robust authentication
94
        schema_dir, sys.executable)) != 0:
1764 by Canonical.com Patch Queue Manager
Now make check fails if anything goes wrong when loading the sampledata. r=stub
95
        print 'Failed to create database or load sampledata.'
1102 by Canonical.com Patch Queue Manager
Lucille had some XXXs which should have been NOTEs
96
        return 1
97
98
    # Sanity check the database. No point running tests if the
99
    # bedrock is crumbling.
5821.2.85 by James Henstridge
Add "make check_launchpad_storm_on_merge" target that runs the tests
100
    con = psycopg2.connect('dbname=launchpad_ftest_template')
1102 by Canonical.com Patch Queue Manager
Lucille had some XXXs which should have been NOTEs
101
    cur = con.cursor()
102
    cur.execute('show search_path')
103
    search_path = cur.fetchone()[0]
104
    if search_path != '$user,public,ts2':
105
        print 'Search path incorrect.'
106
        print 'Add the following line to /etc/postgresql/postgresql.conf:'
107
        print "    search_path = '$user,public,ts2'"
1064.1.3 by James Henstridge
merge from marius
108
        print "and tell postgresql to reload its configuration file."
1102 by Canonical.com Patch Queue Manager
Lucille had some XXXs which should have been NOTEs
109
        return 1
110
    cur.execute("""
111
        select pg_encoding_to_char(encoding) as encoding from pg_database
112
        where datname='launchpad_ftest_template'
113
        """)
114
    enc = cur.fetchone()[0]
3242.1.5 by Stuart Bishop
Make test_on_merge.py work with PostgreSQL 8.1
115
    if enc not in ('UNICODE', 'UTF8'):
1102 by Canonical.com Patch Queue Manager
Lucille had some XXXs which should have been NOTEs
116
        print 'Database encoding incorrectly set'
117
        return 1
1257 by Canonical.com Patch Queue Manager
Improve database locale checks, add locale sanity check to test_on_merge.py and improve test_on_merge output
118
    cur.execute(r"""
119
        SELECT setting FROM pg_settings
120
        WHERE context='internal' AND name='lc_ctype'
121
        """)
122
    loc = cur.fetchone()[0]
2083 by Canonical.com Patch Queue Manager
[r=jamesh] testrunner improvements (?)
123
    #if not (loc.startswith('en_') or loc in ('C', 'en')):
124
    if loc != 'C':
1257 by Canonical.com Patch Queue Manager
Improve database locale checks, add locale sanity check to test_on_merge.py and improve test_on_merge output
125
        print 'Database locale incorrectly set. Need to rerun initdb.'
126
        return 1
127
1102 by Canonical.com Patch Queue Manager
Lucille had some XXXs which should have been NOTEs
128
    # Explicity close our connections - things will fail if we leave open
129
    # connections.
130
    cur.close()
131
    del cur
132
    con.close()
133
    del con
134
135
    print 'Running tests.'
2083 by Canonical.com Patch Queue Manager
[r=jamesh] testrunner improvements (?)
136
    os.chdir(here)
137
    cmd = [sys.executable, 'test.py'] + sys.argv[1:]
138
    print ' '.join(cmd)
4107.1.9 by Stuart Bishop
Increase test_on_merge timeout to one hour
139
140
    # Run the test suite and return the error code
141
    #return call(cmd)
142
3308.1.2 by Stuart Bishop
Make test_on_merge.py do incremental output
143
    proc = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=STDOUT)
2083 by Canonical.com Patch Queue Manager
[r=jamesh] testrunner improvements (?)
144
    proc.stdin.close()
145
3258.1.1 by Andrew Bennetts
Fix backwards timeout detection logic in test_on_merge.py
146
    # Do proc.communicate(), but timeout if there's no activity on stdout or
147
    # stderr for too long.
3308.1.2 by Stuart Bishop
Make test_on_merge.py do incremental output
148
    open_readers = set([proc.stdout])
3308.1.4 by Stuart Bishop
Fix test_on_merge.py incremental output
149
    while open_readers:
2083 by Canonical.com Patch Queue Manager
[r=jamesh] testrunner improvements (?)
150
        rlist, wlist, xlist = select(open_readers, [], [], TIMEOUT)
151
4092.2.18 by Barry Warsaw
Respond to spiv's review:
152
        if len(rlist) == 0:
3258.1.1 by Andrew Bennetts
Fix backwards timeout detection logic in test_on_merge.py
153
            if proc.poll() is not None:
2083 by Canonical.com Patch Queue Manager
[r=jamesh] testrunner improvements (?)
154
                break
6393.2.2 by Joey Stanford
working updates since I had to change the line for pyflakes
155
            print ("\nA test appears to be hung. There has been no output for"
156
                " %d seconds. Sending SIGTERM." % TIMEOUT)
2083 by Canonical.com Patch Queue Manager
[r=jamesh] testrunner improvements (?)
157
            killem(proc.pid, SIGTERM)
158
            time.sleep(3)
3258.1.1 by Andrew Bennetts
Fix backwards timeout detection logic in test_on_merge.py
159
            if proc.poll() is not None:
6393.2.2 by Joey Stanford
working updates since I had to change the line for pyflakes
160
                print ("\nSIGTERM did not work. Sending SIGKILL.")
2083 by Canonical.com Patch Queue Manager
[r=jamesh] testrunner improvements (?)
161
                killem(proc.pid, SIGKILL)
4092.2.12 by Barry Warsaw
Thanks to jamesh, do a better job of draining the subprocess's stdout and
162
            # Drain the subprocess's stdout and stderr.
163
            sys.stdout.write(proc.stdout.read())
164
            break
2083 by Canonical.com Patch Queue Manager
[r=jamesh] testrunner improvements (?)
165
166
        if proc.stdout in rlist:
3308.1.2 by Stuart Bishop
Make test_on_merge.py do incremental output
167
            chunk = os.read(proc.stdout.fileno(), 1024)
3367.1.2 by Stuart Bishop
Don't insert random spaces in test_on_merge.py output
168
            sys.stdout.write(chunk)
3308.1.2 by Stuart Bishop
Make test_on_merge.py do incremental output
169
            if chunk == "":
3308.1.4 by Stuart Bishop
Fix test_on_merge.py incremental output
170
                open_readers.remove(proc.stdout)
3308.1.2 by Stuart Bishop
Make test_on_merge.py do incremental output
171
3308.1.4 by Stuart Bishop
Fix test_on_merge.py incremental output
172
    rv = proc.wait()
3308.1.2 by Stuart Bishop
Make test_on_merge.py do incremental output
173
    if rv == 0:
6393.2.2 by Joey Stanford
working updates since I had to change the line for pyflakes
174
        print '\nSuccessfully ran all tests.'
1102 by Canonical.com Patch Queue Manager
Lucille had some XXXs which should have been NOTEs
175
    else:
3308.1.2 by Stuart Bishop
Make test_on_merge.py do incremental output
176
        print '\nTests failed (exit code %d)' % rv
177
178
    return rv
179
1102 by Canonical.com Patch Queue Manager
Lucille had some XXXs which should have been NOTEs
180
2083 by Canonical.com Patch Queue Manager
[r=jamesh] testrunner improvements (?)
181
def killem(pid, signal):
182
    """Kill the process group leader identified by pid and other group members
183
184
    Note that test.py sets its process to a process group leader.
185
    """
186
    try:
187
        os.killpg(os.getpgid(pid), signal)
188
    except OSError, x:
189
        if x.errno == errno.ESRCH:
190
            pass
191
        else:
192
            raise
193
1102 by Canonical.com Patch Queue Manager
Lucille had some XXXs which should have been NOTEs
194
if __name__ == '__main__':
195
    sys.exit(main())