Mercurial > hg > octave-nkf
view scripts/testfun/assert.m @ 15063:36cbcc37fdb8
Refactor configure.ac to make it more understandable.
Use common syntax for messages in config.h
Correct typos, refer to libraries in all caps, use two spaces after period.
Follow Autoconf guidelines and place general tests before specific tests.
* configure.ac, m4/acinclude.m4: Use common syntax for messages in config.h
Correct typos, refer to libraries in all caps, use two spaces after period.
Follow Autoconf guidelines and place general tests before specific tests.
author | Rik <rik@octave.org> |
---|---|
date | Tue, 31 Jul 2012 10:28:51 -0700 |
parents | 5d3a684236b0 |
children | 333243133364 |
line wrap: on
line source
## Copyright (C) 2000-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 {Function File} {} assert (@var{cond}) ## @deftypefnx {Function File} {} assert (@var{cond}, @var{errmsg}, @dots{}) ## @deftypefnx {Function File} {} assert (@var{cond}, @var{msg_id}, @var{errmsg}, @dots{}) ## @deftypefnx {Function File} {} assert (@var{observed}, @var{expected}) ## @deftypefnx {Function File} {} assert (@var{observed}, @var{expected}, @var{tol}) ## ## Produce an error if the specified condition is not met. @code{assert} can ## be called in three different ways. ## ## @table @code ## @item assert (@var{cond}) ## @itemx assert (@var{cond}, @var{errmsg}, @dots{}) ## @itemx assert (@var{cond}, @var{msg_id}, @var{errmsg}, @dots{}) ## Called with a single argument @var{cond}, @code{assert} produces an ## error if @var{cond} is zero. When called with more than one argument the ## additional arguments are passed to the @code{error} function. ## ## @item assert (@var{observed}, @var{expected}) ## Produce an error if observed is not the same as expected. Note that ## @var{observed} and @var{expected} can be scalars, vectors, matrices, ## strings, cell arrays, or structures. ## ## @item assert (@var{observed}, @var{expected}, @var{tol}) ## Produce an error if observed is not the same as expected but equality ## comparison for numeric data uses a tolerance @var{tol}. ## If @var{tol} is positive then it is an absolute tolerance which will produce ## an error if @code{abs (@var{observed} - @var{expected}) > abs (@var{tol})}. ## If @var{tol} is negative then it is a relative tolerance which will produce ## an error if @code{abs (@var{observed} - @var{expected}) > ## abs (@var{tol} * @var{expected})}. If @var{expected} is zero @var{tol} will ## always be interpreted as an absolute tolerance. ## @end table ## @seealso{test, fail, error} ## @end deftypefn ## FIXME: Output throttling: don't print out the entire 100x100 matrix, ## but instead give a summary; don't print out the whole list, just ## say what the first different element is, etc. To do this, make ## the message generation type specific. function assert (cond, varargin) in = deblank (argn(1,:)); for i = 2:rows (argn) in = cstrcat (in, ",", deblank (argn(i,:))); endfor in = cstrcat ("(", in, ")"); if (nargin == 1 || (nargin > 1 && islogical (cond) && ischar (varargin{1}))) if ((! isnumeric (cond) && ! islogical (cond)) || ! all (cond(:))) if (nargin == 1) ## Say which elements failed? error ("assert %s failed", in); else error (varargin{:}); endif endif else if (nargin < 2 || nargin > 3) print_usage (); endif expected = varargin{1}; if (nargin < 3) tol = 0; else tol = varargin{2}; endif if (exist ("argn") == 0) argn = " "; endif coda = ""; iserror = 0; if (ischar (expected)) iserror = (! ischar (cond) || ! strcmp (cond, expected)); elseif (iscell (expected)) if (! iscell (cond) || any (size (cond) != size (expected))) iserror = 1; else try for i = 1:length (expected(:)) assert (cond{i}, expected{i}, tol); endfor catch iserror = 1; end_try_catch endif elseif (isstruct (expected)) if (! isstruct (cond) || any (size (cond) != size (expected)) || rows (fieldnames (cond)) != rows (fieldnames (expected))) iserror = 1; else try #empty = numel (cond) == 0; empty = isempty (cond); normal = (numel (cond) == 1); for [v, k] = cond if (! isfield (expected, k)) error (); endif if (empty) v = {}; elseif (normal) v = {v}; else v = v(:)'; endif assert (v, {expected.(k)}, tol); endfor catch iserror = 1; end_try_catch endif elseif (ndims (cond) != ndims (expected) || any (size (cond) != size (expected))) iserror = 1; coda = "Dimensions don't match"; else if (nargin < 3) ## Without explicit tolerance, be more strict. if (! strcmp (class (cond), class (expected))) iserror = 1; coda = cstrcat ("Class ", class (cond), " != ", class (expected)); elseif (isnumeric (cond)) if (issparse (cond) != issparse (expected)) if (issparse (cond)) iserror = 1; coda = "sparse != non-sparse"; else iserror = 1; coda = "non-sparse != sparse"; endif elseif (iscomplex (cond) != iscomplex (expected)) if (iscomplex (cond)) iserror = 1; coda = "complex != real"; else iserror = 1; coda = "real != complex"; endif endif endif endif if (! iserror) ## Numeric. A = cond(:); B = expected(:); ## Check exceptional values. if (any (isna (A) != isna (B))) iserror = 1; coda = "NAs don't match"; elseif (any (isnan (A) != isnan (B))) iserror = 1; coda = "NaNs don't match"; ## Try to avoid problems comparing strange values like Inf+NaNi. elseif (any (isinf (A) != isinf (B)) || any (A(isinf (A) & ! isnan (A)) != B(isinf (B) & ! isnan (B)))) iserror = 1; coda = "Infs don't match"; else ## Check normal values. A = A(isfinite (A)); B = B(isfinite (B)); if (tol == 0) err = any (A != B); errtype = "values do not match"; elseif (tol >= 0) err = max (abs (A - B)); errtype = "maximum absolute error %g exceeds tolerance %g"; else abserr = max (abs (A(B == 0))); A = A(B != 0); B = B(B != 0); relerr = max (abs (A - B) ./ abs (B)); err = max ([abserr; relerr]); errtype = "maximum relative error %g exceeds tolerance %g"; endif if (err > abs (tol)) iserror = 1; coda = sprintf (errtype, err, abs (tol)); endif endif endif endif if (! iserror) return; endif ## Pretty print the "expected but got" info, trimming leading and ## trailing "\n". str = disp (expected); idx = find (str != "\n"); if (! isempty (idx)) str = str(idx(1):idx(end)); endif str2 = disp (cond); idx = find (str2 != "\n"); if (! isempty (idx)) str2 = str2 (idx(1):idx(end)); endif msg = cstrcat ("assert ", in, " expected\n", str, "\nbut got\n", str2); if (! isempty (coda)) msg = cstrcat (msg, "\n", coda); endif error ("%s", msg); endif endfunction ## empty input %!assert ([]) %!assert (zeros (3,0), zeros (3,0)) %!error assert (zeros (3,0), zeros (0,2)) %!error assert (zeros (3,0), []) %!error <Dimensions don't match> assert (zeros (2,0,2), zeros (2,0)) ## conditions %!assert (isempty ([])) %!assert (1) %!error assert (0) %!assert (ones (3,1)) %!assert (ones (1,3)) %!assert (ones (3,4)) %!error assert ([1,0,1]) %!error assert ([1;1;0]) %!error assert ([1,0;1,1]) ## scalars %!error assert (3, [3,3; 3,3]) %!error assert ([3,3; 3,3], 3) %!assert (3, 3) %!assert (3+eps, 3, eps) %!assert (3, 3+eps, eps) %!error assert (3+2*eps, 3, eps) %!error assert (3, 3+2*eps, eps) ## vectors %!assert ([1,2,3],[1,2,3]); %!assert ([1;2;3],[1;2;3]); %!error assert ([2;2;3],[1;2;3]); %!error assert ([1,2,3],[1;2;3]); %!error assert ([1,2],[1,2,3]); %!error assert ([1;2;3],[1;2]); %!assert ([1,2;3,4],[1,2;3,4]); %!error assert ([1,4;3,4],[1,2;3,4]) %!error assert ([1,3;2,4;3,5],[1,2;3,4]) ## must give a small tolerance for floating point errors on relative %!assert (100+100*eps, 100, -2*eps) %!assert (100, 100+100*eps, -2*eps) %!error assert (100+300*eps, 100, -2*eps) %!error assert (100, 100+300*eps, -2*eps) %!error assert (3, [3,3]) %!error assert (3, 4) ## test relative vs. absolute tolerances %!test assert (0.1+eps, 0.1, 2*eps); # accept absolute %!error assert (0.1+eps, 0.1, -2*eps); # fail relative %!test assert (100+100*eps, 100, -2*eps); # accept relative %!error assert (100+100*eps, 100, 2*eps); # fail absolute ## exceptional values %!assert ([NaN, NA, Inf, -Inf, 1+eps, eps], [NaN, NA, Inf, -Inf, 1, 0], eps) %!error assert (NaN, 1) %!error assert (NA, 1) %!error assert (-Inf, Inf) ## strings %!assert ("dog", "dog") %!error assert ("dog", "cat") %!error assert ("dog", 3) %!error assert (3, "dog") ## structures %!shared x,y %! x.a = 1; x.b=[2, 2]; %! y.a = 1; y.b=[2, 2]; %!assert (x, y) %!test y.b=3; %!error assert (x, y) %!error assert (3, x) %!error assert (x, 3) %!test %! # Empty structures %! x = resize (x, 0, 1); %! y = resize (y, 0, 1); %! assert (x, y); ## cell arrays %!test %! x = {[3], [1,2,3]; 100+100*eps, "dog"}; %! y = x; %! assert (x, y); %! y = x; y(1,1) = [2]; %! fail ("assert (x, y)"); %! y = x; y(1,2) = [0, 2, 3]; %! fail ("assert (x, y)"); %! y = x; y(2,1) = 101; %! fail ("assert (x, y)"); %! y = x; y(2,2) = "cat"; %! fail ("assert (x, y)"); %% Test input validation %!error assert %!error assert (1,2,3,4)