From 3bd6a10d6513be4adc5878602d629ef861bfb7d3 Mon Sep 17 00:00:00 2001 From: Jose Rodriguez Date: Sun, 6 Oct 2019 14:11:27 +0200 Subject: [PATCH 1/3] Allow tests passing cmdline params to zxb When doing a doctest, this update adds the feature to send extra parameters to the zxb executable. This allows testing invoking zxb with different cmdline params (i.e. to test for incompatible params set by the user from the command-line) --- tests/functional/test.py | 33 +++++++++++++++++++++++++-------- tests/functional/test_.py | 2 ++ 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/tests/functional/test.py b/tests/functional/test.py index 76dd31310..70ef7a461 100755 --- a/tests/functional/test.py +++ b/tests/functional/test.py @@ -238,7 +238,7 @@ def updateTest(tfname, pattern_): f.write(''.join(lines)) -def testPREPRO(fname, pattern_=None, inline=None): +def testPREPRO(fname, pattern_=None, inline=None, cmdline_args=None): """ Test preprocessing file. Test is done by preprocessing the file and then comparing the output against an expected one. The output file can optionally be filtered using a filter_ regexp (see above). @@ -253,6 +253,9 @@ def testPREPRO(fname, pattern_=None, inline=None): if inline is None: inline = INLINE + if cmdline_args is None: + cmdline_args = [] + tfname = os.path.join(TEMP_DIR, 'test' + getName(fname) + os.extsep + 'out') okfile = os.path.join(os.path.dirname(fname), getName(fname) + os.extsep + 'out') @@ -268,6 +271,8 @@ def testPREPRO(fname, pattern_=None, inline=None): os.unlink(okfile) options = [os.path.basename(fname), '-o', tfname] + prep + options.extend(cmdline_args) + if inline: func = lambda: zxbpp.entry_point(options) else: @@ -291,7 +296,7 @@ def testPREPRO(fname, pattern_=None, inline=None): return result -def testASM(fname, inline=None): +def testASM(fname, inline=None, cmdline_args=None): """ Test assembling an ASM (.asm) file. Test is done by assembling the source code into a binary and then comparing the output file against an expected binary output. @@ -302,6 +307,9 @@ def testASM(fname, inline=None): if inline is None: inline = INLINE + if cmdline_args is None: + cmdline_args = [] + tfname = os.path.join(TEMP_DIR, 'test' + getName(fname) + os.extsep + 'bin') prep = ['-e', '/dev/null'] if CLOSE_STDERR else ['-e', STDERR] okfile = os.path.join(os.path.dirname(fname), getName(fname) + os.extsep + 'bin') @@ -312,6 +320,7 @@ def testASM(fname, inline=None): os.unlink(okfile) options = [fname, '-o', tfname] + prep + options.extend(cmdline_args) if inline: func = lambda: zxbasm.main(options) @@ -327,7 +336,7 @@ def testASM(fname, inline=None): return result -def testBAS(fname, filter_=None, inline=None): +def testBAS(fname, filter_=None, inline=None, cmdline_args=None): """ Test compiling a BASIC (.bas) file. Test is done by compiling the source code into asm and then comparing the output asm against an expected asm output. The output asm file can optionally be filtered using a filter_ regexp (see above). @@ -340,7 +349,11 @@ def testBAS(fname, filter_=None, inline=None): if inline is None: inline = INLINE + if cmdline_args is None: + cmdline_args = [] + options, tfname, ext = _get_testbas_options(fname) + options.extend(cmdline_args) okfile = os.path.join(os.path.dirname(fname), getName(fname) + os.extsep + ext) if UPDATE and os.path.exists(okfile): @@ -363,11 +376,13 @@ def testBAS(fname, filter_=None, inline=None): return result -def testFiles(file_list): +def testFiles(file_list, cmdline_args=None): """ Run tests for the given file extension """ global EXIT_CODE, COUNTER, FAILED COUNTER = 0 + if cmdline_args is None: + cmdline_args = [] for fname in file_list: fname = fname @@ -375,11 +390,11 @@ def testFiles(file_list): if ext == 'asm': if os.path.exists(os.path.join(os.path.dirname(fname), getName(fname) + os.extsep + 'bas')): continue # Ignore asm files which have a .bas since they're test results - result = testASM(fname, inline=INLINE) + result = testASM(fname, inline=INLINE, cmdline_args=cmdline_args) elif ext == 'bas': - result = testBAS(fname, filter_=FILTER, inline=INLINE) + result = testBAS(fname, filter_=FILTER, inline=INLINE, cmdline_args=cmdline_args) elif ext == 'bi': - result = testPREPRO(fname, pattern_=FILTER, inline=INLINE) + result = testPREPRO(fname, pattern_=FILTER, inline=INLINE, cmdline_args=cmdline_args) else: result = None @@ -519,6 +534,8 @@ def main(argv=None): parser.add_argument('-q', '--quiet', action='store_true', help='Run quietly, suppressing normal output') parser.add_argument('-e', '--stderr', type=str, default=None, help='File for stderr messages') parser.add_argument('-S', '--use-shell', action='store_true', help='Use system shell for test instead of inline') + parser.add_argument('-O', '--option', action='append', help='Option to pass to compiler in a test ' + '(can be used many times)') args = parser.parse_args(argv) STDERR = args.stderr @@ -541,7 +558,7 @@ def main(argv=None): if args.update: upgradeTest(args.FILES, args.update) else: - testFiles(args.FILES) + testFiles(args.FILES, args.option) finally: if temp_dir_created: diff --git a/tests/functional/test_.py b/tests/functional/test_.py index 270d9400c..9756b3b22 100755 --- a/tests/functional/test_.py +++ b/tests/functional/test_.py @@ -43,6 +43,8 @@ def main(): current_path = os.path.abspath(os.getcwd()) os.chdir(os.path.realpath(os.path.dirname(__file__) or os.curdir)) result = doctest.testfile('test_errmsg.txt') # evaluates to True on failure + if not result.failed: + result = doctest.testfile('test_cmdline.txt') # Evaluates to True on failure os.chdir(current_path) return int(result.failed) From 59ef6132c26d24695f37b192a52325806b231755 Mon Sep 17 00:00:00 2001 From: Jose Rodriguez Date: Sun, 6 Oct 2019 22:30:45 +0200 Subject: [PATCH 2/3] Use pytest for test_ target --- tests/functional/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/functional/Makefile b/tests/functional/Makefile index f98e08550..1ea91cad4 100644 --- a/tests/functional/Makefile +++ b/tests/functional/Makefile @@ -9,7 +9,8 @@ diffbas: test: prepro bin asm bas test_: - ./test_.py + pytest . -k 'test_errmsg or test_cmdline' + # ./test_.py prepro: ./test.py *.bi From af519853c49f568ccbd9bbdbe3e064b2c2d30f1e Mon Sep 17 00:00:00 2001 From: Jose Rodriguez Date: Sun, 6 Oct 2019 22:30:58 +0200 Subject: [PATCH 3/3] Fix crash when specifiying -M and -A at once Flags --asm and --mmap are incompatible. The compiler should exit gracefully. --- tests/functional/test_cmdline.txt | 15 +++++++++++++++ zxb.py | 9 +++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 tests/functional/test_cmdline.txt diff --git a/tests/functional/test_cmdline.txt b/tests/functional/test_cmdline.txt new file mode 100644 index 000000000..9d02d2f21 --- /dev/null +++ b/tests/functional/test_cmdline.txt @@ -0,0 +1,15 @@ +>>> from test_ import process_file +>>> import os +>>> os.environ['COLUMNS'] = '80' + +>>> process_file('arrbase1.bas', ['-q', '-S', '-O --asm', '-O --mmap arrbase1.map']) +usage: zxb [-h] [-d] [-O OPTIMIZE] [-o OUTPUT_FILE] [-T] [-t] [-B] [-a] [-A] + [-S ORG] [-e STDERR] [--array-base ARRAY_BASE] + [--string-base STRING_BASE] [-Z] [-H HEAP_SIZE] [--debug-memory] + [--debug-array] [--strict-bool] [--enable-break] [-E] [--explicit] + [-D DEFINES] [-M MEMORY_MAP] [-i] [-I INCLUDE_PATH] [--strict] + [--headerless] [--version] [--parse-only] + [--append-binary APPEND_BINARY] + [--append-headless-binary APPEND_HEADLESS_BINARY] + PROGRAM +zxb: error: Option --asm and --mmap cannot be used together diff --git a/zxb.py b/zxb.py index bf6e95276..13e14d78b 100755 --- a/zxb.py +++ b/zxb.py @@ -209,6 +209,10 @@ def main(args=None): parser.error('Option --append-binary needs either --tap or --tzx') return 5 + if options.asm and options.memory_map: + parser.error('Option --asm and --mmap cannot be used together') + return 6 + OPTIONS.use_loader.value = options.basic OPTIONS.autorun.value = options.autorun @@ -345,8 +349,9 @@ def main(args=None): return 5 # Error in assembly if OPTIONS.memory_map.value: - with open_file(OPTIONS.memory_map.value, 'wt', 'utf-8') as f: - f.write(asmparse.MEMORY.memory_map) + if asmparse.MEMORY is not None: + with open_file(OPTIONS.memory_map.value, 'wt', 'utf-8') as f: + f.write(asmparse.MEMORY.memory_map) return gl.has_errors # Exit success