ctest/mytests.c
Tyge Løvset 6f2f65adf1 1. Improved default accuracy handling for real numbers: relative accuracy error. (tol < 0). _TOL still uses absolute error spec.
2. Added ASSERT_NOT_STR(), ASSERT_STRSTR() and ASSERT_NOT_STRSTR() + wide string versions - search for containing string.
3. Added ASSERT_LT(), ASSERT_LE(), ASSERT_GT(), ASSERT_GE() - new integer comparisons functions with useful error reporting.
4. Added ASSERT_FLT_NEAR(), ASSERT_FLT_FAR() - uses float relative accuracy error.
5. Added ASSERT_DBL_LT(), ASSERT_DBL_GT() -  - new double comparisons functions with useful error reporting.

Added some tests. This is a compact and minimum code change to add this functionality.
2023-01-17 11:02:43 +01:00

238 lines
5.0 KiB
C

/* Copyright 2011-2023 Bas van den Berg
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdlib.h>
#include "ctest.h"
// basic test without setup/teardown
CTEST(suite1, test1) {
}
// there are many different ASSERT macro's (see ctest.h)
CTEST(suite1, test2) {
ASSERT_EQUAL(1,2);
}
CTEST(suite2, test1) {
ASSERT_STR("foo", "bar");
}
CTEST(suite3, test3) {
}
// A test suite with a setup/teardown function
// This is converted into a struct that's automatically passed to all tests in the suite
CTEST_DATA(memtest) {
unsigned char* buffer;
};
// Optional setup function for suite, called before every test in suite
CTEST_SETUP(memtest) {
CTEST_LOG("%s() data=%p buffer=%p", __func__, (void*)data, (void*)data->buffer);
data->buffer = (unsigned char*)malloc(1024);
}
// Optional teardown function for suite, called after every test in suite
CTEST_TEARDOWN(memtest) {
CTEST_LOG("%s() data=%p buffer=%p", __func__, (void*)data, (void*)data->buffer);
if (data->buffer) free(data->buffer);
}
// These tests are called with the struct* (named data) as argument
CTEST2(memtest, test1) {
CTEST_LOG("%s() data=%p buffer=%p", __func__, (void*)data, (void*)data->buffer);
}
CTEST2_SKIP(memtest, test3) {
(void)data;
ASSERT_FAIL();
}
CTEST2(memtest, test2) {
CTEST_LOG("%s() data=%p buffer=%p", __func__, (void*)data, (void*)data->buffer);
ASSERT_FAIL();
}
CTEST_DATA(fail) {
int unused;
};
// Asserts can also be used in setup/teardown functions
CTEST_SETUP(fail) {
(void)data;
ASSERT_FAIL();
}
CTEST2(fail, test1) {
(void)data;
}
CTEST_DATA(weaklinkage) {
int number;
};
// This suite has data, but no setup/teardown
CTEST2(weaklinkage, test1) {
(void)data;
CTEST_LOG("%s()", __func__);
}
CTEST2(weaklinkage, test2) {
(void)data;
CTEST_LOG("%s()", __func__);
}
CTEST_DATA(nosetup) {
int value;
};
CTEST_TEARDOWN(nosetup) {
(void)data;
CTEST_LOG("%s()", __func__);
}
CTEST2(nosetup, test1) {
(void)data;
CTEST_LOG("%s()", __func__);
}
// more ASSERT examples
CTEST(ctest, test_assert_str) {
ASSERT_STR("foo", "foo");
ASSERT_STR("foo", "bar");
}
CTEST(ctest, test_assert_equal) {
ASSERT_EQUAL(123, 123);
ASSERT_EQUAL(123, 456);
}
CTEST(ctest, test_assert_not_equal) {
ASSERT_NOT_EQUAL(123, 456);
ASSERT_NOT_EQUAL(123, 123);
}
CTEST(ctest, test_assert_interval) {
ASSERT_INTERVAL(10, 20, 15);
ASSERT_INTERVAL(1000, 2000, 3000);
}
CTEST(ctest, test_assert_null) {
ASSERT_NULL(NULL);
ASSERT_NULL((void*)0xdeadbeef);
}
CTEST(ctest, test_assert_not_null_const) {
ASSERT_NOT_NULL((const char*)"hallo");
}
CTEST(ctest, test_assert_not_null) {
ASSERT_NOT_NULL((void*)0xdeadbeef);
ASSERT_NOT_NULL(NULL);
}
CTEST(ctest, test_assert_true) {
ASSERT_TRUE(1);
ASSERT_TRUE(0);
}
CTEST(ctest, test_assert_false) {
ASSERT_FALSE(0);
ASSERT_FALSE(1);
}
CTEST_SKIP(ctest, test_skip) {
ASSERT_FAIL();
}
CTEST(ctest, test_assert_fail) {
ASSERT_FAIL();
}
/* Test that NULL-strings won't result in segv */
CTEST(ctest, test_null_null) {
ASSERT_STR(NULL, NULL);
}
CTEST(ctest, test_null_string) {
ASSERT_STR(NULL, "shouldfail");
}
CTEST(ctest, test_string_null) {
ASSERT_STR("shouldfail", NULL);
}
CTEST(ctest, test_string_diff_ptrs) {
const char *str = "abc\0abc";
ASSERT_STR(str, str+4);
}
CTEST(ctest, test_large_numbers) {
unsigned long exp = 4200000000u;
ASSERT_EQUAL_U(exp, 4200000000u);
ASSERT_NOT_EQUAL_U(exp, 1200000000u);
}
CTEST(ctest, test_ctest_err) {
CTEST_ERR("error log");
}
CTEST(ctest, test_dbl_near) {
double a = 0.000111;
ASSERT_DBL_NEAR(0.0001, a);
}
CTEST(ctest, test_dbl_near_tol) {
double a = 0.000111;
ASSERT_DBL_NEAR_TOL(0.0001, a, 1e-5); /* will fail */
}
CTEST(ctest, test_dbl_far) {
double a = 1.1;
ASSERT_DBL_FAR(1., a);
ASSERT_DBL_FAR_TOL(1., a, 0.01);
}
CTEST(ctest, test_assert_compare) {
ASSERT_LT(123, 456);
ASSERT_GE(123, 123);
ASSERT_GT(99, 100);
}
CTEST(ctest, test_dbl_near2) {
float a = 0.000001000003f;
ASSERT_FLT_NEAR(0.000001f, a); /* ok, uses float epsilon -1e-5 */
ASSERT_DBL_NEAR_TOL(0.000001, a, -1e-5); /* ok, tol < 0 = relative err (epsilon) */
ASSERT_DBL_NEAR(0.000001, a); /* fail, tol = -1e-12 (epsilon) */
}
CTEST(ctest, test_dbl_compare) {
float a = 0.000001000003f;
ASSERT_DBL_LT(0.000001, a);
ASSERT_DBL_GT(0.000001, a); /* fail */
}
CTEST(ctest, test_str_contains) {
ASSERT_NOT_STR("Hello", "World");
ASSERT_STRSTR("Hello", "ello");
ASSERT_NOT_STRSTR("Hello", "ello");
}