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
|
/// @file
/// @brief unit test for overflow.h
#include <assert.h>
#include <limits.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
// were we asked to test the fallback C code?
#ifdef SUPPRESS_BUILTINS
#ifdef __GNUC__
#undef __GNUC__
#endif
#ifdef __clang__
#undef __clang__
#endif
#endif
#include <util/overflow.h>
/// a test case
typedef struct {
int operand1; ///< left-hand side
int operand2; ///< right-hand side
bool should_overflow; ///< should addition be expected to overflow?
} testcase_t;
/// cases to run
static const testcase_t TESTS[] = {
{.operand1 = 0, .operand2 = 0},
{.operand1 = 0, .operand2 = 1},
{.operand1 = 0, .operand2 = -1},
{.operand1 = 0, .operand2 = 2},
{.operand1 = 0, .operand2 = -2},
{.operand1 = 0, .operand2 = INT_MAX},
{.operand1 = 0, .operand2 = INT_MIN},
{.operand1 = 0, .operand2 = INT_MAX - 1},
{.operand1 = 0, .operand2 = INT_MIN + 1},
{.operand1 = 1, .operand2 = 0},
{.operand1 = 1, .operand2 = 1},
{.operand1 = 1, .operand2 = -1},
{.operand1 = 1, .operand2 = 2},
{.operand1 = 1, .operand2 = -2},
{.operand1 = 1, .operand2 = INT_MAX, .should_overflow = true},
{.operand1 = 1, .operand2 = INT_MIN},
{.operand1 = 1, .operand2 = INT_MAX - 1},
{.operand1 = 1, .operand2 = INT_MIN + 1},
{.operand1 = -1, .operand2 = 0},
{.operand1 = -1, .operand2 = 1},
{.operand1 = -1, .operand2 = -1},
{.operand1 = -1, .operand2 = 2},
{.operand1 = -1, .operand2 = -2},
{.operand1 = -1, .operand2 = INT_MAX},
{.operand1 = -1, .operand2 = INT_MIN, .should_overflow = true},
{.operand1 = -1, .operand2 = INT_MAX - 1},
{.operand1 = -1, .operand2 = INT_MIN + 1},
{.operand1 = 2, .operand2 = 0},
{.operand1 = 2, .operand2 = 1},
{.operand1 = 2, .operand2 = -1},
{.operand1 = 2, .operand2 = 2},
{.operand1 = 2, .operand2 = -2},
{.operand1 = 2, .operand2 = INT_MAX, .should_overflow = true},
{.operand1 = 2, .operand2 = INT_MIN},
{.operand1 = 2, .operand2 = INT_MAX - 1, .should_overflow = true},
{.operand1 = 2, .operand2 = INT_MIN + 1},
{.operand1 = -2, .operand2 = 0},
{.operand1 = -2, .operand2 = 1},
{.operand1 = -2, .operand2 = -1},
{.operand1 = -2, .operand2 = 2},
{.operand1 = -2, .operand2 = -2},
{.operand1 = -2, .operand2 = INT_MAX},
{.operand1 = -2, .operand2 = INT_MIN, .should_overflow = true},
{.operand1 = -2, .operand2 = INT_MAX - 1},
{.operand1 = -2, .operand2 = INT_MIN + 1, .should_overflow = true},
{.operand1 = INT_MAX, .operand2 = 0},
{.operand1 = INT_MAX, .operand2 = 1, .should_overflow = true},
{.operand1 = INT_MAX, .operand2 = -1},
{.operand1 = INT_MAX, .operand2 = 2, .should_overflow = true},
{.operand1 = INT_MAX, .operand2 = -2},
{.operand1 = INT_MAX, .operand2 = INT_MAX, .should_overflow = true},
{.operand1 = INT_MAX, .operand2 = INT_MIN},
{.operand1 = INT_MAX, .operand2 = INT_MAX - 1, .should_overflow = true},
{.operand1 = INT_MAX, .operand2 = INT_MIN + 1},
{.operand1 = INT_MIN, .operand2 = 0},
{.operand1 = INT_MIN, .operand2 = 1},
{.operand1 = INT_MIN, .operand2 = -1, .should_overflow = true},
{.operand1 = INT_MIN, .operand2 = 2},
{.operand1 = INT_MIN, .operand2 = -2, .should_overflow = true},
{.operand1 = INT_MIN, .operand2 = INT_MAX},
{.operand1 = INT_MIN, .operand2 = INT_MIN, .should_overflow = true},
{.operand1 = INT_MIN, .operand2 = INT_MAX - 1},
{.operand1 = INT_MIN, .operand2 = INT_MIN + 1, .should_overflow = true},
{.operand1 = INT_MAX - 1, .operand2 = 0},
{.operand1 = INT_MAX - 1, .operand2 = 1},
{.operand1 = INT_MAX - 1, .operand2 = -1},
{.operand1 = INT_MAX - 1, .operand2 = 2, .should_overflow = true},
{.operand1 = INT_MAX - 1, .operand2 = -2},
{.operand1 = INT_MAX - 1, .operand2 = INT_MAX, .should_overflow = true},
{.operand1 = INT_MAX - 1, .operand2 = INT_MIN},
{.operand1 = INT_MAX - 1, .operand2 = INT_MAX - 1, .should_overflow = true},
{.operand1 = INT_MAX - 1, .operand2 = INT_MIN + 1},
{.operand1 = INT_MIN + 1, .operand2 = 0},
{.operand1 = INT_MIN + 1, .operand2 = 1},
{.operand1 = INT_MIN + 1, .operand2 = -1},
{.operand1 = INT_MIN + 1, .operand2 = 2},
{.operand1 = INT_MIN + 1, .operand2 = -2, .should_overflow = true},
{.operand1 = INT_MIN + 1, .operand2 = INT_MAX},
{.operand1 = INT_MIN + 1, .operand2 = INT_MIN, .should_overflow = true},
{.operand1 = INT_MIN + 1, .operand2 = INT_MAX - 1},
{.operand1 = INT_MIN + 1, .operand2 = INT_MIN + 1, .should_overflow = true},
};
int main(void) {
for (size_t i = 0; i < sizeof(TESTS) / sizeof(TESTS[0]); ++i) {
const int op1 = TESTS[i].operand1;
const int op2 = TESTS[i].operand2;
int answer;
const bool did_overflow = sadd_overflow(op1, op2, &answer);
const bool should_overflow = TESTS[i].should_overflow;
if (did_overflow != should_overflow) {
fprintf(stderr, "%d + %d should%s have overflowed and it did%s\n", op1,
op2, should_overflow ? "" : " not", did_overflow ? "" : " not");
return EXIT_FAILURE;
}
if (!did_overflow && op1 + op2 != answer) {
fprintf(stderr, "%d + %d is %d but result was %d\n", op1, op2, op1 + op2,
answer);
return EXIT_FAILURE;
}
}
return EXIT_SUCCESS;
}
|