# HG changeset patch # User Mike Miller # Date 1491157253 25200 # Node ID d18843ff4dfd0b400c1d19bf163a81a887113f08 # Parent d36f06f07082e6f086a6e8cfc888c419261d6fce Rewrite the test suite to run Octave-style built-in tests * Makefile.am (M_FILES): New declaration. (TST_FILES): New derived declaration. (%.cc-tst): New rule to generate test scripts from compiled sources. (check-local): Call __py_tests__.m script file to run test suite. (CLEANFILES): Include fntests.log and *-tst. * __py_tests__.m: New script file to run built-in tests. * .hgignore: Include fntests.log and *.cc-tst. diff -r d36f06f07082 -r d18843ff4dfd .hgignore --- a/.hgignore Sun Apr 02 10:06:42 2017 -0700 +++ b/.hgignore Sun Apr 02 11:20:53 2017 -0700 @@ -46,6 +46,9 @@ (^|/)PKG_(ADD|DEL) (^|/)octave-workspace +(^|/)fntests\.log$ +(^|/).*\.cc-tst$ + # e.g. doc/faq/OctaveFAQ.info # doc/interpreter/octave.info-4 ^doc/.*\.info(-\d)?$ diff -r d36f06f07082 -r d18843ff4dfd Makefile.am --- a/Makefile.am Sun Apr 02 10:06:42 2017 -0700 +++ b/Makefile.am Sun Apr 02 11:20:53 2017 -0700 @@ -39,6 +39,22 @@ INSTALL.md \ README.md +M_FILES = \ + @py/py.m \ + @py/subsref.m \ + @pyobject/cell.m \ + @pyobject/char.m \ + @pyobject/display.m \ + @pyobject/dummy.m \ + @pyobject/fieldnames.m \ + @pyobject/methods.m \ + @pyobject/pyobject.m \ + @pyobject/subsasgn.m \ + @pyobject/subsref.m \ + __py_tests__.m \ + pyargs.m \ + pyversion.m + OCT_FILES = \ __py_struct_from_dict__.oct \ pycall.oct \ @@ -63,6 +79,8 @@ test/exceptions.py \ test/test.py +TST_FILES = $(addsuffix -tst,$(OCT_SOURCE_FILES)) + EXTRA_DIST = $(DOC_FILES) $(OCT_SOURCE_FILES) $(PY_FILES) EXTRA_libdir = $(PYTAVE_MODULE_INSTALL_PATH) @@ -77,7 +95,7 @@ libpytave_la_CPPFLAGS = $(AM_CPPFLAGS) libpytave_la_SOURCES = $(COMMON_SOURCE_FILES) $(PYTAVE_HEADER_FILES) -CLEANFILES = *.oct PKG_ADD PKG_DEL +CLEANFILES = *.oct *-tst PKG_ADD PKG_DEL fntests.log SUFFIXES = .oct AM_V_MKOCTFILE = $(am__v_MKOCTFILE_$(V)) @@ -93,6 +111,13 @@ %.oct: %.cc libpytave.la $(PYTAVE_HEADER_FILES) $(AM_V_MKOCTFILE)$(OCT_LINK) $< $(OCT_LIBS) +%.cc-tst: %.cc + $(AM_V_GEN)rm -f $@-t $@ && \ + ( echo "## DO NOT EDIT! Generated automatically from $( $@-t && \ + mv $@-t $@ + PKG_ADD: $(OCT_SOURCE_FILES) $(AM_V_GEN)for f in $(OCT_SOURCE_FILES); do \ b=$${f%.cc}; \ @@ -127,6 +152,5 @@ @echo " PYTHONPATH=\"\$$(pwd)/.libs:\$$(pwd)/package\" python" @echo "" -check-local: - PYTHONPATH="$(abs_srcdir)/package:$$(pwd)/package:$$(pwd)/.libs" $(PYTHON) $(srcdir)/test/exceptions.py - PYTHONPATH="$(abs_srcdir)/package:$$(pwd)/package:$$(pwd)/.libs" $(PYTHON) $(srcdir)/test/test.py +check-local: $(M_FILES) $(TST_FILES) + octave-cli --path="$(abs_builddir)" --path="$(abs_srcdir)" __py_tests__.m $(M_FILES) $(TST_FILES) diff -r d36f06f07082 -r d18843ff4dfd __py_tests__.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/__py_tests__.m Sun Apr 02 11:20:53 2017 -0700 @@ -0,0 +1,164 @@ +## Copyright (C) 2017 Mike Miller +## Copyright (C) 2005-2017 David Bateman +## +## This file is part of Pytave. +## +## Pytave is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or +## (at your option) any later version. +## +## Pytave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Pytave; see the file COPYING. If not, see +## . + +## This is a script file, derived from Octave's __run_test_suite__.m +true; + +function retval = __run_py_tests__ (varargin) + + files_with_no_tests = {}; + files_with_tests = {}; + + pso = page_screen_output (); + + logfile = make_absolute_filename ("fntests.log"); + unwind_protect + page_screen_output (false); + try + fid = fopen (logfile, "wt"); + if (fid < 0) + error ("__run_test_suite__: could not open %s for writing", logfile); + endif + test ("", "explain", fid); + dp = dn = dxf = dsk = drtsk = 0; + puts ("\nIntegrated test scripts:\n\n"); + for i = 1:length (varargin) + f = varargin{i}; + if (has_tests (f)) + print_test_file_name (f); + [p, n, xf, sk, rtsk] = test (f, "quiet", fid); + print_pass_fail (p, n, xf, sk, rtsk); + dp += p; + dn += n; + dxf += xf; + dsk += sk; + drtsk += rtsk; + files_with_tests(end+1) = f; + else + ## To reduce the list length, only mark .cc files that contain + ## DEFUN definitions. + files_with_no_tests(end+1) = f; + endif + endfor + + puts ("\nSummary:\n\n"); + nfail = dn - dp - dxf; + printf (" PASS %6d\n", dp); + printf (" FAIL %6d\n", nfail); + if (dxf > 0) + printf (" XFAIL %6d\n", dxf); + endif + if (dsk > 0) + printf (" SKIPPED (feature) %6d\n", dsk); + endif + if (drtsk > 0) + printf (" SKIPPED (run-time condition) %6d\n", drtsk); + endif + puts ("\n"); + printf ("See the file %s for additional details.\n", logfile); + if (dxf > 0) + puts ("\n"); + puts ("Items listed as XFAIL above are known bugs.\n"); + puts ("Bug report numbers for them may be found in the log file:\n"); + puts (logfile); + puts ("\nPlease help improve Pytave by contributing fixes for them.\n"); + endif + if (dsk > 0 || drtsk > 0) + puts ("\n"); + puts ("Tests are most often skipped because the features they require\n"); + puts ("have been disabled. Features are most often disabled because\n"); + puts ("they require dependencies that were not present when Octave or\n"); + puts ("Pytave was built.\n"); + endif + + report_files_with_no_tests (files_with_tests, files_with_no_tests, ".m"); + + puts ("\nPlease help improve Pytave by contributing tests for these files\n"); + printf ("(see the list in the file %s).\n\n", logfile); + + fprintf (fid, "\nFiles with no tests:\n\n%s", + list_in_columns (files_with_no_tests, 80)); + fclose (fid); + catch + disp (lasterr ()); + end_try_catch + unwind_protect_cleanup + page_screen_output (pso); + end_unwind_protect + retval = (nfail != 0); +endfunction + +function print_test_file_name (nm) + filler = repmat (".", 1, 60-length (nm)); + printf (" %s %s", nm, filler); +endfunction + +function print_pass_fail (p, n, xf, sk, rtsk) + + if ((n + sk + rtsk) > 0) + printf (" PASS %4d/%-4d", p, n); + nfail = n - p - xf; + if (nfail > 0) + printf ("\n%71s %3d", "FAIL ", nfail); + endif + if (sk > 0) + printf ("\n%71s %3d", "(missing feature) SKIP ", sk); + endif + if (rtsk > 0) + printf ("\n%71s %3d", "(run-time condition) SKIP ", rtsk); + endif + if (xf > 0) + printf ("\n%71s %3d", "XFAIL", xf); + endif + endif + puts ("\n"); + +endfunction + +function retval = has_tests (f) + + fid = fopen (f); + if (fid < 0) + error ("__run_test_suite__: fopen failed: %s", f); + endif + + str = fread (fid, "*char")'; + fclose (fid); + retval = ! isempty (regexp (str, + '^%!(assert|error|fail|test|xtest|warning)', + 'lineanchors', 'once')); + +endfunction + +function n = num_elts_matching_pattern (lst, pat) + n = sum (! cellfun ("isempty", regexp (lst, pat, 'once'))); +endfunction + +function report_files_with_no_tests (with, without, typ) + pat = ['\' typ "$"]; + n_with = num_elts_matching_pattern (with, pat); + n_without = num_elts_matching_pattern (without, pat); + n_tot = n_with + n_without; + printf ("\n%d (of %d) %s files have no tests.\n", n_without, n_tot, typ); +endfunction + +exit (__run_py_tests__ (argv (){:})); + +## Mark this file as fully tested. +%!assert (1)