]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
iropt-test: Also test with random inputs; reorg the code a bit
authorFlorian Krohm <flo2030@eich-krohm.de>
Wed, 16 Jul 2025 11:51:15 +0000 (11:51 +0000)
committerFlorian Krohm <flo2030@eich-krohm.de>
Wed, 16 Jul 2025 11:51:15 +0000 (11:51 +0000)
New utility functions: get_random_value and get_selected_values
Add command line option -rNUM to specify the number of random tests
per operator.

none/tests/iropt-test/binary.c
none/tests/iropt-test/iropt-test.vgtest
none/tests/iropt-test/main.c
none/tests/iropt-test/unary.c
none/tests/iropt-test/util.c
none/tests/iropt-test/vtest.h

index c3f36c1884826642b903ec46f3dbadef8ecdc7e4..ec4fa21d1c50e81767c1a51d78a53a6d44adebed 100644 (file)
 #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);
 }
 
 
index 8becafdf8cad83c04d16289a72854da37a11d461..de31de6046644044d98e5c1c746e2786bc6a1be1 100644 (file)
@@ -1,4 +1,5 @@
 prog: iropt-test
-#args: -v -v
+#args: -v -v -r10
+args: -r100
 vgopts: -q --vex-guest-chase=no
 
index 28b8d23e4be1906ee4ed26401934f02fa8fd9363..2622515e5550e04a4e7663c0c47c9833b8f5832b 100644 (file)
@@ -38,18 +38,23 @@ static void check_irops_table(void);
 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;
@@ -72,7 +77,7 @@ main(int argc, char *argv[])
       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);
 
index 44af3203dd6989380a5084c2b1fc242112d03138..bb261384874a1df3112ef6fa47dfde3ffca9dc38 100644 (file)
 */
 
 #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);
 
@@ -38,47 +40,25 @@ test_unary_op(const irop_t *op, test_data_t *data)
    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__);
@@ -87,10 +67,11 @@ test_unary_op(const irop_t *op, test_data_t *data)
 
 
 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];
@@ -101,6 +82,21 @@ run_tests(const irop_t *op, test_data_t *data, unsigned num_val,
 }
 
 
+/* 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)
index 80e58570fe60f29c17d60cf0f014e357cb5c989d..072ff90c36c1037db566e8ac73d0b90591b09a0a 100644 (file)
@@ -104,3 +104,58 @@ bitsof_irtype(IRType ty)
       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__);
+   }
+}
index d9c1ddaae54f4a3736626c63fe328f17da2c4aca..47b397f6819277de7aad4e28716f52eeb140631d 100644 (file)
@@ -84,8 +84,11 @@ void panic(const char *, ...) __attribute__((noreturn));
 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