#include "vtest.h"
static void check_result(const irop_t *, const test_data_t *);
-static void run_tests(const irop_t *, test_data_t *, unsigned, uint64_t *,
- unsigned, uint64_t *);
+static void run_tests(const irop_t *, test_data_t *);
+static void run_shift_tests(const irop_t *, test_data_t *);
static int is_shift_op(IROp);
void
test_binary_op(const irop_t *op, test_data_t *data)
{
- opnd_t *opnd_l = &data->opnds[0];
-
- switch (opnd_l->type) {
- case Ity_I1: {
- uint64_t values[] = { 0, 1 };
-
- run_tests(op, data, NUM_EL(values), values, NUM_EL(values), values);
- break;
- }
+ if (is_shift_op(op->op))
+ run_shift_tests(op, data);
+ else
+ run_tests(op, data);
+}
- case Ity_I8: {
- uint64_t values[] = { 0, 1, 2, UINT8_MAX - 1, UINT8_MAX };
- uint64_t shifts[] = { 0, 1, 2, 6, 7 };
- if (is_shift_op(op->op))
- run_tests(op, data, NUM_EL(values), values, NUM_EL(shifts), shifts);
- else
- run_tests(op, data, NUM_EL(values), values, NUM_EL(values), values);
- break;
- }
+static void
+run_selected_tests(const irop_t *op, test_data_t *data)
+{
+ opnd_t *opnd_l = &data->opnds[0];
+ opnd_t *opnd_r = &data->opnds[1];
+ unsigned num_val_l, num_val_r;
+ const uint64_t *values_l = get_selected_values(opnd_l->type, &num_val_l);
+ const uint64_t *values_r = get_selected_values(opnd_r->type, &num_val_r);
- case Ity_I16: {
- uint64_t values[] = { 0, 1, 2, UINT16_MAX - 1, UINT16_MAX };
- uint64_t shifts[] = { 0, 1, 2, 14, 15 };
+ for (unsigned i = 0; i < num_val_l; ++i) {
+ opnd_l->value = values_l[i];
+ for (unsigned j = 0; j < num_val_r; ++j) {
+ opnd_r->value = values_r[j];
- if (is_shift_op(op->op))
- run_tests(op, data, NUM_EL(values), values, NUM_EL(shifts), shifts);
- else
- run_tests(op, data, NUM_EL(values), values, NUM_EL(values), values);
- break;
+ valgrind_execute_test(op, data);
+ check_result(op, data);
+ }
}
+}
- case Ity_I32: {
- uint64_t values[] = { 0, 1, 2, UINT32_MAX - 1, UINT32_MAX };
- uint64_t shifts[] = { 0, 1, 2, 30, 31 };
-
- if (is_shift_op(op->op))
- run_tests(op, data, NUM_EL(values), values, NUM_EL(shifts), shifts);
- else
- run_tests(op, data, NUM_EL(values), values, NUM_EL(values), values);
- break;
- }
- case Ity_I64: {
- uint64_t values[] = { 0, 1, 2, UINT64_MAX - 1, UINT64_MAX };
- uint64_t shifts[] = { 0, 1, 2, 62, 63 };
+/* Test with pseudo-random numbers */
+static void
+run_random_tests(const irop_t *op, test_data_t *data)
+{
+ opnd_t *opnd_l = &data->opnds[0];
+ opnd_t *opnd_r = &data->opnds[1];
- if (is_shift_op(op->op))
- run_tests(op, data, NUM_EL(values), values, NUM_EL(shifts), shifts);
- else
- run_tests(op, data, NUM_EL(values), values, NUM_EL(values), values);
- break;
- }
+ for (unsigned i = 0; i < num_random_tests; ++i) {
+ opnd_l->value = get_random_value(opnd_l->type);
+ opnd_r->value = get_random_value(opnd_r->type);
- default:
- panic(__func__);
+ valgrind_execute_test(op, data);
+ check_result(op, data);
}
}
+/* OP is a shift operator. */
static void
-run_tests(const irop_t *op, test_data_t *data, unsigned num_val_l,
- uint64_t *values_l, unsigned num_val_r, uint64_t *values_r)
+run_shift_tests(const irop_t *op, test_data_t *data)
{
opnd_t *opnd_l = &data->opnds[0];
opnd_t *opnd_r = &data->opnds[1];
+ unsigned num_shiftee;
+ const uint64_t *shiftee = get_selected_values(opnd_l->type, &num_shiftee);
+ unsigned max_shift_amount = bitsof_irtype(opnd_r->type) - 1;
- for (unsigned i = 0; i < num_val_l; ++i) {
- opnd_l->value = values_l[i];
- for (unsigned j = 0; j < num_val_r; ++j) {
- opnd_r->value = values_r[j];
+ /* Shift selected values with all possible shift amounts */
+ for (unsigned i = 0; i < num_shiftee; ++i) {
+ opnd_l->value = shiftee[i];
+ for (unsigned j = 0; j < max_shift_amount; ++j) {
+ opnd_r->value = j;
valgrind_execute_test(op, data);
check_result(op, data);
}
}
+
+ /* Shift random values with random shift amounts */
+ for (unsigned i = 0; i < num_random_tests; ++i) {
+ opnd_l->value = get_random_value(opnd_l->type);
+ opnd_r->value = get_random_value(opnd_r->type) & max_shift_amount;
+
+ valgrind_execute_test(op, data);
+ check_result(op, data);
+ }
+}
+
+
+static void
+run_tests(const irop_t *op, test_data_t *data)
+{
+ run_selected_tests(op, data);
+ run_random_tests(op, data);
}
prog: iropt-test
-#args: -v -v
+#args: -v -v -r10
+args: -r100
vgopts: -q --vex-guest-chase=no
static test_data_t *new_test_data(const irop_t *);
int verbose = 0;
+unsigned num_random_tests;
int
main(int argc, char *argv[])
{
assert(sizeof(long long) == 8);
+ assert(RAND_MAX == INT32_MAX);
for (int i = 1; i < argc; ++i) {
if (strcmp(argv[i], "-v") == 0)
++verbose;
- else if (strcmp(argv[i], "--help") == 0) {
+ else if (strncmp(argv[i], "-r", 2) == 0) {
+ num_random_tests = atoi(argv[i] + 2);
+ } else if (strcmp(argv[i], "--help") == 0) {
printf("\niropt-test [ -v | --help ]\n");
+ printf("\n\t -rNUM number of random tests per IRop\n");
printf("\n\t -v verbose mode; shows IROps being tested\n");
printf("\n\t -v -v verbose mode, extreme edition\n\n");
return 0;
const irop_t *op = irops +i;
if (verbose)
- printf("\nTesting operator %s\n", op->name);
+ printf("Testing operator %s\n", op->name);
test_data_t *data = new_test_data(op);
*/
#include <stdio.h> // printf
+#include <stdlib.h> // rand
#include <stdint.h> // UINT64_MAX
#include "vtest.h"
static void check_result(const irop_t *, const test_data_t *);
-static void run_tests(const irop_t *, test_data_t *, unsigned, uint64_t *);
+static void run_selected_tests(const irop_t *, test_data_t *);
+static void run_random_tests(const irop_t *, test_data_t *);
static uint64_t left(uint64_t, unsigned);
static uint32_t popcount(uint64_t);
opnd_t *opnd = &data->opnds[0];
switch (opnd->type) {
- case Ity_I1: {
- uint64_t values[] = { 0, 1 };
-
- run_tests(op, data, NUM_EL(values), values);
- break;
- }
-
+ case Ity_I1:
case Ity_I8: {
- uint64_t values[] = { 0, 1, 2, UINT8_MAX - 1, UINT8_MAX };
-
- run_tests(op, data, NUM_EL(values), values);
- break;
- }
-
- case Ity_I16: {
- uint64_t values[] = { 0, 1, 2, UINT16_MAX - 1, UINT16_MAX,
- /* and for the benefit of Iop_16HIto8: */
- 1 << 8, 2 << 8, UINT8_MAX << 8
- };
-
- run_tests(op, data, NUM_EL(values), values);
- break;
- }
-
- case Ity_I32: {
- uint64_t values[] = { 0, 1, 2, UINT32_MAX - 1, UINT32_MAX,
- /* and for the benefit of Iop_32HIto16: */
- 1 << 16, 2 << 16, (uint64_t)UINT16_MAX << 16
- };
- run_tests(op, data, NUM_EL(values), values);
+ /* Exhaustive */
+ unsigned max = (1 << bitsof_irtype(opnd->type)) - 1;
+ for (unsigned i = 0; i <= max; ++i) {
+ opnd->value = i;
+
+ valgrind_execute_test(op, data);
+ check_result(op, data);
+ }
break;
}
- case Ity_I64: {
- uint64_t values[] = { 0, 1, 2, UINT64_MAX - 1, UINT64_MAX,
- /* and for the benefit of Iop_64HIto32: */
- (uint64_t)1 << 32, (uint64_t)2 << 32, (uint64_t)UINT32_MAX << 32
- };
- run_tests(op, data, NUM_EL(values), values);
+ case Ity_I16:
+ case Ity_I32:
+ case Ity_I64:
+ run_selected_tests(op, data);
+ run_random_tests(op, data);
break;
- }
default:
panic(__func__);
static void
-run_tests(const irop_t *op, test_data_t *data, unsigned num_val,
- uint64_t *values)
+run_selected_tests(const irop_t *op, test_data_t *data)
{
opnd_t *opnd = &data->opnds[0];
+ unsigned num_val;
+ const uint64_t *values = get_selected_values(opnd->type, &num_val);
for (unsigned i = 0; i < num_val; ++i) {
opnd->value = values[i];
}
+/* Test with pseudo-random numbers */
+static void
+run_random_tests(const irop_t *op, test_data_t *data)
+{
+ opnd_t *opnd = &data->opnds[0];
+
+ for (unsigned i = 0; i < num_random_tests; ++i) {
+ opnd->value = get_random_value(opnd->type);
+
+ valgrind_execute_test(op, data);
+ check_result(op, data);
+ }
+}
+
+
/* Check the result of a unary operation. */
static void
check_result(const irop_t *op, const test_data_t *data)
panic(__func__);
}
}
+
+
+uint64_t
+get_random_value(IRType type)
+{
+ uint64_t val = rand();
+
+ switch (type) {
+ case Ity_I1: return val & 0x1;
+ case Ity_I8: return val & UINT8_MAX;
+ case Ity_I16: return val & UINT16_MAX;
+ case Ity_I32: return val & UINT32_MAX;
+ case Ity_I64:
+ /* Note, that RAND_MAX == INT32_MAX. Therefore, simply concatenating
+ two rand() values would never produce a value with MSB == 1 */
+ val <<= (32 + 1);
+ val |= rand() << 1;
+ val |= rand() & 0x1;
+ return val;
+
+ default:
+ panic(__func__);
+ }
+}
+
+
+const uint64_t *
+get_selected_values(IRType type, unsigned *num_val)
+{
+ static const uint64_t values_1bit[] = { 0, 1 };
+ static const uint64_t values_8bit[] = { 0, 1, 2,
+ UINT8_MAX - 1, UINT8_MAX };
+ static const uint64_t values_16bit[] = { 0, 1, 2,
+ UINT8_MAX - 1, UINT8_MAX, UINT8_MAX + 1,
+ UINT16_MAX - 1, UINT16_MAX };
+ static const uint64_t values_32bit[] = { 0, 1, 2,
+ UINT8_MAX - 1, UINT8_MAX, UINT8_MAX + 1,
+ UINT16_MAX - 1, UINT16_MAX, UINT16_MAX + 1,
+ UINT32_MAX - 1, UINT32_MAX };
+ static const uint64_t values_64bit[] = { 0, 1, 2,
+ UINT8_MAX - 1, UINT8_MAX, UINT8_MAX + 1,
+ UINT16_MAX - 1, UINT16_MAX, UINT16_MAX + 1,
+ UINT32_MAX - 1, UINT32_MAX, UINT32_MAX + 1,
+ UINT64_MAX - 1, UINT64_MAX };
+
+ switch (type) {
+ case Ity_I1: *num_val = NUM_EL(values_1bit); return values_1bit;
+ case Ity_I8: *num_val = NUM_EL(values_8bit); return values_8bit;
+ case Ity_I16: *num_val = NUM_EL(values_16bit); return values_16bit;
+ case Ity_I32: *num_val = NUM_EL(values_32bit); return values_32bit;
+ case Ity_I64: *num_val = NUM_EL(values_64bit); return values_64bit;
+ default:
+ panic(__func__);
+ }
+}
void complain(const irop_t *, const test_data_t *, uint64_t expected);
unsigned bitsof_irtype(IRType);
+uint64_t get_random_value(IRType);
+const uint64_t *get_selected_values(IRType, unsigned *);
/* Exported variables */
extern int verbose;
+extern unsigned num_random_tests;
#endif // VTEST_H