Mercurial > octave-nkf
view scripts/testfun/test.m @ 14237:11949c9795a0
Revamp %!demos in m-files to use Octave coding conventions on spacing, etc.
Add clf() to all demos using plot features to get reproducibility.
Use 64 as input to all colormaps (jet (64)) to get reproducibility.
* bicubic.m, cell2mat.m, celldisp.m, cplxpair.m, interp1.m, interp2.m,
interpft.m, interpn.m, profile.m, profshow.m, convhull.m, delaunay.m,
griddata.m, inpolygon.m, voronoi.m, autumn.m, bone.m, contrast.m, cool.m,
copper.m, flag.m, gmap40.m, gray.m, hot.m, hsv.m, image.m, imshow.m, jet.m,
ocean.m, pink.m, prism.m, rainbow.m, spring.m, summer.m, white.m, winter.m,
condest.m, onenormest.m, axis.m, clabel.m, colorbar.m, comet.m, comet3.m,
compass.m, contour.m, contour3.m, contourf.m, cylinder.m, daspect.m,
ellipsoid.m, errorbar.m, ezcontour.m, ezcontourf.m, ezmesh.m, ezmeshc.m,
ezplot.m, ezplot3.m, ezpolar.m, ezsurf.m, ezsurfc.m, feather.m, fill.m,
fplot.m, grid.m, hold.m, isosurface.m, legend.m, loglog.m, loglogerr.m,
pareto.m, patch.m, pbaspect.m, pcolor.m, pie.m, pie3.m, plot3.m, plotmatrix.m,
plotyy.m, polar.m, quiver.m, quiver3.m, rectangle.m, refreshdata.m, ribbon.m,
rose.m, scatter.m, scatter3.m, semilogx.m, semilogxerr.m, semilogy.m,
semilogyerr.m, shading.m, slice.m, sombrero.m, stairs.m, stem.m, stem3.m,
subplot.m, surf.m, surfc.m, surfl.m, surfnorm.m, text.m, title.m, trimesh.m,
triplot.m, trisurf.m, uigetdir.m, uigetfile.m, uimenu.m, uiputfile.m,
waitbar.m, xlim.m, ylim.m, zlim.m, mkpp.m, pchip.m, polyaffine.m, spline.m,
bicgstab.m, cgs.m, gplot.m, pcg.m, pcr.m, treeplot.m, strtok.m, demo.m,
example.m, rundemos.m, speed.m, test.m, calendar.m, datestr.m, datetick.m,
weekday.m: Revamp %!demos to use Octave coding conventions on spacing, etc.
author | Rik <octave@nomad.inbox5.com> |
---|---|
date | Fri, 20 Jan 2012 12:59:53 -0800 |
parents | 68fd9f95e1f9 |
children | 7277fe922e99 |
line wrap: on
line source
## Copyright (C) 2005-2012 Paul Kienzle ## ## 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/>. ## -*- texinfo -*- ## @deftypefn {Command} {} test @var{name} ## @deftypefnx {Command} {} test @var{name} quiet|normal|verbose ## @deftypefnx {Function File} {} test ('@var{name}', 'quiet|normal|verbose', @var{fid}) ## @deftypefnx {Function File} {} test ([], 'explain', @var{fid}) ## @deftypefnx {Function File} {@var{success} =} test (@dots{}) ## @deftypefnx {Function File} {[@var{n}, @var{max}] =} test (@dots{}) ## @deftypefnx {Function File} {[@var{code}, @var{idx}] =} test ('@var{name}', 'grabdemo') ## ## Perform tests from the first file in the loadpath matching @var{name}. ## @code{test} can be called as a command or as a function. Called with ## a single argument @var{name}, the tests are run interactively and stop ## after the first error is encountered. ## ## With a second argument the tests which are performed and the amount of ## output is selected. ## ## @table @asis ## @item 'quiet' ## Don't report all the tests as they happen, just the errors. ## ## @item 'normal' ## Report all tests as they happen, but don't do tests which require ## user interaction. ## ## @item 'verbose' ## Do tests which require user interaction. ## @end table ## ## The argument @var{fid} can be used to allow batch processing. Errors ## can be written to the already open file defined by @var{fid}, and ## hopefully when Octave crashes this file will tell you what was happening ## when it did. You can use @code{stdout} if you want to see the results as ## they happen. You can also give a file name rather than an @var{fid}, in ## which case the contents of the file will be replaced with the log from ## the current test. ## ## Called with a single output argument @var{success}, @code{test} returns ## true if all of the tests were successful. Called with two output arguments ## @var{n} and @var{max}, the number of successful tests and the total number ## of tests in the file @var{name} are returned. ## ## If the second argument is the string 'grabdemo', the contents of the demo ## blocks are extracted but not executed. Code for all code blocks is ## concatenated and returned as @var{code} with @var{idx} being a vector of ## positions of the ends of the demo blocks. ## ## If the second argument is 'explain', then @var{name} is ignored and an ## explanation of the line markers used is written to the file @var{fid}. ## @seealso{assert, fail, error, demo, example} ## @end deftypefn ## FIXME: * Consider using keyword fail rather then error? This allows us ## to make a functional form of error blocks, which means we ## can include them in test sections which means that we can use ## octave flow control for both kinds of tests. function [__ret1, __ret2, __ret3, __ret4] = test (__name, __flag, __fid) ## Information from test will be introduced by "key". persistent __signal_fail = "!!!!! "; persistent __signal_empty = "????? "; persistent __signal_block = " ***** "; persistent __signal_file = ">>>>> "; persistent __signal_skip = "----- "; __xfail = 0; __xskip = 0; if (nargin < 2 || isempty (__flag)) __flag = "quiet"; endif if (nargin < 3) __fid = []; endif if (nargin < 1 || nargin > 3 || (! ischar (__name) && ! isempty (__name)) || ! ischar (__flag)) print_usage (); endif if (isempty (__name) && (nargin != 3 || ! strcmp (__flag, "explain"))) print_usage (); endif __batch = (! isempty (__fid)); ## Decide if error messages should be collected. __close_fid = 0; if (__batch) if (ischar (__fid)) __fid = fopen (__fid, "wt"); if (__fid < 0) error ("test: could not open log file"); endif __close_fid = 1; endif fprintf (__fid, "%sprocessing %s\n", __signal_file, __name); fflush (__fid); else __fid = stdout; endif if (strcmp (__flag, "normal")) __grabdemo = 0; __rundemo = 0; __verbose = __batch; elseif (strcmp (__flag, "quiet")) __grabdemo = 0; __rundemo = 0; __verbose = 0; elseif (strcmp (__flag, "verbose")) __grabdemo = 0; __rundemo = 1; __verbose = 1; elseif (strcmp (__flag, "grabdemo")) __grabdemo = 1; __rundemo = 0; __verbose = 0; __demo_code = ""; __demo_idx = []; elseif (strcmp (__flag, "explain")) fprintf (__fid, "# %s new test file\n", __signal_file); fprintf (__fid, "# %s no tests in file\n", __signal_empty); fprintf (__fid, "# %s test had an unexpected result\n", __signal_fail); fprintf (__fid, "# %s code for the test\n", __signal_block); fprintf (__fid, "# Search for the unexpected results in the file\n"); fprintf (__fid, "# then page back to find the file name which caused it.\n"); fprintf (__fid, "# The result may be an unexpected failure (in which\n"); fprintf (__fid, "# case an error will be reported) or an unexpected\n"); fprintf (__fid, "# success (in which case no error will be reported).\n"); fflush (__fid); if (__close_fid) fclose(__fid); endif return; else error ("test: unknown flag '%s'", __flag); endif ## Locate the file to test. __file = file_in_loadpath (__name, "all"); if (isempty (__file)) __file = file_in_loadpath (cstrcat (__name, ".m"), "all"); endif if (isempty (__file)) __file = file_in_loadpath (cstrcat (__name, ".cc"), "all"); endif if (iscell (__file)) ## If repeats, return first in path. if (isempty (__file)) __file = ""; else __file = __file{1}; endif endif if (isempty (__file)) if (__grabdemo) __ret1 = ""; __ret2 = []; else if (exist (__name) == 3) fprintf (__fid, "%s%s source code with tests for dynamically linked function not found\n", __signal_empty, __name); else fprintf (__fid, "%s%s does not exist in path\n", __signal_empty, __name); endif fflush (__fid); if (nargout > 0) __ret1 = __ret2 = 0; endif endif if (__close_fid) fclose(__fid); endif return; endif ## Grab the test code from the file. __body = __extract_test_code (__file); if (isempty (__body)) if (__grabdemo) __ret1 = ""; __ret2 = []; else fprintf (__fid, "%s%s has no tests available\n", __signal_empty, __file); fflush (__fid); if (nargout > 0) __ret1 = __ret2 = 0; endif endif if (__close_fid) fclose(__fid); endif return; else ## Add a dummy comment block to the end for ease of indexing. if (__body (length(__body)) == "\n") __body = sprintf ("\n%s#", __body); else __body = sprintf ("\n%s\n#", __body); endif endif ## Chop it up into blocks for evaluation. __lineidx = find (__body == "\n"); __blockidx = __lineidx(find (! isspace (__body(__lineidx+1))))+1; ## Ready to start tests ... if in batch mode, tell us what is happening. if (__verbose) disp (cstrcat (__signal_file, __file)); endif ## Assume all tests will pass. __all_success = 1; ## Process each block separately, initially with no shared variables. __tests = __successes = 0; __shared = " "; __shared_r = " "; __clear = ""; for __i = 1:length(__blockidx)-1 ## Extract the block. __block = __body(__blockidx(__i):__blockidx(__i+1)-2); ## Let the user/logfile know what is happening. if (__verbose) fprintf (__fid, "%s%s\n", __signal_block, __block); fflush (__fid); endif ## Split __block into __type and __code. __idx = find (! isletter (__block)); if (isempty (__idx)) __type = __block; __code = ""; else __type = __block(1:__idx(1)-1); __code = __block(__idx(1):length(__block)); endif ## Assume the block will succeed. __success = 1; __msg = []; ### DEMO ## If in __grabdemo mode, then don't process any other block type. ## So that the other block types don't have to worry about ## this __grabdemo mode, the demo block processor grabs all block ## types and skips those which aren't demo blocks. __isdemo = strcmp (__type, "demo"); if (__grabdemo || __isdemo) __istest = 0; if (__grabdemo && __isdemo) if (isempty(__demo_code)) __demo_code = __code; __demo_idx = [1, length(__demo_code)+1]; else __demo_code = cstrcat(__demo_code, __code); __demo_idx = [__demo_idx, length(__demo_code)+1]; endif elseif (__rundemo && __isdemo) try ## process the code in an environment without variables eval (sprintf ("function __test__()\n%s\nendfunction", __code)); __test__; input ("Press <enter> to continue: ", "s"); catch __success = 0; __msg = sprintf ("%sdemo failed\n%s", __signal_fail, lasterr ()); end_try_catch clear __test__; endif ## Code already processed. __code = ""; ### SHARED elseif (strcmp (__type, "shared")) __istest = 0; ## Separate initialization code from variables. __idx = find (__code == "\n"); if (isempty (__idx)) __vars = __code; __code = ""; else __vars = __code (1:__idx(1)-1); __code = __code (__idx(1):length(__code)); endif ## Strip comments off the variables. __idx = find (__vars == "%" | __vars == "#"); if (! isempty (__idx)) __vars = __vars(1:__idx(1)-1); endif ## Assign default values to variables. try __vars = deblank (__vars); if (! isempty (__vars)) eval (cstrcat (strrep (__vars, ",", "=[];"), "=[];")); __shared = __vars; __shared_r = cstrcat ("[ ", __vars, "] = "); else __shared = " "; __shared_r = " "; endif catch ## Couldn't declare, so don't initialize. __code = ""; __success = 0; __msg = sprintf ("%sshared variable initialization failed\n", __signal_fail); end_try_catch ## Clear shared function definitions. eval (__clear, ""); __clear = ""; ## Initialization code will be evaluated below. ### FUNCTION elseif (strcmp (__type, "function")) __istest = 0; persistent __fn = 0; __name_position = function_name (__block); if (isempty (__name_position)) __success = 0; __msg = sprintf ("%stest failed: missing function name\n", __signal_fail); else __name = __block(__name_position(1):__name_position(2)); __code = __block; try eval(__code); ## Define the function __clear = sprintf ("%sclear %s;\n", __clear, __name); catch __success = 0; __msg = sprintf ("%stest failed: syntax error\n%s", __signal_fail, lasterr ()); end_try_catch endif __code = ""; ### ENDFUNCTION elseif (strcmp (__type, "endfunction")) ## endfunction simply declares the end of a previous function block. ## There is no processing to be done here, just skip to next block. __istest = 0; __code = ""; ### ASSERT/FAIL elseif (strcmp (__type, "assert") || strcmp (__type, "fail")) __istest = 1; ## Put the keyword back on the code. __code = __block; ## The code will be evaluated below as a test block. ### ERROR/WARNING elseif (strcmp (__type, "error") || strcmp(__type, "warning")) __istest = 1; __warning = strcmp (__type, "warning"); [__pattern, __id, __code] = getpattern (__code); if (__id) __patstr = ["id=",__id]; else __patstr = ["<",__pattern,">"]; endif try eval (sprintf ("function __test__(%s)\n%s\nendfunction", __shared, __code)); catch __success = 0; __msg = sprintf ("%stest failed: syntax error\n%s", __signal_fail, lasterr ()); end_try_catch if (__success) __success = 0; __warnstate = warning ("query", "quiet"); warning ("on", "quiet"); try eval (sprintf ("__test__(%s);", __shared)); if (! __warning) __msg = sprintf ("%sexpected %s but got no error\n", __signal_fail, __patstr); else if (! isempty (__id)) [~, __err] = lastwarn; __mismatch = ! strcmp (__err, __id); else __err = trimerr (lastwarn, "warning"); __mismatch = isempty (regexp (__err, __pattern, "once")); endif warning (__warnstate.state, "quiet"); if (isempty (__err)) __msg = sprintf ("%sexpected %s but got no warning\n", __signal_fail, __patstr); elseif (__mismatch) __msg = sprintf ("%sexpected %s but got %s\n", __signal_fail, __patstr, __err); else __success = 1; endif endif catch if (! isempty (__id)) [~, __err] = lasterr; __mismatch = ! strcmp (__err, __id); else __err = trimerr (lasterr, "error"); __mismatch = isempty (regexp (__err, __pattern, "once")); endif warning (__warnstate.state, "quiet"); if (__warning) __msg = sprintf ("%sexpected warning %s but got error %s\n", __signal_fail, __patstr, __err); elseif (__mismatch) __msg = sprintf ("%sexpected %s but got %s\n", __signal_fail, __patstr, __err); else __success = 1; endif end_try_catch clear __test__; endif ## Code already processed. __code = ""; ### TESTIF elseif (strcmp (__type, "testif")) __e = regexp (__code, '.$', 'lineanchors', 'once'); ## Strip comment any comment from testif line before looking for features __feat_line = strtok (__code(1:__e), '#%'); __feat = regexp (__feat_line, '\w+', 'match'); __have_feat = strfind (octave_config_info ("DEFS"), __feat); if (any (cellfun ("isempty", __have_feat))) __xskip++; __istest = 0; __code = ""; # Skip the code. __msg = sprintf ("%sskipped test\n", __signal_skip); else __istest = 1; __code = __code(__e + 1 : end); endif ### TEST elseif (strcmp (__type, "test") || strcmp (__type, "xtest")) __istest = 1; ## Code will be evaluated below. ### Comment block. elseif (strcmp (__block(1:1), "#")) __istest = 0; __code = ""; # skip the code ### Unknown block. else __istest = 1; __success = 0; __msg = sprintf ("%sunknown test type!\n", __signal_fail); __code = ""; # skip the code endif ## evaluate code for test, shared, and assert. if (! isempty(__code)) try ## FIXME: need to check for embedded test functions, which cause ## segfaults, until issues with subfunctions in functions are resolved. embed_func = regexp (__code, '^\s*function ', 'once', 'lineanchors'); if (isempty (embed_func)) eval (sprintf ("function %s__test__(%s)\n%s\nendfunction", __shared_r,__shared, __code)); eval (sprintf ("%s__test__(%s);", __shared_r, __shared)); else error (["Functions embedded in %!test blocks are not allowed.\n", ... "Use the %!function/%!endfunction syntax instead to define shared functions for testing.\n"]); endif catch if (strcmp (__type, "xtest")) __msg = sprintf ("%sknown failure\n%s", __signal_fail, lasterr ()); __xfail++; else __msg = sprintf ("%stest failed\n%s", __signal_fail, lasterr ()); __success = 0; endif if (isempty (lasterr ())) error ("empty error text, probably Ctrl-C --- aborting"); endif end_try_catch clear __test__; endif ## All done. Remember if we were successful and print any messages. if (! isempty (__msg)) ## Make sure the user knows what caused the error. if (! __verbose) fprintf (__fid, "%s%s\n", __signal_block, __block); fflush (__fid); endif fputs (__fid, __msg); fputs (__fid, "\n"); fflush (__fid); ## Show the variable context. if (! strcmp (__type, "error") && ! strcmp (__type, "testif") && ! all (__shared == " ")) fputs (__fid, "shared variables "); eval (sprintf ("fdisp(__fid,bundle(%s));", __shared)); fflush (__fid); endif endif if (__success == 0) __all_success = 0; ## Stop after one error if not in batch mode. if (! __batch) if (nargout > 0) __ret1 = __ret2 = 0; endif if (__close_fid) fclose(__fid); endif return; endif endif __tests += __istest; __successes += __success * __istest; endfor eval (__clear, ""); if (nargout == 0) if (__tests || __xfail || __xskip) if (__xfail) printf ("PASSES %d out of %d tests (%d expected failures)\n", __successes, __tests, __xfail); else printf ("PASSES %d out of %d tests\n", __successes, __tests); endif if (__xskip) printf ("Skipped %d tests due to missing features\n", __xskip); endif else printf ("%s%s has no tests available\n", __signal_empty, __file); endif elseif (__grabdemo) __ret1 = __demo_code; __ret2 = __demo_idx; elseif (nargout == 1) __ret1 = __all_success; else __ret1 = __successes; __ret2 = __tests; __ret3 = __xfail; __ret4 = __xskip; endif endfunction ## Create structure with fieldnames the name of the input variables. function s = varstruct (varargin) for i = 1:nargin s.(deblank (argn(i,:))) = varargin{i}; endfor endfunction ## Find [start,end] of fn in 'function [a,b] = fn'. function pos = function_name (def) pos = []; ## Find the end of the name. right = find (def == "(", 1); if (isempty (right)) return; endif right = find (def(1:right-1) != " ", 1, "last"); ## Find the beginning of the name. left = max ([find(def(1:right)==" ", 1, "last"), ... find(def(1:right)=="=", 1, "last")]); if (isempty (left)) return; endif left++; ## Return the end points of the name. pos = [left, right]; endfunction ## Strip <pattern> from '<pattern> code'. ## Also handles 'id=ID code' function [pattern, id, rest] = getpattern (str) pattern = "."; id = []; rest = str; str = trimleft (str); if (! isempty (str) && str(1) == "<") close = index (str, ">"); if (close) pattern = str(2:close-1); rest = str(close+1:end); endif elseif (strncmp (str, "id=", 3)) [id, rest] = strtok (str(4:end)); endif endfunction ## Strip '.*prefix:' from '.*prefix: msg\n' and strip trailing blanks. function msg = trimerr (msg, prefix) idx = index (msg, cstrcat (prefix, ":")); if (idx > 0) msg(1:idx+length(prefix)) = []; endif msg = trimleft (deblank (msg)); endfunction ## Strip leading blanks from string. function str = trimleft (str) idx = find (isspace (str)); leading = find (idx == 1:length(idx)); if (! isempty (leading)) str = str(leading(end)+1:end); endif endfunction ## Make a structure out of the named variables ## (based on Etienne Grossmann's tar function). function s = bundle (varargin) for i = 1:nargin s.(deblank (argn(i,:))) = varargin{i}; endfor endfunction function body = __extract_test_code (nm) fid = fopen (nm, "rt"); body = []; if (fid >= 0) while (! feof (fid)) ln = fgetl (fid); if (length (ln) >= 2 && strcmp (ln(1:2), "%!")) body = [body, "\n"]; if (length(ln) > 2) body = cstrcat (body, ln(3:end)); endif endif endwhile fclose (fid); endif endfunction ### Test for test for missing features %!testif OCTAVE_SOURCE %! ## This test should be run %! assert (true); ### Disable this test to avoid spurious skipped test for "make check" % !testif HAVE_FOOBAR % ! ## missing feature. Fail if this test is run % ! error("Failed missing feature test"); ### Test for a known failure %!xtest error("This test is known to fail") ### example from toeplitz %!shared msg1,msg2 %! msg1="C must be a vector"; %! msg2="C and R must be vectors"; %!fail ('toeplitz([])', msg1); %!fail ('toeplitz([1,2;3,4])', msg1); %!fail ('toeplitz([1,2],[])', msg2); %!fail ('toeplitz([1,2],[1,2;3,4])', msg2); %!fail ('toeplitz ([1,2;3,4],[1,2])', msg2); % !fail ('toeplitz','usage: toeplitz'); # usage doesn't generate an error % !fail ('toeplitz(1, 2, 3)', 'usage: toeplitz'); %!test assert (toeplitz ([1,2,3], [1,4]), [1,4; 2,1; 3,2]); %!demo toeplitz ([1,2,3,4],[1,5,6]) ### example from kron %!#error kron # FIXME suppress these until we can handle output %!#error kron(1,2,3) %!test assert (isempty (kron ([], rand(3, 4)))) %!test assert (isempty (kron (rand (3, 4), []))) %!test assert (isempty (kron ([], []))) %!shared A, B %!test %! A = [1, 2, 3; 4, 5, 6]; %! B = [1, -1; 2, -2]; %!assert (size (kron (zeros (3, 0), A)), [ 3*rows(A), 0 ]) %!assert (size (kron (zeros (0, 3), A)), [ 0, 3*columns(A) ]) %!assert (size (kron (A, zeros (3, 0))), [ 3*rows(A), 0 ]) %!assert (size (kron (A, zeros (0, 3))), [ 0, 3*columns(A) ]) %!assert (kron (pi, e), pi*e) %!assert (kron (pi, A), pi*A) %!assert (kron (A, e), e*A) %!assert (kron ([1, 2, 3], A), [ A, 2*A, 3*A ]) %!assert (kron ([1; 2; 3], A), [ A; 2*A; 3*A ]) %!assert (kron ([1, 2; 3, 4], A), [ A, 2*A; 3*A, 4*A ]) %!test %! res = [1,-1,2,-2,3,-3; 2,-2,4,-4,6,-6; 4,-4,5,-5,6,-6; 8,-8,10,-10,12,-12]; %! assert (kron (A, B), res) ### an extended demo from specgram %!#demo %! ## Speech spectrogram %! [x, Fs] = auload(file_in_loadpath("sample.wav")); # audio file %! step = fix(5*Fs/1000); # one spectral slice every 5 ms %! window = fix(40*Fs/1000); # 40 ms data window %! fftn = 2^nextpow2(window); # next highest power of 2 %! [S, f, t] = specgram(x, fftn, Fs, window, window-step); %! S = abs(S(2:fftn*4000/Fs,:)); # magnitude in range 0<f<=4000 Hz. %! S = S/max(max(S)); # normalize magnitude so that max is 0 dB. %! S = max(S, 10^(-40/10)); # clip below -40 dB. %! S = min(S, 10^(-3/10)); # clip above -3 dB. %! imagesc(flipud(20*log10(S)), 1); %! % you should now see a spectrogram in the image window ### now test test itself %!## usage and error testing % !fail ('test','usage.*test') # no args, generates usage() % !fail ('test(1,2,3,4)','usage.*test') # too many args, generates usage() %!fail ('test("test", "bogus")','unknown flag') # incorrect args %!fail ('garbage','garbage.*undefined') # usage on nonexistent function should be %!error test # no args, generates usage() %!error test(1,2,3,4) # too many args, generates usage() %!error <unknown flag> test("test", 'bogus'); # incorrect args, generates error() %!error <garbage' undefined> garbage # usage on nonexistent function should be %!error test("test", 'bogus'); # test without pattern %!test %! lastwarn(); # clear last warning just in case %!warning <warning message> warning('warning message'); %!## test of shared variables %!shared a # create a shared variable %!test a=3; # assign to a shared variable %!test assert(a,3) # variable should equal 3 %!shared b,c # replace shared variables %!test assert (!exist("a")); # a no longer exists %!test assert (isempty(b)); # variables start off empty %!shared a,b,c # recreate a shared variable %!test assert (isempty(a)); # value is empty even if it had a previous value %!test a=1; b=2; c=3; # give values to all variables %!test assert ([a,b,c],[1,2,3]); # test all of them together %!test c=6; # update a value %!test assert([a, b, c],[1, 2, 6]); # show that the update sticks %!shared # clear all shared variables %!test assert(!exist("a")) # show that they are cleared %!shared a,b,c # support for initializer shorthand %! a=1; b=2; c=4; %!function x = __test_a(y) %! x = 2*y; %!endfunction %!assert(__test_a(2),4); # Test a test function %!function __test_a (y) %! x = 2*y; %!endfunction %!test %! __test_a(2); # Test a test function with no return value %!function [x,z] = __test_a (y) %! x = 2*y; %! z = 3*y; %!endfunction %!test # Test a test function with multiple returns %! [x,z] = __test_a(3); %! assert(x,6); %! assert(z,9); %!## test of assert block %!assert (isempty([])) # support for test assert shorthand %!## demo blocks %!demo # multiline demo block %! t = [0:0.01:2*pi]; x = sin (t); %! plot (t,x); %! % you should now see a sine wave in your figure window %!demo a=3 # single line demo blocks work too %!## this is a comment block. it can contain anything. %!## %! it is the "#" as the block type that makes it a comment %! and it stays as a comment even through continuation lines %! which means that it works well with commenting out whole tests % !# failure tests. All the following should fail. These tests should % !# be disabled unless you are developing test() since users don't % !# like to be presented with expected failures. I use % ! to disable. % !test error("---------Failure tests. Use test('test','verbose',1)"); % !test assert([a,b,c],[1,3,6]); # variables have wrong values % !bogus # unknown block type % !error toeplitz([1,2,3]); # correct usage % !test syntax errors) # syntax errors fail properly % !shared garbage in # variables must be comma separated % !error syntax++error # error test fails on syntax errors % !error "succeeds."; # error test fails if code succeeds % !error <wrong pattern> error("message") # error pattern must match % !demo with syntax error # syntax errors in demo fail properly % !shared a,b,c % !demo # shared variables not available in demo % ! assert(exist("a")) % !error % ! test('/etc/passwd'); % ! test("nonexistent file"); % ! ## These don't signal an error, so the test for an error fails. Note % ! ## that the call doesn't reference the current fid (it is unavailable), % ! ## so of course the informational message is not printed in the log.