Mercurial > hg > octave-nkf
comparison scripts/testfun/assert.m @ 17255:a28c0d73e253
assert.m: Added many more %!tests for function. Fixed multiple bugs discovered.
* scripts/testfun/assert.m: Adjust call_depth at every exit point of function to
fix recursion errors. Fix incorrectly reported errors with row vector input.
Add new reason text "expected XXX, but observed YYY" where XXX is "cell" or
"struct". Stop reporting multiple errors when condition is both an exceptional
value and not meeting tolerance. Improve %!tests to actually catch assert failing
in the correct way, rather than just failing.
author | Rik <rik@octave.org> |
---|---|
date | Thu, 15 Aug 2013 12:27:37 -0700 |
parents | e3870f594d8b |
children | 09543e9c8f40 |
comparison
equal
deleted
inserted
replaced
17254:7fb4461997aa | 17255:a28c0d73e253 |
---|---|
75 endfor | 75 endfor |
76 in = ["(" in ")"]; | 76 in = ["(" in ")"]; |
77 | 77 |
78 if (nargin == 1 || (nargin > 1 && islogical (cond) && ischar (varargin{1}))) | 78 if (nargin == 1 || (nargin > 1 && islogical (cond) && ischar (varargin{1}))) |
79 if ((! isnumeric (cond) && ! islogical (cond)) || ! all (cond(:))) | 79 if ((! isnumeric (cond) && ! islogical (cond)) || ! all (cond(:))) |
80 call_depth--; | |
80 if (nargin == 1) | 81 if (nargin == 1) |
81 ## Perhaps, say which elements failed? | 82 ## Perhaps, say which elements failed? |
82 error ("assert %s failed", in); | 83 error ("assert %s failed", in); |
83 else | 84 else |
84 error (varargin{:}); | 85 error (varargin{:}); |
98 err.expected = {}; | 99 err.expected = {}; |
99 err.reason = {}; | 100 err.reason = {}; |
100 | 101 |
101 if (ischar (expected)) | 102 if (ischar (expected)) |
102 if (! ischar (cond)) | 103 if (! ischar (cond)) |
103 err.index{end+1} = "[]"; | 104 err.index{end+1} = "."; |
104 err.expected{end+1} = expected; | 105 err.expected{end+1} = expected; |
105 if (isnumeric (cond)) | 106 if (isnumeric (cond)) |
106 err.observed{end+1} = num2str (cond); | 107 err.observed{end+1} = num2str (cond); |
107 err.reason{end+1} = "Expected string, but observed number"; | 108 err.reason{end+1} = "Expected string, but observed number"; |
108 elseif (iscell (cond)) | |
109 err.observed{end+1} = "{}"; | |
110 err.reason{end+1} = "Expected string, but observed cell"; | |
111 else | 109 else |
112 err.observed{end+1} = "[]"; | 110 err.observed{end+1} = "O"; |
113 err.reason{end+1} = "Expected string, but observed struct"; | 111 err.reason{end+1} = ["Expected string, but observed " class(cond)]; |
114 end | 112 endif |
115 elseif (! strcmp (cond, expected)) | 113 elseif (! strcmp (cond, expected)) |
116 err.index{end+1} = "[]"; | 114 err.index{end+1} = "[]"; |
117 err.observed{end+1} = cond; | 115 err.observed{end+1} = cond; |
118 err.expected{end+1} = expected; | 116 err.expected{end+1} = expected; |
119 err.reason{end+1} = "Strings don't match"; | 117 err.reason{end+1} = "Strings don't match"; |
120 endif | 118 endif |
121 | 119 |
122 elseif (iscell (expected)) | 120 elseif (iscell (expected)) |
123 if (! iscell (cond) || any (size (cond) != size (expected))) | 121 if (! iscell (cond)) |
124 err.index{end+1} = "{}"; | 122 err.index{end+1} = "."; |
125 err.observed{end+1} = "O"; | 123 err.observed{end+1} = "O"; |
126 err.expected{end+1} = "E"; | 124 err.expected{end+1} = "E"; |
127 err.reason{end+1} = "Cell sizes don't match"; | 125 err.reason{end+1} = ["Expected cell, but observed " class(cond)]; |
126 elseif (ndims (cond) != ndims (expected) | |
127 || any (size (cond) != size (expected))) | |
128 err.index{end+1} = "."; | |
129 err.observed{end+1} = ["O(" sprintf("%dx", size(cond))(1:end-1) ")"]; | |
130 err.expected{end+1} = ["E(" sprintf("%dx", size(expected))(1:end-1) ")"]; | |
131 err.reason{end+1} = "Dimensions don't match"; | |
128 else | 132 else |
129 try | 133 try |
130 ## Recursively compare cell arrays | 134 ## Recursively compare cell arrays |
131 for i = 1:length (expected(:)) | 135 for i = 1:length (expected(:)) |
132 assert (cond{i}, expected{i}, tol); | 136 assert (cond{i}, expected{i}, tol); |
138 err.reason{end+1} = "Cell configuration error"; | 142 err.reason{end+1} = "Cell configuration error"; |
139 end_try_catch | 143 end_try_catch |
140 endif | 144 endif |
141 | 145 |
142 elseif (isstruct (expected)) | 146 elseif (isstruct (expected)) |
143 if (! isstruct (cond) || any (size (cond) != size (expected)) | 147 if (! isstruct (cond)) |
144 || rows (fieldnames (cond)) != rows (fieldnames (expected))) | 148 err.index{end+1} = "."; |
145 err.index{end+1} = "{}"; | |
146 err.observed{end+1} = "O"; | 149 err.observed{end+1} = "O"; |
147 err.expected{end+1} = "E"; | 150 err.expected{end+1} = "E"; |
151 err.reason{end+1} = ["Expected struct, but observed " class(cond)]; | |
152 elseif (ndims (cond) != ndims (expected) | |
153 || any (size (cond) != size (expected)) | |
154 || rows (fieldnames (cond)) != rows (fieldnames (expected))) | |
155 | |
156 err.index{end+1} = "."; | |
157 err.observed{end+1} = ["O(" sprintf("%dx", size(cond))(1:end-1) ")"]; | |
158 err.expected{end+1} = ["E(" sprintf("%dx", size(expected))(1:end-1) ")"]; | |
148 err.reason{end+1} = "Structure sizes don't match"; | 159 err.reason{end+1} = "Structure sizes don't match"; |
149 else | 160 else |
150 try | 161 try |
151 empty = isempty (cond); | 162 empty = isempty (cond); |
152 normal = (numel (cond) == 1); | 163 normal = (numel (cond) == 1); |
217 | 228 |
218 A = cond; | 229 A = cond; |
219 B = expected; | 230 B = expected; |
220 | 231 |
221 ## Check exceptional values. | 232 ## Check exceptional values. |
222 erridx = find ( isna (real (A)) != isna (real (B)) | 233 errvec = ( isna (real (A)) != isna (real (B)) |
223 | isna (imag (A)) != isna (imag (B))); | 234 | isna (imag (A)) != isna (imag (B))); |
235 erridx = find (errvec); | |
224 if (! isempty (erridx)) | 236 if (! isempty (erridx)) |
225 err.index(end+1:end + length (erridx)) = ... | 237 err.index(end+1:end+length (erridx)) = ... |
226 ind2tuple (size (A), erridx); | 238 ind2tuple (size (A), erridx); |
227 err.observed(end+1:end + length (erridx)) = ... | 239 err.observed(end+1:end+length (erridx)) = ... |
228 strtrim (cellstr (num2str (A(erridx) (:)))); | 240 strtrim (cellstr (num2str (A(erridx) (:)))); |
229 err.expected(end+1:end + length (erridx)) = ... | 241 err.expected(end+1:end+length (erridx)) = ... |
230 strtrim (cellstr (num2str (B(erridx) (:)))); | 242 strtrim (cellstr (num2str (B(erridx) (:)))); |
231 err.reason(end+1:end + length (erridx)) = ... | 243 err.reason(end+1:end+length (erridx)) = ... |
232 cellstr (repmat ("'NA' mismatch", length (erridx), 1)); | 244 repmat ({"'NA' mismatch"}, length (erridx), 1); |
233 endif | 245 endif |
234 | 246 errseen = errvec; |
235 erridx = find ( isnan (real (A)) != isnan (real (B)) | 247 |
236 | isnan (imag (A)) != isnan (imag (B))); | 248 errvec = ( isnan (real (A)) != isnan (real (B)) |
249 | isnan (imag (A)) != isnan (imag (B))); | |
250 erridx = find (errvec & !errseen); | |
237 if (! isempty (erridx)) | 251 if (! isempty (erridx)) |
238 err.index(end+1:end + length (erridx)) = ... | 252 err.index(end+1:end+length (erridx)) = ... |
239 ind2tuple (size (A), erridx); | 253 ind2tuple (size (A), erridx); |
240 err.observed(end+1:end + length (erridx)) = ... | 254 err.observed(end+1:end+length (erridx)) = ... |
241 strtrim (cellstr (num2str (A(erridx) (:)))); | 255 strtrim (cellstr (num2str (A(erridx) (:)))); |
242 err.expected(end+1:end + length (erridx)) = ... | 256 err.expected(end+1:end+length (erridx)) = ... |
243 strtrim (cellstr (num2str (B(erridx) (:)))); | 257 strtrim (cellstr (num2str (B(erridx) (:)))); |
244 err.reason(end+1:end + length (erridx)) = ... | 258 err.reason(end+1:end+length (erridx)) = ... |
245 cellstr (repmat ("'NaN' mismatch", length (erridx), 1)); | 259 repmat ({"'NaN' mismatch"}, length (erridx), 1); |
246 endif | 260 endif |
247 | 261 errseen |= errvec; |
248 erridx = find (((isinf (real (A)) | isinf (real (B))) ... | 262 |
249 & real (A) != real (B)) ... | 263 errvec = ((isinf (real (A)) | isinf (real (B))) ... |
250 | ((isinf (imag (A)) | isinf (imag (B))) | 264 & (real (A) != real (B))) ... |
251 & imag (A) != imag (B))); | 265 | ((isinf (imag (A)) | isinf (imag (B))) ... |
266 & (imag (A) != imag (B))); | |
267 erridx = find (errvec & !errseen); | |
252 if (! isempty (erridx)) | 268 if (! isempty (erridx)) |
253 err.index(end+1:end + length (erridx)) = ... | 269 err.index(end+1:end+length (erridx)) = ... |
254 ind2tuple (size (A), erridx); | 270 ind2tuple (size (A), erridx); |
255 err.observed(end+1:end + length (erridx)) = ... | 271 err.observed(end+1:end+length (erridx)) = ... |
256 strtrim (cellstr (num2str (A(erridx) (:)))); | 272 strtrim (cellstr (num2str (A(erridx) (:)))); |
257 err.expected(end+1:end + length (erridx)) = ... | 273 err.expected(end+1:end+length (erridx)) = ... |
258 strtrim (cellstr (num2str (B(erridx) (:)))); | 274 strtrim (cellstr (num2str (B(erridx) (:)))); |
259 err.reason(end+1:end + length (erridx)) = ... | 275 err.reason(end+1:end+length (erridx)) = ... |
260 cellstr (repmat ("'Inf' mismatch", length (erridx), 1)); | 276 repmat ({"'Inf' mismatch"}, length (erridx), 1); |
261 endif | 277 endif |
278 errseen |= errvec; | |
262 | 279 |
263 ## Check normal values. | 280 ## Check normal values. |
264 ## Replace exceptional values already checked above by zero. | 281 ## Replace exceptional values already checked above by zero. |
265 A_null_real = real (A); | 282 A_null_real = real (A); |
266 B_null_real = real (B); | 283 B_null_real = real (B); |
267 exclude = ! isfinite (A_null_real) & ! isfinite (B_null_real); | 284 exclude = errseen | ! isfinite (A_null_real) & ! isfinite (B_null_real); |
268 A_null_real(exclude) = 0; | 285 A_null_real(exclude) = 0; |
269 B_null_real(exclude) = 0; | 286 B_null_real(exclude) = 0; |
270 A_null_imag = imag (A); | 287 A_null_imag = imag (A); |
271 B_null_imag = imag (B); | 288 B_null_imag = imag (B); |
272 exclude = ! isfinite (A_null_imag) & ! isfinite (B_null_imag); | 289 exclude = errseen | ! isfinite (A_null_imag) & ! isfinite (B_null_imag); |
273 A_null_imag(exclude) = 0; | 290 A_null_imag(exclude) = 0; |
274 B_null_imag(exclude) = 0; | 291 B_null_imag(exclude) = 0; |
275 A_null = complex (A_null_real, A_null_imag); | 292 A_null = complex (A_null_real, A_null_imag); |
276 B_null = complex (B_null_real, B_null_imag); | 293 B_null = complex (B_null_real, B_null_imag); |
277 if (isscalar (tol)) | 294 if (isscalar (tol)) |
281 endif | 298 endif |
282 | 299 |
283 k = (mtol == 0); | 300 k = (mtol == 0); |
284 erridx = find ((A_null != B_null) & k); | 301 erridx = find ((A_null != B_null) & k); |
285 if (! isempty (erridx)) | 302 if (! isempty (erridx)) |
286 err.index(end+1:end + length (erridx)) = ... | 303 err.index(end+1:end+length (erridx)) = ... |
287 ind2tuple (size (A), erridx); | 304 ind2tuple (size (A), erridx); |
288 err.observed(end+1:end + length (erridx)) = ... | 305 err.observed(end+1:end+length (erridx)) = ... |
289 strtrim (cellstr (num2str (A(erridx) (:)))); | 306 strtrim (cellstr (num2str (A(erridx) (:)))); |
290 err.expected(end+1:end + length (erridx)) = ... | 307 err.expected(end+1:end+length (erridx)) = ... |
291 strtrim (cellstr (num2str (B(erridx) (:)))); | 308 strtrim (cellstr (num2str (B(erridx) (:)))); |
292 err.reason(end+1:end + length (erridx)) = ... | 309 err.reason(end+1:end+length (erridx)) = ... |
293 ostrsplit (deblank (sprintf ("Abs err %g exceeds tol %g\n", ... | 310 ostrsplit (deblank (sprintf ("Abs err %.5g exceeds tol %.5g\n",... |
294 [abs(A_null(erridx) - B_null(erridx)) mtol(erridx)]')), "\n"); | 311 [abs(A_null(erridx) - B_null(erridx))(:) mtol(erridx)(:)]')), "\n"); |
295 endif | 312 endif |
296 | 313 |
297 k = (mtol > 0); | 314 k = (mtol > 0); |
298 erridx = find ((abs (A_null - B_null) > mtol) & k); | 315 erridx = find ((abs (A_null - B_null) > mtol) & k); |
299 if (! isempty (erridx)) | 316 if (! isempty (erridx)) |
300 err.index(end+1:end + length (erridx)) = ... | 317 err.index(end+1:end+length (erridx)) = ... |
301 ind2tuple (size (A), erridx); | 318 ind2tuple (size (A), erridx); |
302 err.observed(end+1:end + length (erridx)) = ... | 319 err.observed(end+1:end+length (erridx)) = ... |
303 strtrim (cellstr (num2str (A(erridx) (:)))); | 320 strtrim (cellstr (num2str (A(erridx) (:)))); |
304 err.expected(end+1:end + length (erridx)) = ... | 321 err.expected(end+1:end+length (erridx)) = ... |
305 strtrim (cellstr (num2str (B(erridx) (:)))); | 322 strtrim (cellstr (num2str (B(erridx) (:)))); |
306 err.reason(end+1:end + length (erridx)) = ... | 323 err.reason(end+1:end+length (erridx)) = ... |
307 ostrsplit (deblank (sprintf ("Abs err %g exceeds tol %g\n", ... | 324 ostrsplit (deblank (sprintf ("Abs err %.5g exceeds tol %.5g\n",... |
308 [abs(A_null(erridx) - B_null(erridx)) mtol(erridx)]')), "\n"); | 325 [abs(A_null(erridx) - B_null(erridx))(:) mtol(erridx)(:)]')), "\n"); |
309 endif | 326 endif |
310 | 327 |
311 k = (mtol < 0); | 328 k = (mtol < 0); |
312 if (any (k)) | 329 if (any (k(:))) |
313 ## Test for absolute error where relative error can't be calculated. | 330 ## Test for absolute error where relative error can't be calculated. |
314 erridx = find ((B_null == 0) & abs (A_null) > abs (mtol) & k); | 331 erridx = find ((B_null == 0) & abs (A_null) > abs (mtol) & k); |
315 if (! isempty (erridx)) | 332 if (! isempty (erridx)) |
316 err.index(end+1:end + length (erridx)) = ... | 333 err.index(end+1:end+length (erridx)) = ... |
317 ind2tuple (size (A), erridx); | 334 ind2tuple (size (A), erridx); |
318 err.observed(end+1:end + length (erridx)) = ... | 335 err.observed(end+1:end+length (erridx)) = ... |
319 strtrim (cellstr (num2str (A(erridx) (:)))); | 336 strtrim (cellstr (num2str (A(erridx) (:)))); |
320 err.expected(end+1:end + length (erridx)) = ... | 337 err.expected(end+1:end+length (erridx)) = ... |
321 strtrim (cellstr (num2str (B(erridx) (:)))); | 338 strtrim (cellstr (num2str (B(erridx) (:)))); |
322 err.reason(end+1:end + length (erridx)) = ... | 339 err.reason(end+1:end+length (erridx)) = ... |
323 ostrsplit (deblank (sprintf ("Abs err %g exceeds tol %g\n", | 340 ostrsplit (deblank (sprintf ("Abs err %.5g exceeds tol %.5g\n", |
324 [abs(A_null(erridx) - B_null(erridx)) -mtol(erridx)]')), "\n"); | 341 [abs(A_null(erridx) - B_null(erridx)) -mtol(erridx)]')), "\n"); |
325 endif | 342 endif |
326 ## Test for relative error | 343 ## Test for relative error |
327 Bdiv = Inf (size (B_null)); | 344 Bdiv = Inf (size (B_null)); |
328 Bdiv(k & (B_null != 0)) = B_null(k & (B_null != 0)); | 345 Bdiv(k & (B_null != 0)) = B_null(k & (B_null != 0)); |
329 relerr = abs ((A_null - B_null) ./ abs (Bdiv)); | 346 relerr = abs ((A_null - B_null) ./ abs (Bdiv)); |
330 erridx = find ((relerr > abs (mtol)) & k); | 347 erridx = find ((relerr > abs (mtol)) & k); |
331 if (! isempty (erridx)) | 348 if (! isempty (erridx)) |
332 err.index(end+1:end + length (erridx)) = ... | 349 err.index(end+1:end+length (erridx)) = ... |
333 ind2tuple (size (A), erridx); | 350 ind2tuple (size (A), erridx); |
334 err.observed(end+1:end + length (erridx)) = ... | 351 err.observed(end+1:end+length (erridx)) = ... |
335 strtrim (cellstr (num2str (A(erridx) (:)))); | 352 strtrim (cellstr (num2str (A(erridx) (:)))); |
336 err.expected(end+1:end + length (erridx)) = ... | 353 err.expected(end+1:end+length (erridx)) = ... |
337 strtrim (cellstr (num2str (B(erridx) (:)))); | 354 strtrim (cellstr (num2str (B(erridx) (:)))); |
338 err.reason(end+1:end + length (erridx)) = ... | 355 err.reason(end+1:end+length (erridx)) = ... |
339 ostrsplit (deblank (sprintf ("Rel err %g exceeds tol %g\n", | 356 ostrsplit (deblank (sprintf ("Rel err %.5g exceeds tol %.5g\n", |
340 [relerr(erridx) -mtol(erridx)]')), "\n"); | 357 [relerr(erridx)(:) -mtol(erridx)(:)]')), "\n"); |
341 endif | 358 endif |
342 endif | 359 endif |
343 endif | 360 endif |
344 | 361 |
345 endif | 362 endif |
367 | 384 |
368 | 385 |
369 ## empty input | 386 ## empty input |
370 %!assert ([]) | 387 %!assert ([]) |
371 %!assert (zeros (3,0), zeros (3,0)) | 388 %!assert (zeros (3,0), zeros (3,0)) |
372 %!error assert (zeros (3,0), zeros (0,2)) | 389 %!error <O\(3x0\)\s+E\(0x2\)> assert (zeros (3,0), zeros (0,2)) |
373 %!error assert (zeros (3,0), []) | 390 %!error <Dimensions don't match> assert (zeros (3,0), []) |
374 %!error <Dimensions don't match> assert (zeros (2,0,2), zeros (2,0)) | 391 %!error <Dimensions don't match> assert (zeros (2,0,2), zeros (2,0)) |
375 | 392 |
376 ## conditions | 393 ## conditions |
377 %!assert (isempty ([])) | 394 %!assert (isempty ([])) |
378 %!assert (1) | 395 %!assert (1) |
383 %!error assert ([1,0,1]) | 400 %!error assert ([1,0,1]) |
384 %!error assert ([1;1;0]) | 401 %!error assert ([1;1;0]) |
385 %!error assert ([1,0;1,1]) | 402 %!error assert ([1,0;1,1]) |
386 | 403 |
387 ## scalars | 404 ## scalars |
388 %!error assert (3, [3,3; 3,3]) | 405 %!error <Dimensions don't match> assert (3, [3,3]) |
389 %!error assert ([3,3; 3,3], 3) | 406 %!error <Dimensions don't match> assert (3, [3,3; 3,3]) |
407 %!error <Dimensions don't match> assert ([3,3; 3,3], 3) | |
390 %!assert (3, 3) | 408 %!assert (3, 3) |
409 %!error <Abs err 1 exceeds tol> assert (3, 4) | |
391 %!assert (3+eps, 3, eps) | 410 %!assert (3+eps, 3, eps) |
392 %!assert (3, 3+eps, eps) | 411 %!assert (3, 3+eps, eps) |
393 %!error assert (3+2*eps, 3, eps) | 412 %!error <Abs err 4.4409e-16 exceeds tol> assert (3+2*eps, 3, eps) |
394 %!error assert (3, 3+2*eps, eps) | 413 %!error <Abs err 4.4409e-16 exceeds tol> assert (3, 3+2*eps, eps) |
395 | 414 |
396 ## vectors | 415 ## vectors |
397 %!assert ([1,2,3],[1,2,3]); | 416 %!assert ([1,2,3],[1,2,3]); |
398 %!assert ([1;2;3],[1;2;3]); | 417 %!assert ([1;2;3],[1;2;3]); |
399 %!error assert ([2,2,3,3],[1,2,3,4]); | 418 %!error <Abs err 1 exceeds tol 0> assert ([2,2,3,3],[1,2,3,4]); |
400 %!error assert ([6;6;7;7],[5;6;7;8]); | 419 %!error <Abs err 1 exceeds tol 0.5> assert ([2,2,3,3],[1,2,3,4],0.5); |
401 %!error assert ([1,2,3],[1;2;3]); | 420 %!error <Rel err 1 exceeds tol 0.1> assert ([2,2,3,5],[1,2,3,4],-0.1); |
402 %!error assert ([1,2],[1,2,3]); | 421 %!error <Abs err 1 exceeds tol 0> assert ([6;6;7;7],[5;6;7;8]); |
403 %!error assert ([1;2;3],[1;2]); | 422 %!error <Abs err 1 exceeds tol 0.5> assert ([6;6;7;7],[5;6;7;8],0.5); |
423 %!error <Rel err .* exceeds tol 0.1> assert ([6;6;7;7],[5;6;7;8],-0.1); | |
424 %!error <Dimensions don't match> assert ([1,2,3],[1;2;3]); | |
425 %!error <Dimensions don't match> assert ([1,2],[1,2,3]); | |
426 %!error <Dimensions don't match> assert ([1;2;3],[1;2]); | |
427 | |
428 ## matrices | |
404 %!assert ([1,2;3,4],[1,2;3,4]); | 429 %!assert ([1,2;3,4],[1,2;3,4]); |
405 %!error assert ([1,4;3,4],[1,2;3,4]) | 430 %!error <\(1,2\)\s+4\s+2> assert ([1,4;3,4],[1,2;3,4]) |
406 %!error assert ([1,3;2,4;3,5],[1,2;3,4]) | 431 %!error <Dimensions don't match> assert ([1,3;2,4;3,5],[1,2;3,4]) |
407 | 432 %!test # 2-D matrix |
408 ## matrices | |
409 %!test | |
410 %! A = [1 2 3]'*[1,2]; | 433 %! A = [1 2 3]'*[1,2]; |
411 %! assert (A,A); | 434 %! assert (A, A); |
412 %! fail ("assert (A.*(A!=2),A)"); | 435 %! fail ("assert (A.*(A!=2),A)"); |
436 %!test # N-D matrix | |
413 %! X = zeros (2,2,3); | 437 %! X = zeros (2,2,3); |
414 %! Y = X; | 438 %! Y = X; |
415 %! Y (1,2,3) = 1; | 439 %! Y(1,2,3) = 1.5; |
416 %! fail ("assert (X,Y)"); | 440 %! fail ("assert (X,Y)", "\(1,2,3\).*Abs err 1.5 exceeds tol 0"); |
417 | 441 |
418 ## must give a small tolerance for floating point errors on relative | 442 ## must give a small tolerance for floating point errors on relative |
419 %!assert (100+100*eps, 100, -2*eps) | 443 %!assert (100+100*eps, 100, -2*eps) |
420 %!assert (100, 100+100*eps, -2*eps) | 444 %!assert (100, 100+100*eps, -2*eps) |
421 %!error assert (100+300*eps, 100, -2*eps) | 445 %!error <Rel err .* exceeds tol> assert (100+300*eps, 100, -2*eps) |
422 %!error assert (100, 100+300*eps, -2*eps) | 446 %!error <Rel err .* exceeds tol> assert (100, 100+300*eps, -2*eps) |
423 %!error assert (3, [3,3]) | |
424 %!error assert (3, 4) | |
425 | 447 |
426 ## test relative vs. absolute tolerances | 448 ## test relative vs. absolute tolerances |
427 %!test assert (0.1+eps, 0.1, 2*eps); # accept absolute | 449 %!test assert (0.1+eps, 0.1, 2*eps); |
428 %!error assert (0.1+eps, 0.1, -2*eps); # fail relative | 450 %!error <Rel err 2.2204e-15 exceeds tol> assert (0.1+eps, 0.1, -2*eps); |
429 %!test assert (100+100*eps, 100, -2*eps); # accept relative | 451 %!test assert (100+100*eps, 100, -2*eps); |
430 %!error assert (100+100*eps, 100, 2*eps); # fail absolute | 452 %!error <Abs err 2.8422e-14 exceeds tol> assert (100+100*eps, 100, 2*eps); |
453 | |
454 ## Corner case of relative tolerance with 0 divider | |
455 %!error <Abs err 2 exceeds tol 0.1> assert (2, 0, -0.1) | |
456 | |
457 ## Extra checking of inputs when tolerance unspecified. | |
458 %!error <Class single != double> assert (single (1), 1) | |
459 %!error <Class uint8 != uint16> assert (uint8 (1), uint16 (1)) | |
460 %!error <sparse != non-sparse> assert (sparse([1]), [1]) | |
461 %!error <non-sparse != sparse> assert ([1], sparse([1])) | |
462 %!error <complex != real> assert (1+i, 1) | |
463 %!error <real != complex> assert (1, 1+i) | |
431 | 464 |
432 ## exceptional values | 465 ## exceptional values |
433 %!assert ([NaN, NA, Inf, -Inf, 1+eps, eps], [NaN, NA, Inf, -Inf, 1, 0], eps) | 466 %!assert ([NaN, NA, Inf, -Inf, 1+eps, eps], [NaN, NA, Inf, -Inf, 1, 0], eps) |
434 %!error assert (NaN, 1) | 467 |
435 %!error assert ([NaN 1], [1 NaN]) | 468 %!error <'NaN' mismatch> assert (NaN, 1) |
436 %!error assert (NA, 1) | 469 %!error <'NaN' mismatch> assert ([NaN 1], [1 NaN]) |
470 %!test | |
471 %! try | |
472 %! assert ([NaN 1], [1 NaN]); | |
473 %! catch | |
474 %! errmsg = lasterr (); | |
475 %! if (sum (errmsg () == "\n") != 4) | |
476 %! error ("Too many errors reported for NaN assert"); | |
477 %! elseif (strfind (errmsg, "NA")) | |
478 %! error ("NA reported for NaN assert"); | |
479 %! elseif (strfind (errmsg, "Abs err NaN exceeds tol 0")) | |
480 %! error ("Abs err reported for NaN assert"); | |
481 %! endif | |
482 %! end_try_catch | |
483 | |
484 %!error <'NA' mismatch> assert (NA, 1) | |
437 %!error assert ([NA 1]', [1 NA]') | 485 %!error assert ([NA 1]', [1 NA]') |
486 %!test | |
487 %! try | |
488 %! assert ([NA 1]', [1 NA]'); | |
489 %! catch | |
490 %! errmsg = lasterr (); | |
491 %! if (sum (errmsg () == "\n") != 4) | |
492 %! error ("Too many errors reported for NA assert"); | |
493 %! elseif (strfind (errmsg, "NaN")) | |
494 %! error ("NaN reported for NA assert"); | |
495 %! elseif (strfind (errmsg, "Abs err NA exceeds tol 0")) | |
496 %! error ("Abs err reported for NA assert"); | |
497 %! endif | |
498 %! end_try_catch | |
438 %!error assert ([(complex (NA, 1)) (complex (2, NA))], [(complex (NA, 2)) 2]) | 499 %!error assert ([(complex (NA, 1)) (complex (2, NA))], [(complex (NA, 2)) 2]) |
439 %!error assert (-Inf, Inf) | 500 |
440 %!error assert ([-Inf Inf], [Inf -Inf]) | 501 %!error <'Inf' mismatch> assert (-Inf, Inf) |
441 %!error assert (complex (Inf, 0.2), complex (-Inf, 0.2 + 2*eps), eps) | 502 %!error <'Inf' mismatch> assert ([-Inf Inf], [Inf -Inf]) |
503 %!test | |
504 %! try | |
505 %! assert (complex (Inf, 0.2), complex (-Inf, 0.2 + 2*eps), eps); | |
506 %! catch | |
507 %! errmsg = lasterr (); | |
508 %! if (sum (errmsg () == "\n") != 3) | |
509 %! error ("Too many errors reported for Inf assert"); | |
510 %! elseif (strfind (errmsg, "Abs err")) | |
511 %! error ("Abs err reported for Inf assert"); | |
512 %! endif | |
513 %! end_try_catch | |
514 %!error <Abs err> assert (complex (Inf, 0.2), complex (Inf, 0.2 + 2*eps), eps) | |
442 | 515 |
443 ## strings | 516 ## strings |
444 %!assert ("dog", "dog") | 517 %!assert ("dog", "dog") |
445 %!error assert ("dog", "cat") | 518 %!error <Strings don't match> assert ("dog", "cat") |
446 %!error assert ("dog", 3) | 519 %!error <Expected string, but observed number> assert (3, "dog") |
447 %!error assert (3, "dog") | 520 %!error <Class char != double> assert ("dog", [3 3 3]) |
448 %!error assert (cellstr ("dog"), "dog") | 521 %!error <Expected string, but observed cell> assert ({"dog"}, "dog") |
449 %!error assert (cell2struct ({"dog"; 3}, {"pet", "age"}, 1), "dog"); | 522 %!error <Expected string, but observed struct> assert (struct ("dog", 3), "dog") |
450 | |
451 ## structures | |
452 %!shared x,y | |
453 %! x.a = 1; x.b=[2, 2]; | |
454 %! y.a = 1; y.b=[2, 2]; | |
455 %!assert (x, y) | |
456 %!test y.b=3; | |
457 %!error assert (x, y) | |
458 %!error assert (3, x) | |
459 %!error assert (x, 3) | |
460 %!test | |
461 %! # Empty structures | |
462 %! x = resize (x, 0, 1); | |
463 %! y = resize (y, 0, 1); | |
464 %! assert (x, y); | |
465 | 523 |
466 ## cell arrays | 524 ## cell arrays |
525 %!error <Expected cell, but observed double> assert (1, {1}) | |
526 %!error <Dimensions don't match> assert (cell (1,2,3), cell (3,2,1)) | |
527 %!test | |
528 %! x = {{{1}}, 2}; # cell with multiple levels | |
529 %! y = x; | |
530 %! assert (x,y); | |
531 %! y{1}{1}{1} = 3; | |
532 %! fail ("assert (x,y)", "Abs err 2 exceeds tol 0"); | |
533 | |
467 %!test | 534 %!test |
468 %! x = {[3], [1,2,3]; 100+100*eps, "dog"}; | 535 %! x = {[3], [1,2,3]; 100+100*eps, "dog"}; |
469 %! y = x; | 536 %! y = x; |
470 %! assert (x, y); | 537 %! assert (x, y); |
471 %! y = x; y(1,1) = [2]; | 538 %! y = x; y(1,1) = [2]; |
477 %! y = x; y(2,2) = "cat"; | 544 %! y = x; y(2,2) = "cat"; |
478 %! fail ("assert (x, y)"); | 545 %! fail ("assert (x, y)"); |
479 %! y = x; y(1,1) = [2]; y(1,2) = [0, 2, 3]; y(2,1) = 101; y(2,2) = "cat"; | 546 %! y = x; y(1,1) = [2]; y(1,2) = [0, 2, 3]; y(2,1) = 101; y(2,2) = "cat"; |
480 %! fail ("assert (x, y)"); | 547 %! fail ("assert (x, y)"); |
481 | 548 |
482 ## variable tolerance | 549 ## structures |
550 %!error <Expected struct, but observed double> assert (1, struct ("a", 1)) | |
551 %!error <Structure sizes don't match> | |
552 %! x(1,2,3).a = 1; | |
553 %! y(1,2).a = 1; | |
554 %! assert (x,y); | |
555 %!error <Structure sizes don't match> | |
556 %! x(1,2,3).a = 1; | |
557 %! y(3,2,2).a = 1; | |
558 %! assert (x,y); | |
559 %!error <Structure sizes don't match> | |
560 %! x.a = 1; x.b = 1; | |
561 %! y.a = 1; | |
562 %! assert (x,y); | |
563 %!error <'b' is not an expected field> | |
564 %! x.b = 1; | |
565 %! y.a = 1; | |
566 %! assert (x,y); | |
567 | |
568 %!test | |
569 %! x.a = 1; x.b=[2, 2]; | |
570 %! y.a = 1; y.b=[2, 2]; | |
571 %! assert (x, y); | |
572 %! y.b=3; | |
573 %! fail ("assert (x, y)"); | |
574 %! fail ("assert (3, x)"); | |
575 %! fail ("assert (x, 3)"); | |
576 %! ## Empty structures | |
577 %! x = resize (x, 0, 1); | |
578 %! y = resize (y, 0, 1); | |
579 %! assert (x, y); | |
580 | |
581 ## vector of tolerances | |
483 %!test | 582 %!test |
484 %! x = [-40:0]; | 583 %! x = [-40:0]; |
485 %! y1 = (10.^x).*(10.^x); | 584 %! y1 = (10.^x).*(10.^x); |
486 %! y2 = 10.^(2*x); | 585 %! y2 = 10.^(2*x); |
487 %! assert (y1, y2, eps (y1)); | 586 %! assert (y1, y2, eps (y1)); |
488 %! fail ("assert (y1, y2 + eps*1e-70, eps (y1))"); | 587 %! fail ("assert (y1, y2 + eps*1e-70, eps (y1))"); |
588 | |
589 ## Multiple tolerances | |
590 %!test | |
591 %! x = [1 2; 3 4]; | |
592 %! y = [0 -1; 1 2]; | |
593 %! tol = [-0.1 0; -0.2 0.3]; | |
594 %! try | |
595 %! assert (x, y, tol); | |
596 %! catch | |
597 %! errmsg = lasterr (); | |
598 %! if (sum (errmsg () == "\n") != 6) | |
599 %! error ("Incorrect number of errors reported"); | |
600 %! endif | |
601 %! assert (!isempty (regexp (errmsg, '\(1,2\).*Abs err 3 exceeds tol 0\>'))); | |
602 %! assert (!isempty (regexp (errmsg, '\(2,2\).*Abs err 2 exceeds tol 0.3'))); | |
603 %! assert (!isempty (regexp (errmsg, '\(1,1\).*Abs err 1 exceeds tol 0.1'))); | |
604 %! assert (!isempty (regexp (errmsg, '\(2,1\).*Rel err 2 exceeds tol 0.2'))); | |
605 %! end_try_catch | |
489 | 606 |
490 ## test input validation | 607 ## test input validation |
491 %!error assert () | 608 %!error assert () |
492 %!error assert (1,2,3,4) | 609 %!error assert (1,2,3,4) |
493 | 610 |