// testcase() needs to be defined before running this, // with, possibly, -run testcase.mata- // code below will attempt to define -noisy_sqrt()-, // -meta_test()-, and a variable -meta-, so these // should not already be defined mata numeric noisy_sqrt(numeric a, | real scalar noise) { real scalar nrows, ncols numeric matrix noise_mat if (args() == 1) { noise = 1e-5 } nrows = rows(a) ncols = cols(a) noise_mat = rnormal(nrows, ncols, 0, noise) if (eltype(a) == "complex") { noise_mat = noise_mat :+ (rnormal(nrows, ncols, 0, noise) * 1i) } return(sqrt(a) :+ noise_mat) } // Create a testcase to be tested. The instance of it will be called "meta". // The name is needed for any assert_method_error() calls. class meta_test extends testcase { real scalar setup_count, setup_once_count real scalar teardown_count, teardown_once_count void new() virtual void setup() virtual void setup_once() virtual void teardown() virtual void teardown_once() void unexp_errors() void test_capture() void test_assert() void test_assert_error() void test_method_capture() void test_assert_method_error() void test_assert_equal() void test_assert_unequal() void test_assert_all() void test_assert_any() void test_assert_equal_contents() void test_assert_close() void intentional_errors() void intentional_failures() void setup_teardown_counts() void simple_func() } void meta_test::new() { this.setup_count = 0 this.setup_once_count = 0 this.teardown_count = 0 this.teardown_once_count = 0 } // Define setup(), teardown(), setup_once(), teardown_once(). // At the end of testing it will be verified that each ran as // many times as expected. void meta_test::setup() { this.setup_count = this.setup_count + 1 } void meta_test::setup_once() { this.setup_once_count = this.setup_once_count + 1 } void meta_test::teardown() { this.teardown_count = this.teardown_count + 1 } void meta_test::teardown_once() { this.teardown_once_count = this.teardown_once_count + 1 } void meta_test::unexp_errors() { // no args allowed in run() this.assert_method_error(3001, "meta", "run", &0) // undefined test name this.noisy_capture = 0 this.assert(this.__run_method("no_such_test") == 3000) this.noisy_capture = 1 } void meta_test::test_capture() { real colvector score real scalar testnum testnum = this.__testnum // __capture() takes two arguments: // 1. pointer(function) scalar func_ptr // 2. pointer vector (or zero-dim matrix) arg_ptrs this.assert_method_error( 3001, "meta", "__capture",(&(&noisy_sqrt())) ) this.assert_method_error( 3001, "meta", "__capture", (&(&noisy_sqrt()), &(&0), &(&0)) ) this.assert_equal(this.__capture(&noisy_sqrt(), &0), 0) this.assert_equal(this.__capture(&noisy_sqrt(), &"blah"), 3251) } void meta_test::test_assert() { real colvector score real scalar testnum testnum = this.__testnum // assert_error() takes four arguments: // 1. real scalar err_num // 2. pointer(function) scalar func_ptr // 3. pointer vector (or zero-dim matrix) arg_ptrs this.assert_method_error( 3001, "meta", "assert_error", (&0, &(&noisy_sqrt())) ) this.assert_method_error( 3001, "meta", "assert_error", (&0, &(&noisy_sqrt()), &(&J(0,0,NULL)), &(&0)) ) this.assert_error(3251, &noisy_sqrt(), &"blah") score = this.__pass_fail_error this.assert_error(0, &noisy_sqrt(), &"blah") if (score[testnum,1] == this.__pass_fail_error[testnum,1] && score[testnum,2] + 1 == this.__pass_fail_error[testnum,2]) { this.__pass_fail_error[testnum, 1..3] = score[testnum, 1..3] + (1, 0, 0) } else { this.__pass_fail_error[testnum, 1..3] = score[testnum, 1..3] + (0, 1, 0) } } void meta_test::test_assert_error() { real colvector score real scalar testnum testnum = this.__testnum // assert_error() takes four arguments: // 1. real scalar err_num // 2. pointer(function) scalar func_ptr // 3. optional pointer vector (or zero-dim matrix) arg_ptrs this.assert_method_error( 3001, "meta", "assert_error", (&0, &(&noisy_sqrt()), &(&J(0,0,NULL)), &(&0)) ) this.assert_error(3251, &noisy_sqrt(), &"blah") // assert_error allows missing error number in case you want to test // for error, but don't know the error number this.assert_error(., &noisy_sqrt(), &"blah") // assert_error allows error number zero for no error this.assert_error(0, &noisy_sqrt(), &1) // this is an intentional failure, so will leave an error message, but // the error message will only print if there are other errors here score = this.__pass_fail_error this.assert_error(0, &noisy_sqrt(), &"blah") if (score[testnum,1] == this.__pass_fail_error[testnum,1] && score[testnum,2] + 1 == this.__pass_fail_error[testnum,2]) { this.__pass_fail_error[testnum, 1..3] = score[testnum, 1..3] + (1, 0, 0) } else { this.__pass_fail_error[testnum, 1..3] = score[testnum, 1..3] + (0, 1, 0) } // this is an intentional failure, so will leave an error message, but // the error message will only print if there are other errors here score = this.__pass_fail_error this.assert_error(., &noisy_sqrt(), &1) if (score[testnum,1] == this.__pass_fail_error[testnum,1] && score[testnum,2] + 1 == this.__pass_fail_error[testnum,2]) { this.__pass_fail_error[testnum, 1..3] = score[testnum, 1..3] + (1, 0, 0) } else { this.__pass_fail_error[testnum, 1..3] = score[testnum, 1..3] + (0, 1, 0) } } void meta_test::test_method_capture() { // __method_capture() takes three arguments: // 1. string scalar class_name // 2. string scalar func_name // 3. pointer vector (or zero-dim matrix) arg_ptrs // missing third arg for __method_capture this.assert_method_error( 3001, "meta", "__method_capture", (&"meta", &"simple_func") ) // too many args given to __method_capture this.assert_method_error( 3001, "meta", "__method_capture", (&"meta", &"simple_func", &(&0), &(&0)) ) this.assert_equal(this.__method_capture("meta", "simple_func", J(0,0,NULL)), 0) this.assert_equal(this.__method_capture("meta", "simple_func", &"blah"), 3001) } void meta_test::test_assert_method_error() { real colvector score real scalar testnum testnum = this.__testnum // assert_method_error() takes four arguments: // 1. real scalar err_num // 2. string scalar class_name // 3. string scalar func_name // 4. optional pointer vector (or zero-dim matrix) arg_ptrs this.assert_method_error( 3001, "meta", "assert_method_error", (&"meta", &"simple_func") ) this.assert_method_error( 3001, "meta", "assert_method_error", (&0, &"meta", &"simple_func", &(&0), &(&0)) ) // assert_method_error allows missing error number in case you want // to test for error, but don't know the error number this.assert_method_error( ., "meta", "assert_method_error", (&0, &"meta", &"simple_func", &(&0), &(&0)) ) // assert_error allows error number zero for no error this.assert_method_error(0, "meta", "simple_func", J(0,0,.)) // The next test should add one to pass _and_ fail, since it involves // two calls to assert_method_error(). If that happens, just count that // as one pass. score = this.__pass_fail_error this.assert_method_error( 0, "meta", "assert_method_error", (&1111, &"meta", &"simple_func", &J(0,0,NULL)) ) if (score[testnum,1] + 1 == this.__pass_fail_error[testnum,1] && score[testnum,2] + 1 == this.__pass_fail_error[testnum,2]) { this.__pass_fail_error[testnum, 1..3] = score[testnum, 1..3] + (1, 0, 0) } else { this.__pass_fail_error[testnum, 1..3] = score[testnum, 1..3] + (0, 1, 0) } } void meta_test::test_assert_equal() { real colvector score real scalar testnum testnum = this.__testnum // assert_close() takes one arguments, which must be numeric this.assert_method_error(3001, "meta", "assert_unequal", &3) this.assert_method_error(3001, "meta", "assert_unequal", (&3, &4, &1)) // check that assert_unequal() passes when it should // and fails when it should this.assert_equal(1, 1 + 0i) this.assert_equal("blah", "b" + "l" + "a" + "h") this.assert_equal((1, 0 + 0i \ 0, 1), I(2)) score = this.__pass_fail_error this.assert_equal((1, 0 \ 0, 1), (1, 0 \ 1, 1)) if (score[testnum,1] == this.__pass_fail_error[testnum,1] && score[testnum,2] + 1 == this.__pass_fail_error[testnum,2]) { this.__pass_fail_error[testnum, 1..3] = score[testnum, 1..3] + (1, 0, 0) } else { this.__pass_fail_error[testnum, 1..3] = score[testnum, 1..3] + (0, 1, 0) } } void meta_test::test_assert_unequal() { real colvector score real scalar testnum testnum = this.__testnum // assert_close() takes one arguments, which must be numeric this.assert_method_error(3001, "meta", "assert_unequal", &3) this.assert_method_error(3001, "meta", "assert_unequal", (&3, &4, &1)) // check that assert_unequal() passes when it should // and fails when it should this.assert_unequal(NULL, 10) this.assert_unequal("blah", 8) this.assert_unequal((1, 0 \ 0, 1), (0, 1 \ 1, 0)) this.assert_unequal((1, 0 \ 0, 1), (1, 0)) score = this.__pass_fail_error this.assert_unequal(1, 1 + 0i) if (score[testnum,1] == this.__pass_fail_error[testnum,1] && score[testnum,2] + 1 == this.__pass_fail_error[testnum,2]) { this.__pass_fail_error[testnum, 1..3] = score[testnum, 1..3] + (1, 0, 0) } else { this.__pass_fail_error[testnum, 1..3] = score[testnum, 1..3] + (0, 1, 0) } } void meta_test::test_assert_all() { real colvector score real scalar testnum testnum = this.__testnum // assert_close() takes one argument, which must be numeric this.assert_method_error(3001, "meta", "assert_all", J(0,0,NULL)) this.assert_method_error(3001, "meta", "assert_all", (&3, &4)) // check that assert_all() passes when it should // and fails when it should this.assert_all((1, 1, 1, 1 \ 1, 1, 1, 1)) this.assert_all((1, 1, 1, 1)) this.assert_all(1) score = this.__pass_fail_error this.assert_all((1, 1, 1, 1 \ 1, 0, 1, 1)) if (score[testnum,1] == this.__pass_fail_error[testnum,1] && score[testnum,2] + 1 == this.__pass_fail_error[testnum,2]) { this.__pass_fail_error[testnum, 1..3] = score[testnum, 1..3] + (1, 0, 0) } else { this.__pass_fail_error[testnum, 1..3] = score[testnum, 1..3] + (0, 1, 0) } } void meta_test::test_assert_any() { real colvector score real scalar testnum testnum = this.__testnum // assert_close() takes one argument, which must be numeric this.assert_method_error(3001, "meta", "assert_any", J(0,0,NULL)) this.assert_method_error(3001, "meta", "assert_any", (&3, &4)) // check that assert_any() passes when it should // and fails when it should this.assert_any((0, 0, 1, 0 \ 0, 0, 0, 0)) this.assert_any((0, 0, 1, 0)) this.assert_any(1) score = this.__pass_fail_error this.assert_any((0, 0, 0, 0 \ 0, 0, 0, 0)) if (score[testnum,1] == this.__pass_fail_error[testnum,1] && score[testnum,2] + 1 == this.__pass_fail_error[testnum,2]) { this.__pass_fail_error[testnum, 1..3] = score[testnum, 1..3] + (1, 0, 0) } else { this.__pass_fail_error[testnum, 1..3] = score[testnum, 1..3] + (0, 1, 0) } } void meta_test::test_assert_equal_contents() { transmorphic a, b, A, B string scalar astr, bstr real scalar testnum testnum = this.__testnum // assert_close() takes two or three arguments and // all args must be numeric this.assert_method_error(3001, "meta", "assert_equal_contents", (&3)) this.assert_method_error(3001, "meta", "assert_equal_contents", (&3, &4, &1, &2)) // check that assert_close() passes when it should // and fails when it should // pass //-------- // real a = (1, 1e-6 \ -1e-6, -10) b = (-10, 1, 1e-6, -1e-6) this.assert_equal_contents(a, b) // string a = ("a", "b" \ "c", "d" \ "a", "d") b = ("c", "d", "d", "a", "a", "b") this.assert_equal_contents(a, b) this.assert_equal_contents(a, ("a" \ "b" \ "c" \ "d" \ "a" \ "d")) this.assert_equal_contents(a, ("a", "b", "c", "d"), 0) this.assert_equal_contents(a, ("a" \ "b" \ "c" \ "d"), 0) // real and "complex" real a = (0, 1 \ 2, 3 \ 1, 1) b = (2 + 0i, 1 + 0i, 3 + 0i, 0, 1, 1 + 0i) this.assert_equal_contents(a, b) this.assert_equal_contents(a, (0 + 0i, 1 + 0i, 2 + 0i, 3 + 0i), 0) // complex a = (0, 1 + 12i \ 0.2 + 3.5i, 3 \ 1, 1) b = (0.2 + 3.5i, 1 + 0i, 3 + 0i, 0, 1, 1 + 12i) this.assert_equal_contents(a, b) // pointer astr = "a" bstr = "b" a = (&astr, &bstr \ &astr, &bstr) b = (&astr, &astr, &bstr, &bstr) this.assert_equal_contents(a, b) this.assert_equal_contents(a, (&bstr, &astr), 0) // struct A = (asarray_create(), asarray_create() \ asarray_create(), asarray_create()) B = (asarray_create(), asarray_create(), asarray_create(), asarray_create()) this.assert_equal_contents(A[1,1], B[1]) this.assert_equal_contents(A, B) asarray(A[2,1], "a", 1) asarray(A[2,1], "b", 2) asarray(B[3], "a", 10) asarray(B[3], "b", 20) A[2,1] = B[3] this.assert_equal_contents(A, B) B = (B , asarray_create()) this.assert_equal_contents(A, B, 0) // fail //-------- // covered in this.intentional_failures() // error //-------- // covered in this.intentional_errors() } void meta_test::test_assert_close() { real colvector score real matrix a, b complex matrix c, d real scalar testnum testnum = this.__testnum // assert_close() takes two or three arguments and // all args must be numeric this.assert_method_error(3001, "meta", "assert_close", (&3)) this.assert_method_error(3001, "meta", "assert_close", (&3, &4, &1, &2)) // check that assert_close() passes when it should // and fails when it should //real a = (1, 1e-6 \ -1e-6, -10) b = a :+ 1e-12 this.assert_close(a, b) score = this.__pass_fail_error this.assert_close(a, b, 1e-16) if (score[testnum,1] == this.__pass_fail_error[testnum,1] && score[testnum,2] + 1 == this.__pass_fail_error[testnum,2]) { this.__pass_fail_error[testnum, 1..3] = score[testnum, 1..3] + (1, 0, 0) } else { this.__pass_fail_error[testnum, 1..3] = score[testnum, 1..3] + (0, 1, 0) } score = this.__pass_fail_error b = a :+ 1e-10 this.assert_close(a, b) if (score[testnum,1] == this.__pass_fail_error[testnum,1] && score[testnum,2] + 1 == this.__pass_fail_error[testnum,2]) { this.__pass_fail_error[testnum, 1..3] = score[testnum, 1..3] + (1, 0, 0) } else { this.__pass_fail_error[testnum, 1..3] = score[testnum, 1..3] + (0, 1, 0) } // complex c = (1 + 1i, 1e-6 \ -1e-6 - 1i, -10) d = c :+ 1e-12 this.assert_close(c, d) score = this.__pass_fail_error this.assert_close(c, d, 1e-16) if (score[testnum,1] == this.__pass_fail_error[testnum,1] && score[testnum,2] + 1 == this.__pass_fail_error[testnum,2]) { this.__pass_fail_error[testnum, 1..3] = score[testnum, 1..3] + (1, 0, 0) } else { this.__pass_fail_error[testnum, 1..3] = score[testnum, 1..3] + (0, 1, 0) } score = this.__pass_fail_error d = c :+ 1e-10 this.assert_close(c, d) if (score[testnum,1] == this.__pass_fail_error[testnum,1] && score[testnum,2] + 1 == this.__pass_fail_error[testnum,2]) { this.__pass_fail_error[testnum, 1..3] = score[testnum, 1..3] + (1, 0, 0) } else { this.__pass_fail_error[testnum, 1..3] = score[testnum, 1..3] + (0, 1, 0) } } void meta_test::intentional_errors() { this.assert("blah") this.assert(1i) this.assert((1, 1)) this.assert_error("no", &noisy_sqrt(), &J(1, 1, 1)) this.assert_error(1i, &noisy_sqrt(), &J(1, 1, 1)) this.assert_error((30, 20), &noisy_sqrt(), &J(1, 1, 1)) this.assert_error(3200, "blah", &J(1, 1, 1)) this.assert_error(3200, (&noisy_sqrt(), &noisy_sqrt()), &J(1, 1, 1)) this.assert_error(3200, &noisy_sqrt(), J(3,1,1)) this.assert_error(3200, &noisy_sqrt(), J(3,3,NULL)) this.assert_method_error("no", "meta", "simple_func") this.assert_method_error(1i, "meta", "simple_func") this.assert_method_error((30, 20), "meta", "simple_func") this.assert_method_error(3200, &"meta", "simple_func") this.assert_method_error(3200, ("meta", "meta"), "simple_func") this.assert_method_error(3200, "meta", &"simple_func") this.assert_method_error(3200, "meta", ("simple_func", "simple_func")) this.assert_method_error(3200, "meta", "simple_func", J(1,1,1)) this.assert_method_error(3200, "meta", "simple_func", J(3,3,NULL)) // assert_equal() and assert_unequal() allow any eltype and orgtype this.assert_all("blah") this.assert_all((1, 1 + 1i, 1i)) this.assert_any("blah") this.assert_any((0, 1i, 0)) this.assert_close("blah", 3) this.assert_close(3, "blah") this.assert_close(3, 3, "blah") this.assert_close(3, 3, 1i * 1e-12) this.assert_close(3, 3, (1e-12, 1e-12)) this.assert_equal_contents(10, testcase()) this.assert_equal_contents(testcase(), 10) // make sure everything above leads to error ::assert(this.__pass_fail_error[this.__testnum, 1..3] == (0, 0, 30)) } void meta_test::intentional_failures() { real matrix a, b transmorphic A, B this.assert_error(0, &noisy_sqrt(), &"blah") this.assert_method_error(0, "meta", "simple_func", &"blah") this.assert_equal((1, 0 \ 0, 1), (1, 0 \ 1, 1)) this.assert_equal((1, 0 \ 0, 1), "blah") this.assert_equal((1, 0 \ 0, 1), (1, 0)) this.assert_equal((1, 0, 0, 1), (1, 0, 0, 1)') this.assert_unequal(1, 1 + 0i) this.assert_all((1, 1, 1, 1 \ 1, 0, 1, 1)) this.assert_any((0, 0, 0, 0 \ 0, 0, 0, 0)) a = (1, 1e-6 \ -1e-6, -10) b = a :+ 1e-10 this.assert_close(a, b) this.assert_close(a, (1, 1e-6)) this.assert_equal_contents((9, 10), (10, 11)) this.assert_equal_contents((9, 10), (9, 10, 11)) this.assert_equal_contents((9, 10, 11), (9, 10)) this.assert_equal_contents((9, 11), (9, 10)) this.assert_equal_contents((9, 10), (9, 10, 11), 0) this.assert_equal_contents((9, 10), (9, 10, 10)) this.assert_equal_contents((9, 9, 10), (9, 10, 10)) this.assert_equal_contents((9, 10), (9, 10 + 1i)) this.assert_equal_contents((9, 10), (&9, &10)) this.assert_equal_contents(10, asarray_create()) this.assert_equal_contents(asarray_create(), 10) A = (asarray_create(), asarray_create() \ asarray_create(), asarray_create()) B = (asarray_create(), asarray_create(), asarray_create(), asarray_create()) asarray(A[2,1], "a", 1) asarray(A[2,1], "b", 2) asarray(B[3], "a", 10) asarray(B[3], "b", 20) this.assert_equal_contents(A, B) A[2,1] = B[3] B = (B , asarray_create()) this.assert_equal_contents(A, B) // try to get failure in different part of code B = (asarray_create(), asarray_create(), asarray_create(), B) this.assert_equal_contents(A, B) // make sure everything above leads to failure ::assert(this.__pass_fail_error[this.__testnum, 1..3] == (0, 25, 0)) } void meta_test::setup_teardown_counts() { real scalar testnum testnum = this.__testnum this.assert(this.setup_count == testnum) this.assert(this.setup_once_count == 1) this.assert(this.teardown_count == testnum - 1) this.assert(this.teardown_once_count == 0) // teardown() and teardown_once() need post-test checks; see below } // just a simple function for testing void meta_test::simple_func() { return } meta = meta_test() meta.name = "meta" meta.test_names = ( "unexp_errors", "test_capture", "test_assert_error", "test_method_capture", "test_assert_method_error", "test_assert_equal", "test_assert_unequal", "test_assert_all", "test_assert_any", "test_assert_equal_contents", "test_assert_close", "intentional_errors", "intentional_failures", "setup_teardown_counts" ) meta.run() // need post-test asserts to check that teardown() & teardown_once() // occurred the expected number of times assert(meta.teardown_count == length(meta.test_names)) assert(meta.teardown_once_count == 1) // drop meta, put errors in setup(), teardown(), etc mata drop meta void meta_test::setup_once() { noisy_sqrt() } void meta_test::setup() { noisy_sqrt() } void meta_test::teardown() { noisy_sqrt() } void meta_test::teardown_once() { noisy_sqrt() } meta = meta_test() meta.name = "meta" meta.test_names = ( "test_assert_all", "test_assert_any" ) meta.exit_setup_error = 0 meta.exit_teardown_error = 0 meta.run() meta.exit_setup_error = 1 meta.exit_teardown_error = 1 meta.run() // clean up mata drop noisy_sqrt() mata drop meta mata drop meta_test() end