change look-up -> look up
[scons.git] / testing / framework / TestCmdTests.py
blob61c0c5da97de7f1d1f97b56377578fddb852fa58
1 #!/usr/bin/env python
3 # Copyright 2000-2010 Steven Knight
5 # This module is free software, and you may redistribute it and/or modify
6 # it under the same terms as Python itself, so long as this copyright message
7 # and disclaimer are retained in their original form.
9 # IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
10 # SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF
11 # THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
12 # DAMAGE.
14 # THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
15 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
16 # PARTICULAR PURPOSE. THE CODE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS,
17 # AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
18 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
20 # Python License: https://docs.python.org/3/license.html#psf-license
22 """
23 Unit tests for the TestCmd.py module.
24 """
26 import os
27 import shutil
28 import stat
29 import subprocess
30 import sys
31 import tempfile
32 import time
33 import unittest
34 from io import StringIO
35 from contextlib import closing
36 from collections import UserList
37 from subprocess import PIPE
39 from SCons.Util import to_bytes, to_str
42 # Strip the current directory so we get the right TestCmd.py module.
43 sys.path = sys.path[1:]
45 import TestCmd
46 from TestCmd import _python_
48 def _is_readable(path):
49 # XXX this doesn't take into account UID, it assumes it's our file
50 return os.stat(path)[stat.ST_MODE] & stat.S_IREAD
52 def _is_writable(path):
53 # XXX this doesn't take into account UID, it assumes it's our file
54 return os.stat(path)[stat.ST_MODE] & stat.S_IWRITE
56 def _is_executable(path):
57 # XXX this doesn't take into account UID, it assumes it's our file
58 return os.stat(path)[stat.ST_MODE] & stat.S_IEXEC
60 def _clear_dict(dict, *keys) -> None:
61 for key in keys:
62 try:
63 del dict[key]
64 except KeyError:
65 pass
68 class ExitError(Exception):
69 pass
71 class TestCmdTestCase(unittest.TestCase):
72 """Base class for TestCmd test cases, with fixture and utility methods."""
74 def setUp(self) -> None:
75 self.orig_cwd = os.getcwd()
77 def tearDown(self) -> None:
78 os.chdir(self.orig_cwd)
80 def setup_run_scripts(self):
81 class T:
82 pass
84 t = T()
86 t.script = 'script'
87 t.scriptx = 'scriptx.bat'
88 t.script1 = 'script_1.txt'
89 t.scriptout = 'scriptout'
90 t.scripterr = 'scripterr'
91 fmt = "import os, sys; cwd = os.getcwd(); " + \
92 "sys.stdout.write('%s: STDOUT: %%s: %%s\\n' %% (cwd, sys.argv[1:])); " + \
93 "sys.stderr.write('%s: STDERR: %%s: %%s\\n' %% (cwd, sys.argv[1:]))"
94 fmtout = "import os, sys; cwd = os.getcwd(); " + \
95 "sys.stdout.write('%s: STDOUT: %%s: %%s\\n' %% (cwd, sys.argv[1:]))"
96 fmterr = "import os, sys; cwd = os.getcwd(); " + \
97 "sys.stderr.write('%s: STDERR: %%s: %%s\\n' %% (cwd, sys.argv[1:]))"
98 text = fmt % (t.script, t.script)
99 textx = fmt % (t.scriptx, t.scriptx)
100 if sys.platform == 'win32':
101 textx = textx.replace('%', '%%')
102 textx = f"@{_python_} -c \"{textx}\" %1 %2 %3 %4 %5 %6 %7 %8 %9\n"
103 else:
104 textx = f"#!{_python_}\n{textx}\n"
105 text1 = f"A first line to be ignored!\n{fmt % (t.script1, t.script1)}"
106 textout = fmtout % t.scriptout
107 texterr = fmterr % t.scripterr
109 run_env = TestCmd.TestCmd(workdir = '')
110 run_env.subdir('sub dir')
111 t.run_env = run_env
113 t.sub_dir = run_env.workpath('sub dir')
114 t.script_path = run_env.workpath('sub dir', t.script)
115 t.scriptx_path = run_env.workpath('sub dir', t.scriptx)
116 t.script1_path = run_env.workpath('sub dir', t.script1)
117 t.scriptout_path = run_env.workpath('sub dir', t.scriptout)
118 t.scripterr_path = run_env.workpath('sub dir', t.scripterr)
120 run_env.write(t.script_path, text)
121 run_env.write(t.scriptx_path, textx)
122 run_env.write(t.script1_path, text1)
123 run_env.write(t.scriptout_path, textout)
124 run_env.write(t.scripterr_path, texterr)
126 os.chmod(t.script_path, 0o644) # XXX UNIX-specific
127 os.chmod(t.scriptx_path, 0o755) # XXX UNIX-specific
128 os.chmod(t.script1_path, 0o644) # XXX UNIX-specific
129 os.chmod(t.scriptout_path, 0o644) # XXX UNIX-specific
130 os.chmod(t.scripterr_path, 0o644) # XXX UNIX-specific
132 t.orig_cwd = os.getcwd()
134 t.workdir = run_env.workpath('sub dir')
135 os.chdir(t.workdir)
137 return t
139 def translate_newlines(self, data):
140 data = data.replace("\r\n", "\n")
141 return data
143 def call_python(self, indata, python=None):
144 if python is None:
145 python = sys.executable
146 cp = subprocess.run(python, input=to_bytes(indata), stderr=PIPE, stdout=PIPE)
147 stdout = self.translate_newlines(to_str(cp.stdout))
148 stderr = self.translate_newlines(to_str(cp.stderr))
149 return stdout, stderr, cp.returncode
151 def popen_python(self, indata, status: int=0, stdout: str="", stderr: str="", python=None) -> None:
152 if python is None:
153 python = sys.executable
154 _stdout, _stderr, _status = self.call_python(indata, python)
155 assert _status == status, (
156 f"status = {_status}, expected {status}\n"
157 f"STDOUT ===================\n{_stdout}"
158 f"STDERR ===================\n{_stderr}"
160 assert _stdout == stdout, (
161 f"Expected STDOUT ==========\n{stdout}"
162 f"Actual STDOUT ============\n{_stdout}"
163 f"STDERR ===================\n{_stderr}"
165 assert _stderr == stderr, (
166 f"Expected STDERR ==========\n{stderr}"
167 f"Actual STDERR ============\n{_stderr}"
170 def run_match(self, content, *args) -> None:
171 expect = "%s: %s: %s: %s\n" % args
172 content = self.translate_newlines(to_str(content))
173 assert content == expect, (
174 f"Expected {args[1] + expect} ==========\n"
175 f"Actual {args[1] + content} ============\n"
180 class __init__TestCase(TestCmdTestCase):
181 def test_init(self) -> None:
182 """Test init()"""
183 test = TestCmd.TestCmd()
184 test = TestCmd.TestCmd(description = 'test')
185 test = TestCmd.TestCmd(description = 'test', program = 'foo')
186 test = TestCmd.TestCmd(description = 'test',
187 program = 'foo',
188 universal_newlines=None)
192 class basename_TestCase(TestCmdTestCase):
193 def test_basename(self) -> None:
194 """Test basename() [XXX TO BE WRITTEN]"""
195 assert 1 == 1
199 class cleanup_TestCase(TestCmdTestCase):
200 def test_cleanup(self) -> None:
201 """Test cleanup()"""
202 test = TestCmd.TestCmd(workdir = '')
203 wdir = test.workdir
204 test.write('file1', "Test file #1\n")
205 test.cleanup()
206 assert not os.path.exists(wdir)
208 def test_writable(self) -> None:
209 """Test cleanup() when the directory isn't writable"""
210 test = TestCmd.TestCmd(workdir = '')
211 wdir = test.workdir
212 test.write('file2', "Test file #2\n")
213 os.chmod(test.workpath('file2'), 0o400)
214 os.chmod(wdir, 0o500)
215 test.cleanup()
216 assert not os.path.exists(wdir)
218 def test_shutil(self) -> None:
219 """Test cleanup() when used with shutil"""
220 test = TestCmd.TestCmd(workdir = '')
221 wdir = test.workdir
222 os.chdir(wdir)
224 import shutil
225 save_rmtree = shutil.rmtree
226 def my_rmtree(dir, ignore_errors: int=0, wdir=wdir, _rmtree=save_rmtree):
227 assert os.getcwd() != wdir
228 return _rmtree(dir, ignore_errors=ignore_errors)
229 try:
230 shutil.rmtree = my_rmtree
231 test.cleanup()
232 finally:
233 shutil.rmtree = save_rmtree
235 def test_atexit(self) -> None:
236 """Test cleanup when atexit is used"""
237 self.popen_python(f"""\
238 import atexit
239 import sys
240 import TestCmd
242 sys.path = [r'{self.orig_cwd}'] + sys.path
244 @atexit.register
245 def cleanup():
246 print("cleanup()")
248 result = TestCmd.TestCmd(workdir='')
249 sys.exit(0)
250 """, stdout='cleanup()\n')
253 class chmod_TestCase(TestCmdTestCase):
254 def test_chmod(self) -> None:
255 """Test chmod()"""
256 test = TestCmd.TestCmd(workdir = '', subdir = 'sub')
258 wdir_file1 = os.path.join(test.workdir, 'file1')
259 wdir_sub_file2 = os.path.join(test.workdir, 'sub', 'file2')
261 with open(wdir_file1, 'w') as f:
262 f.write("")
263 with open(wdir_sub_file2, 'w') as f:
264 f.write("")
266 if sys.platform == 'win32':
268 test.chmod(wdir_file1, stat.S_IREAD)
269 test.chmod(['sub', 'file2'], stat.S_IWRITE)
271 file1_mode = stat.S_IMODE(os.stat(wdir_file1)[stat.ST_MODE])
272 assert file1_mode == 0o444, f'0{file1_mode:o}'
273 file2_mode = stat.S_IMODE(os.stat(wdir_sub_file2)[stat.ST_MODE])
274 assert file2_mode == 0o666, f'0{file2_mode:o}'
276 test.chmod('file1', stat.S_IWRITE)
277 test.chmod(wdir_sub_file2, stat.S_IREAD)
279 file1_mode = stat.S_IMODE(os.stat(wdir_file1)[stat.ST_MODE])
280 assert file1_mode == 0o666, f'0{file1_mode:o}'
281 file2_mode = stat.S_IMODE(os.stat(wdir_sub_file2)[stat.ST_MODE])
282 assert file2_mode == 0o444, f'0{file2_mode:o}'
284 else:
286 test.chmod(wdir_file1, 0o700)
287 test.chmod(['sub', 'file2'], 0o760)
289 file1_mode = stat.S_IMODE(os.stat(wdir_file1)[stat.ST_MODE])
290 assert file1_mode == 0o700, f'0{file1_mode:o}'
291 file2_mode = stat.S_IMODE(os.stat(wdir_sub_file2)[stat.ST_MODE])
292 assert file2_mode == 0o760, f'0{file2_mode:o}'
294 test.chmod('file1', 0o765)
295 test.chmod(wdir_sub_file2, 0o567)
297 file1_mode = stat.S_IMODE(os.stat(wdir_file1)[stat.ST_MODE])
298 assert file1_mode == 0o765, f'0{file1_mode:o}'
299 file2_mode = stat.S_IMODE(os.stat(wdir_sub_file2)[stat.ST_MODE])
300 assert file2_mode == 0o567, f'0{file2_mode:o}'
304 class combine_TestCase(TestCmdTestCase):
305 def test_combine(self):
306 """Test combining stdout and stderr"""
307 run_env = TestCmd.TestCmd(workdir = '')
308 run_env.write('run1', """import sys
309 sys.stdout.write("run1 STDOUT %s\\n" % sys.argv[1:])
310 sys.stdout.write("run1 STDOUT second line\\n")
311 sys.stderr.write("run1 STDERR %s\\n" % sys.argv[1:])
312 sys.stderr.write("run1 STDERR second line\\n")
313 sys.stdout.write("run1 STDOUT third line\\n")
314 sys.stderr.write("run1 STDERR third line\\n")
315 """)
316 run_env.write('run2', """import sys
317 sys.stdout.write("run2 STDOUT %s\\n" % sys.argv[1:])
318 sys.stdout.write("run2 STDOUT second line\\n")
319 sys.stderr.write("run2 STDERR %s\\n" % sys.argv[1:])
320 sys.stderr.write("run2 STDERR second line\\n")
321 sys.stdout.write("run2 STDOUT third line\\n")
322 sys.stderr.write("run2 STDERR third line\\n")
323 """)
324 cwd = os.getcwd()
325 os.chdir(run_env.workdir)
326 # Everything before this prepared our "source directory."
327 # Now do the real test.
328 try:
329 test = TestCmd.TestCmd(interpreter = 'python',
330 workdir = '',
331 combine = 1)
332 output = test.stdout()
333 if output is not None:
334 raise IndexError(f"got unexpected output:\n\t`{output}'\n")
336 # The underlying system subprocess implementations can combine
337 # stdout and stderr in different orders, so we accomodate both.
339 test.program_set('run1')
340 test.run(arguments = 'foo bar')
341 stdout_lines = """\
342 run1 STDOUT ['foo', 'bar']
343 run1 STDOUT second line
344 run1 STDOUT third line
346 stderr_lines = """\
347 run1 STDERR ['foo', 'bar']
348 run1 STDERR second line
349 run1 STDERR third line
351 foo_bar_expect = (stdout_lines + stderr_lines,
352 stderr_lines + stdout_lines)
354 test.program_set('run2')
355 test.run(arguments = 'snafu')
356 stdout_lines = """\
357 run2 STDOUT ['snafu']
358 run2 STDOUT second line
359 run2 STDOUT third line
361 stderr_lines = """\
362 run2 STDERR ['snafu']
363 run2 STDERR second line
364 run2 STDERR third line
366 snafu_expect = (stdout_lines + stderr_lines,
367 stderr_lines + stdout_lines)
369 # XXX SHOULD TEST ABSOLUTE NUMBER AS WELL
370 output = test.stdout()
371 output = self.translate_newlines(output)
372 assert output in snafu_expect, output
373 error = test.stderr()
374 assert error == '', error
376 output = test.stdout(run = -1)
377 output = self.translate_newlines(output)
378 assert output in foo_bar_expect, output
379 error = test.stderr(-1)
380 assert error == '', error
381 finally:
382 os.chdir(cwd)
386 class description_TestCase(TestCmdTestCase):
387 def test_description(self) -> None:
388 """Test description()"""
389 test = TestCmd.TestCmd()
390 assert test.description is None, 'initialized description?'
391 test = TestCmd.TestCmd(description = 'test')
392 assert test.description == 'test', 'uninitialized description'
393 test.description_set('foo')
394 assert test.description == 'foo', 'did not set description'
398 class diff_TestCase(TestCmdTestCase):
399 def test_diff_re(self) -> None:
400 """Test diff_re()"""
401 result = TestCmd.diff_re(["abcde"], ["abcde"])
402 result = list(result)
403 assert result == [], result
404 result = TestCmd.diff_re(["a.*e"], ["abcde"])
405 result = list(result)
406 assert result == [], result
407 result = TestCmd.diff_re(["a.*e"], ["xxx"])
408 result = list(result)
409 assert result == ['1c1', "< 'a.*e'", '---', "> 'xxx'"], result
411 def test_diff_custom_function(self) -> None:
412 """Test diff() using a custom function"""
413 self.popen_python(f"""import sys
414 sys.path = [r'{self.orig_cwd}'] + sys.path
415 import TestCmd
416 def my_diff(a, b):
417 return [
418 '*****',
420 '*****',
422 '*****',
424 test = TestCmd.TestCmd(diff = my_diff)
425 test.diff("a\\nb1\\nc\\n", "a\\nb2\\nc\\n", "STDOUT")
426 sys.exit(0)
427 """,
428 stdout = """\
429 STDOUT==========================================================================
430 *****
431 ['a', 'b1', 'c']
432 *****
433 ['a', 'b2', 'c']
434 *****
435 """)
437 def test_diff_string(self) -> None:
438 self.popen_python(f"""import sys
439 sys.path = [r'{self.orig_cwd}'] + sys.path
440 import TestCmd
441 test = TestCmd.TestCmd(diff = 'diff_re')
442 test.diff("a\\nb1\\nc\\n", "a\\nb2\\nc\\n", 'STDOUT')
443 sys.exit(0)
444 """,
445 stdout = """\
446 STDOUT==========================================================================
448 < 'b1'
450 > 'b2'
451 """)
453 def test_error(self) -> None:
454 """Test handling a compilation error in TestCmd.diff_re()"""
455 script_input = f"""import sys
456 sys.path = [r'{self.orig_cwd}'] + sys.path
457 import TestCmd
458 assert TestCmd.diff_re([r"a.*(e"], ["abcde"])
459 sys.exit(0)
461 stdout, stderr, status = self.call_python(script_input)
462 assert status == 1, status
463 expect1 = "Regular expression error in '^a.*(e$': missing )"
464 expect2 = "Regular expression error in '^a.*(e$': unbalanced parenthesis"
465 assert (stderr.find(expect1) != -1 or
466 stderr.find(expect2) != -1), repr(stderr)
468 def test_simple_diff_static_method(self) -> None:
469 """Test calling the TestCmd.TestCmd.simple_diff() static method"""
470 self.popen_python(f"""import sys
471 sys.path = [r'{self.orig_cwd}'] + sys.path
472 import TestCmd
473 result = TestCmd.TestCmd.simple_diff(['a', 'b', 'c', 'e', 'f1'],
474 ['a', 'c', 'd', 'e', 'f2'])
475 result = list(result)
476 expect = ['2d1', '< b', '3a3', '> d', '5c5', '< f1', '---', '> f2']
477 assert result == expect, result
478 sys.exit(0)
479 """)
481 def test_context_diff_static_method(self) -> None:
482 """Test calling the TestCmd.TestCmd.context_diff() static method"""
483 self.popen_python(f"""import sys
484 sys.path = [r'{self.orig_cwd}'] + sys.path
485 import TestCmd
486 result = TestCmd.TestCmd.context_diff(['a\\n', 'b\\n', 'c\\n', 'e\\n', 'f1\\n'],
487 ['a\\n', 'c\\n', 'd\\n', 'e\\n', 'f2\\n'])
488 result = list(result)
489 expect = [
490 '*** \\n',
491 '--- \\n',
492 '***************\\n',
493 '*** 1,5 ****\\n',
494 ' a\\n',
495 '- b\\n',
496 ' c\\n',
497 ' e\\n',
498 '! f1\\n',
499 '--- 1,5 ----\\n',
500 ' a\\n',
501 ' c\\n',
502 '+ d\\n',
503 ' e\\n',
504 '! f2\\n',
506 assert result == expect, result
507 sys.exit(0)
508 """)
510 def test_unified_diff_static_method(self) -> None:
511 """Test calling the TestCmd.TestCmd.unified_diff() static method"""
512 self.popen_python(f"""import sys
513 sys.path = [r'{self.orig_cwd}'] + sys.path
514 import TestCmd
515 result = TestCmd.TestCmd.unified_diff(['a\\n', 'b\\n', 'c\\n', 'e\\n', 'f1\\n'],
516 ['a\\n', 'c\\n', 'd\\n', 'e\\n', 'f2\\n'])
517 result = list(result)
518 expect = [
519 '--- \\n',
520 '+++ \\n',
521 '@@ -1,5 +1,5 @@\\n',
522 ' a\\n',
523 '-b\\n',
524 ' c\\n',
525 '+d\\n',
526 ' e\\n',
527 '-f1\\n',
528 '+f2\\n'
530 assert result == expect, result
531 sys.exit(0)
532 """)
534 def test_diff_re_static_method(self) -> None:
535 """Test calling the TestCmd.TestCmd.diff_re() static method"""
536 self.popen_python(f"""import sys
537 sys.path = [r'{self.orig_cwd}'] + sys.path
538 import TestCmd
539 result = TestCmd.TestCmd.diff_re(['a', 'b', 'c', '.', 'f1'],
540 ['a', 'c', 'd', 'e', 'f2'])
541 result = list(result)
542 expect = [
543 '2c2',
544 "< 'b'",
545 '---',
546 "> 'c'",
547 '3c3',
548 "< 'c'",
549 '---',
550 "> 'd'",
551 '5c5',
552 "< 'f1'",
553 '---',
554 "> 'f2'"
556 assert result == expect, result
557 sys.exit(0)
558 """)
562 class diff_stderr_TestCase(TestCmdTestCase):
563 def test_diff_stderr_default(self) -> None:
564 """Test diff_stderr() default behavior"""
565 self.popen_python(fr"""import sys
566 sys.path = [r'{self.orig_cwd}'] + sys.path
567 import TestCmd
568 test = TestCmd.TestCmd()
569 test.diff_stderr('a\nb1\nc\n', 'a\nb2\nc\n')
570 sys.exit(0)
571 """,
572 stdout="""\
574 < b1
576 > b2
577 """)
579 def test_diff_stderr_not_affecting_diff_stdout(self) -> None:
580 """Test diff_stderr() not affecting diff_stdout() behavior"""
581 self.popen_python(fr"""
582 import sys
583 sys.path = [r'{self.orig_cwd}'] + sys.path
584 import TestCmd
585 test = TestCmd.TestCmd(diff_stderr='diff_re')
586 print("diff_stderr:")
587 test.diff_stderr('a\nb.\nc\n', 'a\nbb\nc\n')
588 print("diff_stdout:")
589 test.diff_stdout('a\nb.\nc\n', 'a\nbb\nc\n')
590 sys.exit(0)
591 """,
592 stdout="""\
593 diff_stderr:
594 diff_stdout:
596 < b.
598 > bb
599 """)
601 def test_diff_stderr_custom_function(self) -> None:
602 """Test diff_stderr() using a custom function"""
603 self.popen_python(fr"""import sys
604 sys.path = [r'{self.orig_cwd}'] + sys.path
605 import TestCmd
606 def my_diff(a, b):
607 return ["a:"] + a + ["b:"] + b
608 test = TestCmd.TestCmd(diff_stderr=my_diff)
609 test.diff_stderr('abc', 'def')
610 sys.exit(0)
611 """,
612 stdout="""\
617 """)
619 def test_diff_stderr_TestCmd_function(self) -> None:
620 """Test diff_stderr() using a TestCmd function"""
621 self.popen_python(fr"""import sys
622 sys.path = [r'{self.orig_cwd}'] + sys.path
623 import TestCmd
624 test = TestCmd.TestCmd(diff_stderr = TestCmd.diff_re)
625 test.diff_stderr('a\n.\n', 'b\nc\n')
626 sys.exit(0)
627 """,
628 stdout="""\
630 < 'a'
632 > 'b'
633 """)
635 def test_diff_stderr_static_method(self) -> None:
636 """Test diff_stderr() using a static method"""
637 self.popen_python(fr"""import sys
638 sys.path = [r'{self.orig_cwd}'] + sys.path
639 import TestCmd
640 test = TestCmd.TestCmd(diff_stderr=TestCmd.TestCmd.diff_re)
641 test.diff_stderr('a\n.\n', 'b\nc\n')
642 sys.exit(0)
643 """,
644 stdout="""\
646 < 'a'
648 > 'b'
649 """)
651 def test_diff_stderr_string(self) -> None:
652 """Test diff_stderr() using a string to fetch the diff method"""
653 self.popen_python(fr"""import sys
654 sys.path = [r'{self.orig_cwd}'] + sys.path
655 import TestCmd
656 test = TestCmd.TestCmd(diff_stderr='diff_re')
657 test.diff_stderr('a\n.\n', 'b\nc\n')
658 sys.exit(0)
659 """,
660 stdout="""\
662 < 'a'
664 > 'b'
665 """)
669 class diff_stdout_TestCase(TestCmdTestCase):
670 def test_diff_stdout_default(self) -> None:
671 """Test diff_stdout() default behavior"""
672 self.popen_python(fr"""import sys
673 sys.path = [r'{self.orig_cwd}'] + sys.path
674 import TestCmd
675 test = TestCmd.TestCmd()
676 test.diff_stdout('a\nb1\nc\n', 'a\nb2\nc\n')
677 sys.exit(0)
678 """,
679 stdout="""\
681 < b1
683 > b2
684 """)
686 def test_diff_stdout_not_affecting_diff_stderr(self) -> None:
687 """Test diff_stdout() not affecting diff_stderr() behavior"""
688 self.popen_python(fr"""
689 import sys
690 sys.path = [r'{self.orig_cwd}'] + sys.path
691 import TestCmd
692 test = TestCmd.TestCmd(diff_stdout='diff_re')
693 print("diff_stdout:")
694 test.diff_stdout('a\nb.\nc\n', 'a\nbb\nc\n')
695 print("diff_stderr:")
696 test.diff_stderr('a\nb.\nc\n', 'a\nbb\nc\n')
697 sys.exit(0)
698 """,
699 stdout="""\
700 diff_stdout:
701 diff_stderr:
703 < b.
705 > bb
706 """)
708 def test_diff_stdout_custom_function(self) -> None:
709 """Test diff_stdout() using a custom function"""
710 self.popen_python(fr"""import sys
711 sys.path = [r'{self.orig_cwd}'] + sys.path
712 import TestCmd
713 def my_diff(a, b):
714 return ["a:"] + a + ["b:"] + b
715 test = TestCmd.TestCmd(diff_stdout=my_diff)
716 test.diff_stdout('abc', 'def')
717 sys.exit(0)
718 """,
719 stdout="""\
724 """)
726 def test_diff_stdout_TestCmd_function(self) -> None:
727 """Test diff_stdout() using a TestCmd function"""
728 self.popen_python(fr"""import sys
729 sys.path = [r'{self.orig_cwd}'] + sys.path
730 import TestCmd
731 test = TestCmd.TestCmd(diff_stdout = TestCmd.diff_re)
732 test.diff_stdout('a\n.\n', 'b\nc\n')
733 sys.exit(0)
734 """,
735 stdout="""\
737 < 'a'
739 > 'b'
740 """)
742 def test_diff_stdout_static_method(self) -> None:
743 """Test diff_stdout() using a static method"""
744 self.popen_python(fr"""import sys
745 sys.path = [r'{self.orig_cwd}'] + sys.path
746 import TestCmd
747 test = TestCmd.TestCmd(diff_stdout=TestCmd.TestCmd.diff_re)
748 test.diff_stdout('a\n.\n', 'b\nc\n')
749 sys.exit(0)
750 """,
751 stdout="""\
753 < 'a'
755 > 'b'
756 """)
758 def test_diff_stdout_string(self) -> None:
759 """Test diff_stdout() using a string to fetch the diff method"""
760 self.popen_python(fr"""import sys
761 sys.path = [r'{self.orig_cwd}'] + sys.path
762 import TestCmd
763 test = TestCmd.TestCmd(diff_stdout='diff_re')
764 test.diff_stdout('a\n.\n', 'b\nc\n')
765 sys.exit(0)
766 """,
767 stdout="""\
769 < 'a'
771 > 'b'
772 """)
776 class exit_TestCase(TestCmdTestCase):
777 def test_exit(self) -> None:
778 """Test exit()"""
779 def _test_it(cwd, tempdir, condition, preserved):
780 close_true = {'pass_test': 1, 'fail_test': 0, 'no_result': 0}
781 exit_status = {'pass_test': 0, 'fail_test': 1, 'no_result': 2}
782 result_string = {'pass_test': "PASSED\n",
783 'fail_test': "FAILED test at line 5 of <stdin>\n",
784 'no_result': "NO RESULT for test at line 5 of <stdin>\n"}
785 global ExitError
786 input = f"""import sys
787 sys.path = [r'{cwd}'] + sys.path
788 import TestCmd
789 test = TestCmd.TestCmd(workdir = '{tempdir}')
790 test.{condition}()
792 stdout, stderr, status = self.call_python(input, python="python")
793 if close_true[condition]:
794 unexpected = (status != 0)
795 else:
796 unexpected = (status == 0)
797 if unexpected:
798 msg = "Unexpected exit status from python: %s\n"
799 raise ExitError(msg % status + stdout + stderr)
800 if status != exit_status[condition]:
801 msg = "Expected exit status %d, got %d\n"
802 raise ExitError(msg % (exit_status[condition], status))
803 if stderr != result_string[condition]:
804 msg = "Expected error output:\n%s\nGot error output:\n%s"
805 raise ExitError(msg % (result_string[condition], stderr))
806 if preserved:
807 if not os.path.exists(tempdir):
808 msg = "Working directory %s was mistakenly removed\n"
809 raise ExitError(msg % tempdir + stdout)
810 else:
811 if os.path.exists(tempdir):
812 msg = "Working directory %s was mistakenly preserved\n"
813 raise ExitError(msg % tempdir + stdout)
815 run_env = TestCmd.TestCmd(workdir = '')
816 os.chdir(run_env.workdir)
817 # Everything before this prepared our "source directory."
818 # Now do the real test.
819 try:
820 cwd = self.orig_cwd
821 _clear_dict(os.environ, 'PRESERVE', 'PRESERVE_PASS', 'PRESERVE_FAIL', 'PRESERVE_NO_RESULT')
822 _test_it(cwd, 'dir01', 'pass_test', 0)
823 _test_it(cwd, 'dir02', 'fail_test', 0)
824 _test_it(cwd, 'dir03', 'no_result', 0)
825 os.environ['PRESERVE'] = '1'
826 _test_it(cwd, 'dir04', 'pass_test', 1)
827 _test_it(cwd, 'dir05', 'fail_test', 1)
828 _test_it(cwd, 'dir06', 'no_result', 1)
829 del os.environ['PRESERVE']
830 os.environ['PRESERVE_PASS'] = '1'
831 _test_it(cwd, 'dir07', 'pass_test', 1)
832 _test_it(cwd, 'dir08', 'fail_test', 0)
833 _test_it(cwd, 'dir09', 'no_result', 0)
834 del os.environ['PRESERVE_PASS']
835 os.environ['PRESERVE_FAIL'] = '1'
836 _test_it(cwd, 'dir10', 'pass_test', 0)
837 _test_it(cwd, 'dir11', 'fail_test', 1)
838 _test_it(cwd, 'dir12', 'no_result', 0)
839 del os.environ['PRESERVE_FAIL']
840 os.environ['PRESERVE_NO_RESULT'] = '1'
841 _test_it(cwd, 'dir13', 'pass_test', 0)
842 _test_it(cwd, 'dir14', 'fail_test', 0)
843 _test_it(cwd, 'dir15', 'no_result', 1)
844 del os.environ['PRESERVE_NO_RESULT']
845 finally:
846 _clear_dict(os.environ, 'PRESERVE', 'PRESERVE_PASS', 'PRESERVE_FAIL', 'PRESERVE_NO_RESULT')
850 class fail_test_TestCase(TestCmdTestCase):
851 def test_fail_test(self) -> None:
852 """Test fail_test()"""
853 run_env = TestCmd.TestCmd(workdir = '')
854 run_env.write('run', """import sys
855 sys.stdout.write("run: STDOUT\\n")
856 sys.stderr.write("run: STDERR\\n")
857 """)
858 os.chdir(run_env.workdir)
859 # Everything before this prepared our "source directory."
860 # Now do the real test.
861 self.popen_python(f"""import sys
862 sys.path = [r'{self.orig_cwd}'] + sys.path
863 import TestCmd
864 TestCmd.fail_test(condition = 1)
865 """, status = 1, stderr = "FAILED test at line 4 of <stdin>\n")
867 self.popen_python(f"""import sys
868 sys.path = [r'{self.orig_cwd}'] + sys.path
869 import TestCmd
870 test = TestCmd.TestCmd(program = 'run', interpreter = 'python', workdir = '')
871 test.run()
872 test.fail_test(condition = (test.status == 0))
873 """, status = 1, stderr = f"FAILED test of {run_env.workpath('run')}\n\tat line 6 of <stdin>\n")
875 self.popen_python(f"""import sys
876 sys.path = [r'{self.orig_cwd}'] + sys.path
877 import TestCmd
878 test = TestCmd.TestCmd(program = 'run', interpreter = 'python', description = 'xyzzy', workdir = '')
879 test.run()
880 test.fail_test(condition = (test.status == 0))
881 """, status = 1, stderr = f"FAILED test of {run_env.workpath('run')} [xyzzy]\n\tat line 6 of <stdin>\n")
883 self.popen_python(f"""import sys
884 sys.path = [r'{self.orig_cwd}'] + sys.path
885 import TestCmd
886 test = TestCmd.TestCmd(program = 'run', interpreter = 'python', workdir = '')
887 test.run()
888 def xxx():
889 sys.stderr.write("printed on failure\\n")
890 test.fail_test(condition = (test.status == 0), function = xxx)
891 """, status = 1, stderr = f"printed on failure\nFAILED test of {run_env.workpath('run')}\n\tat line 8 of <stdin>\n")
893 self.popen_python(f"""import sys
894 sys.path = [r'{self.orig_cwd}'] + sys.path
895 import TestCmd
896 def test1(self):
897 self.run()
898 self.fail_test(condition = (self.status == 0))
899 def test2(self):
900 test1(self)
901 test2(TestCmd.TestCmd(program = 'run', interpreter = 'python', workdir = ''))
902 """, status = 1, stderr = f"FAILED test of {run_env.workpath('run')}\n\tat line 6 of <stdin> (test1)\n\tfrom line 8 of <stdin> (test2)\n\tfrom line 9 of <stdin>\n")
904 self.popen_python(f"""import sys
905 sys.path = [r'{self.orig_cwd}'] + sys.path
906 import TestCmd
907 def test1(self):
908 self.run()
909 self.fail_test(condition = (self.status == 0), skip = 1)
910 def test2(self):
911 test1(self)
912 test2(TestCmd.TestCmd(program = 'run', interpreter = 'python', workdir = ''))
913 """, status = 1, stderr = f"FAILED test of {run_env.workpath('run')}\n\tat line 8 of <stdin> (test2)\n\tfrom line 9 of <stdin>\n")
917 class interpreter_TestCase(TestCmdTestCase):
918 def test_interpreter(self) -> None:
919 """Test interpreter()"""
920 run_env = TestCmd.TestCmd(workdir = '')
921 run_env.write('run', """import sys
922 sys.stdout.write("run: STDOUT\\n")
923 sys.stderr.write("run: STDERR\\n")
924 """)
925 os.chdir(run_env.workdir)
926 # Everything before this prepared our "source directory."
927 # Now do the real test.
928 test = TestCmd.TestCmd(program = 'run', workdir = '')
929 test.interpreter_set('foo')
930 assert test.interpreter == 'foo', 'did not set interpreter'
931 test.interpreter_set('python')
932 assert test.interpreter == 'python', 'did not set interpreter'
933 test.run()
937 class match_TestCase(TestCmdTestCase):
938 def test_match_default(self) -> None:
939 """Test match() default behavior"""
940 test = TestCmd.TestCmd()
941 assert test.match("abcde\n", "a.*e\n")
942 assert test.match("12345\nabcde\n", "1\\d+5\na.*e\n")
943 lines = ["vwxyz\n", "67890\n"]
944 regexes = ["v[^a-u]*z\n", "6[^ ]+0\n"]
945 assert test.match(lines, regexes)
947 def test_match_custom_function(self) -> None:
948 """Test match() using a custom function"""
949 def match_length(lines, matches):
950 return len(lines) == len(matches)
951 test = TestCmd.TestCmd(match=match_length)
952 assert not test.match("123\n", "1\n")
953 assert test.match("123\n", "111\n")
954 assert not test.match("123\n123\n", "1\n1\n")
955 assert test.match("123\n123\n", "111\n111\n")
956 lines = ["123\n", "123\n"]
957 regexes = ["1\n", "1\n"]
958 assert test.match(lines, regexes) # due to equal numbers of lines
960 def test_match_TestCmd_function(self) -> None:
961 """Test match() using a TestCmd function"""
962 test = TestCmd.TestCmd(match = TestCmd.match_exact)
963 assert not test.match("abcde\n", "a.*e\n")
964 assert test.match("abcde\n", "abcde\n")
965 assert not test.match("12345\nabcde\n", "1\\d+5\na.*e\n")
966 assert test.match("12345\nabcde\n", "12345\nabcde\n")
967 lines = ["vwxyz\n", "67890\n"]
968 regexes = [r"v[^a-u]*z\n", r"6[^ ]+0\n"]
969 assert not test.match(lines, regexes)
970 assert test.match(lines, lines)
972 def test_match_static_method(self) -> None:
973 """Test match() using a static method"""
974 test = TestCmd.TestCmd(match=TestCmd.TestCmd.match_exact)
975 assert not test.match("abcde\n", "a.*e\n")
976 assert test.match("abcde\n", "abcde\n")
977 assert not test.match("12345\nabcde\n", "1\\d+5\na.*e\n")
978 assert test.match("12345\nabcde\n", "12345\nabcde\n")
979 lines = ["vwxyz\n", "67890\n"]
980 regexes = [r"v[^a-u]*z\n", r"6[^ ]+0\n"]
981 assert not test.match(lines, regexes)
982 assert test.match(lines, lines)
984 def test_match_string(self) -> None:
985 """Test match() using a string to fetch the match method"""
986 test = TestCmd.TestCmd(match='match_exact')
987 assert not test.match("abcde\n", "a.*e\n")
988 assert test.match("abcde\n", "abcde\n")
989 assert not test.match("12345\nabcde\n", "1\\d+5\na.*e\n")
990 assert test.match("12345\nabcde\n", "12345\nabcde\n")
991 lines = ["vwxyz\n", "67890\n"]
992 regexes = [r"v[^a-u]*z\n", r"6[^ ]+0\n"]
993 assert not test.match(lines, regexes)
994 assert test.match(lines, lines)
998 class match_exact_TestCase(TestCmdTestCase):
999 def test_match_exact_function(self) -> None:
1000 """Test calling the TestCmd.match_exact() function"""
1001 assert not TestCmd.match_exact("abcde\\n", "a.*e\\n")
1002 assert TestCmd.match_exact("abcde\\n", "abcde\\n")
1004 def test_match_exact_instance_method(self) -> None:
1005 """Test calling the TestCmd.TestCmd().match_exact() instance method"""
1006 test = TestCmd.TestCmd()
1007 assert not test.match_exact("abcde\\n", "a.*e\\n")
1008 assert test.match_exact("abcde\\n", "abcde\\n")
1010 def test_match_exact_static_method(self) -> None:
1011 """Test calling the TestCmd.TestCmd.match_exact() static method"""
1012 assert not TestCmd.TestCmd.match_exact("abcde\\n", "a.*e\\n")
1013 assert TestCmd.TestCmd.match_exact("abcde\\n", "abcde\\n")
1015 def test_evaluation(self) -> None:
1016 """Test match_exact() evaluation"""
1017 test = TestCmd.TestCmd()
1018 assert not test.match_exact("abcde\n", "a.*e\n")
1019 assert test.match_exact("abcde\n", "abcde\n")
1020 assert not test.match_exact(["12345\n", "abcde\n"], ["1[0-9]*5\n", "a.*e\n"])
1021 assert test.match_exact(["12345\n", "abcde\n"], ["12345\n", "abcde\n"])
1022 assert not test.match_exact(UserList(["12345\n", "abcde\n"]),
1023 ["1[0-9]*5\n", "a.*e\n"])
1024 assert test.match_exact(UserList(["12345\n", "abcde\n"]),
1025 ["12345\n", "abcde\n"])
1026 assert not test.match_exact(["12345\n", "abcde\n"],
1027 UserList(["1[0-9]*5\n", "a.*e\n"]))
1028 assert test.match_exact(["12345\n", "abcde\n"],
1029 UserList(["12345\n", "abcde\n"]))
1030 assert not test.match_exact("12345\nabcde\n", "1[0-9]*5\na.*e\n")
1031 assert test.match_exact("12345\nabcde\n", "12345\nabcde\n")
1032 lines = ["vwxyz\n", "67890\n"]
1033 regexes = ["v[^a-u]*z\n", "6[^ ]+0\n"]
1034 assert not test.match_exact(lines, regexes)
1035 assert test.match_exact(lines, lines)
1039 class match_re_dotall_TestCase(TestCmdTestCase):
1040 def test_match_re_dotall_function(self) -> None:
1041 """Test calling the TestCmd.match_re_dotall() function"""
1042 assert TestCmd.match_re_dotall("abcde\nfghij\n", r"a.*j\n")
1044 def test_match_re_dotall_instance_method(self) -> None:
1045 """Test calling the TestCmd.TestCmd().match_re_dotall() instance method"""
1046 test = TestCmd.TestCmd()
1047 test.match_re_dotall("abcde\\nfghij\\n", r"a.*j\\n")
1049 def test_match_re_dotall_static_method(self) -> None:
1050 """Test calling the TestCmd.TestCmd.match_re_dotall() static method"""
1051 assert TestCmd.TestCmd.match_re_dotall("abcde\nfghij\n", r"a.*j\n")
1053 def test_error(self) -> None:
1054 """Test handling a compilation error in TestCmd.match_re_dotall()"""
1055 run_env = TestCmd.TestCmd(workdir = '')
1056 cwd = os.getcwd()
1057 os.chdir(run_env.workdir)
1058 # Everything before this prepared our "source directory."
1059 # Now do the real test.
1060 try:
1061 script_input = f"""import sys
1062 sys.path = [r'{cwd}'] + sys.path
1063 import TestCmd
1064 assert TestCmd.match_re_dotall("abcde", r"a.*(e")
1065 sys.exit(0)
1067 stdout, stderr, status = self.call_python(script_input)
1068 assert status == 1, status
1069 expect1 = "Regular expression error in '^a.*(e$': missing )"
1070 expect2 = "Regular expression error in '^a.*(e$': unbalanced parenthesis"
1071 assert (stderr.find(expect1) != -1 or
1072 stderr.find(expect2) != -1), repr(stderr)
1073 finally:
1074 os.chdir(cwd)
1076 def test_evaluation(self) -> None:
1077 """Test match_re_dotall() evaluation"""
1078 test = TestCmd.TestCmd()
1079 assert test.match_re_dotall("abcde\nfghij\n", r"a.*e\nf.*j\n")
1080 assert test.match_re_dotall("abcde\nfghij\n", r"a[^j]*j\n")
1081 assert test.match_re_dotall("abcde\nfghij\n", r"abcde\nfghij\n")
1082 assert test.match_re_dotall(["12345\n", "abcde\n", "fghij\n"],
1083 [r"1[0-9]*5\n", r"a.*e\n", r"f.*j\n"])
1084 assert test.match_re_dotall(["12345\n", "abcde\n", "fghij\n"],
1085 [r"1.*j\n"])
1086 assert test.match_re_dotall(["12345\n", "abcde\n", "fghij\n"],
1087 [r"12345\n", r"abcde\n", r"fghij\n"])
1088 assert test.match_re_dotall(UserList(["12345\n", "abcde\n", "fghij\n"]),
1089 [r"1[0-9]*5\n", r"a.*e\n", r"f.*j\n"])
1090 assert test.match_re_dotall(UserList(["12345\n", "abcde\n", "fghij\n"]),
1091 [r"1.*j\n"])
1092 assert test.match_re_dotall(UserList(["12345\n", "abcde\n", "fghij\n"]),
1093 [r"12345\n", r"abcde\n", r"fghij\n"])
1094 assert test.match_re_dotall(["12345\n", "abcde\n", "fghij\n"],
1095 UserList([r"1[0-9]*5\n", r"a.*e\n", r"f.*j\n"]))
1096 assert test.match_re_dotall(["12345\n", "abcde\n", "fghij\n"],
1097 UserList([r"1.*j\n"]))
1098 assert test.match_re_dotall(["12345\n", "abcde\n", "fghij\n"],
1099 UserList([r"12345\n", r"abcde\n", r"fghij\n"]))
1100 assert test.match_re_dotall("12345\nabcde\nfghij\n",
1101 r"1[0-9]*5\na.*e\nf.*j\n")
1102 assert test.match_re_dotall("12345\nabcde\nfghij\n", r"1.*j\n")
1103 assert test.match_re_dotall("12345\nabcde\nfghij\n",
1104 r"12345\nabcde\nfghij\n")
1105 lines = ["vwxyz\n", "67890\n"]
1106 regexes = [r"v[^a-u]*z\n", r"6[^ ]+0\n"]
1107 assert test.match_re_dotall(lines, regexes)
1108 assert test.match_re_dotall(lines, lines)
1112 class match_re_TestCase(TestCmdTestCase):
1113 def test_match_re_function(self) -> None:
1114 """Test calling the TestCmd.match_re() function"""
1115 assert TestCmd.match_re("abcde\n", "a.*e\n")
1117 def test_match_re_instance_method(self) -> None:
1118 """Test calling the TestCmd.TestCmd().match_re() instance method"""
1119 test = TestCmd.TestCmd()
1120 assert test.match_re("abcde\n", "a.*e\n")
1122 def test_match_re_static_method(self) -> None:
1123 """Test calling the TestCmd.TestCmd.match_re() static method"""
1124 assert TestCmd.TestCmd.match_re("abcde\n", "a.*e\n")
1126 def test_error(self) -> None:
1127 """Test handling a compilation error in TestCmd.match_re()"""
1128 run_env = TestCmd.TestCmd(workdir = '')
1129 cwd = os.getcwd()
1130 os.chdir(run_env.workdir)
1131 # Everything before this prepared our "source directory."
1132 # Now do the real test.
1133 try:
1134 script_input = f"""import sys
1135 sys.path = [r'{cwd}'] + sys.path
1136 import TestCmd
1137 assert TestCmd.match_re("abcde\
1138 ", "a.*(e\
1140 sys.exit(0)
1142 stdout, stderr, status = self.call_python(script_input)
1143 assert status == 1, status
1144 expect1 = "Regular expression error in '^a.*(e$': missing )"
1145 expect2 = "Regular expression error in '^a.*(e$': unbalanced parenthesis"
1146 assert (stderr.find(expect1) != -1 or
1147 stderr.find(expect2) != -1), repr(stderr)
1148 finally:
1149 os.chdir(cwd)
1151 def test_evaluation(self) -> None:
1152 """Test match_re() evaluation"""
1153 test = TestCmd.TestCmd()
1154 assert test.match_re("abcde\n", "a.*e\n")
1155 assert test.match_re("abcde\n", "abcde\n")
1156 assert test.match_re(["12345\n", "abcde\n"], ["1[0-9]*5\n", "a.*e\n"])
1157 assert test.match_re(["12345\n", "abcde\n"], ["12345\n", "abcde\n"])
1158 assert test.match_re(UserList(["12345\n", "abcde\n"]),
1159 ["1[0-9]*5\n", "a.*e\n"])
1160 assert test.match_re(UserList(["12345\n", "abcde\n"]),
1161 ["12345\n", "abcde\n"])
1162 assert test.match_re(["12345\n", "abcde\n"],
1163 UserList(["1[0-9]*5\n", "a.*e\n"]))
1164 assert test.match_re(["12345\n", "abcde\n"],
1165 UserList(["12345\n", "abcde\n"]))
1166 assert test.match_re("12345\nabcde\n", "1[0-9]*5\na.*e\n")
1167 assert test.match_re("12345\nabcde\n", "12345\nabcde\n")
1168 lines = ["vwxyz\n", "67890\n"]
1169 regexes = [r"v[^a-u]*z\n", r"6[^ ]+0\n"]
1170 assert test.match_re(lines, regexes)
1171 assert test.match_re(lines, lines)
1175 class match_stderr_TestCase(TestCmdTestCase):
1176 def test_match_stderr_default(self) -> None:
1177 """Test match_stderr() default behavior"""
1178 test = TestCmd.TestCmd()
1179 assert test.match_stderr("abcde\n", "a.*e\n")
1180 assert test.match_stderr("12345\nabcde\n", "1\\d+5\na.*e\n")
1181 lines = ["vwxyz\n", "67890\n"]
1182 regexes = [r"v[^a-u]*z\n", r"6[^ ]+0\n"]
1183 assert test.match_stderr(lines, regexes)
1185 def test_match_stderr_not_affecting_match_stdout(self) -> None:
1186 """Test match_stderr() not affecting match_stdout() behavior"""
1187 test = TestCmd.TestCmd(match_stderr=TestCmd.TestCmd.match_exact)
1189 assert not test.match_stderr("abcde\n", "a.*e\n")
1190 assert test.match_stderr("abcde\n", "abcde\n")
1191 assert not test.match_stderr("12345\nabcde\n", "1\\d+5\na.*e\n")
1192 assert test.match_stderr("12345\nabcde\n", "12345\nabcde\n")
1193 lines = ["vwxyz\n", "67890\n"]
1194 regexes = [r"v[^a-u]*z\n", r"6[^ ]+0\n"]
1195 assert not test.match_stderr(lines, regexes)
1196 assert test.match_stderr(lines, lines)
1198 assert test.match_stdout("abcde\n", "a.*e\n")
1199 assert test.match_stdout("12345\nabcde\n", "1\\d+5\na.*e\n")
1200 lines = ["vwxyz\n", "67890\n"]
1201 regexes = [r"v[^a-u]*z\n", r"6[^ ]+0\n"]
1202 assert test.match_stdout(lines, regexes)
1204 def test_match_stderr_custom_function(self) -> None:
1205 """Test match_stderr() using a custom function"""
1206 def match_length(lines, matches):
1207 return len(lines) == len(matches)
1208 test = TestCmd.TestCmd(match_stderr=match_length)
1209 assert not test.match_stderr("123\n", "1\n")
1210 assert test.match_stderr("123\n", "111\n")
1211 assert not test.match_stderr("123\n123\n", "1\n1\n")
1212 assert test.match_stderr("123\n123\n", "111\n111\n")
1213 lines = ["123\n", "123\n"]
1214 regexes = [r"1\n", r"1\n"]
1215 assert test.match_stderr(lines, regexes) # equal numbers of lines
1217 def test_match_stderr_TestCmd_function(self) -> None:
1218 """Test match_stderr() using a TestCmd function"""
1219 test = TestCmd.TestCmd(match_stderr = TestCmd.match_exact)
1220 assert not test.match_stderr("abcde\n", "a.*e\n")
1221 assert test.match_stderr("abcde\n", "abcde\n")
1222 assert not test.match_stderr("12345\nabcde\n", "1\\d+5\na.*e\n")
1223 assert test.match_stderr("12345\nabcde\n", "12345\nabcde\n")
1224 lines = ["vwxyz\n", "67890\n"]
1225 regexes = [r"v[^a-u]*z\n", r"6[^ ]+0\n"]
1226 assert not test.match_stderr(lines, regexes)
1227 assert test.match_stderr(lines, lines)
1229 def test_match_stderr_static_method(self) -> None:
1230 """Test match_stderr() using a static method"""
1231 test = TestCmd.TestCmd(match_stderr=TestCmd.TestCmd.match_exact)
1232 assert not test.match_stderr("abcde\n", "a.*e\n")
1233 assert test.match_stderr("abcde\n", "abcde\n")
1234 assert not test.match_stderr("12345\nabcde\n", "1\\d+5\na.*e\n")
1235 assert test.match_stderr("12345\nabcde\n", "12345\nabcde\n")
1236 lines = ["vwxyz\n", "67890\n"]
1237 regexes = [r"v[^a-u]*z\n", r"6[^ ]+0\n"]
1238 assert not test.match_stderr(lines, regexes)
1239 assert test.match_stderr(lines, lines)
1241 def test_match_stderr_string(self) -> None:
1242 """Test match_stderr() using a string to fetch the match method"""
1243 test = TestCmd.TestCmd(match_stderr='match_exact')
1244 assert not test.match_stderr("abcde\n", "a.*e\n")
1245 assert test.match_stderr("abcde\n", "abcde\n")
1246 assert not test.match_stderr("12345\nabcde\n", "1\\d+5\na.*e\n")
1247 assert test.match_stderr("12345\nabcde\n", "12345\nabcde\n")
1248 lines = ["vwxyz\n", "67890\n"]
1249 regexes = [r"v[^a-u]*z\n", r"6[^ ]+0\n"]
1250 assert not test.match_stderr(lines, regexes)
1251 assert test.match_stderr(lines, lines)
1255 class match_stdout_TestCase(TestCmdTestCase):
1256 def test_match_stdout_default(self) -> None:
1257 """Test match_stdout() default behavior"""
1258 test = TestCmd.TestCmd()
1259 assert test.match_stdout("abcde\n", "a.*e\n")
1260 assert test.match_stdout("12345\nabcde\n", "1\\d+5\na.*e\n")
1261 lines = ["vwxyz\n", "67890\n"]
1262 regexes = [r"v[^a-u]*z\n", r"6[^ ]+0\n"]
1263 assert test.match_stdout(lines, regexes)
1265 def test_match_stdout_not_affecting_match_stderr(self) -> None:
1266 """Test match_stdout() not affecting match_stderr() behavior"""
1267 test = TestCmd.TestCmd(match_stdout=TestCmd.TestCmd.match_exact)
1269 assert not test.match_stdout("abcde\n", "a.*e\n")
1270 assert test.match_stdout("abcde\n", "abcde\n")
1271 assert not test.match_stdout("12345\nabcde\n", "1\\d+5\na.*e\n")
1272 assert test.match_stdout("12345\nabcde\n", "12345\nabcde\n")
1273 lines = ["vwxyz\n", "67890\n"]
1274 regexes = [r"v[^a-u]*z\n", r"6[^ ]+0\n"]
1275 assert not test.match_stdout(lines, regexes)
1276 assert test.match_stdout(lines, lines)
1278 assert test.match_stderr("abcde\n", "a.*e\n")
1279 assert test.match_stderr("12345\nabcde\n", "1\\d+5\na.*e\n")
1280 lines = ["vwxyz\n", "67890\n"]
1281 regexes = [r"v[^a-u]*z\n", r"6[^ ]+0\n"]
1282 assert test.match_stderr(lines, regexes)
1284 def test_match_stdout_custom_function(self) -> None:
1285 """Test match_stdout() using a custom function"""
1286 def match_length(lines, matches):
1287 return len(lines) == len(matches)
1288 test = TestCmd.TestCmd(match_stdout=match_length)
1289 assert not test.match_stdout("123\n", "1\n")
1290 assert test.match_stdout("123\n", "111\n")
1291 assert not test.match_stdout("123\n123\n", "1\n1\n")
1292 assert test.match_stdout("123\n123\n", "111\n111\n")
1293 lines = ["123\n", "123\n"]
1294 regexes = [r"1\n", r"1\n"]
1295 assert test.match_stdout(lines, regexes) # equal numbers of lines
1297 def test_match_stdout_TestCmd_function(self) -> None:
1298 """Test match_stdout() using a TestCmd function"""
1299 test = TestCmd.TestCmd(match_stdout = TestCmd.match_exact)
1300 assert not test.match_stdout("abcde\n", "a.*e\n")
1301 assert test.match_stdout("abcde\n", "abcde\n")
1302 assert not test.match_stdout("12345\nabcde\n", "1\\d+5\na.*e\n")
1303 assert test.match_stdout("12345\nabcde\n", "12345\nabcde\n")
1304 lines = ["vwxyz\n", "67890\n"]
1305 regexes = [r"v[^a-u]*z\n", r"6[^ ]+0\n"]
1306 assert not test.match_stdout(lines, regexes)
1307 assert test.match_stdout(lines, lines)
1309 def test_match_stdout_static_method(self) -> None:
1310 """Test match_stdout() using a static method"""
1311 test = TestCmd.TestCmd(match_stdout=TestCmd.TestCmd.match_exact)
1312 assert not test.match_stdout("abcde\n", "a.*e\n")
1313 assert test.match_stdout("abcde\n", "abcde\n")
1314 assert not test.match_stdout("12345\nabcde\n", "1\\d+5\na.*e\n")
1315 assert test.match_stdout("12345\nabcde\n", "12345\nabcde\n")
1316 lines = ["vwxyz\n", "67890\n"]
1317 regexes = [r"v[^a-u]*z\n", r"6[^ ]+0\n"]
1318 assert not test.match_stdout(lines, regexes)
1319 assert test.match_stdout(lines, lines)
1321 def test_match_stdout_string(self) -> None:
1322 """Test match_stdout() using a string to fetch the match method"""
1323 test = TestCmd.TestCmd(match_stdout='match_exact')
1324 assert not test.match_stdout("abcde\n", "a.*e\n")
1325 assert test.match_stdout("abcde\n", "abcde\n")
1326 assert not test.match_stdout("12345\nabcde\n", "1\\d+5\na.*e\n")
1327 assert test.match_stdout("12345\nabcde\n", "12345\nabcde\n")
1328 lines = ["vwxyz\n", "67890\n"]
1329 regexes = [r"v[^a-u]*z\n", r"6[^ ]+0\n"]
1330 assert not test.match_stdout(lines, regexes)
1331 assert test.match_stdout(lines, lines)
1335 class no_result_TestCase(TestCmdTestCase):
1336 def test_no_result(self) -> None:
1337 """Test no_result()"""
1338 run_env = TestCmd.TestCmd(workdir = '')
1339 run_env.write('run', """import sys
1340 sys.stdout.write("run: STDOUT\\n")
1341 sys.stderr.write("run: STDERR\\n")
1342 """)
1343 os.chdir(run_env.workdir)
1344 # Everything before this prepared our "source directory."
1345 # Now do the real test.
1346 self.popen_python(f"""import sys
1347 sys.path = [r'{self.orig_cwd}'] + sys.path
1348 import TestCmd
1349 TestCmd.no_result(condition = 1)
1350 """, status = 2, stderr = "NO RESULT for test at line 4 of <stdin>\n")
1352 self.popen_python(f"""import sys
1353 sys.path = [r'{self.orig_cwd}'] + sys.path
1354 import TestCmd
1355 test = TestCmd.TestCmd(program = 'run', interpreter = 'python', workdir = '')
1356 test.run()
1357 test.no_result(condition = (test.status == 0))
1358 """, status = 2, stderr = f"NO RESULT for test of {run_env.workpath('run')}\n\tat line 6 of <stdin>\n")
1360 self.popen_python(f"""import sys
1361 sys.path = [r'{self.orig_cwd}'] + sys.path
1362 import TestCmd
1363 test = TestCmd.TestCmd(program = 'run', interpreter = 'python', description = 'xyzzy', workdir = '')
1364 test.run()
1365 test.no_result(condition = (test.status == 0))
1366 """, status = 2, stderr = f"NO RESULT for test of {run_env.workpath('run')} [xyzzy]\n\tat line 6 of <stdin>\n")
1368 self.popen_python(f"""import sys
1369 sys.path = [r'{self.orig_cwd}'] + sys.path
1370 import TestCmd
1371 test = TestCmd.TestCmd(program = 'run', interpreter = 'python', workdir = '')
1372 test.run()
1373 def xxx():
1374 sys.stderr.write("printed on no result\\n")
1375 test.no_result(condition = (test.status == 0), function = xxx)
1376 """, status = 2, stderr = f"printed on no result\nNO RESULT for test of {run_env.workpath('run')}\n\tat line 8 of <stdin>\n")
1378 self.popen_python(f"""import sys
1379 sys.path = [r'{self.orig_cwd}'] + sys.path
1380 import TestCmd
1381 def test1(self):
1382 self.run()
1383 self.no_result(condition = (self.status == 0))
1384 def test2(self):
1385 test1(self)
1386 test2(TestCmd.TestCmd(program = 'run', interpreter = 'python', workdir = ''))
1387 """, status = 2, stderr = f"NO RESULT for test of {run_env.workpath('run')}\n\tat line 6 of <stdin> (test1)\n\tfrom line 8 of <stdin> (test2)\n\tfrom line 9 of <stdin>\n")
1389 self.popen_python(f"""import sys
1390 sys.path = [r'{self.orig_cwd}'] + sys.path
1391 import TestCmd
1392 def test1(self):
1393 self.run()
1394 self.no_result(condition = (self.status == 0), skip = 1)
1395 def test2(self):
1396 test1(self)
1397 test2(TestCmd.TestCmd(program = 'run', interpreter = 'python', workdir = ''))
1398 """, status = 2, stderr = f"NO RESULT for test of {run_env.workpath('run')}\n\tat line 8 of <stdin> (test2)\n\tfrom line 9 of <stdin>\n")
1402 class pass_test_TestCase(TestCmdTestCase):
1403 def test_pass_test(self) -> None:
1404 """Test pass_test()"""
1405 run_env = TestCmd.TestCmd(workdir = '')
1406 run_env.write('run', """import sys
1407 sys.stdout.write("run: STDOUT\\n")
1408 sys.stderr.write("run: STDERR\\n")
1409 """)
1410 os.chdir(run_env.workdir)
1411 # Everything before this prepared our "source directory."
1412 # Now do the real test.
1413 self.popen_python(f"""import sys
1414 sys.path = [r'{self.orig_cwd}'] + sys.path
1415 import TestCmd
1416 TestCmd.pass_test(condition = 1)
1417 """, stderr = "PASSED\n")
1419 self.popen_python(f"""import sys
1420 sys.path = [r'{self.orig_cwd}'] + sys.path
1421 import TestCmd
1422 test = TestCmd.TestCmd(program = 'run', interpreter = 'python', workdir = '')
1423 test.run()
1424 test.pass_test(condition = (test.status == 0))
1425 """, stderr = "PASSED\n")
1427 self.popen_python(f"""import sys
1428 sys.path = [r'{self.orig_cwd}'] + sys.path
1429 import TestCmd
1430 test = TestCmd.TestCmd(program = 'run', interpreter = 'python', workdir = '')
1431 test.run()
1432 def brag():
1433 sys.stderr.write("printed on success\\n")
1434 test.pass_test(condition = (test.status == 0), function = brag)
1435 """, stderr = "printed on success\nPASSED\n")
1437 # TODO(sgk): SHOULD ALSO TEST FAILURE CONDITIONS
1441 class preserve_TestCase(TestCmdTestCase):
1442 def test_preserve(self) -> None:
1443 """Test preserve()"""
1444 def cleanup_test(test, cond=None, stdout: str="") -> None:
1445 save = sys.stdout
1446 with closing(StringIO()) as io:
1447 sys.stdout = io
1448 try:
1449 if cond:
1450 test.cleanup(cond)
1451 else:
1452 test.cleanup()
1453 o = io.getvalue()
1454 assert o == stdout, f"o = `{o}', stdout = `{stdout}'"
1455 finally:
1456 sys.stdout = save
1458 test = TestCmd.TestCmd(workdir='')
1459 wdir = test.workdir
1460 try:
1461 test.write('file1', "Test file #1\n")
1462 #test.cleanup()
1463 cleanup_test(test, )
1464 assert not os.path.exists(wdir)
1465 finally:
1466 if os.path.exists(wdir):
1467 shutil.rmtree(wdir, ignore_errors=1)
1468 test._dirlist.remove(wdir)
1470 test = TestCmd.TestCmd(workdir='')
1471 wdir = test.workdir
1472 try:
1473 test.write('file2', "Test file #2\n")
1474 test.preserve('pass_test')
1475 cleanup_test(test, 'pass_test', f"Preserved directory {wdir}\n")
1476 assert os.path.isdir(wdir)
1477 cleanup_test(test, 'fail_test')
1478 assert not os.path.exists(wdir)
1479 finally:
1480 if os.path.exists(wdir):
1481 shutil.rmtree(wdir, ignore_errors = 1)
1482 test._dirlist.remove(wdir)
1484 test = TestCmd.TestCmd(workdir = '')
1485 wdir = test.workdir
1486 try:
1487 test.write('file3', "Test file #3\n")
1488 test.preserve('fail_test')
1489 cleanup_test(test, 'fail_test', f"Preserved directory {wdir}\n")
1490 assert os.path.isdir(wdir)
1491 cleanup_test(test, 'pass_test')
1492 assert not os.path.exists(wdir)
1493 finally:
1494 if os.path.exists(wdir):
1495 shutil.rmtree(wdir, ignore_errors = 1)
1496 test._dirlist.remove(wdir)
1498 test = TestCmd.TestCmd(workdir = '')
1499 wdir = test.workdir
1500 try:
1501 test.write('file4', "Test file #4\n")
1502 test.preserve('fail_test', 'no_result')
1503 cleanup_test(test, 'fail_test', f"Preserved directory {wdir}\n")
1504 assert os.path.isdir(wdir)
1505 cleanup_test(test, 'no_result', f"Preserved directory {wdir}\n")
1506 assert os.path.isdir(wdir)
1507 cleanup_test(test, 'pass_test')
1508 assert not os.path.exists(wdir)
1509 finally:
1510 if os.path.exists(wdir):
1511 shutil.rmtree(wdir, ignore_errors = 1)
1512 test._dirlist.remove(wdir)
1514 test = TestCmd.TestCmd(workdir = '')
1515 wdir = test.workdir
1516 try:
1517 test.preserve()
1518 cleanup_test(test, 'pass_test', f"Preserved directory {wdir}\n")
1519 assert os.path.isdir(wdir)
1520 cleanup_test(test, 'fail_test', f"Preserved directory {wdir}\n")
1521 assert os.path.isdir(wdir)
1522 cleanup_test(test, 'no_result', f"Preserved directory {wdir}\n")
1523 assert os.path.isdir(wdir)
1524 finally:
1525 if os.path.exists(wdir):
1526 shutil.rmtree(wdir, ignore_errors = 1)
1527 test._dirlist.remove(wdir)
1531 class program_TestCase(TestCmdTestCase):
1532 def test_program(self) -> None:
1533 """Test program()"""
1534 test = TestCmd.TestCmd()
1535 assert test.program is None, 'initialized program?'
1536 test = TestCmd.TestCmd(program = 'test')
1537 assert test.program == os.path.join(os.getcwd(), 'test'), 'uninitialized program'
1538 test.program_set('foo')
1539 assert test.program == os.path.join(os.getcwd(), 'foo'), 'did not set program'
1543 class read_TestCase(TestCmdTestCase):
1544 def test_read(self):
1545 """Test read()"""
1546 test = TestCmd.TestCmd(workdir = '', subdir = 'foo')
1547 wdir_file1 = os.path.join(test.workdir, 'file1')
1548 wdir_file2 = os.path.join(test.workdir, 'file2')
1549 wdir_foo_file3 = os.path.join(test.workdir, 'foo', 'file3')
1550 wdir_file4 = os.path.join(test.workdir, 'file4')
1551 wdir_file5 = os.path.join(test.workdir, 'file5')
1553 with open(wdir_file1, 'wb') as f:
1554 f.write(to_bytes(""))
1555 with open(wdir_file2, 'wb') as f:
1556 f.write(to_bytes("Test\nfile\n#2.\n"))
1557 with open(wdir_foo_file3, 'wb') as f:
1558 f.write(to_bytes("Test\nfile\n#3.\n"))
1559 with open(wdir_file4, 'wb') as f:
1560 f.write(to_bytes("Test\nfile\n#4.\n"))
1561 with open(wdir_file5, 'wb') as f:
1562 f.write(to_bytes("Test\r\nfile\r\n#5.\r\n"))
1564 try:
1565 contents = test.read('no_file')
1566 except IOError: # expect "No such file or directory"
1567 pass
1568 except:
1569 raise
1571 try:
1572 test.read(test.workpath('file_x'), mode = 'w')
1573 except ValueError: # expect "mode must begin with 'r'
1574 pass
1575 except:
1576 raise
1578 def _file_matches(file, contents, expected) -> None:
1579 contents = to_str(contents)
1580 assert contents == expected, \
1581 "Expected contents of " + str(file) + "==========\n" + \
1582 expected + \
1583 "Actual contents of " + str(file) + "============\n" + \
1584 contents
1586 _file_matches(wdir_file1, test.read('file1'), "")
1587 _file_matches(wdir_file2, test.read('file2'), "Test\nfile\n#2.\n")
1588 _file_matches(wdir_foo_file3, test.read(['foo', 'file3']),
1589 "Test\nfile\n#3.\n")
1590 _file_matches(wdir_foo_file3,
1591 test.read(UserList(['foo', 'file3'])),
1592 "Test\nfile\n#3.\n")
1593 _file_matches(wdir_file4, test.read('file4', mode = 'r'),
1594 "Test\nfile\n#4.\n")
1595 _file_matches(wdir_file5, test.read('file5', mode = 'rb'),
1596 "Test\r\nfile\r\n#5.\r\n")
1600 class rmdir_TestCase(TestCmdTestCase):
1601 def test_rmdir(self):
1602 """Test rmdir()"""
1603 test = TestCmd.TestCmd(workdir = '')
1605 try:
1606 test.rmdir(['no', 'such', 'dir'])
1607 except FileNotFoundError:
1608 pass
1609 else:
1610 raise Exception("did not catch expected FileNotFoundError")
1612 test.subdir(['sub'],
1613 ['sub', 'dir'],
1614 ['sub', 'dir', 'one'])
1616 s = test.workpath('sub')
1617 s_d = test.workpath('sub', 'dir')
1618 s_d_o = test.workpath('sub', 'dir', 'one')
1620 try:
1621 test.rmdir(['sub'])
1622 except OSError:
1623 pass
1624 else:
1625 raise Exception("did not catch expected OSError")
1627 assert os.path.isdir(s_d_o), f"{s_d_o} is gone?"
1629 try:
1630 test.rmdir(['sub'])
1631 except OSError:
1632 pass
1633 else:
1634 raise Exception("did not catch expected OSError")
1636 assert os.path.isdir(s_d_o), f"{s_d_o} is gone?"
1638 test.rmdir(['sub', 'dir', 'one'])
1640 assert not os.path.exists(s_d_o), f"{s_d_o} exists?"
1641 assert os.path.isdir(s_d), f"{s_d} is gone?"
1643 test.rmdir(['sub', 'dir'])
1645 assert not os.path.exists(s_d), f"{s_d} exists?"
1646 assert os.path.isdir(s), f"{s} is gone?"
1648 test.rmdir('sub')
1650 assert not os.path.exists(s), f"{s} exists?"
1653 class run_TestCase(TestCmdTestCase):
1654 def test_run(self) -> None:
1655 """Test run()"""
1657 t = self.setup_run_scripts()
1659 # Everything before this prepared our "source directory."
1660 # Now do the real test.
1661 try:
1662 test = TestCmd.TestCmd(program = t.script,
1663 interpreter = 'python',
1664 workdir = '',
1665 subdir = 'script_subdir')
1667 test.run()
1668 self.run_match(test.stdout(), t.script, "STDOUT", t.workdir,
1669 repr([]))
1670 self.run_match(test.stderr(), t.script, "STDERR", t.workdir,
1671 repr([]))
1673 test.run(arguments = 'arg1 arg2 arg3')
1674 self.run_match(test.stdout(), t.script, "STDOUT", t.workdir,
1675 repr(['arg1', 'arg2', 'arg3']))
1676 self.run_match(test.stderr(), t.script, "STDERR", t.workdir,
1677 repr(['arg1', 'arg2', 'arg3']))
1679 test.run(program = t.scriptx, arguments = 'foo')
1680 self.run_match(test.stdout(), t.scriptx, "STDOUT", t.workdir,
1681 repr(['foo']))
1682 self.run_match(test.stderr(), t.scriptx, "STDERR", t.workdir,
1683 repr(['foo']))
1685 test.run(chdir = os.curdir, arguments = 'x y z')
1686 self.run_match(test.stdout(), t.script, "STDOUT", test.workdir,
1687 repr(['x', 'y', 'z']))
1688 self.run_match(test.stderr(), t.script, "STDERR", test.workdir,
1689 repr(['x', 'y', 'z']))
1691 test.run(chdir = 'script_subdir')
1692 script_subdir = test.workpath('script_subdir')
1693 self.run_match(test.stdout(), t.script, "STDOUT", script_subdir,
1694 repr([]))
1695 self.run_match(test.stderr(), t.script, "STDERR", script_subdir,
1696 repr([]))
1698 test.run(program = t.script1, interpreter = ['python', '-x'])
1699 self.run_match(test.stdout(), t.script1, "STDOUT", t.workdir,
1700 repr([]))
1701 self.run_match(test.stderr(), t.script1, "STDERR", t.workdir,
1702 repr([]))
1704 try:
1705 test.run(chdir = 'no_subdir')
1706 except OSError:
1707 pass
1709 test.run(program = 'no_script', interpreter = 'python')
1710 assert test.status is not None, test.status
1712 try:
1713 test.run(program = 'no_script', interpreter = 'no_interpreter')
1714 except OSError:
1715 # Python versions that use subprocess throw an OSError
1716 # exception when they try to execute something that
1717 # isn't there.
1718 pass
1719 else:
1720 # Python versions that use os.popen3() or the Popen3
1721 # class run things through the shell, which just returns
1722 # a non-zero exit status.
1723 assert test.status is not None, test.status
1725 testx = TestCmd.TestCmd(program = t.scriptx,
1726 workdir = '',
1727 subdir = 't.scriptx_subdir')
1729 testx.run()
1730 self.run_match(testx.stdout(), t.scriptx, "STDOUT", t.workdir,
1731 repr([]))
1732 self.run_match(testx.stderr(), t.scriptx, "STDERR", t.workdir,
1733 repr([]))
1735 testx.run(arguments = 'foo bar')
1736 self.run_match(testx.stdout(), t.scriptx, "STDOUT", t.workdir,
1737 repr(['foo', 'bar']))
1738 self.run_match(testx.stderr(), t.scriptx, "STDERR", t.workdir,
1739 repr(['foo', 'bar']))
1741 testx.run(program = t.script, interpreter = 'python', arguments = 'bar')
1742 self.run_match(testx.stdout(), t.script, "STDOUT", t.workdir,
1743 repr(['bar']))
1744 self.run_match(testx.stderr(), t.script, "STDERR", t.workdir,
1745 repr(['bar']))
1747 testx.run(chdir = os.curdir, arguments = 'baz')
1748 self.run_match(testx.stdout(), t.scriptx, "STDOUT", testx.workdir,
1749 repr(['baz']))
1750 self.run_match(testx.stderr(), t.scriptx, "STDERR", testx.workdir,
1751 repr(['baz']))
1753 testx.run(chdir = 't.scriptx_subdir')
1754 t.scriptx_subdir = testx.workpath('t.scriptx_subdir')
1755 self.run_match(testx.stdout(), t.scriptx, "STDOUT", t.scriptx_subdir,
1756 repr([]))
1757 self.run_match(testx.stderr(), t.scriptx, "STDERR", t.scriptx_subdir,
1758 repr([]))
1760 testx.run(program = t.script1, interpreter = ('python', '-x'))
1761 self.run_match(testx.stdout(), t.script1, "STDOUT", t.workdir,
1762 repr([]))
1763 self.run_match(testx.stderr(), t.script1, "STDERR", t.workdir,
1764 repr([]))
1766 s = os.path.join('.', t.scriptx)
1767 testx.run(program = [s])
1768 self.run_match(testx.stdout(), t.scriptx, "STDOUT", t.workdir,
1769 repr([]))
1770 self.run_match(testx.stderr(), t.scriptx, "STDERR", t.workdir,
1771 repr([]))
1773 try:
1774 testx.run(chdir = 'no_subdir')
1775 except OSError:
1776 pass
1778 try:
1779 testx.run(program = 'no_program')
1780 except OSError:
1781 # Python versions that use subprocess throw an OSError
1782 # exception when they try to execute something that
1783 # isn't there.
1784 pass
1785 else:
1786 # Python versions that use os.popen3() or the Popen3
1787 # class run things through the shell, which just returns
1788 # a non-zero exit status.
1789 assert test.status is not None
1791 test1 = TestCmd.TestCmd(program = t.script1,
1792 interpreter = ['python', '-x'],
1793 workdir = '')
1795 test1.run()
1796 self.run_match(test1.stdout(), t.script1, "STDOUT", t.workdir,
1797 repr([]))
1798 self.run_match(test1.stderr(), t.script1, "STDERR", t.workdir,
1799 repr([]))
1801 finally:
1802 os.chdir(t.orig_cwd)
1804 def test_run_subclass(self) -> None:
1805 """Test run() through a subclass with different signatures"""
1807 t = self.setup_run_scripts()
1809 # Everything before this prepared our "source directory."
1810 # Now do the real test.
1812 class MyTestCmdSubclass(TestCmd.TestCmd):
1813 def start(self, additional_argument=None, **kw):
1814 return TestCmd.TestCmd.start(self, **kw)
1816 try:
1817 test = MyTestCmdSubclass(program = t.script,
1818 interpreter = 'python',
1819 workdir = '',
1820 subdir = 'script_subdir')
1822 test.run()
1823 self.run_match(test.stdout(), t.script, "STDOUT", t.workdir,
1824 repr([]))
1825 self.run_match(test.stderr(), t.script, "STDERR", t.workdir,
1826 repr([]))
1827 finally:
1828 os.chdir(t.orig_cwd)
1831 class run_verbose_TestCase(TestCmdTestCase):
1832 def test_run_verbose(self) -> None:
1833 """Test the run() method's verbose attribute"""
1835 # Prepare our "source directory."
1836 t = self.setup_run_scripts()
1838 save_stdout = sys.stderr
1839 save_stderr = sys.stderr
1841 try:
1842 # Test calling TestCmd() with an explicit verbose = 1.
1844 test = TestCmd.TestCmd(program = t.script,
1845 interpreter = 'python',
1846 workdir = '',
1847 verbose = 1)
1849 with closing(StringIO()) as sys.stdout, closing(StringIO()) as sys.stderr:
1850 test.run(arguments = ['arg1 arg2'])
1851 o = sys.stdout.getvalue()
1852 assert o == '', o
1853 e = sys.stderr.getvalue()
1854 expect = f'python "{t.script_path}" "arg1 arg2\"\n'
1855 assert expect == e, (expect, e)
1857 testx = TestCmd.TestCmd(program = t.scriptx,
1858 workdir = '',
1859 verbose = 1)
1861 with closing(StringIO()) as sys.stdout, closing(StringIO()) as sys.stderr:
1862 testx.run(arguments = ['arg1 arg2'])
1863 expect = f'"{t.scriptx_path}" "arg1 arg2\"\n'
1864 o = sys.stdout.getvalue()
1865 assert o == '', o
1866 e = sys.stderr.getvalue()
1867 assert expect == e, (expect, e)
1869 # Test calling TestCmd() with an explicit verbose = 2.
1871 outerr_fmt = """\
1872 ============ STATUS: 0
1873 ============ BEGIN STDOUT (len=%s):
1874 %s============ END STDOUT
1875 ============ BEGIN STDERR (len=%s)
1876 %s============ END STDERR
1879 out_fmt = """\
1880 ============ STATUS: 0
1881 ============ BEGIN STDOUT (len=%s):
1882 %s============ END STDOUT
1885 err_fmt = """\
1886 ============ STATUS: 0
1887 ============ BEGIN STDERR (len=%s)
1888 %s============ END STDERR
1891 test = TestCmd.TestCmd(program = t.script,
1892 interpreter = 'python',
1893 workdir = '',
1894 verbose = 2)
1896 with closing(StringIO()) as sys.stdout, closing(StringIO()) as sys.stderr:
1897 test.run(arguments = ['arg1 arg2'])
1899 line_fmt = "script: %s: %s: ['arg1 arg2']\n"
1900 stdout_line = line_fmt % ('STDOUT', t.sub_dir)
1901 stderr_line = line_fmt % ('STDERR', t.sub_dir)
1902 expect = outerr_fmt % (len(stdout_line), stdout_line,
1903 len(stderr_line), stderr_line)
1904 o = sys.stdout.getvalue()
1905 assert expect == o, (expect, o)
1907 expect = f'python "{t.script_path}" "arg1 arg2\"\n'
1908 e = sys.stderr.getvalue()
1909 assert e == expect, (e, expect)
1911 testx = TestCmd.TestCmd(program = t.scriptx,
1912 workdir = '',
1913 verbose = 2)
1915 with closing(StringIO()) as sys.stdout, closing(StringIO()) as sys.stderr:
1916 testx.run(arguments = ['arg1 arg2'])
1918 line_fmt = "scriptx.bat: %s: %s: ['arg1 arg2']\n"
1919 stdout_line = line_fmt % ('STDOUT', t.sub_dir)
1920 stderr_line = line_fmt % ('STDERR', t.sub_dir)
1921 expect = outerr_fmt % (len(stdout_line), stdout_line,
1922 len(stderr_line), stderr_line)
1923 o = sys.stdout.getvalue()
1924 assert expect == o, (expect, o)
1926 expect = f'"{t.scriptx_path}" "arg1 arg2\"\n'
1927 e = sys.stderr.getvalue()
1928 assert e == expect, (e, expect)
1930 # Test calling TestCmd() with an explicit verbose = 3.
1932 test = TestCmd.TestCmd(program = t.scriptout,
1933 interpreter = 'python',
1934 workdir = '',
1935 verbose = 2)
1937 with closing(StringIO()) as sys.stdout, closing(StringIO()) as sys.stderr:
1938 test.run(arguments = ['arg1 arg2'])
1940 line_fmt = "scriptout: %s: %s: ['arg1 arg2']\n"
1941 stdout_line = line_fmt % ('STDOUT', t.sub_dir)
1942 expect = out_fmt % (len(stdout_line), stdout_line)
1943 o = sys.stdout.getvalue()
1944 assert expect == o, (expect, o)
1946 e = sys.stderr.getvalue()
1947 expect = f'python "{t.scriptout_path}" "arg1 arg2\"\n'
1948 assert e == expect, (e, expect)
1950 test = TestCmd.TestCmd(program = t.scriptout,
1951 interpreter = 'python',
1952 workdir = '',
1953 verbose = 3)
1955 with closing(StringIO()) as sys.stdout, closing(StringIO()) as sys.stderr:
1956 test.run(arguments = ['arg1 arg2'])
1958 line_fmt = "scriptout: %s: %s: ['arg1 arg2']\n"
1959 stdout_line = line_fmt % ('STDOUT', t.sub_dir)
1960 expect = outerr_fmt % (len(stdout_line), stdout_line,
1961 '0', '')
1962 o = sys.stdout.getvalue()
1963 assert expect == o, (expect, o)
1965 e = sys.stderr.getvalue()
1966 expect = f'python "{t.scriptout_path}" "arg1 arg2\"\n'
1967 assert e == expect, (e, expect)
1969 # Test letting TestCmd() pick up verbose = 2 from the environment.
1971 os.environ['TESTCMD_VERBOSE'] = '2'
1973 test = TestCmd.TestCmd(program = t.script,
1974 interpreter = 'python',
1975 workdir = '')
1977 with closing(StringIO()) as sys.stdout, closing(StringIO()) as sys.stderr:
1978 test.run(arguments = ['arg1 arg2'])
1980 line_fmt = "script: %s: %s: ['arg1 arg2']\n"
1981 stdout_line = line_fmt % ('STDOUT', t.sub_dir)
1982 stderr_line = line_fmt % ('STDERR', t.sub_dir)
1983 expect = outerr_fmt % (len(stdout_line), stdout_line,
1984 len(stderr_line), stderr_line)
1985 o = sys.stdout.getvalue()
1986 assert expect == o, (expect, o)
1988 expect = f'python "{t.script_path}" "arg1 arg2\"\n'
1989 e = sys.stderr.getvalue()
1990 assert e == expect, (e, expect)
1992 testx = TestCmd.TestCmd(program = t.scriptx,
1993 workdir = '')
1995 with closing(StringIO()) as sys.stdout, closing(StringIO()) as sys.stderr:
1996 testx.run(arguments = ['arg1 arg2'])
1998 line_fmt = "scriptx.bat: %s: %s: ['arg1 arg2']\n"
1999 stdout_line = line_fmt % ('STDOUT', t.sub_dir)
2000 stderr_line = line_fmt % ('STDERR', t.sub_dir)
2001 expect = outerr_fmt % (len(stdout_line), stdout_line,
2002 len(stderr_line), stderr_line)
2003 o = sys.stdout.getvalue()
2004 assert expect == o, (expect, o)
2006 expect = f'"{t.scriptx_path}" "arg1 arg2\"\n'
2007 e = sys.stderr.getvalue()
2008 assert e == expect, (e, expect)
2010 # Test letting TestCmd() pick up verbose = 1 from the environment.
2012 os.environ['TESTCMD_VERBOSE'] = '1'
2014 test = TestCmd.TestCmd(program = t.script,
2015 interpreter = 'python',
2016 workdir = '',
2017 verbose = 1)
2019 with closing(StringIO()) as sys.stdout, closing(StringIO()) as sys.stderr:
2020 test.run(arguments = ['arg1 arg2'])
2021 o = sys.stdout.getvalue()
2022 assert o == '', o
2023 e = sys.stderr.getvalue()
2024 expect = f'python "{t.script_path}" "arg1 arg2\"\n'
2025 assert expect == e, (expect, e)
2027 testx = TestCmd.TestCmd(program = t.scriptx,
2028 workdir = '',
2029 verbose = 1)
2031 with closing(StringIO()) as sys.stdout, closing(StringIO()) as sys.stderr:
2032 testx.run(arguments = ['arg1 arg2'])
2033 expect = f'"{t.scriptx_path}" "arg1 arg2\"\n'
2034 o = sys.stdout.getvalue()
2035 assert o == '', o
2036 e = sys.stderr.getvalue()
2037 assert expect == e, (expect, e)
2039 finally:
2040 sys.stdout = save_stdout
2041 sys.stderr = save_stderr
2042 os.chdir(t.orig_cwd)
2043 os.environ['TESTCMD_VERBOSE'] = ''
2047 class set_diff_function_TestCase(TestCmdTestCase):
2048 def test_set_diff_function(self) -> None:
2049 """Test set_diff_function()"""
2050 self.popen_python(fr"""import sys
2051 sys.path = [r'{self.orig_cwd}'] + sys.path
2052 import TestCmd
2053 test = TestCmd.TestCmd()
2054 test.diff("a\n", "a\n")
2055 test.set_diff_function('diff_re')
2056 test.diff(".\n", "a\n")
2057 sys.exit(0)
2058 """)
2060 def test_set_diff_function_stdout(self) -> None:
2061 """Test set_diff_function(): stdout"""
2062 self.popen_python(f"""import sys
2063 sys.path = [r'{self.orig_cwd}'] + sys.path
2064 import TestCmd
2065 test = TestCmd.TestCmd()
2066 print("diff:")
2067 test.diff("a\\n", "a\\n")
2068 print("diff_stdout:")
2069 test.diff_stdout("a\\n", "a\\n")
2070 test.set_diff_function(stdout='diff_re')
2071 print("diff:")
2072 test.diff(".\\n", "a\\n")
2073 print("diff_stdout:")
2074 test.diff_stdout(".\\n", "a\\n")
2075 sys.exit(0)
2076 """,
2077 stdout="""\
2078 diff:
2079 diff_stdout:
2080 diff:
2085 diff_stdout:
2086 """)
2088 def test_set_diff_function_stderr(self) -> None:
2089 """Test set_diff_function(): stderr """
2090 self.popen_python(f"""import sys
2091 sys.path = [r'{self.orig_cwd}'] + sys.path
2092 import TestCmd
2093 test = TestCmd.TestCmd()
2094 print("diff:")
2095 test.diff("a\\n", "a\\n")
2096 print("diff_stderr:")
2097 test.diff_stderr("a\\n", "a\\n")
2098 test.set_diff_function(stderr='diff_re')
2099 print("diff:")
2100 test.diff(".\\n", "a\\n")
2101 print("diff_stderr:")
2102 test.diff_stderr(".\\n", "a\\n")
2103 sys.exit(0)
2104 """,
2105 stdout="""\
2106 diff:
2107 diff_stderr:
2108 diff:
2113 diff_stderr:
2114 """)
2118 class set_match_function_TestCase(TestCmdTestCase):
2119 def test_set_match_function(self) -> None:
2120 """Test set_match_function()"""
2121 test = TestCmd.TestCmd()
2122 assert test.match("abcde\n", "a.*e\n")
2123 assert test.match("abcde\n", "abcde\n")
2125 test.set_match_function('match_exact')
2127 assert not test.match("abcde\n", "a.*e\n")
2128 assert test.match("abcde\n", "abcde\n")
2130 def test_set_match_function_stdout(self) -> None:
2131 """Test set_match_function(): stdout """
2132 test = TestCmd.TestCmd()
2133 assert test.match("abcde\n", "a.*e\n")
2134 assert test.match("abcde\n", "abcde\n")
2135 assert test.match_stdout("abcde\n", "a.*e\n")
2136 assert test.match_stdout("abcde\n", "abcde\n")
2138 test.set_match_function(stdout='match_exact')
2140 assert test.match("abcde\n", "a.*e\n")
2141 assert test.match("abcde\n", "abcde\n")
2142 assert not test.match_stdout("abcde\n", "a.*e\n")
2143 assert test.match_stdout("abcde\n", "abcde\n")
2145 def test_set_match_function_stderr(self) -> None:
2146 """Test set_match_function(): stderr """
2147 test = TestCmd.TestCmd()
2148 assert test.match("abcde\n", "a.*e\n")
2149 assert test.match("abcde\n", "abcde\n")
2150 assert test.match_stderr("abcde\n", "a.*e\n")
2151 assert test.match_stderr("abcde\n", "abcde\n")
2153 test.set_match_function(stderr='match_exact')
2155 assert test.match("abcde\n", "a.*e\n")
2156 assert test.match("abcde\n", "abcde\n")
2157 assert not test.match_stderr("abcde\n", "a.*e\n")
2158 assert test.match_stderr("abcde\n", "abcde\n")
2162 class sleep_TestCase(TestCmdTestCase):
2163 def test_sleep(self) -> None:
2164 """Test sleep()"""
2165 test = TestCmd.TestCmd()
2167 start = time.perf_counter()
2168 test.sleep()
2169 end = time.perf_counter()
2170 diff = end - start
2171 assert diff > 0.9, f"only slept {diff:f} seconds (start {start:f}, end {end:f}), not default"
2173 start = time.perf_counter()
2174 test.sleep(3)
2175 end = time.perf_counter()
2176 diff = end - start
2177 assert diff > 2.9, f"only slept {diff:f} seconds (start {start:f}, end {end:f}), not 3"
2181 class stderr_TestCase(TestCmdTestCase):
2182 def test_stderr(self):
2183 """Test stderr()"""
2184 run_env = TestCmd.TestCmd(workdir = '')
2185 run_env.write('run1', """import sys
2186 sys.stdout.write("run1 STDOUT %s\\n" % sys.argv[1:])
2187 sys.stdout.write("run1 STDOUT second line\\n")
2188 sys.stderr.write("run1 STDERR %s\\n" % sys.argv[1:])
2189 sys.stderr.write("run1 STDERR second line\\n")
2190 """)
2191 run_env.write('run2', """import sys
2192 sys.stdout.write("run2 STDOUT %s\\n" % sys.argv[1:])
2193 sys.stdout.write("run2 STDOUT second line\\n")
2194 sys.stderr.write("run2 STDERR %s\\n" % sys.argv[1:])
2195 sys.stderr.write("run2 STDERR second line\\n")
2196 """)
2197 os.chdir(run_env.workdir)
2198 # Everything before this prepared our "source directory."
2199 # Now do the real test.
2200 test = TestCmd.TestCmd(interpreter = 'python', workdir = '')
2201 try:
2202 output = test.stderr()
2203 except IndexError:
2204 pass
2205 else:
2206 if output is not None:
2207 raise IndexError(f"got unexpected output:\n{output}")
2208 test.program_set('run1')
2209 test.run(arguments = 'foo bar')
2210 test.program_set('run2')
2211 test.run(arguments = 'snafu')
2212 # XXX SHOULD TEST ABSOLUTE NUMBER AS WELL
2213 output = test.stderr()
2214 assert output == "run2 STDERR ['snafu']\nrun2 STDERR second line\n", output
2215 output = test.stderr(run = -1)
2216 assert output == "run1 STDERR ['foo', 'bar']\nrun1 STDERR second line\n", output
2220 class command_args_TestCase(TestCmdTestCase):
2221 def test_command_args(self) -> None:
2222 """Test command_args()"""
2223 run_env = TestCmd.TestCmd(workdir = '')
2224 os.chdir(run_env.workdir)
2225 # Everything before this prepared our "source directory."
2226 # Now do the real test.
2227 test = TestCmd.TestCmd(workdir = '')
2229 r = test.command_args('prog')
2230 expect = [run_env.workpath('prog')]
2231 self.assertEqual(expect, r)
2233 r = test.command_args(test.workpath('new_prog'))
2234 expect = [test.workpath('new_prog')]
2235 self.assertEqual(expect, r)
2237 r = test.command_args('prog', 'python')
2238 expect = ['python', run_env.workpath('prog')]
2239 self.assertEqual(expect, r)
2241 r = test.command_args('prog', 'python', 'arg1 arg2')
2242 expect = ['python', run_env.workpath('prog'), 'arg1', 'arg2']
2243 self.assertEqual(expect, r)
2245 r = test.command_args('prog', 'python', 'arg1 arg2=value')
2246 expect = ['python', run_env.workpath('prog'), 'arg1', 'arg2=value']
2247 with self.subTest():
2248 self.assertEqual(expect, r)
2250 r = test.command_args('prog', 'python', ['arg1', 'arg2=with space'])
2251 expect = ['python', run_env.workpath('prog'), 'arg1', 'arg2=with space']
2252 with self.subTest():
2253 self.assertEqual(expect, r)
2255 test.program_set('default_prog')
2256 default_prog = run_env.workpath('default_prog')
2258 r = test.command_args()
2259 expect = [default_prog]
2260 self.assertEqual(expect, r)
2262 r = test.command_args(interpreter='PYTHON')
2263 expect = ['PYTHON', default_prog]
2264 self.assertEqual(expect, r)
2266 r = test.command_args(interpreter='PYTHON', arguments='arg3 arg4')
2267 expect = ['PYTHON', default_prog, 'arg3', 'arg4']
2268 self.assertEqual(expect, r)
2270 # Test arguments = dict
2271 r = test.command_args(interpreter='PYTHON', arguments={'VAR1':'1'})
2272 expect = ['PYTHON', default_prog, 'VAR1=1']
2273 self.assertEqual(expect, r)
2275 test.interpreter_set('default_python')
2277 r = test.command_args()
2278 expect = ['default_python', default_prog]
2279 self.assertEqual(expect, r)
2281 r = test.command_args(arguments='arg5 arg6')
2282 expect = ['default_python', default_prog, 'arg5', 'arg6']
2283 self.assertEqual(expect, r)
2285 r = test.command_args('new_prog_1')
2286 expect = [run_env.workpath('new_prog_1')]
2287 self.assertEqual(expect, r)
2289 r = test.command_args(program='new_prog_2')
2290 expect = [run_env.workpath('new_prog_2')]
2291 self.assertEqual(expect, r)
2294 class start_TestCase(TestCmdTestCase):
2295 def setup_run_scripts(self):
2296 t = TestCmdTestCase.setup_run_scripts(self)
2297 t.recv_script = 'script_recv'
2298 t.recv_script_path = t.run_env.workpath(t.sub_dir, t.recv_script)
2299 t.recv_out_path = t.run_env.workpath('script_recv.out')
2300 text = f"""import os
2301 import sys
2303 class Unbuffered:
2304 def __init__(self, file):
2305 self.file = file
2306 def write(self, arg):
2307 self.file.write(arg)
2308 self.file.flush()
2309 def __getattr__(self, attr):
2310 return getattr(self.file, attr)
2312 sys.stdout = Unbuffered(sys.stdout)
2313 sys.stderr = Unbuffered(sys.stderr)
2315 sys.stdout.write('script_recv: STDOUT\\n')
2316 sys.stderr.write('script_recv: STDERR\\n')
2317 with open(r'{t.recv_out_path}', 'w') as logfp:
2318 while True:
2319 line = sys.stdin.readline()
2320 if not line:
2321 break
2322 logfp.write('script_recv: ' + line)
2323 sys.stdout.write('script_recv: STDOUT: ' + line)
2324 sys.stderr.write('script_recv: STDERR: ' + line)
2326 t.run_env.write(t.recv_script_path, text)
2327 os.chmod(t.recv_script_path, 0o644) # XXX UNIX-specific
2328 return t
2330 def _cleanup(self, popen) -> None:
2331 """Quiet Python ResourceWarning after wait()"""
2332 if popen.stdout:
2333 popen.stdout.close()
2334 if popen.stderr:
2335 popen.stderr.close()
2337 def test_start(self) -> None:
2338 """Test start()"""
2340 t = self.setup_run_scripts()
2342 # Everything before this prepared our "source directory."
2343 # Now do the real test.
2344 try:
2345 test = TestCmd.TestCmd(program = t.script,
2346 interpreter = 'python',
2347 workdir = '',
2348 subdir = 'script_subdir')
2350 p = test.start()
2351 self.run_match(p.stdout.read(), t.script, "STDOUT", t.workdir,
2352 repr([]))
2353 self.run_match(p.stderr.read(), t.script, "STDERR", t.workdir,
2354 repr([]))
2355 p.wait()
2356 self._cleanup(p)
2358 p = test.start(arguments='arg1 arg2 arg3')
2359 self.run_match(p.stdout.read(), t.script, "STDOUT", t.workdir,
2360 repr(['arg1', 'arg2', 'arg3']))
2361 self.run_match(p.stderr.read(), t.script, "STDERR", t.workdir,
2362 repr(['arg1', 'arg2', 'arg3']))
2363 p.wait()
2364 self._cleanup(p)
2366 p = test.start(program=t.scriptx, arguments='foo')
2367 self.run_match(p.stdout.read(), t.scriptx, "STDOUT", t.workdir,
2368 repr(['foo']))
2369 self.run_match(p.stderr.read(), t.scriptx, "STDERR", t.workdir,
2370 repr(['foo']))
2371 p.wait()
2372 self._cleanup(p)
2374 p = test.start(program=t.script1, interpreter=['python', '-x'])
2375 self.run_match(p.stdout.read(), t.script1, "STDOUT", t.workdir,
2376 repr([]))
2377 self.run_match(p.stderr.read(), t.script1, "STDERR", t.workdir,
2378 repr([]))
2379 p.wait()
2380 self._cleanup(p)
2382 p = test.start(program='no_script', interpreter='python')
2383 status = p.wait()
2384 self._cleanup(p)
2385 assert status is not None, status
2387 try:
2388 p = test.start(program='no_script', interpreter='no_interpreter')
2389 except OSError:
2390 # Python versions that use subprocess throw an OSError
2391 # exception when they try to execute something that
2392 # isn't there.
2393 pass
2394 else:
2395 status = p.wait()
2396 self._cleanup(p)
2397 # Python versions that use os.popen3() or the Popen3
2398 # class run things through the shell, which just returns
2399 # a non-zero exit status.
2400 assert status is not None, status
2402 testx = TestCmd.TestCmd(program = t.scriptx,
2403 workdir = '',
2404 subdir = 't.scriptx_subdir')
2406 p = testx.start()
2407 self.run_match(p.stdout.read(), t.scriptx, "STDOUT", t.workdir,
2408 repr([]))
2409 self.run_match(p.stderr.read(), t.scriptx, "STDERR", t.workdir,
2410 repr([]))
2411 p.wait()
2412 self._cleanup(p)
2414 p = testx.start(arguments='foo bar')
2415 self.run_match(p.stdout.read(), t.scriptx, "STDOUT", t.workdir,
2416 repr(['foo', 'bar']))
2417 self.run_match(p.stderr.read(), t.scriptx, "STDERR", t.workdir,
2418 repr(['foo', 'bar']))
2419 p.wait()
2420 self._cleanup(p)
2422 p = testx.start(program=t.script, interpreter='python', arguments='bar')
2423 self.run_match(p.stdout.read(), t.script, "STDOUT", t.workdir,
2424 repr(['bar']))
2425 self.run_match(p.stderr.read(), t.script, "STDERR", t.workdir,
2426 repr(['bar']))
2427 p.wait()
2428 self._cleanup(p)
2430 p = testx.start(program=t.script1, interpreter=('python', '-x'))
2431 self.run_match(p.stdout.read(), t.script1, "STDOUT", t.workdir,
2432 repr([]))
2433 self.run_match(p.stderr.read(), t.script1, "STDERR", t.workdir,
2434 repr([]))
2435 p.wait()
2436 self._cleanup(p)
2438 s = os.path.join('.', t.scriptx)
2439 p = testx.start(program=[s])
2440 self.run_match(p.stdout.read(), t.scriptx, "STDOUT", t.workdir,
2441 repr([]))
2442 self.run_match(p.stderr.read(), t.scriptx, "STDERR", t.workdir,
2443 repr([]))
2444 p.wait()
2445 self._cleanup(p)
2447 try:
2448 testx.start(program='no_program')
2449 except OSError:
2450 # Python versions that use subprocess throw an OSError
2451 # exception when they try to execute something that
2452 # isn't there.
2453 pass
2454 else:
2455 # Python versions that use os.popen3() or the Popen3
2456 # class run things through the shell, which just dies
2457 # trying to execute the non-existent program before
2458 # we can wait() for it.
2459 try:
2460 p = p.wait()
2461 self._cleanup(p)
2462 except OSError:
2463 pass
2465 test1 = TestCmd.TestCmd(program = t.script1,
2466 interpreter = ['python', '-x'],
2467 workdir = '')
2469 p = test1.start()
2470 self.run_match(p.stdout.read(), t.script1, "STDOUT", t.workdir,
2471 repr([]))
2472 self.run_match(p.stderr.read(), t.script1, "STDERR", t.workdir,
2473 repr([]))
2474 p.wait()
2475 self._cleanup(p)
2477 finally:
2478 os.chdir(t.orig_cwd)
2480 def test_finish(self) -> None:
2481 """Test finish()"""
2483 t = self.setup_run_scripts()
2485 # Everything before this prepared our "source directory."
2486 # Now do the real test.
2487 try:
2489 test = TestCmd.TestCmd(program = t.recv_script,
2490 interpreter = 'python',
2491 workdir = '',
2492 subdir = 'script_subdir')
2494 test.start(stdin=1)
2495 test.finish()
2496 expect_stdout = """\
2497 script_recv: STDOUT
2499 expect_stderr = """\
2500 script_recv: STDERR
2502 stdout = test.stdout()
2503 assert stdout == expect_stdout, stdout
2504 stderr = test.stderr()
2505 assert stderr == expect_stderr, stderr
2507 p = test.start(stdin=1)
2508 p.send('input\n')
2509 test.finish(p)
2510 expect_stdout = """\
2511 script_recv: STDOUT
2512 script_recv: STDOUT: input
2514 expect_stderr = """\
2515 script_recv: STDERR
2516 script_recv: STDERR: input
2518 stdout = test.stdout()
2519 assert stdout == expect_stdout, stdout
2520 stderr = test.stderr()
2521 assert stderr == expect_stderr, stderr
2523 p = test.start(combine=True, stdin=1)
2524 p.send('input\n')
2525 test.finish(p)
2526 expect_stdout = """\
2527 script_recv: STDOUT
2528 script_recv: STDERR
2529 script_recv: STDOUT: input
2530 script_recv: STDERR: input
2532 expect_stderr = ""
2533 stdout = test.stdout()
2534 assert stdout == expect_stdout, stdout
2535 stderr = test.stderr()
2536 assert stderr == expect_stderr, stderr
2538 finally:
2539 os.chdir(t.orig_cwd)
2541 def test_recv(self) -> None:
2542 """Test the recv() method of objects returned by start()"""
2544 t = self.setup_run_scripts()
2546 # Everything before this prepared our "source directory."
2547 # Now do the real test.
2548 try:
2549 test = TestCmd.TestCmd(program = t.script,
2550 interpreter = 'python',
2551 workdir = '',
2552 subdir = 'script_subdir')
2554 p = test.start()
2555 stdout = p.recv()
2556 while stdout == '':
2557 import time
2558 time.sleep(1)
2559 stdout = p.recv()
2560 self.run_match(stdout, t.script, "STDOUT", t.workdir,
2561 repr([]))
2562 p.wait()
2564 finally:
2565 os.chdir(t.orig_cwd)
2567 def test_recv_err(self) -> None:
2568 """Test the recv_err() method of objects returned by start()"""
2570 t = self.setup_run_scripts()
2572 # Everything before this prepared our "source directory."
2573 # Now do the real test.
2574 try:
2576 test = TestCmd.TestCmd(program = t.script,
2577 interpreter = 'python',
2578 workdir = '',
2579 subdir = 'script_subdir')
2581 p = test.start()
2582 stderr = p.recv_err()
2583 while stderr == '':
2584 import time
2585 time.sleep(1)
2586 stderr = p.recv_err()
2587 self.run_match(stderr, t.script, "STDERR", t.workdir,
2588 repr([]))
2589 p.wait()
2592 finally:
2593 os.chdir(t.orig_cwd)
2595 def test_send(self) -> None:
2596 """Test the send() method of objects returned by start()"""
2598 t = self.setup_run_scripts()
2600 # Everything before this prepared our "source directory."
2601 # Now do the real test.
2602 try:
2604 test = TestCmd.TestCmd(program = t.recv_script,
2605 interpreter = 'python',
2606 workdir = '',
2607 subdir = 'script_subdir')
2609 p = test.start(stdin=1)
2610 input = 'stdin.write() input to the receive script\n'
2611 p.stdin.write(to_bytes(input))
2612 p.stdin.close()
2613 p.wait()
2614 with open(t.recv_out_path, 'r') as f:
2615 result = to_str(f.read())
2616 expect = f"script_recv: {input}"
2617 assert result == expect, f"Result:[{result}] should match\nExpected:[{expect}]"
2619 # TODO: Python 3.6+ ResourceWarning: unclosed file <_io.BufferedReader name=9>
2620 p = test.start(stdin=1)
2621 input = 'send() input to the receive script\n'
2622 p.send(input)
2623 p.stdin.close()
2624 p.wait()
2625 with open(t.recv_out_path, 'r') as f:
2626 result = to_str(f.read())
2627 expect = f"script_recv: {input}"
2628 assert result == expect, repr(result)
2630 finally:
2631 os.chdir(t.orig_cwd)
2633 # TODO(sgk): figure out how to eliminate the race conditions here.
2634 def __FLAKY__test_send_recv(self) -> None:
2635 """Test the send_recv() method of objects returned by start()"""
2637 t = self.setup_run_scripts()
2639 # Everything before this prepared our "source directory."
2640 # Now do the real test.
2641 try:
2643 test = TestCmd.TestCmd(program = t.recv_script,
2644 interpreter = 'python',
2645 workdir = '',
2646 subdir = 'script_subdir')
2648 def do_send_recv(p, input):
2649 send, stdout, stderr = p.send_recv(input)
2650 stdout = self.translate_newlines(stdout)
2651 stderr = self.translate_newlines(stderr)
2652 return send, stdout, stderr
2654 p = test.start(stdin=1)
2655 input = 'input to the receive script\n'
2656 send, stdout, stderr = do_send_recv(p, input)
2657 # Buffering issues and a race condition prevent this from
2658 # being completely deterministic, so check for both null
2659 # output and the first write() on each stream.
2660 assert stdout in ("", "script_recv: STDOUT\n"), stdout
2661 assert stderr in ("", "script_recv: STDERR\n"), stderr
2662 send, stdout, stderr = do_send_recv(p, input)
2663 assert stdout in ("", "script_recv: STDOUT\n"), stdout
2664 assert stderr in ("", "script_recv: STDERR\n"), stderr
2665 p.stdin.close()
2666 stdout = self.translate_newlines(p.recv())
2667 stderr = self.translate_newlines(p.recv_err())
2668 assert stdout in ("", "script_recv: STDOUT\n"), stdout
2669 assert stderr in ("", "script_recv: STDERR\n"), stderr
2670 p.wait()
2671 stdout = self.translate_newlines(p.recv())
2672 stderr = self.translate_newlines(p.recv_err())
2673 expect_stdout = """\
2674 script_recv: STDOUT
2675 script_recv: STDOUT: input to the receive script
2676 script_recv: STDOUT: input to the receive script
2678 expect_stderr = """\
2679 script_recv: STDERR
2680 script_recv: STDERR: input to the receive script
2681 script_recv: STDERR: input to the receive script
2683 assert stdout == expect_stdout, stdout
2684 assert stderr == expect_stderr, stderr
2685 with open(t.recv_out_path, 'rb') as f:
2686 result = f.read()
2687 expect = f"script_recv: {input}" * 2
2688 assert result == expect, (result, stdout, stderr)
2690 finally:
2691 os.chdir(t.orig_cwd)
2695 class stdin_TestCase(TestCmdTestCase):
2696 def test_stdin(self) -> None:
2697 """Test stdin()"""
2698 run_env = TestCmd.TestCmd(workdir = '')
2699 run_env.write('run', """\
2700 import fileinput
2701 for line in fileinput.input():
2702 print('Y'.join(line[:-1].split('X')))
2703 """)
2704 run_env.write('input', "X on X this X line X\n")
2705 os.chdir(run_env.workdir)
2706 # Everything before this prepared our "source directory."
2707 # Now do the real test.
2708 test = TestCmd.TestCmd(program = 'run', interpreter = 'python', workdir = '')
2709 test.run(arguments = 'input')
2710 assert test.stdout() == "Y on Y this Y line Y\n"
2711 test.run(stdin = "X is X here X tooX\n")
2712 assert test.stdout() == "Y is Y here Y tooY\n"
2713 test.run(stdin = """X here X
2714 X there X
2715 """)
2716 assert test.stdout() == "Y here Y\nY there Y\n"
2717 test.run(stdin = ["X line X\n", "X another X\n"])
2718 assert test.stdout() == "Y line Y\nY another Y\n"
2722 class stdout_TestCase(TestCmdTestCase):
2723 def test_stdout(self):
2724 """Test stdout()"""
2725 run_env = TestCmd.TestCmd(workdir = '')
2726 run_env.write('run1', """\
2727 import sys
2728 sys.stdout.write("run1 STDOUT %s\\n" % sys.argv[1:])
2729 sys.stdout.write("run1 STDOUT second line\\n")
2730 sys.stderr.write("run1 STDERR %s\\n" % sys.argv[1:])
2731 sys.stderr.write("run1 STDERR second line\\n")
2732 """)
2733 run_env.write('run2', """\
2734 import sys
2735 sys.stdout.write("run2 STDOUT %s\\n" % sys.argv[1:])
2736 sys.stdout.write("run2 STDOUT second line\\n")
2737 sys.stderr.write("run2 STDERR %s\\n" % sys.argv[1:])
2738 sys.stderr.write("run2 STDERR second line\\n")
2739 """)
2740 os.chdir(run_env.workdir)
2741 # Everything before this prepared our "source directory."
2742 # Now do the real test.
2743 test = TestCmd.TestCmd(interpreter = 'python', workdir = '')
2744 output = test.stdout()
2745 if output is not None:
2746 raise IndexError(f"got unexpected output:\n\t`{output}'\n")
2747 test.program_set('run1')
2748 test.run(arguments = 'foo bar')
2749 test.program_set('run2')
2750 test.run(arguments = 'snafu')
2751 # XXX SHOULD TEST ABSOLUTE NUMBER AS WELL
2752 output = test.stdout()
2753 assert output == "run2 STDOUT ['snafu']\nrun2 STDOUT second line\n", output
2754 output = test.stdout(run = -1)
2755 assert output == "run1 STDOUT ['foo', 'bar']\nrun1 STDOUT second line\n", output
2758 class subdir_TestCase(TestCmdTestCase):
2759 def test_subdir(self) -> None:
2760 """Test subdir()"""
2761 # intermediate directories are created
2762 test = TestCmd.TestCmd(workdir='', subdir=['no', 'such', 'subdir'])
2763 assert os.path.exists(test.workpath('no'))
2765 test = TestCmd.TestCmd(workdir='', subdir='foo')
2766 assert os.path.isdir(test.workpath('foo'))
2768 # single subdir
2769 assert test.subdir('bar')
2770 assert os.path.isdir(test.workpath('bar'))
2772 # subdir "works" even if existing
2773 assert test.subdir('bar')
2775 # single subdir as a list
2776 assert test.subdir(['foo', 'succeed'])
2777 assert os.path.isdir(test.workpath('foo', 'succeed'))
2779 if os.name != "nt":
2780 assert not os.path.exists(test.workpath('foo', 'fail'))
2782 # subdir creation without write permissions fails
2783 if os.name != "nt":
2784 os.chmod(test.workpath('foo'), 0o500)
2785 assert not test.subdir(['foo', 'fail'])
2787 # create descended path
2788 assert test.subdir(['sub', 'dir', 'ectory'])
2789 assert os.path.isdir(test.workpath('sub'))
2790 assert os.path.exists(test.workpath('sub', 'dir'))
2791 assert os.path.exists(test.workpath('sub', 'dir', 'ectory'))
2793 # test multiple subdirs in one call, each should "succeed"
2794 assert (
2795 test.subdir('one', UserList(['one', 'two']), ['one', 'two', 'three']) == 3
2797 assert os.path.isdir(test.workpath('one', 'two', 'three'))
2800 class symlink_TestCase(TestCmdTestCase):
2801 @unittest.skipIf(sys.platform == 'win32', "Skip symlink test on win32")
2802 def test_symlink(self) -> None:
2803 """Test symlink()"""
2804 test = TestCmd.TestCmd(workdir = '', subdir = 'foo')
2805 wdir_file1 = os.path.join(test.workdir, 'file1')
2806 wdir_target1 = os.path.join(test.workdir, 'target1')
2807 wdir_foo_file2 = os.path.join(test.workdir, 'foo', 'file2')
2808 wdir_target2 = os.path.join(test.workdir, 'target2')
2809 wdir_foo_target2 = os.path.join(test.workdir, 'foo', 'target2')
2811 test.symlink('target1', 'file1')
2812 assert os.path.islink(wdir_file1)
2813 assert not os.path.exists(wdir_file1)
2814 with open(wdir_target1, 'w') as f:
2815 f.write("")
2816 assert os.path.exists(wdir_file1)
2818 test.symlink('target2', ['foo', 'file2'])
2819 assert os.path.islink(wdir_foo_file2)
2820 assert not os.path.exists(wdir_foo_file2)
2821 with open(wdir_target2, 'w') as f:
2822 f.write("")
2823 assert not os.path.exists(wdir_foo_file2)
2824 with open(wdir_foo_target2, 'w') as f:
2825 f.write("")
2826 assert os.path.exists(wdir_foo_file2)
2830 class tempdir_TestCase(TestCmdTestCase):
2831 def setUp(self) -> None:
2832 TestCmdTestCase.setUp(self)
2833 self._tempdir = tempfile.mkdtemp()
2834 os.chdir(self._tempdir)
2836 def tearDown(self) -> None:
2837 TestCmdTestCase.tearDown(self)
2838 os.rmdir(self._tempdir)
2840 def test_tempdir(self) -> None:
2841 """Test tempdir()"""
2842 test = TestCmd.TestCmd()
2843 tdir1 = test.tempdir()
2844 assert os.path.isdir(tdir1)
2845 test.workdir_set(None)
2846 test.cleanup()
2847 assert not os.path.exists(tdir1)
2849 test = TestCmd.TestCmd()
2850 tdir2 = test.tempdir('temp')
2851 assert os.path.isdir(tdir2)
2852 tdir3 = test.tempdir()
2853 assert os.path.isdir(tdir3)
2854 test.workdir_set(None)
2855 test.cleanup()
2856 assert not os.path.exists(tdir2)
2857 assert not os.path.exists(tdir3)
2860 timeout_script = """\
2861 import sys
2862 import time
2863 seconds = int(sys.argv[1])
2864 sys.stdout.write('sleeping %s\\n' % seconds)
2865 sys.stdout.flush()
2866 time.sleep(seconds)
2867 sys.stdout.write('slept %s\\n' % seconds)
2868 sys.stdout.flush()
2869 sys.exit(0)
2872 class timeout_TestCase(TestCmdTestCase):
2873 def test_initialization(self) -> None:
2874 """Test initializating a TestCmd with a timeout"""
2875 test = TestCmd.TestCmd(workdir='', timeout=2)
2876 test.write('sleep.py', timeout_script)
2878 test.run([sys.executable, test.workpath('sleep.py'), '4'])
2879 assert test.stderr() == '', test.stderr()
2880 assert test.stdout() == 'sleeping 4\n', test.stdout()
2882 test.run([sys.executable, test.workpath('sleep.py'), '4'])
2883 assert test.stderr() == '', test.stderr()
2884 assert test.stdout() == 'sleeping 4\n', test.stdout()
2886 def test_cancellation(self) -> None:
2887 """Test timer cancellation after firing"""
2888 test = TestCmd.TestCmd(workdir='', timeout=4)
2889 test.write('sleep.py', timeout_script)
2891 test.run([sys.executable, test.workpath('sleep.py'), '6'])
2892 assert test.stderr() == '', test.stderr()
2893 assert test.stdout() == 'sleeping 6\n', test.stdout()
2895 test.run([sys.executable, test.workpath('sleep.py'), '2'])
2896 assert test.stderr() == '', test.stderr()
2897 assert test.stdout() == 'sleeping 2\nslept 2\n', test.stdout()
2899 test.run([sys.executable, test.workpath('sleep.py'), '6'])
2900 assert test.stderr() == '', test.stderr()
2901 assert test.stdout() == 'sleeping 6\n', test.stdout()
2903 def test_run(self) -> None:
2904 """Test run() timeout"""
2905 test = TestCmd.TestCmd(workdir='', timeout=8)
2906 test.write('sleep.py', timeout_script)
2908 test.run([sys.executable, test.workpath('sleep.py'), '2'], timeout=4)
2909 assert test.stderr() == '', test.stderr()
2910 assert test.stdout() == 'sleeping 2\nslept 2\n', test.stdout()
2912 test.run([sys.executable, test.workpath('sleep.py'), '6'], timeout=4)
2913 assert test.stderr() == '', test.stderr()
2914 assert test.stdout() == 'sleeping 6\n', test.stdout()
2916 # This method has been removed
2917 #def test_set_timeout(self):
2918 # """Test set_timeout()"""
2919 # test = TestCmd.TestCmd(workdir='', timeout=2)
2920 # test.write('sleep.py', timeout_script)
2922 # test.run([sys.executable, test.workpath('sleep.py'), '4'])
2923 # assert test.stderr() == '', test.stderr()
2924 # assert test.stdout() == 'sleeping 4\n', test.stdout()
2926 # test.set_timeout(None)
2928 # test.run([sys.executable, test.workpath('sleep.py'), '4'])
2929 # assert test.stderr() == '', test.stderr()
2930 # assert test.stdout() == 'sleeping 4\nslept 4\n', test.stdout()
2932 # test.set_timeout(6)
2934 # test.run([sys.executable, test.workpath('sleep.py'), '4'])
2935 # assert test.stderr() == '', test.stderr()
2936 # assert test.stdout() == 'sleeping 4\nslept 4\n', test.stdout()
2938 # test.run([sys.executable, test.workpath('sleep.py'), '8'])
2939 # assert test.stderr() == '', test.stderr()
2940 # assert test.stdout() == 'sleeping 8\n', test.stdout()
2944 class unlink_TestCase(TestCmdTestCase):
2945 def test_unlink(self):
2946 """Test unlink()"""
2947 test = TestCmd.TestCmd(workdir = '', subdir = 'foo')
2948 wdir_file1 = os.path.join(test.workdir, 'file1')
2949 wdir_file2 = os.path.join(test.workdir, 'file2')
2950 wdir_foo_file3a = os.path.join(test.workdir, 'foo', 'file3a')
2951 wdir_foo_file3b = os.path.join(test.workdir, 'foo', 'file3b')
2952 wdir_foo_file4 = os.path.join(test.workdir, 'foo', 'file4')
2953 wdir_file5 = os.path.join(test.workdir, 'file5')
2955 with open(wdir_file1, 'w') as f:
2956 f.write("")
2957 with open(wdir_file2, 'w') as f:
2958 f.write("")
2959 with open(wdir_foo_file3a, 'w') as f:
2960 f.write("")
2961 with open(wdir_foo_file3b, 'w') as f:
2962 f.write("")
2963 with open(wdir_foo_file4, 'w') as f:
2964 f.write("")
2965 with open(wdir_file5, 'w') as f:
2966 f.write("")
2968 try:
2969 contents = test.unlink('no_file')
2970 except OSError: # expect "No such file or directory"
2971 pass
2972 except:
2973 raise
2975 test.unlink("file1")
2976 assert not os.path.exists(wdir_file1)
2978 test.unlink(wdir_file2)
2979 assert not os.path.exists(wdir_file2)
2981 test.unlink(['foo', 'file3a'])
2982 assert not os.path.exists(wdir_foo_file3a)
2984 test.unlink(UserList(['foo', 'file3b']))
2985 assert not os.path.exists(wdir_foo_file3b)
2987 test.unlink([test.workdir, 'foo', 'file4'])
2988 assert not os.path.exists(wdir_foo_file4)
2990 # Make it so we can't unlink file5.
2991 # For UNIX, remove write permission from the dir and the file.
2992 # For Windows, open the file.
2993 os.chmod(test.workdir, 0o500)
2994 os.chmod(wdir_file5, 0o400)
2995 with open(wdir_file5, 'r'):
2996 try:
2997 try:
2998 test.unlink('file5')
2999 except OSError: # expect "Permission denied"
3000 pass
3001 except:
3002 raise
3003 finally:
3004 os.chmod(test.workdir, 0o700)
3005 os.chmod(wdir_file5, 0o600)
3008 class unlink_files_TestCase(TestCmdTestCase):
3009 def test_unlink_files(self):
3010 """Test unlink_files()"""
3011 test = TestCmd.TestCmd(workdir = '', subdir = 'foo')
3012 wdir_file1 = os.path.join(test.workdir, 'file1')
3013 wdir_file2 = os.path.join(test.workdir, 'file2')
3014 wdir_foo_file3a = os.path.join(test.workdir, 'foo', 'file3a')
3015 wdir_foo_file3b = os.path.join(test.workdir, 'foo', 'file3b')
3016 wdir_foo_file3c = os.path.join(test.workdir, 'foo', 'file3c')
3017 wdir_foo_file3d = os.path.join(test.workdir, 'foo', 'file3d')
3018 wdir_foo_file4a = os.path.join(test.workdir, 'foo', 'file4a')
3019 wdir_foo_file4b = os.path.join(test.workdir, 'foo', 'file4b')
3020 wdir_foo_file4c = os.path.join(test.workdir, 'foo', 'file4c')
3021 wdir_foo_file4d = os.path.join(test.workdir, 'foo', 'file4d')
3022 wdir_file5 = os.path.join(test.workdir, 'file5')
3024 with open(wdir_file1, 'w') as f:
3025 f.write("")
3026 with open(wdir_file2, 'w') as f:
3027 f.write("")
3028 with open(wdir_foo_file3a, 'w') as f:
3029 f.write("")
3030 with open(wdir_foo_file3b, 'w') as f:
3031 f.write("")
3032 with open(wdir_foo_file3c, 'w') as f:
3033 f.write("")
3034 with open(wdir_foo_file3d, 'w') as f:
3035 f.write("")
3036 with open(wdir_foo_file4a, 'w') as f:
3037 f.write("")
3038 with open(wdir_foo_file4b, 'w') as f:
3039 f.write("")
3040 with open(wdir_foo_file4c, 'w') as f:
3041 f.write("")
3042 with open(wdir_foo_file4d, 'w') as f:
3043 f.write("")
3044 with open(wdir_file5, 'w') as f:
3045 f.write("")
3047 test.unlink_files('', [
3048 'no_file_a',
3049 'no_file_b',
3052 test.unlink_files('', [
3053 'file1',
3054 'file2',
3056 assert not os.path.exists(wdir_file1)
3057 assert not os.path.exists(wdir_file2)
3059 test.unlink_files('foo', [
3060 'file3a',
3061 'file3b',
3063 assert not os.path.exists(wdir_foo_file3a)
3064 assert not os.path.exists(wdir_foo_file3b)
3066 test.unlink_files(['foo'], [
3067 'file3c',
3068 'file3d',
3070 assert not os.path.exists(wdir_foo_file3c)
3071 assert not os.path.exists(wdir_foo_file3d)
3073 test.unlink_files('', [
3074 ['foo', 'file4a'],
3075 ['foo', 'file4b'],
3077 assert not os.path.exists(wdir_foo_file4a)
3078 assert not os.path.exists(wdir_foo_file4b)
3080 test.unlink_files([''], [
3081 ['foo', 'file4c'],
3082 ['foo', 'file4d'],
3084 assert not os.path.exists(wdir_foo_file4c)
3085 assert not os.path.exists(wdir_foo_file4d)
3087 # Make it so we can't unlink file5.
3088 # For UNIX, remove write permission from the dir and the file.
3089 # For Windows, open the file.
3090 os.chmod(test.workdir, 0o500)
3091 os.chmod(wdir_file5, 0o400)
3092 with open(wdir_file5, 'r'):
3093 try:
3094 try:
3095 test.unlink_files('', ['file5'])
3096 except OSError: # expect "Permission denied"
3097 pass
3098 except:
3099 raise
3100 finally:
3101 os.chmod(test.workdir, 0o700)
3102 os.chmod(wdir_file5, 0o600)
3105 class touch_TestCase(TestCmdTestCase):
3106 def test_touch(self) -> None:
3107 """Test touch()"""
3108 test = TestCmd.TestCmd(workdir = '', subdir = 'sub')
3110 wdir_file1 = os.path.join(test.workdir, 'file1')
3111 wdir_sub_file2 = os.path.join(test.workdir, 'sub', 'file2')
3113 with open(wdir_file1, 'w') as f:
3114 f.write("")
3115 with open(wdir_sub_file2, 'w') as f:
3116 f.write("")
3118 file1_old_time = os.path.getmtime(wdir_file1)
3119 file2_old_time = os.path.getmtime(wdir_sub_file2)
3121 test.sleep()
3123 test.touch(wdir_file1)
3125 file1_new_time = os.path.getmtime(wdir_file1)
3126 assert file1_new_time > file1_old_time
3128 test.touch('file1', file1_old_time)
3130 result = os.path.getmtime(wdir_file1)
3131 # Sub-second granularity of file systems may still vary.
3132 # On Windows, the two times may be off by a microsecond.
3133 assert int(result) == int(file1_old_time), (result, file1_old_time)
3135 test.touch(['sub', 'file2'])
3137 file2_new_time = os.path.getmtime(wdir_sub_file2)
3138 assert file2_new_time > file2_old_time
3142 class verbose_TestCase(TestCmdTestCase):
3143 def test_verbose(self) -> None:
3144 """Test verbose()"""
3145 test = TestCmd.TestCmd()
3146 assert test.verbose == 0, 'verbose already initialized?'
3147 test = TestCmd.TestCmd(verbose = 1)
3148 assert test.verbose == 1, 'did not initialize verbose'
3149 test.verbose = 2
3150 assert test.verbose == 2, 'did not set verbose'
3154 class workdir_TestCase(TestCmdTestCase):
3155 def test_workdir(self):
3156 """Test workdir()"""
3157 run_env = TestCmd.TestCmd(workdir = '')
3158 os.chdir(run_env.workdir)
3159 # Everything before this prepared our "source directory."
3160 # Now do the real test.
3161 test = TestCmd.TestCmd()
3162 assert test.workdir is None
3164 test = TestCmd.TestCmd(workdir = None)
3165 assert test.workdir is None
3167 test = TestCmd.TestCmd(workdir = '')
3168 assert test.workdir is not None
3169 assert os.path.isdir(test.workdir)
3171 test = TestCmd.TestCmd(workdir = 'dir')
3172 assert test.workdir is not None
3173 assert os.path.isdir(test.workdir)
3175 no_such_subdir = os.path.join('no', 'such', 'subdir')
3176 try:
3177 test = TestCmd.TestCmd(workdir = no_such_subdir)
3178 except OSError: # expect "No such file or directory"
3179 pass
3180 except:
3181 raise
3183 test = TestCmd.TestCmd(workdir = 'foo')
3184 workdir_foo = test.workdir
3185 assert workdir_foo is not None
3187 test.workdir_set('bar')
3188 workdir_bar = test.workdir
3189 assert workdir_bar is not None
3191 try:
3192 test.workdir_set(no_such_subdir)
3193 except OSError:
3194 pass # expect "No such file or directory"
3195 except:
3196 raise
3197 assert workdir_bar == test.workdir
3199 assert os.path.isdir(workdir_foo)
3200 assert os.path.isdir(workdir_bar)
3204 class workdirs_TestCase(TestCmdTestCase):
3205 def test_workdirs(self) -> None:
3206 """Test workdirs()"""
3207 test = TestCmd.TestCmd()
3208 assert test.workdir is None
3209 test.workdir_set('')
3210 wdir1 = test.workdir
3211 test.workdir_set('')
3212 wdir2 = test.workdir
3213 assert os.path.isdir(wdir1)
3214 assert os.path.isdir(wdir2)
3215 test.cleanup()
3216 assert not os.path.exists(wdir1)
3217 assert not os.path.exists(wdir2)
3221 class workpath_TestCase(TestCmdTestCase):
3222 def test_workpath(self) -> None:
3223 """Test workpath()"""
3224 test = TestCmd.TestCmd()
3225 assert test.workdir is None
3227 test = TestCmd.TestCmd(workdir = '')
3228 wpath = test.workpath('foo', 'bar')
3229 assert wpath == os.path.join(test.workdir, 'foo', 'bar')
3232 class readable_TestCase(TestCmdTestCase):
3233 @unittest.skipIf(sys.platform == 'win32', "Skip permission fiddling on win32")
3234 def test_readable(self) -> None:
3235 """Test readable()"""
3236 test = TestCmd.TestCmd(workdir = '', subdir = 'foo')
3237 test.write('file1', "Test file #1\n")
3238 test.write(['foo', 'file2'], "Test file #2\n")
3239 os.symlink('no_such_file', test.workpath('dangling_symlink'))
3241 test.readable(test.workdir, 0)
3242 # XXX skip these tests if euid == 0?
3243 assert not _is_readable(test.workdir)
3244 assert not _is_readable(test.workpath('file1'))
3245 assert not _is_readable(test.workpath('foo'))
3246 assert not _is_readable(test.workpath('foo', 'file2'))
3248 test.readable(test.workdir, 1)
3249 assert _is_readable(test.workdir)
3250 assert _is_readable(test.workpath('file1'))
3251 assert _is_readable(test.workpath('foo'))
3252 assert _is_readable(test.workpath('foo', 'file2'))
3254 test.readable(test.workdir, 0)
3255 # XXX skip these tests if euid == 0?
3256 assert not _is_readable(test.workdir)
3257 assert not _is_readable(test.workpath('file1'))
3258 assert not _is_readable(test.workpath('foo'))
3259 assert not _is_readable(test.workpath('foo', 'file2'))
3261 test.readable(test.workpath('file1'), 1)
3262 assert _is_readable(test.workpath('file1'))
3264 test.readable(test.workpath('file1'), 0)
3265 assert not _is_readable(test.workpath('file1'))
3267 test.readable(test.workdir, 1)
3271 class writable_TestCase(TestCmdTestCase):
3272 @unittest.skipIf(sys.platform == 'win32', "Skip permission fiddling on win32")
3273 def test_writable(self) -> None:
3274 """Test writable()"""
3275 test = TestCmd.TestCmd(workdir = '', subdir = 'foo')
3276 test.write('file1', "Test file #1\n")
3277 test.write(['foo', 'file2'], "Test file #2\n")
3278 os.symlink('no_such_file', test.workpath('dangling_symlink'))
3280 test.writable(test.workdir, 0)
3281 # XXX skip these tests if euid == 0?
3282 assert not _is_writable(test.workdir)
3283 assert not _is_writable(test.workpath('file1'))
3284 assert not _is_writable(test.workpath('foo'))
3285 assert not _is_writable(test.workpath('foo', 'file2'))
3287 test.writable(test.workdir, 1)
3288 assert _is_writable(test.workdir)
3289 assert _is_writable(test.workpath('file1'))
3290 assert _is_writable(test.workpath('foo'))
3291 assert _is_writable(test.workpath('foo', 'file2'))
3293 test.writable(test.workdir, 0)
3294 # XXX skip these tests if euid == 0?
3295 assert not _is_writable(test.workdir)
3296 assert not _is_writable(test.workpath('file1'))
3297 assert not _is_writable(test.workpath('foo'))
3298 assert not _is_writable(test.workpath('foo', 'file2'))
3300 test.writable(test.workpath('file1'), 1)
3301 assert _is_writable(test.workpath('file1'))
3303 test.writable(test.workpath('file1'), 0)
3304 assert not _is_writable(test.workpath('file1'))
3307 class executable_TestCase(TestCmdTestCase):
3308 @unittest.skipIf(sys.platform == 'win32', "Skip permission fiddling on win32")
3309 def test_executable(self) -> None:
3310 """Test executable()"""
3311 test = TestCmd.TestCmd(workdir = '', subdir = 'foo')
3312 test.write('file1', "Test file #1\n")
3313 test.write(['foo', 'file2'], "Test file #2\n")
3314 os.symlink('no_such_file', test.workpath('dangling_symlink'))
3316 def make_executable(fname) -> None:
3317 st = os.stat(fname)
3318 os.chmod(fname, stat.S_IMODE(st[stat.ST_MODE]|0o100))
3320 def make_non_executable(fname) -> None:
3321 st = os.stat(fname)
3322 os.chmod(fname, stat.S_IMODE(st[stat.ST_MODE]&~0o100))
3324 test.executable(test.workdir, 0)
3325 # XXX skip these tests if euid == 0?
3326 assert not _is_executable(test.workdir)
3327 make_executable(test.workdir)
3328 assert not _is_executable(test.workpath('file1'))
3329 assert not _is_executable(test.workpath('foo'))
3330 make_executable(test.workpath('foo'))
3331 assert not _is_executable(test.workpath('foo', 'file2'))
3332 make_non_executable(test.workpath('foo'))
3333 make_non_executable(test.workdir)
3335 test.executable(test.workdir, 1)
3336 assert _is_executable(test.workdir)
3337 assert _is_executable(test.workpath('file1'))
3338 assert _is_executable(test.workpath('foo'))
3339 assert _is_executable(test.workpath('foo', 'file2'))
3341 test.executable(test.workdir, 0)
3342 # XXX skip these tests if euid == 0?
3343 assert not _is_executable(test.workdir)
3344 make_executable(test.workdir)
3345 assert not _is_executable(test.workpath('file1'))
3346 assert not _is_executable(test.workpath('foo'))
3347 make_executable(test.workpath('foo'))
3348 assert not _is_executable(test.workpath('foo', 'file2'))
3350 test.executable(test.workpath('file1'), 1)
3351 assert _is_executable(test.workpath('file1'))
3353 test.executable(test.workpath('file1'), 0)
3354 assert not _is_executable(test.workpath('file1'))
3356 test.executable(test.workdir, 1)
3360 class write_TestCase(TestCmdTestCase):
3361 def test_write(self):
3362 """Test write()"""
3363 test = TestCmd.TestCmd(workdir = '', subdir = 'foo')
3364 test.write('file1', "Test file #1\n")
3365 test.write(['foo', 'file2'], "Test file #2\n")
3366 try:
3367 test.write(['bar', 'file3'], "Test file #3 (should not get created)\n")
3368 except IOError: # expect "No such file or directory"
3369 pass
3370 except:
3371 raise
3372 test.write(test.workpath('file4'), "Test file #4.\n")
3373 test.write(test.workpath('foo', 'file5'), "Test file #5.\n")
3374 try:
3375 test.write(test.workpath('bar', 'file6'), "Test file #6 (should not get created)\n")
3376 except IOError: # expect "No such file or directory"
3377 pass
3378 except:
3379 raise
3381 try:
3382 test.write('file7', "Test file #8.\n", mode = 'r')
3383 except ValueError: # expect "mode must begin with 'w'
3384 pass
3385 except:
3386 raise
3388 test.write('file8', "Test file #8.\n", mode = 'w')
3389 test.write('file9', "Test file #9.\r\n", mode = 'wb')
3391 if os.name != "nt":
3392 os.chmod(test.workdir, 0o500)
3393 try:
3394 test.write('file10', "Test file #10 (should not get created).\n")
3395 except IOError: # expect "Permission denied"
3396 pass
3397 except:
3398 raise
3400 assert os.path.isdir(test.workpath('foo'))
3401 assert not os.path.exists(test.workpath('bar'))
3402 assert os.path.isfile(test.workpath('file1'))
3403 assert os.path.isfile(test.workpath('foo', 'file2'))
3404 assert not os.path.exists(test.workpath('bar', 'file3'))
3405 assert os.path.isfile(test.workpath('file4'))
3406 assert os.path.isfile(test.workpath('foo', 'file5'))
3407 assert not os.path.exists(test.workpath('bar', 'file6'))
3408 assert not os.path.exists(test.workpath('file7'))
3409 assert os.path.isfile(test.workpath('file8'))
3410 assert os.path.isfile(test.workpath('file9'))
3411 if os.name != "nt":
3412 assert not os.path.exists(test.workpath('file10'))
3414 with open(test.workpath('file8'), 'r') as f:
3415 res = f.read()
3416 assert res == "Test file #8.\n", res
3417 with open(test.workpath('file9'), 'rb') as f:
3418 res = to_str(f.read())
3419 assert res == "Test file #9.\r\n", res
3422 class variables_TestCase(TestCmdTestCase):
3423 def test_variables(self) -> None:
3424 """Test global variables"""
3425 run_env = TestCmd.TestCmd(workdir = '')
3427 variables = [
3428 'fail_test',
3429 'no_result',
3430 'pass_test',
3431 'match_exact',
3432 'match_re',
3433 'match_re_dotall',
3434 'python',
3435 '_python_',
3436 'TestCmd',
3439 script = "import TestCmd\n" + \
3440 '\n'.join([ "print(TestCmd.%s\n)" % v for v in variables ])
3441 run_env.run(program=sys.executable, stdin=script)
3442 stderr = run_env.stderr()
3443 assert stderr == "", stderr
3445 script = "from TestCmd import *\n" + \
3446 '\n'.join([ "print(%s)" % v for v in variables ])
3447 run_env.run(program=sys.executable, stdin=script)
3448 stderr = run_env.stderr()
3449 assert stderr == "", stderr
3452 if __name__ == "__main__":
3453 unittest.main()
3455 # Local Variables:
3456 # tab-width:4
3457 # indent-tabs-mode:nil
3458 # End:
3459 # vim: set expandtab tabstop=4 shiftwidth=4: