changeset 2086:d4a591afe37e octave-forge

Update FSF address and more texinfo in preparation for inclusion in octave
author adb014
date Thu, 27 Oct 2005 19:51:19 +0000
parents 6024b57032df
children a553fa229880
files extra/testfun/assert.m extra/testfun/demo.m extra/testfun/example.m extra/testfun/pretty.cc extra/testfun/speed.m extra/testfun/test.m
diffstat 6 files changed, 295 insertions(+), 130 deletions(-) [+]
line wrap: on
line diff
--- a/extra/testfun/assert.m	Wed Oct 26 22:07:36 2005 +0000
+++ b/extra/testfun/assert.m	Thu Oct 27 19:51:19 2005 +0000
@@ -12,7 +12,8 @@
 ##
 ## You should have received a copy of the GNU General Public License
 ## along with this program; if not, write to the Free Software
-## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+## 02110-1301  USA
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} assert (@var{cond})
--- a/extra/testfun/demo.m	Wed Oct 26 22:07:36 2005 +0000
+++ b/extra/testfun/demo.m	Thu Oct 27 19:51:19 2005 +0000
@@ -12,7 +12,8 @@
 ##
 ## You should have received a copy of the GNU General Public License
 ## along with this program; if not, write to the Free Software
-## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+## 02110-1301  USA
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} demo ('@var{name}',@var{n})
--- a/extra/testfun/example.m	Wed Oct 26 22:07:36 2005 +0000
+++ b/extra/testfun/example.m	Thu Oct 27 19:51:19 2005 +0000
@@ -12,7 +12,8 @@
 ##
 ## You should have received a copy of the GNU General Public License
 ## along with this program; if not, write to the Free Software
-## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+## 02110-1301  USA
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} example ('@var{name}',@var{n})
--- a/extra/testfun/pretty.cc	Wed Oct 26 22:07:36 2005 +0000
+++ b/extra/testfun/pretty.cc	Thu Oct 27 19:51:19 2005 +0000
@@ -16,17 +16,22 @@
 for more details.
 
 You should have received a copy of the GNU General Public License
-along with this program; see the file COPYING.  If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301  USA
 */
 
 #include <octave/oct.h>
 #include <octave/oct-strstrm.h>
 
 DEFUN_DLD (pretty, args, ,
-"str = pretty (v)\n\
+  "-*- texinfo -*-\n\
+@deftypefn {Loadable Function} {@var{str} =} pretty (@var{v})\n\
 \n\
-Equivalent to x=disp(v), but disp doesn't return a value ...")
+Equivalent to @code{disp(@var{v})}, but returns the output as a string\n\
+@var{str}.
+\n\
+@end deftypefn")
 {
   octave_value_list retval;
 
--- a/extra/testfun/speed.m	Wed Oct 26 22:07:36 2005 +0000
+++ b/extra/testfun/speed.m	Thu Oct 27 19:51:19 2005 +0000
@@ -12,75 +12,97 @@
 ##
 ## You should have received a copy of the GNU General Public License
 ## along with this program; if not, write to the Free Software
-## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+## 02110-1301  USA
 
-## speed(f, init, max_n, f2, tol, err)
+## -*- texinfo -*-
+## @deftypefn {Function File} {} speed(@var{f}, @var{init}, @var{max_n}, @var{f2}, @var{tol}, @var{err})
+## @deftypefnx {Function File} {@var{r} =} speed(@dots{})
 ##
-##   Determine the execution time of an expression for various n.
-##   The n are log-spaced from 1 to max_n.  For each n, an
-##   initialization expression is computed to create whatever
-##   data are needed for the test.
+## Determine the execution time of an expression for various @var{n}.
+## The @var{n} are log-spaced from 1 to @var{max_n}.  For each @var{n},
+## an initialization expression is computed to create whatever data
+## are needed for the test. Called without output arguments the data
+## is presented graphically. Called with an output argument @var{r},
+## the speedup ratio is returned instead of displaying it graphically.
+##
+## @table @code
+## @item @var{f}
+## The expression to evaluate.
+##
+## @item @var{max_n}
+## The maximum test length to run. Default value is 100.
 ##
-##   f is the expression to evaluate.
-##   max_n = 100 is the maximum test length to run.
-##   init = "x = randn(n, 1);"
-##     Initialization expression for function argument values.  Use 'k' 
-##     for the test number and 'n' for the size of the test.  This should
-##     compute values for all variables listed in args.  Note that init
-##     will be evaluated first for k=0, so things which are constant
-##     throughout the test can be computed then.
-##   f2 = []
-##     is an alternative expression to evaluate, so the speed of the two
-##     can be compared
-##   tol = eps
-##     if tol is inf, then no comparison will be made between the
-##     results of express f and expression f2.  Otherwise, expression
-##     f should produce a value v and expression f2 should produce
-##     a value v2, and these shall be compared using assert(v,v2,tol,err)
+## @item @var{init}
+## Initialization expression for function argument values.  Use @var{k} 
+## for the test number and @var{n} for the size of the test.  This should
+## compute values for all variables listed in args.  Note that init will
+## be evaluated first for k=0, so things which are constant throughout
+## the test can be computed then. The default value is @code{@var{x} =
+## randn (@var{n}, 1);}.
 ##
-## r = speed (...)
-##   Returns the average speedup ratio instead of displaying and plotting.
+## @item @var{f2}
+## An alternative expression to evaluate, so the speed of the two
+## can be compared. Default is @code{[]}.
+##
+## @item @var{tol}
+## If @var{tol} is @code{Inf}, then no comparison will be made between the
+## results of expression @var{f} and expression @var{f2}.  Otherwise,
+## expression @var{f} should produce a value @var{v} and expression @var{f2} 
+## should produce a value @var{v2}, and these shall be compared using 
+## @code{assert(@var{v},@var{v2},@var{tol},@var{err}). The default is
+## @code{eps}.
+## @end table
 ##
 ## Some global variables are also referenced. Choose values suitable to
 ## your machine and your work style.
-##    speed_test_plot = 1
-##       if true, plot a nice speed comparison graph
-##    speed_test_numtests = 25
-##       number of vector lengths to test
+##
+## @table @code
+## @item speed_test_plot
+## If true, plot a nice speed comparison graph. Default is true.
+##
+## @item speed_test_numtests
+## Number of vector lengths to test. The default is 25.
+## @end table
 ##
 ## Some comments on the graphs.  The line on the speedup ratio graph 
 ## should be larger than 1 if your function is faster.  The slope on
 ## the runtime graph shows you the O(f) speed characteristics.  Where it
 ## is flat, execution time is O(1).  Where it is sloping, execution time
-## is O(n^m), with steeper slopes for larger n.  Generally vectorizing
+## is O(n^m), with steeper slopes for larger @var{n}.  Generally vectorizing
 ## a function will not change the slope of the run-time graph, but it
 ## will shift it relative to the original.
 ##
-## Example
-##   % If you had an original version of xcorr using for loops and
-##   % another version using FFT, you could compare the run speed
-##   % for various lags as follows, or for a fixed lag with varying
-##   % vector lengths as follows:
+## A simple example is
+##
+## @example
+##   speed("strrep(s,x,y)", "s=blanks(n);x=' ';y='b';", 100)
+## @end example
 ##
+## A more complex example, if you had an original version of @code{xcorr}
+## using for loops and another version using an FFT, you could compare the
+## run speed for various lags as follows, or for a fixed lag with varying
+## vector lengths as follows:
+##
+## @example
 ##   speed("v=xcorr(x,n)", "x=rand(128,1);", 100, ...
 ##         "v2=xcorr_orig(x,n)", 100*eps,'rel')
 ##   speed("v=xcorr(x,15)", "x=rand(20+n,1);", 100, ...
 ##         "v2=xcorr_orig(x,n)", 100*eps,'rel')
-##
-##   % Assuming one of the two versions is in xcorr_orig, this would
-##   % would compare their speed and their output values.  Note that the
-##   % FFT version is not exact, so we specify an acceptable tolerance on
-##   % the comparison (100*eps), and the errors should be computed
-##   % relatively, as abs( (x-y)./y ) rather than absolutely as abs(x-y).
+## @end example
 ##
-## Example
-##   speed("strrep(s,x,y)", "s=blanks(n);x=' ';y='b';", 100)
+## Assuming one of the two versions is in @var{xcorr_orig}, this would
+## would compare their speed and their output values.  Note that the
+## FFT version is not exact, so we specify an acceptable tolerance on
+## the comparison @code{100*eps}, and the errors should be computed
+## relatively, as @code{abs((@var{x} - @var{y})./@var{y})} rather than 
+## absolutely as @code{abs(@var{x} - @var{y})}.
 ##
-## Type example('speed') to see some real examples.  Note for 
+## Type @code{example('speed')} to see some real examples. Note for 
 ## obscure reasons, you can't run examples 1 and 2 directly using 
-## demo('speed').  Instead use: 
-##    eval(example('speed',1))
-##    eval(example('speed',2))
+## @code{demo('speed')}. Instead use, @code{eval(example('speed',1))}
+## and @code{eval(example('speed',2))}.
+## @end deftypefn
 
 ## TODO: consider two dimensional speedup surfaces for functions like kron.
 function __ratio_r = speed (__f1, __init, __max_n, __f2, __tol, __err)
--- a/extra/testfun/test.m	Wed Oct 26 22:07:36 2005 +0000
+++ b/extra/testfun/test.m	Thu Oct 27 19:51:19 2005 +0000
@@ -12,175 +12,307 @@
 ##
 ## You should have received a copy of the GNU General Public License
 ## along with this program; if not, write to the Free Software
-## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+## 02110-1301  USA
 
-## test name
-##   Perform tests interactively, stopping at the first error.
-##   Tests are from the first file matching 'name', 'name.m' 
-##   in your loadpath.
+## -*- texinfo -*-
+## @deftypefn {Function File} {} test @var{name}
+## @deftypefnx {Function File} {} 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')
 ##
-## test name quiet|normal|verbose
-##   Perform tests interactively, stopping at the first error.
-##   'quiet': Don't report all the tests as they happen, just the errors.
-##   'normal': Report all tests as they happen, but don't do tests
-##       which require user interaction.
-##   'verbose': Do tests which require user interaction.
+## 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.
 ##
-## test('name', ['quiet'|'normal'|'verbose'], fid)
-##   Batch processing.  Write errors to already open file fid (hopefully
-##   then when octave crashes this file will tell you what was happening
-##   when it did).  You can use stdout if you want to see the results as
-##   they happen.  You can also give a file name rather than an fid, in
-##   which case the contents of the file will be replaced with the log
-##   from the current test.
+## @item 'verbose'
+## Do tests which require user interaction.
+## @end table
 ##
-## success = test(...)
-##   return true if all the tests succeeded.
+## 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.
 ##
-## [n, max] = test(...)
-##   return number of success and number of tests
+## Called with a single output argument @var{success}, @code{test} returns
+## true is all of the tests were successful. Called with two output arguments
+## @var{n} and @var{max}, the number of sucessful test and the total number
+## of tests in the file @var{name} are returned.
 ##
-## [code, idx] = test('name', 'grabdemo')
-##   Extract the contents of the demo blocks, but do not execute them.
-##   code is the concatenation of all the code blocks and
-##   idx is a vector of positions of the ends of the demo blocks.
+## 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
+## concatented and returned as @var{code} with @var{idx} being a vector of
+## positions of the ends of the demo blocks.
 ##
-## test('', 'explain', fid)
-##   Write an explanation of the line markers to the file fid.
+## 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}.
 ##
-## This function process the named script file looking for lines which
-## start with "%! ".  The prefix is stripped off and the rest of the
-## line is processed through the octave interpreter.  If the code
+## @c USE THE TEXT FROM HERE TO CREATE OCTAVE MANUAL ENTRY
+## @code{test} scans the named script file looking for lines which
+## start with @code{%!}. The prefix is stripped off and the rest of the
+## line is processed through the octave interpreter. If the code
 ## generates an error, then the test is said to fail.
 ## 
-## Since eval() will stop at the first error it encounters, you must
+## Since @code{eval()} will stop at the first error it encounters, you must
 ## divide your tests up into blocks, with anything in a separate
 ## block evaluated separately.  Blocks are introduced by the keyword
-## 'test' immediately following the '%!'.  For example,
+## @code{test} immediately following the @code{%!}.  For example,
+##
+## @example
+## @group
 ##    %!test error("this test fails!");
 ##    %!test "this test doesn't fail since it doesn't generate an error";
+## @end group
+## @end example
+##
 ## When a test fails, you will see something like:
+##
+## @example
+## @group
 ##      ***** test error('this test fails!')
 ##    !!!!! test failed
 ##    this test fails!
+## @end group
+## @end example
 ##
 ## Generally, to test if something works, you want to assert that it
 ## produces a correct value.  A real test might look something like
+##
+## @example
+## @group
 ##    %!test
-##    %! A = [1, 2, 3; 4, 5, 6]; B = [1; 2];
-##    %! expect = [ A ; 2*A ];
-##    %! get = kron (B, A);
+##    %! @var{a} = [1, 2, 3; 4, 5, 6]; B = [1; 2];
+##    %! expect = [ @var{a} ; 2*@var{a} ];
+##    %! get = kron (@var{b}, @var{a});
 ##    %! if (any(size(expect) != size(get)))
 ##    %!    error ("wrong size: expected %d,%d but got %d,%d",
 ##    %!           size(expect), size(get));
 ##    %! elseif (any(any(expect!=get)))
 ##    %!    error ("didn't get what was expected.");
 ##    %! endif
-## To make the process easier, use the assert function.  For example,
-## with assert the previous test is reduced to:
+## @end group
+## @end example
+##
+## To make the process easier, use the @code{assert} function.  For example,
+## with @code{assert} the previous test is reduced to:
+##
+## @example
+## @group
 ##    %!test
-##    %! A = [1, 2, 3; 4, 5, 6]; B = [1; 2];
-##    %! assert (kron (B, A), [ A; 2*A ]);
-## Assert can accept a tolerance so that you can compare results
+##    %! @var{a} = [1, 2, 3; 4, 5, 6]; @var{b} = [1; 2];
+##    %! assert (kron (@var{b}, @var{a}), [ @var{a}; 2*@var{a} ]);
+## @end group
+## @end example
+##
+## @code{assert} can accept a tolerance so that you can compare results
 ## absolutely or relatively. For example, the following all succeed:
+##
+## @example
+## @group
 ##    %!test assert (1+eps, 1, 2*eps)          # absolute error
 ##    %!test assert (100+100*eps, 100, -2*eps) # relative error
+## @end group
+## @end example
+##
 ## You can also do the comparison yourself, but still have assert
 ## generate the error:
+##
+## @example
+## @group
 ##    %!test assert (isempty([]))
 ##    %!test assert ([ 1,2; 3,4 ] > 0)
-## Because assert is so frequently used alone in a test block, there
+## @end group
+## @end example
+##
+## Because @code{assert} is so frequently used alone in a test block, there
 ## is a shorthand form:
-##    %!assert (...)
+##
+## @example
+##    %!assert (@dots{})
+## @end example
+##
 ## which is equivalent to:
-##    %!test assert (...)
+##
+## @example
+##    %!test assert (@dots{})
+## @end example
 ##
 ## Each block is evaluated in its own function environment, which means
 ## that variables defined in one block are not automatically shared
 ## with other blocks.  If you do want to share variables, then you
-## must declare them as shared before you use them.  For example, the
-## following declares the variable A, gives it an initial value (default
+## must declare them as @code{shared} before you use them.  For example, the
+## following declares the variable @var{a}, gives it an initial value (default
 ## is empty), then uses it in several subsequent tests.
-##    %!shared A
-##    %! A = [1, 2, 3; 4, 5, 6];
-##    %!assert (kron ([1; 2], A), [ A; 2*A ]);
-##    %!assert (kron ([1, 2], A), [ A, 2*A ]);
-##    %!assert (kron ([1,2; 3,4], A), [ A,2*A; 3*A,4*A ]);
+##
+## @example
+## @group
+##    %!shared @var{a}
+##    %! @var{a} = [1, 2, 3; 4, 5, 6];
+##    %!assert (kron ([1; 2], @var{a}), [ @var{a}; 2*@var{a} ]);
+##    %!assert (kron ([1, 2], @var{a}), [ @var{a}, 2*@var{a} ]);
+##    %!assert (kron ([1,2; 3,4], @var{a}), [ @var{a},2*@var{a}; 3*@var{a},4*@var{a} ]);
+## @end group
+## @end example
+##
 ## You can share several variables at the same time:
-##    %!shared A, B
+##
+## @example
+##    %!shared @var{a}, @var{b}
+## @end example
+##
 ## You can also share test functions:
+##
+## @example
+## @group
 ##    %!shared fn
-##    %!function a = fn(b)
-##    %!  a = 2*b;
-##    %!assert (a(2),4);
+##    %!function @var{a} = fn(@var{b})
+##    %!  @var{a} = 2*@var{b};
+##    %!assert (@var{a}(2),4);
+## @end group
+## @end example
+##
 ## Note that all previous variables and values are lost when a new 
 ## shared block is declared.
 ##
 ## Error and warning blocks are like test blocks, but they only succeed 
 ## if the code generates an error.  You can check the text of the error
-## is correct using an optional regular expression <pattern>.  For example:
+## is correct using an optional regular expression @code{<pattern>}.  
+## For example:
+##
+## @example
 ##    %!error <passes!> error('this test passes!');
+## @end example
+##
 ## If the code doesn't generate an error, the test fails. For example,
+##
+## @example
 ##    %!error "this is an error because it succeeds.";
+## @end example
+##
 ## produces
+##
+## @example
+## @group
 ##    ***** error "this is an error because it succeeds.";
 ##    !!!!! test failed: no error
+## @end group
+## @end example
 ##
 ## It is important to automate the tests as much as possible, however
 ## some tests require user interaction.  These can be isolated into
 ## demo blocks, which if you are in batch mode, are only run when 
-## called with 'demo' or 'verbose'.  The code is displayed before
+## called with @code{demo} or @code{verbose}. The code is displayed before
 ## it is executed. For example,
+##
+## @example
+## @group
 ##    %!demo
-##    %! t=[0:0.01:2*pi]; x=sin(t);
-##    %! plot(t,x);
+##    %! @var{t}=[0:0.01:2*pi]; @var{x}=sin(@var{t});
+##    %! plot(@var{t},@var{x});
 ##    %! ## you should now see a sine wave in your figure window
+## @end group
+## @end example
+##
 ## produces
-##    > t=[0:0.01:2*pi]; x=sin(t);
-##    > plot(t,x);
+##
+## @example
+## @group
+##    > @var{t}=[0:0.01:2*pi]; @var{x}=sin(@var{t});
+##    > plot(@var{t},@var{x});
 ##    > ## you should now see a sine wave in your figure window
 ##    Press <enter> to continue: 
+## @end group
+## @end example
+##
 ## Note that demo blocks cannot use any shared variables.  This is so
 ## that they can be executed by themselves, ignoring all other tests.
 ##
-## If you want to temporarily disable a test block, put '#' in place
+## If you want to temporarily disable a test block, put @code{#} in place
 ## of the block type.  This creates a comment block which is echoed
 ## in the log file, but is not executed.  For example:
+##
+## @example
+## @group
 ##    %!#demo
-##    %! t=[0:0.01:2*pi]; x=sin(t);
-##    %! plot(t,x);
+##    %! @var{t}=[0:0.01:2*pi]; @var{x}=sin(@var{t});
+##    %! plot(@var{t},@var{x});
 ##    %! ## you should now see a sine wave in your figure window
+## @end group
+## @end example
 ##
 ## Block type summary:
-##    %!test       - check that entire block is correct
-##    %!error      - check for correct error message
-##    %!warning    - check for correct warning message
-##    %!demo       - demo only executes in interactive mode
-##    %!#          - comment: ignore everything within the block
-##    %!shared x,y,z       - declares variables for use in multiple tests
-##    %!function           - defines a function value for a shared variable
-##    %!assert (x, y, tol) - shorthand for %!test assert (x, y, tol)
+##
+## @table @code
+## @item %!test
+## check that entire block is correct
+## @item %!error
+## check for correct error message
+## @item %!warning
+## check for correct warning message
+## @item %!demo
+## demo only executes in interactive mode
+## @item %!#
+## comment: ignore everything within the block
+## @item %!shared x,y,z
+## declares variables for use in multiple tests
+## @item %!function
+## defines a function value for a shared variable
+## @item %!assert (x, y, tol)
+## shorthand for %!test assert (x, y, tol)
+## @end table
 ##
 ## You can also create test scripts for builtins and your own C++
 ## functions. Just put a file of the function name on your path without
 ## any extension and it will be picked up by the test procedure.  You
 ## can even embed tests directly in your C++ code:
+##
+## @example
+## @group
 ##    #if 0
 ##    %!test disp('this is a test')
 ##    #endif
+## @end group
+## @end example
+##
 ## or
+##
+## @example
+## @group
 ##    /*
 ##    %!test disp('this is a test')
 ##    */
+## @end group
+## @end example
+##
 ## but then the code will have to be on the load path and the user 
 ## will have to remember to type test('name.cc').  Conversely, you
 ## can separate the tests from normal octave script files by putting
 ## them in plain files with no extension rather than in script files.
-## Don't forget to tell emacs that the plain text file you are using
-## is actually octave code, using something like:
-##    ## -*-octave-*-
+## @c DO I WANT TO INCLUDE THE EDITOR SPECIFIC STATEMENT BELOW???
+## @c Don't forget to tell emacs that the plain text file you are using
+## @c is actually octave code, using something like:
+## @c   ## -*-octave-*-
 ##
-## See Also: error, assert, fail, demo, example
+## @end deftypefn
+## @seealso{error, assert, fail, demo, example}
 
 ## TODO: * Consider using keyword fail rather then error?  This allows us
 ## TODO: to make a functional form of error blocks, which means we
@@ -202,9 +334,12 @@
   if (nargin < 3) 
     __fid = []; 
   endif
-  if (nargin < 1 || nargin > 3 || !ischar(__name) || !ischar(__flag))
+  if (nargin < 1 || nargin > 3 || (!ischar(__name) && !isempty(__name)) || !ischar(__flag))
     usage("success = test('name', ['quiet'|'normal'|'verbose'], fid)");
   endif
+  if (isempty(__name) && (nargin != 3 || !strcmp(__flag, "explain")))
+    usage("test([], 'explain', fid)");
+  endif
   __batch = (!isempty(__fid));
 
   ## decide if error messages should be collected