changeset 24185:068556c5167e

Add BIST test for clear() function (bug #35881). * test/bug-35881/bug-35881.tst: New tests for clear() function which verify that current function is unaffected. * test/bug-35881/bug35881.m: New test code. * test/bug-35881/module.mk: Add test files to build system. * __run_test_suite__.m: Replace global variables with function variables. Use nested functions to access parent's copy of function variable. Modify function to accept two additional inputs: topsrcdir and topbuilddir. * test/fntests.m: Call __run_test_suite__ with topsrcdir and topbuilddir inputs. * test/module.mk: Add bug-35881 files to build system.
author Rik <rik@octave.org>
date Sun, 29 Oct 2017 17:33:41 -0700
parents 7dd3ab97ccd5
children 422814bf8b41
files scripts/testfun/__run_test_suite__.m test/bug-35881/bug-35881.tst test/bug-35881/bug35881.m test/bug-35881/module.mk test/fntests.m test/module.mk
diffstat 6 files changed, 214 insertions(+), 123 deletions(-) [+]
line wrap: on
line diff
--- a/scripts/testfun/__run_test_suite__.m	Sat Oct 28 18:24:14 2017 -0700
+++ b/scripts/testfun/__run_test_suite__.m	Sun Oct 29 17:33:41 2017 -0700
@@ -21,7 +21,7 @@
 ## Undocumented internal function.
 ## @end deftypefn
 
-function [pass, fail, xfail, xbug, skip, rtskip, regress] = __run_test_suite__ (fcndirs, fixedtestdirs)
+function [pass, fail, xfail, xbug, skip, rtskip, regress] = __run_test_suite__ (fcndirs, fixedtestdirs, topsrcdir = [], topbuilddir = [])
 
   testsdir = __octave_config_info__ ("octtestsdir");
   libinterptestdir = fullfile (testsdir, "libinterp");
@@ -32,14 +32,17 @@
     fcndirs = { liboctavetestdir, libinterptestdir, fcnfiledir };
     fixedtestdirs = { fixedtestdir };
   endif
-  global files_with_no_tests;
-  global files_with_tests;
   files_with_no_tests = {};
   files_with_tests = {};
   ## FIXME: These names don't really make sense if we are running
   ##        tests for an installed copy of Octave.
-  global topsrcdir = fcnfiledir;
-  global topbuilddir = testsdir;
+  if (isempty (topsrcdir))
+    topsrcdir = fcnfiledir;
+  endif
+  if (isempty (topbuilddir))
+    topbuilddir = testsdir;
+  endif
+
   pso = page_screen_output ();
   orig_wstate = warning ();
   logfile = make_absolute_filename ("fntests.log");
@@ -145,6 +148,113 @@
     regress = drgrs;
   endif
 
+
+  function [dp, dn, dxf, dxb, dsk, drtsk, drgrs] = run_test_dir (fid, d)
+
+    lst = dir (d);
+    dp = dn = dxf = dxb = dsk = drtsk = drgrs = 0;
+    for i = 1:length (lst)
+      nm = lst(i).name;
+      if (lst(i).isdir
+          && nm(1) != "." && ! strcmp (nm, "private") && nm(1) != "@")
+        [p, n, xf, xb, sk, rtsk, rgrs] = run_test_dir (fid, [d, filesep, nm]);
+        dp += p;
+        dn += n;
+        dxf += xf;
+        dxb += xb;
+        dsk += sk;
+        drtsk += rtsk;
+        drgrs += rgrs;
+      endif
+    endfor
+
+    saved_dir = pwd ();
+    unwind_protect
+      cd (d);
+      for i = 1:length (lst)
+        nm = lst(i).name;
+        if (length (nm) > 4 && strcmpi (nm((end-3):end), ".tst"))
+          p = n = xf = xb = sk = rtsk = 0;
+          ffnm = fullfile (d, nm);
+          if (has_tests (ffnm))
+            print_test_file_name (nm);
+            [p, n, xf, xb, sk, rtsk, rgrs] = test (nm, "quiet", fid);
+            print_pass_fail (p, n, xf, xb, sk, rtsk, rgrs);
+            files_with_tests(end+1) = ffnm;
+          else
+            files_with_no_tests(end+1) = ffnm;
+          endif
+          dp += p;
+          dn += n;
+          dxf += xf;
+          dxb += xb;
+          dsk += sk;
+          drtsk += rtsk;
+          drgrs += rgrs;
+        endif
+      endfor
+    unwind_protect_cleanup
+      cd (saved_dir);
+    end_unwind_protect
+
+  endfunction
+
+  function [dp, dn, dxf, dxb, dsk, drtsk, drgrs] = run_test_script (fid, d)
+
+    lst = dir (d);
+    dp = dn = dxf = dxb = dsk = drtsk = drgrs = 0;
+    for i = 1:length (lst)
+      nm = lst(i).name;
+      if (lst(i).isdir && nm(1) != ".")
+        [p, n, xf, xb, sk, rtsk, rgrs] = run_test_script (fid, [d, filesep, nm]);
+        dp += p;
+        dn += n;
+        dxf += xf;
+        dxb += xb;
+        dsk += sk;
+        drtsk += rtsk;
+        drgrs += rgrs;
+      endif
+    endfor
+
+    for i = 1:length (lst)
+      nm = lst(i).name;
+      ## Ignore hidden files
+      if (nm(1) == '.')
+        continue
+      endif
+      f = fullfile (d, nm);
+      if ((length (nm) > 2 && strcmpi (nm((end-1):end), ".m"))
+          || (length (nm) > 4
+              && (   strcmpi (nm((end-3):end), "-tst")
+                  || strcmpi (nm((end-3):end), ".tst"))))
+        p = n = xf = xb = 0;
+        ## Only run if contains %!test, %!assert, %!error, %!fail, or %!warning
+        if (has_tests (f))
+          tmp = strrep (f, [topsrcdir, filesep], "");
+          tmp = strrep (tmp, [topbuilddir, filesep], "");
+          print_test_file_name (tmp);
+          [p, n, xf, xb, sk, rtsk, rgrs] = test (f, "quiet", fid);
+          print_pass_fail (p, n, xf, xb, sk, rtsk, rgrs);
+          dp += p;
+          dn += n;
+          dxf += xf;
+          dxb += xb;
+          dsk += sk;
+          drtsk += rtsk;
+          drgrs += rgrs;
+          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
+      endif
+    endfor
+    ##  printf("%s%s -> passes %d of %d tests\n", ident, d, dp, dn);
+
+  endfunction
+
 endfunction
 
 function print_test_file_name (nm)
@@ -215,118 +325,6 @@
 
 endfunction
 
-function [dp, dn, dxf, dxb, dsk, drtsk, drgrs] = run_test_dir (fid, d)
-  global files_with_tests;
-  global files_with_no_tests;
-
-  lst = dir (d);
-  dp = dn = dxf = dxb = dsk = drtsk = drgrs = 0;
-  for i = 1:length (lst)
-    nm = lst(i).name;
-    if (lst(i).isdir
-        && nm(1) != "." && ! strcmp (nm, "private") && nm(1) != "@")
-      [p, n, xf, xb, sk, rtsk, rgrs] = run_test_dir (fid, [d, filesep, nm]);
-      dp += p;
-      dn += n;
-      dxf += xf;
-      dxb += xb;
-      dsk += sk;
-      drtsk += rtsk;
-      drgrs += rgrs;
-    endif
-  endfor
-
-  saved_dir = pwd ();
-  unwind_protect
-    cd (d);
-    for i = 1:length (lst)
-      nm = lst(i).name;
-      if (length (nm) > 4 && strcmpi (nm((end-3):end), ".tst"))
-        p = n = xf = xb = sk = rtsk = 0;
-        ffnm = fullfile (d, nm);
-        if (has_tests (ffnm))
-          print_test_file_name (nm);
-          [p, n, xf, xb, sk, rtsk, rgrs] = test (nm, "quiet", fid);
-          print_pass_fail (p, n, xf, xb, sk, rtsk, rgrs);
-          files_with_tests(end+1) = ffnm;
-        else
-          files_with_no_tests(end+1) = ffnm;
-        endif
-        dp += p;
-        dn += n;
-        dxf += xf;
-        dxb += xb;
-        dsk += sk;
-        drtsk += rtsk;
-        drgrs += rgrs;
-      endif
-    endfor
-  unwind_protect_cleanup
-    cd (saved_dir);
-  end_unwind_protect
-
-endfunction
-
-function [dp, dn, dxf, dxb, dsk, drtsk, drgrs] = run_test_script (fid, d)
-  global files_with_tests;
-  global files_with_no_tests;
-  global topsrcdir;
-  global topbuilddir;
-
-  lst = dir (d);
-  dp = dn = dxf = dxb = dsk = drtsk = drgrs = 0;
-  for i = 1:length (lst)
-    nm = lst(i).name;
-    if (lst(i).isdir && nm(1) != ".")
-      [p, n, xf, xb, sk, rtsk, rgrs] = run_test_script (fid, [d, filesep, nm]);
-      dp += p;
-      dn += n;
-      dxf += xf;
-      dxb += xb;
-      dsk += sk;
-      drtsk += rtsk;
-      drgrs += rgrs;
-    endif
-  endfor
-
-  for i = 1:length (lst)
-    nm = lst(i).name;
-    ## Ignore hidden files
-    if (nm(1) == '.')
-      continue
-    endif
-    f = fullfile (d, nm);
-    if ((length (nm) > 2 && strcmpi (nm((end-1):end), ".m"))
-        || (length (nm) > 4
-            && (   strcmpi (nm((end-3):end), "-tst")
-                || strcmpi (nm((end-3):end), ".tst"))))
-      p = n = xf = xb = 0;
-      ## Only run if it contains %!test, %!assert, %!error, %!fail, or %!warning
-      if (has_tests (f))
-        tmp = strrep (f, [topsrcdir, filesep], "");
-        tmp = strrep (tmp, [topbuilddir, filesep], "");
-        print_test_file_name (tmp);
-        [p, n, xf, xb, sk, rtsk, rgrs] = test (f, "quiet", fid);
-        print_pass_fail (p, n, xf, xb, sk, rtsk, rgrs);
-        dp += p;
-        dn += n;
-        dxf += xf;
-        dxb += xb;
-        dsk += sk;
-        drtsk += rtsk;
-        drgrs += rgrs;
-        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
-    endif
-  endfor
-  ##  printf("%s%s -> passes %d of %d tests\n", ident, d, dp, dn);
-
-endfunction
-
 function n = num_elts_matching_pattern (lst, pat)
   n = sum (! cellfun ("isempty", regexp (lst, pat, 'once')));
 endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug-35881/bug-35881.tst	Sun Oct 29 17:33:41 2017 -0700
@@ -0,0 +1,32 @@
+## Copyright (C) 2017 Rik Wehbring
+##
+## This file is part of Octave.
+##
+## Octave 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.
+##
+## Octave 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 Octave; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+%!test
+%! global _tstvar_;  # Final test does "clear all" which removes this var.
+%!
+%! _tstvar_ = struct ("init1",-1, "a1",-1, "init2",-1, "a2",-1);
+%! bug35881 (0); 
+%! assert (_tstvar_, struct ("init1",true, "a1",1, "init2",false, "a2",1));
+%! clear -f bug35881
+%!
+%! _tstvar_ = struct ("init1",-1, "a1",-1, "init2",-1, "a2",-1);
+%! bug35881 (1); 
+%! assert (_tstvar_, struct ("init1",true, "a1",1, "init2",false, "a2",1));
+%!
+%! _tstvar_ = struct ("init1",-1, "a1",-1, "init2",-1, "a2",-1);
+%! fail ("bug35881 (2)", "'a' undefined near line");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug-35881/bug35881.m	Sun Oct 29 17:33:41 2017 -0700
@@ -0,0 +1,60 @@
+function bug35881 (flag = 0)
+  persistent a;
+  global _tstvar_;
+
+  if (isempty (a))
+    a = 1;
+  endif
+
+  _tstvar_.init1 = subf ();
+  _tstvar_.a1 = a;
+  ##ML:fprintf ('a=%d\n', a);
+
+  switch (flag)
+    case 0
+      clear subf;
+    case 1
+      clear functions;
+    case 2
+      clear all;
+  endswitch
+
+  _tstvar_.init2 = subf ();
+  _tstvar_.a2 = a;
+  ##ML:fprintf ('a=%d\n', a);
+  ##ML:fprintf ('------\n\n');
+endfunction
+
+function retval = subf ()
+  persistent x;
+
+  retval = false;
+  ##ML:fprintf ('subf: ');
+  if (isempty (x))
+    x = 1;
+    retval = true;
+    ##ML:fprintf ('INIT, ');
+  endif
+
+endfunction
+
+## Expected results from Matlab 2016A
+## Uncomment "##ML:"
+#{
+>> clear all;  bug35881 (0)
+subf: INIT, a=1
+subf: a=1
+------
+
+>> clear all;  bug35881 (1)
+subf: INIT, a=1
+subf: a=1
+------
+
+>> clear all;  bug35881 (2)
+subf: INIT, a=1
+subf: Reference to a cleared variable a.
+Error in test_clear_inside_function (line 13)
+subf ();  fprintf ('a=%d\n', a); 
+#}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug-35881/module.mk	Sun Oct 29 17:33:41 2017 -0700
@@ -0,0 +1,5 @@
+bug_35881_TEST_FILES = \
+  %reldir%/bug-35881.tst \
+  %reldir%/bug35881.m
+
+TEST_FILES += $(bug_35881_TEST_FILES)
--- a/test/fntests.m	Sat Oct 28 18:24:14 2017 -0700
+++ b/test/fntests.m	Sun Oct 29 17:33:41 2017 -0700
@@ -18,11 +18,6 @@
 
 clear all;
 
-global files_with_no_tests = {};
-global files_with_tests = {};
-global topsrcdir;
-global topbuilddir;
-
 currdir = canonicalize_file_name (".");
 
 debug_on_error (true);
@@ -54,4 +49,4 @@
   fundirs{end+1} = local_script_tree;
 endif
 
-__run_test_suite__ (fundirs, testdirs);
+__run_test_suite__ (fundirs, testdirs, topsrcdir, topbuilddir);
--- a/test/module.mk	Sat Oct 28 18:24:14 2017 -0700
+++ b/test/module.mk	Sun Oct 29 17:33:41 2017 -0700
@@ -47,6 +47,7 @@
 DIRSTAMP_FILES += %reldir%/$(octave_dirstamp)
 
 include %reldir%/bug-35448/module.mk
+include %reldir%/bug-35881/module.mk
 include %reldir%/bug-36025/module.mk
 include %reldir%/bug-38236/module.mk
 include %reldir%/bug-38691/module.mk