File: test_main.py

package info (click to toggle)
pcbasic 2.0.7-9
  • links: PTS
  • area: main
  • in suites: sid
  • size: 35,416 kB
  • sloc: python: 28,411; sh: 103; makefile: 10
file content (313 lines) | stat: -rw-r--r-- 12,204 bytes parent folder | download | duplicates (3)
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
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
# -*- coding: utf-8 -*-

"""
PC-BASIC test.main
unit tests for main script

(c) 2022--2023 Rob Hagemans
This file is released under the GNU GPL version 3 or later.
"""

import io
import sys
import unittest
from tempfile import NamedTemporaryFile

from pcbasic import main
from pcbasic.compat import stdio
from pcbasic.debug import DebugException
from tests.unit.utils import TestCase, run_tests
from pcbasic.compat import PY2, WIN32


class MainTest(TestCase):
    """Unit tests for main script."""

    tag = u'main'

    def test_version(self):
        """Test version call."""
        # currently can only redirect to bytes io
        output = io.BytesIO()
        with stdio.redirect_output(output, 'stdout'):
            main('-v')
        assert output.getvalue().startswith(b'PC-BASIC'), output.getvalue()

    def test_debug_version(self):
        """Test debug version call."""
        # currently can only redirect to bytes io
        output = io.BytesIO()
        with stdio.redirect_output(output, 'stdout'):
            main('-v', '--debug')
        assert output.getvalue().startswith(b'PC-BASIC'), output.getvalue()

    def test_usage(self):
        """Test usage call."""
        output = io.BytesIO()
        with stdio.redirect_output(output, 'stdout'):
            main('-h')
        assert output.getvalue().startswith(b'SYNOPSIS'), output.getvalue()

    def test_script(self):
        """Test script run."""
        output = io.BytesIO()
        with stdio.redirect_output(output, 'stdout'):
            main('-nqe', '?1')
        assert output.getvalue() == b' 1 \r\n', output.getvalue()

    # exercise interfaces

    def test_cli(self):
        """Exercise cli run."""
        with stdio.quiet():
            main('-bq')

    def test_text(self):
        """Exercise text-based run."""
        with stdio.quiet():
            main('-tq')

    def test_graphical(self):
        """Exercise graphical run."""
        with stdio.quiet():
            main('-q')

    def test_bad_interface(self):
        """Exercise run with bad interface."""
        with stdio.quiet():
            main('--interface=_no_such_interface_', '-q')

    # exercise sound

    @unittest.skip('cutting off sound being played on sdl2 leads to segfaults')
    def test_cli_beep(self):
        """Exercise cli run."""
        with stdio.quiet():
            main('-bqe', 'beep')

    @unittest.skip('cutting off sound being played on sdl2 leads to segfaults')
    def test_graphical_beep(self):
        """Exercise graphical run."""
        with stdio.quiet():
            main('-qe', 'beep')

    # resume

    def test_resume_output(self):
        """Test resume with open empty output file."""
        with NamedTemporaryFile('w+b', delete=False) as state_file:
            with stdio.quiet():
                main(
                    "--exec=A=1:open\"z:output.txt\" for output as 1:SYSTEM",
                    '--mount=z:%s' % self.output_path(), '-n',
                    '--state=%s' % state_file.name,
                )
                main(
                    '--resume', '--keys=?#1,A:close:system\\r', '-n',
                    '--state=%s' % state_file.name,
                )
        with open(self.output_path('OUTPUT.TXT'), 'rb') as outfile:
            output = outfile.read()
        assert output == b' 1 \r\n\x1a', repr(output)

    def test_resume_output_used(self):
        """Test resume with open used output file."""
        with NamedTemporaryFile('w+b', delete=False) as state_file:
            with stdio.quiet():
                main(
                    "--exec=A=1:open\"z:output.txt\" for output as 1:?#1,2:SYSTEM",
                    '--mount=z:%s' % self.output_path(), '-n',
                    '--state=%s' % state_file.name,
                )
                main(
                    '--resume', '--keys=?#1,A:close:system\\r', '-n',
                    '--state=%s' % state_file.name,
                )
        with open(self.output_path('OUTPUT.TXT'), 'rb') as outfile:
            output = outfile.read()
        assert output == b' 2 \r\n 1 \r\n\x1a', repr(output)

    def test_resume_input(self):
        """Test resume with open input file."""
        with NamedTemporaryFile('w+b', delete=False) as state_file:
            with stdio.quiet():
                main(
                    '-n',
                    "--exec=open\"z:test.txt\" for output as 1:?#1,1,2:close:open\"z:test.txt\" for input as 1:input#1,a:SYSTEM",
                    '--mount=z:%s' % self.output_path(),
                    '--state=%s' % state_file.name,
                )
                main(
                    '--resume', '--keys=input#1,B:close:open "output.txt" for output as 1:?#1, a; b:close:system\\r', '-n',
                    '--state=%s' % state_file.name,
                )
        with open(self.output_path('OUTPUT.TXT'), 'rb') as outfile:
            output = outfile.read()
        assert output == b' 1  2 \r\n\x1a', repr(output)

    def test_resume_music(self):
        """Test resume with music queue."""
        with NamedTemporaryFile('w+b', delete=False) as state_file:
            with stdio.quiet():
                main(
                    '--exec=play"mbcdefgab>cdefgab"','-nq',
                    '--mount=z:%s' % self.output_path(),
                    '--state=%s' % state_file.name,
                )
                main(
                    '--resume',
                    '--state=%s' % state_file.name,
                    '-nk',
                    'q=play(0)\ropen"z:output.txt" for output as 1:?#1,q:close:system\r',
                )
        with open(self.output_path('OUTPUT.TXT'), 'rb') as outfile:
            output = outfile.read()
        assert output == b' 13 \r\n\x1a', repr(output)


class ConvertTest(TestCase):
    """Unit tests for convert script."""

    tag = u'convert'

    def test_ascii_to_tokenised(self):
        """Test converting raw text to tokenised."""
        with NamedTemporaryFile('w+b', delete=False) as outfile:
            with NamedTemporaryFile('w+b', delete=False) as infile:
                infile.write(b'10 ? 1\r\n\x1a')
                infile.seek(0)
                main('--convert=b', infile.name, outfile.name)
            outfile.seek(0)
            outstr = outfile.read()
            assert outstr == b'\xff\x76\x12\x0a\x00\x91\x20\x12\x00\x00\x00\x1a', outstr

    def test_ascii_to_protected(self):
        """Test converting raw text to protected."""
        with NamedTemporaryFile('w+b', delete=False) as outfile:
            with NamedTemporaryFile('w+b', delete=False) as infile:
                infile.write(b'10 ? 1\r\n\x1a')
                infile.seek(0)
                main('--convert=p', infile.name, outfile.name)
            outfile.seek(0)
            outstr = outfile.read()
            assert outstr == b'\xfe\xe9\xa9\xbf\x54\xe2\x12\xad\xf1\x89\xf9\x1a', outstr

    def test_tokenised_to_ascii(self):
        """Test converting tokenised to raw text."""
        with NamedTemporaryFile('w+b', delete=False) as outfile:
            with NamedTemporaryFile('w+b', delete=False) as infile:
                infile.write(b'\xff\x76\x12\x0a\x00\x91\x20\x12\x00\x00\x00\x1a')
                infile.seek(0)
                main('--convert=a', infile.name, outfile.name)
            outfile.seek(0)
            outstr = outfile.read()
            assert outstr == b'10 PRINT 1\r\n\x1a', outstr

    def test_protected_to_ascii(self):
        """Test converting protected to raw text."""
        with NamedTemporaryFile('w+b', delete=False) as outfile:
            with NamedTemporaryFile('w+b', delete=False) as infile:
                infile.write(b'\xfe\xe9\xa9\xbf\x54\xe2\x12\xad\xf1\x89\xf9\x1a')
                infile.seek(0)
                main('--convert=a', infile.name, outfile.name)
            outfile.seek(0)
            outstr = outfile.read()
            assert outstr == b'10 PRINT 1\r\n\x1a', outstr

    def test_tokenised_to_protected(self):
        """Test converting tokenised to protected."""
        with NamedTemporaryFile('w+b', delete=False) as outfile:
            with NamedTemporaryFile('w+b', delete=False) as infile:
                infile.write(b'\xff\x76\x12\x0a\x00\x91\x20\x12\x00\x00\x00\x1a')
                infile.seek(0)
                main('--convert=p', infile.name, outfile.name)
            outfile.seek(0)
            outstr = outfile.read()
            # note that the EOF gets encrypted too
            assert outstr == b'\xfe\xe9\xa9\xbf\x54\xe2\x12\xad\xf1\x89\xf9\x73\x1a', outstr

    def test_protected_to_tokenised(self):
        """Test converting protected to tokenised."""
        with NamedTemporaryFile('w+b', delete=False) as outfile:
            with NamedTemporaryFile('w+b', delete=False) as infile:
                infile.write(b'\xfe\xe9\xa9\xbf\x54\xe2\x12\xad\xf1\x89\xf9\x1a')
                infile.seek(0)
                main('--convert=b', infile.name, outfile.name)
            outfile.seek(0)
            outstr = outfile.read()
            assert outstr == b'\xff\x76\x12\x0a\x00\x91\x20\x12\x00\x00\x00\x1a', outstr

    def test_default(self):
        """Test converter run."""
        with NamedTemporaryFile('w+b', delete=False) as outfile:
            with NamedTemporaryFile('w+b', delete=False) as infile:
                infile.write(b'\xfe\xe9\xa9\xbf\x54\xe2\x12\xad\xf1\x89\xf9\x1a')
                infile.seek(0)
                main('--convert', infile.name, outfile.name)
            outfile.seek(0)
            outstr = outfile.read()
            assert outstr == b'10 PRINT 1\r\n\x1a', outstr

    @unittest.skipIf(PY2, 'NamedTemoraryFile has no encoding argument in Python 2.')
    def test_ascii_to_tokenised_encoding(self):
        """Test converting utf-8 text to tokenised."""
        with NamedTemporaryFile('w+b', delete=False) as outfile:
            with NamedTemporaryFile('w+', delete=False, encoding='utf-8') as infile:
                infile.write('10 ? "£"\r\n\x1a')
                infile.seek(0)
                main('--text-encoding=utf-8', '--convert=b', infile.name, outfile.name)
            outfile.seek(0)
            outstr = outfile.read()
            assert outstr == b'\xff\x78\x12\x0a\x00\x91\x20\x22\x9c\x22\x00\x00\x00\x1a', outstr

    def test_tokenised_to_ascii_encoding(self):
        """Test converting tokenised to latin-1 text."""
        with io.open(
                self.output_path('latin-1.bas'), 'w+', encoding='latin-1', newline=''
            ) as outfile:
            with io.open(self.output_path('bin.bas'), 'w+b') as infile:
                infile.write(b'\xff\x78\x12\x0a\x00\x91\x20\x22\x9c\x22\x00\x00\x00\x1a')
                infile.seek(0)
                main('--text-encoding=latin-1', '--convert=a', infile.name, outfile.name)
            outfile.seek(0)
            outstr = outfile.read()
            assert outstr == u'10 PRINT "£"\r\n\x1a', repr(outstr)


class DebugTest(TestCase):
    """Unit tests for debugging main calls."""

    tag = u'debug_main'

    def test_debug_version(self):
        """Test debug version call."""
        # currently can only redirect to bytes io
        output = io.BytesIO()
        with stdio.redirect_output(output, 'stdout'):
            main('-v', '--debug')
        assert output.getvalue().startswith(b'PC-BASIC')

    def test_crash_direct(self):
        """Exercise graphical run and trigger bluescreen from direct mode."""
        with NamedTemporaryFile('w+b', delete=False) as state_file:
            with stdio.quiet():
                main(
                    '--extension=crashtest',
                    '-qe', '_CRASH', '-k', 'system\r'
                    '--state=%s' % state_file,
                )

    def test_crash_in_program(self):
        """Exercise graphical run and trigger bluescreen from a program line."""
        return
        with NamedTemporaryFile('w+b', delete=False) as state_file:
            with stdio.quiet():
                main(
                    '--extension=crashtest',
                    '-k', '10 _crash\r20 system\rrun\r',
                    '--state=%s' % state_file,
                )


if __name__ == '__main__':
    run_tests()