summaryrefslogtreecommitdiff
path: root/test/pacman/pactest.py
blob: b5f6d4d7c9259adae66014c0c05b549a37ddaefa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
#! /usr/bin/python2
#
#  pactest : run automated testing on the pacman binary
#
#  Copyright (c) 2006 by Aurelien Foret <orelien@chez.com>
#  Copyright (c) 2006-2017 Pacman Development Team <pacman-dev@archlinux.org>
#
#  This program is free software; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation; either version 2 of the License, or
#  (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program.  If not, see <http://www.gnu.org/licenses/>.

from optparse import OptionParser
import os
import shutil
import sys
import tempfile
import glob
import subprocess

import pmenv
import tap
import util

__author__ = "Aurelien FORET"
__version__ = "0.4"

# writer to send output to multiple destinations simultaneously
class MultiWriter():
    def __init__(self, *outputs):
        self.outputs = outputs

    def write(self, message):
        for op in self.outputs:
            op.write(message)

# duplicate stdout/stderr to a temporary file
class OutputSaver():
    def __init__(self):
        self.save_file = tempfile.NamedTemporaryFile(prefix='pactest-output-')

    def __enter__(self):
        sys.stdout = MultiWriter(sys.stdout, self.save_file)
        sys.stderr = MultiWriter(sys.stderr, self.save_file)
        return self.save_file

    def __exit__(self, type, value, traceback):
        sys.stdout = sys.__stdout__
        sys.stderr = sys.__stderr__
        self.save_file.flush()

def create_parser():
    usage = "usage: %prog [options] <path/to/testfile.py>..."
    description = "Runs automated tests on the pacman binary. Tests are " \
            "described using an easy python syntax, and several can be " \
            "ran at once."
    parser = OptionParser(usage = usage, description = description)

    parser.add_option("-v", "--verbose", action = "count",
                      dest = "verbose", default = 0,
                      help = "print verbose output")
    parser.add_option("-d", "--debug", type = "int",
                      dest = "debug", default = 0,
                      help = "set debug level for pacman")
    parser.add_option("-p", "--pacman", type = "string",
                      dest = "bin", default = None,
                      help = "specify location of the pacman binary")
    parser.add_option("--bindir", type = "string",
                      dest = "bindir", action = "append",
                      help = "specify location of binaries")
    parser.add_option("--keep-root", action = "store_true",
                      dest = "keeproot", default = False,
                      help = "don't remove the generated pacman root filesystem")
    parser.add_option("--nolog", action = "store_true",
                      dest = "nolog", default = False,
                      help = "do not log pacman messages")
    parser.add_option("--gdb", action = "store_true",
                      dest = "gdb", default = False,
                      help = "use gdb while calling pacman")
    parser.add_option("--valgrind", action = "store_true",
                      dest = "valgrind", default = False,
                      help = "use valgrind while calling pacman")
    parser.add_option("--manual-confirm", action = "store_true",
                      dest = "manualconfirm", default = False,
                      help = "do not use --noconfirm for pacman calls")
    parser.add_option("--scriptlet-shell", type = "string",
                      dest = "scriptletshell", default = "/bin/sh",
                      help = "specify path to shell used for install scriptlets")
    parser.add_option("--ldconfig", type = "string",
                      dest = "ldconfig", default = "/sbin/ldconfig",
                      help = "specify path to ldconfig")
    parser.add_option("--review", action = "store_true",
                      dest = "review", default = False,
                      help = "review test files, test output, and saved logs")
    parser.add_option("--editor", action = "store",
                      dest = "editor", default = os.getenv('EDITOR', 'vim'),
                      help = "editor to use for viewing files")
    return parser


if __name__ == "__main__":

    if sys.hexversion < 0x02070000:
        # bailing now with clear message better than mid-run with unhelpful one
        tap.bail("Python versions before 2.7 are not supported.")
        sys.exit(1)

    # parse options
    opt_parser = create_parser()
    (opts, args) = opt_parser.parse_args()

    if args is None or len(args) == 0:
        tap.bail("no tests defined, nothing to do")
        sys.exit(2)

    # instantiate env
    root_path = tempfile.mkdtemp(prefix='pactest-')
    env = pmenv.pmenv(root=root_path)

    # add parsed options to env object
    util.verbose = opts.verbose
    env.pacman["debug"] = opts.debug
    env.pacman["bin"] = opts.bin
    env.pacman["bindir"] = opts.bindir
    env.pacman["nolog"] = opts.nolog
    env.pacman["gdb"] = opts.gdb
    env.pacman["valgrind"] = opts.valgrind
    env.pacman["manual-confirm"] = opts.manualconfirm
    env.pacman["scriptlet-shell"] = opts.scriptletshell
    env.pacman["ldconfig"] = opts.ldconfig

    try:
        for i in args:
            env.addtest(i)
    except Exception as e:
        tap.bail(e)
        os.rmdir(root_path)
        sys.exit(2)

    # run tests
    if not opts.review:
        env.run()
    else:
        # save output in tempfile for review
        with OutputSaver() as save_file:
            env.run()
        files = [save_file.name] + args + glob.glob(root_path + "/var/log/*")
        subprocess.call([opts.editor] + files)

    if not opts.keeproot:
        shutil.rmtree(root_path)
    else:
        tap.diag("pacman testing root saved: %s" % root_path)

    if env.failed > 0:
        sys.exit(1)

# vim: set ts=4 sw=4 et: