1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246
|
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include "greatest.h"
/* Define a suite, compiled seperately. */
extern SUITE(other_suite);
/* Declare a local suite. */
SUITE(suite);
/* Just test against random ints, to show a variety of results. */
TEST example_test_case(void) {
int r = 0;
ASSERT(1 == 1);
r = rand() % 10;
if (r == 1) SKIP();
ASSERT(r >= 1);
PASS();
}
TEST expect_equal(void) {
int i = 9;
ASSERT_EQ(10, i);
PASS();
}
TEST expect_str_equal(void) {
const char *foo = "foo";
ASSERT_STR_EQ("bar", foo);
PASS();
}
/* A boxed int type, used to show type-specific equality tests. */
typedef struct {
int i;
} boxed_int;
/* Callback used to check whether two boxed_ints are equal. */
static int boxed_int_equal_cb(const void *exp, const void *got, void *udata) {
boxed_int *ei = (boxed_int *)exp;
boxed_int *gi = (boxed_int *)got;
/* udata is not used here, but could be used to specify a comparison
* resolution, a string encoding, or any other state that should be
* passed along to the equal and print callbacks. */
(void)udata;
return (ei->i == gi->i);
}
/* Callback to print a boxed_int, used to produce an
* "Exected X, got Y" failure message. */
static int boxed_int_printf_cb(const void *t, void *udata) {
boxed_int *bi = (boxed_int *)t;
(void)udata;
return printf("{%d}", bi->i);
}
/* The struct that stores the previous two functions' pointers. */
static greatest_type_info boxed_int_type_info = {
boxed_int_equal_cb,
boxed_int_printf_cb,
};
TEST expect_boxed_int_equal(void) {
boxed_int a = {3};
boxed_int b = {3};
boxed_int c = {4};
ASSERT_EQUAL_T(&a, &b, &boxed_int_type_info, NULL); /* succeeds */
ASSERT_EQUAL_T(&a, &c, &boxed_int_type_info, NULL); /* fails */
PASS();
}
TEST expect_int_equal_printing_hex(void) {
int a = 0xba5eba11;
int b = 0xf005ba11;
ASSERT_EQ_FMT(a, b, "0x%08x");
PASS();
}
TEST expect_floating_point_range(void) {
ASSERT_IN_RANGEm("in range", -0.00001, -0.000110, 0.00010);
ASSERT_IN_RANGEm("in range", 0.00001, 0.000110, 0.00010);
ASSERT_IN_RANGE(0.00001, 0.000110, 0.00010);
ASSERT_IN_RANGEm("out of range", 0.00001, 0.000111, 0.00010);
PASS();
}
/* Flag, used to confirm that teardown hook is being called. */
static int teardown_was_called = 0;
TEST teardown_example_PASS(void) {
teardown_was_called = 0;
PASS();
}
TEST teardown_example_FAIL(void) {
teardown_was_called = 0;
FAILm("Using FAIL to trigger teardown callback");
}
TEST teardown_example_SKIP(void) {
teardown_was_called = 0;
SKIPm("Using SKIP to trigger teardown callback");
}
/* Example of a test case that calls another function which uses ASSERT. */
static greatest_test_res less_than_three(int arg) {
ASSERT(arg <3);
PASS();
}
TEST example_using_subfunctions(void) {
CHECK_CALL(less_than_three(1)); /* <3 */
CHECK_CALL(less_than_three(5)); /* </3 */
PASS();
}
/* Example of an ANSI C compatible way to do test cases with
* arguments: they are passed one argument, a pointer which
* should be cast back to a struct with the other data. */
TEST parametric_example_c89(void *closure) {
int arg = *(int *) closure;
ASSERT(arg > 10);
PASS();
}
/* If using C99, greatest can also do parametric tests without
* needing to manually manage a closure. */
#if __STDC_VERSION__ >= 19901L
TEST parametric_example_c99(int arg) {
ASSERT(arg > 10);
PASS();
}
#endif
#if GREATEST_USE_LONGJMP
static greatest_test_res subfunction_with_FAIL_WITH_LONGJMP(int arg) {
if (arg == 0) {
FAIL_WITH_LONGJMPm("zero argument (expected failure)");
}
PASS();
}
static greatest_test_res subfunction_with_ASSERT_OR_LONGJMP(int arg) {
ASSERT_OR_LONGJMPm("zero argument (expected failure)", arg != 0);
PASS();
}
TEST fail_via_FAIL_WITH_LONGJMP(void) {
subfunction_with_FAIL_WITH_LONGJMP(0);
PASS();
}
TEST fail_via_ASSERT_OR_LONGJMP(void) {
subfunction_with_ASSERT_OR_LONGJMP(0);
PASS();
}
#endif
static void trace_setup(void *arg) {
printf("-- in setup callback\n");
teardown_was_called = 0;
(void)arg;
}
static void trace_teardown(void *arg) {
printf("-- in teardown callback\n");
teardown_was_called = 1;
(void)arg;
}
/* Primary test suite. */
SUITE(suite) {
int i=0;
printf("\nThis should have some failures:\n");
for (i=0; i<200; i++) {
RUN_TEST(example_test_case);
}
RUN_TEST(expect_equal);
printf("\nThis should fail:\n");
RUN_TEST(expect_str_equal);
printf("\nThis should fail:\n");
RUN_TEST(expect_boxed_int_equal);
printf("\nThis should fail, printing the mismatched values in hex.\n");
RUN_TEST(expect_int_equal_printing_hex);
printf("\nThis should fail and show floating point values just outside the range.\n");
RUN_TEST(expect_floating_point_range);
/* Set so asserts below won't fail if running in list-only or
* first-fail modes. (setup() won't be called and clear it.) */
teardown_was_called = -1;
/* Add setup/teardown for each test case. */
GREATEST_SET_SETUP_CB(trace_setup, NULL);
GREATEST_SET_TEARDOWN_CB(trace_teardown, NULL);
/* Check that the test-specific teardown hook is called. */
RUN_TEST(teardown_example_PASS);
assert(teardown_was_called);
printf("\nThis should fail:\n");
RUN_TEST(teardown_example_FAIL);
assert(teardown_was_called);
printf("This should be skipped:\n");
RUN_TEST(teardown_example_SKIP);
assert(teardown_was_called);
printf("This should fail, but note the subfunction that failed.\n");
RUN_TEST(example_using_subfunctions);
/* Run a test with one void* argument (which can point to a
* struct with multiple arguments). */
printf("\nThis should fail:\n");
i = 10;
RUN_TEST1(parametric_example_c89, &i);
i = 11;
RUN_TEST1(parametric_example_c89, &i);
/* Run a test, with arguments. ('p' for "parametric".) */
#if __STDC_VERSION__ >= 19901L
printf("\nThis should fail:\n");
RUN_TESTp(parametric_example_c99, 10);
RUN_TESTp(parametric_example_c99, 11);
#endif
#if GREATEST_USE_LONGJMP
RUN_TEST(fail_via_FAIL_WITH_LONGJMP);
RUN_TEST(fail_via_ASSERT_OR_LONGJMP);
#endif
}
/* Add all the definitions that need to be in the test runner's main file. */
GREATEST_MAIN_DEFS();
int main(int argc, char **argv) {
GREATEST_MAIN_BEGIN(); /* command-line arguments, initialization. */
RUN_SUITE(suite);
RUN_SUITE(other_suite);
GREATEST_MAIN_END(); /* display results */
}
|