File: basictest.py

package info (click to toggle)
lttoolbox 3.8.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,516 kB
  • sloc: cpp: 13,541; ansic: 3,131; python: 1,212; makefile: 17
file content (173 lines) | stat: -rw-r--r-- 5,825 bytes parent folder | download | duplicates (2)
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
167
168
169
170
171
172
173
# -*- coding: utf-8 -*-
import os
from shutil import rmtree
import signal
from subprocess import run, call, PIPE, Popen
from sys import stderr
from tempfile import mkdtemp
from typing import List

class Alarm(Exception):
    pass

class BasicTest:
    def alarmHandler(self, signum, frame):
        raise Alarm

    def withTimeout(self, seconds, cmd, *args, **kwds):
        # Windows doesn't have SIGALRM
        try:
            signal.signal(signal.SIGALRM, self.alarmHandler)
            signal.alarm(seconds)
            ret = cmd(*args, **kwds)
            signal.alarm(0)         # reset the alarm
        except AttributeError:
            ret = cmd(*args, **kwds)
        return ret

    def communicateFlush(self, string, process):
        if string:
            process.stdin.write(string.encode('utf-8'))
            process.stdin.write(b'\0')
            process.stdin.flush()

        output = []
        char = None
        try:
            char = self.withTimeout(10, process.stdout.read, 1)
        except Alarm:
            print("Timeout before reading a single character!", file=stderr)
        while char and char != b'\0':
            output.append(char)
            try:
                char = self.withTimeout(10, process.stdout.read, 1)
            except Alarm:
                print("Timeout before reading %s chars" % len(output),
                      file=stderr)
                break           # send what we got up till now

        return b"".join(output).decode('utf-8').replace('\r\n', '\n')

    def openPipe(self, procName, args):
        return Popen([os.environ['LTTOOLBOX_PATH']+'/'+procName] + args,
                     stdin=PIPE, stdout=PIPE, stderr=PIPE)
    def closePipe(self, proc, expectFail=False):
        proc.communicate() # let it terminate
        proc.stdin.close()
        proc.stdout.close()
        proc.stderr.close()
        retCode = proc.poll()
        if expectFail:
            self.assertNotEqual(retCode, 0)
        else:
            self.assertEqual(retCode, 0)

    def compileDix(self, dir, dix, flags=None, binName='compiled.bin',
                   expectFail=False):
        return self.callProc('lt-comp',
                             [dir, dix, binName],
                             flags,
                             expectFail)

    def callProc(self, name, bins, flags=None, expectFail=False):
        cmd = [os.environ['LTTOOLBOX_PATH']+'/'+name] + (flags or []) + bins
        res = run(cmd, capture_output=True)
        if (res.returncode == 0) == expectFail:
            print("\nFAILED CMD: " + " ".join(cmd))
            print("\nSTDOUT:", res.stdout)
            print("STDERR:", res.stderr)
        if expectFail:
            self.assertNotEqual(res.returncode, 0)
            return False
        else:
            self.assertEqual(res.returncode, 0)
            return True


class TempDir:
    def __enter__(self):
        self.tmpd = mkdtemp()
        return self.tmpd

    def __exit__(self, *args):
        rmtree(self.tmpd)


class PrintTest(BasicTest):
    """See lt_print test for how to use this. Override runTest if you don't
    want to use NUL flushing."""

    printdix = "data/minimal-mono.dix"
    printdir = "lr"
    expectedOutput = ""
    expectedRetCodeFail = False
    printflags = []

    def compileTest(self, tmpd):
        return self.compileDix(self.printdir, self.printdix,
                               binName=tmpd+'/compiled.bin')

    def runTest(self):
        with TempDir() as tmpd:
            self.compileTest(tmpd)
            self.printresult = self.openPipe('lt-print',
                                             self.printflags
                                             + [tmpd+'/compiled.bin'])

            self.assertEqual(self.communicateFlush(None, self.printresult),
                             self.expectedOutput)

            self.closePipe(self.printresult, self.expectedRetCodeFail)


class ProcTest(BasicTest):
    """See lt_proc test for how to use this. Override runTest if you don't
    want to use NUL flushing."""

    procdix = "data/minimal-mono.dix"
    procdir = "lr"
    compflags = []              # type: List[str]
    procflags = ["-z"]
    inputs = [""]
    expectedOutputs = [""]
    expectedRetCodeFail = False
    expectedCompRetCodeFail = False
    flushing = True

    def compileTest(self, tmpd):
        return self.compileDix(self.procdir, self.procdix,
                               flags=self.compflags,
                               binName=tmpd+'/compiled.bin',
                               expectFail=self.expectedCompRetCodeFail)

    def runTest(self):
        with TempDir() as tmpd:
            if not self.compileTest(tmpd):
                return
            if self.flushing:
                self.runTestFlush(tmpd)
            else:
                self.runTestNoFlush(tmpd)

    def openProc(self, tmpd):
        return self.openPipe('lt-proc', self.procflags+[tmpd+'/compiled.bin'])

    def runTestFlush(self, tmpd):
        proc = self.openProc(tmpd)
        self.assertEqual(len(self.inputs),
                         len(self.expectedOutputs))
        for inp, exp in zip(self.inputs, self.expectedOutputs):
            self.assertEqual(self.communicateFlush(inp+"[][\n]", proc),
                             exp+"[][\n]")
        self.closePipe(proc, self.expectedRetCodeFail)

    def runTestNoFlush(self, tmpd):
        for inp, exp in zip(self.inputs, self.expectedOutputs):
            proc = self.openProc(tmpd)
            self.assertEqual(proc.communicate(input=inp.encode('utf-8'))[0],
                             exp.encode('utf-8'))
            retCode = proc.poll()
            if self.expectedRetCodeFail:
                self.assertNotEqual(retCode, 0)
            else:
                self.assertEqual(retCode, 0)