]> git.proxmox.com Git - grub2.git/commitdiff
* grub-core/tests/div_test.c: New test.
authorVladimir Serbinenko <phcoder@gmail.com>
Fri, 8 Nov 2013 14:01:59 +0000 (15:01 +0100)
committerVladimir Serbinenko <phcoder@gmail.com>
Fri, 8 Nov 2013 14:01:59 +0000 (15:01 +0100)
ChangeLog
grub-core/Makefile.core.def
grub-core/tests/div_test.c [new file with mode: 0644]
grub-core/tests/lib/functional_test.c

index f8a01488091cc8bcf5592a242f29fd9c9acc2009..201050f10b1329c088752268140c4494e393b1aa 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2013-11-08  Vladimir Serbinenko  <phcoder@gmail.com>
+
+       * grub-core/tests/div_test.c: New test.
+
 2013-11-08  Vladimir Testov  <vladimir.testov@rosalab.ru>
 
        * grub-core/gfxmenu/gui_box.c: Updated to work with area status.
index 7f3bae3c60b5acc38b41b638e9bd36af0e16a865..8dd99260ba38d673b7baad589b95251fdf2e1692 100644 (file)
@@ -1855,6 +1855,11 @@ module = {
   common = tests/setjmp_test.c;
 };
 
+module = {
+  name = div_test;
+  common = tests/div_test.c;
+};
+
 module = {
   name = videotest_checksum;
   common = tests/videotest_checksum.c;
diff --git a/grub-core/tests/div_test.c b/grub-core/tests/div_test.c
new file mode 100644 (file)
index 0000000..1928f85
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2013 Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/test.h>
+#include <grub/dl.h>
+#include <grub/misc.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+static grub_uint64_t vectors[][2] = {
+  { 0xffffffffffffffffULL, 1},
+  { 1, 0xffffffffffffffffULL},
+  { 0xffffffffffffffffULL, 0xffffffffffffffffULL},
+  { 1, 1 },
+  { 2, 1 }
+};
+
+static void
+test32 (grub_uint32_t a, grub_uint32_t b)
+{
+  grub_uint64_t q, r;
+  q = grub_divmod64 (a, b, &r);
+  grub_test_assert (r < b, "remainder is larger than dividend: 0x%llx %% 0x%llx = 0x%llx",
+                   (long long) a, (long long) b, (long long) r);
+  grub_test_assert (q * b + r == a, "division doesn't satisfy base property: 0x%llx * 0x%llx + 0x%llx != 0x%llx", (long long) q, (long long) b, (long long) r,
+                   (long long) a);
+  /* Overflow check.  */
+  grub_test_assert ((q >> 32) == 0,
+                   "division overflow in 0x%llx, 0x%llx", (long long) a, (long long) b);
+  grub_test_assert ((r >> 32) == 0,
+                   "division overflow in 0x%llx, 0x%llx", (long long) a, (long long) b);
+  /* q * b + r is at most:
+     0xffffffff * 0xffffffff + 0xffffffff = 0xffffffff00000000
+     so no overflow
+   */
+  grub_test_assert (q == (a / b),
+                   "C compiler division failure in 0x%llx, 0x%llx", (long long) a, (long long) b);
+  grub_test_assert (r == (a % b),
+                   "C compiler modulo failure in 0x%llx, 0x%llx", (long long) a, (long long) b);
+}
+
+static void
+test64 (grub_uint64_t a, grub_uint64_t b)
+{
+  grub_uint64_t q, r;
+  grub_uint64_t x1, x2;
+  q = grub_divmod64 (a, b, &r);
+  grub_test_assert (r < b, "remainder is larger than dividend: 0x%llx %% 0x%llx = 0x%llx",
+                   (long long) a, (long long) b, (long long) r);
+  grub_test_assert (q * b + r == a, "division doesn't satisfy base property: 0x%llx * 0x%llx + 0x%llx != 0x%llx", (long long) q, (long long) b, (long long) r,
+                   (long long) a);
+  /* Overflow checks.  */
+  grub_test_assert ((q >> 32) * (b >> 32) == 0,
+                   "division overflow in 0x%llx, 0x%llx", (long long) a, (long long) b);
+  x1 = (q >> 32) * (b & 0xffffffff);
+  grub_test_assert (x1 < (1LL << 32),
+                   "division overflow in 0x%llx, 0x%llx", (long long) a, (long long) b);
+  x1 <<= 32;
+  x2 = (b >> 32) * (q & 0xffffffff);
+  grub_test_assert (x2 < (1LL << 32),
+                   "division overflow in 0x%llx, 0x%llx", (long long) a, (long long) b);
+  x2 <<= 32;
+  grub_test_assert (x1 <= ~x2,
+                   "division overflow in 0x%llx, 0x%llx", (long long) a, (long long) b);
+  x1 += x2;
+  x2 = (q & 0xffffffff) * (b & 0xffffffff);
+  grub_test_assert (x1 <= ~x2,
+                   "division overflow in 0x%llx, 0x%llx", (long long) a, (long long) b);
+  x1 += x2;
+  grub_test_assert (x1 <= ~r,
+                   "division overflow in 0x%llx, 0x%llx", (long long) a, (long long) b);
+  x1 += r;
+  grub_test_assert (a == x1,
+                   "division overflow test failure in 0x%llx, 0x%llx", (long long) a, (long long) b);
+#if GRUB_TARGET_SIZEOF_VOID_P == 8
+  grub_test_assert (q == (a / b),
+                   "C compiler division failure in 0x%llx, 0x%llx", (long long) a, (long long) b);
+  grub_test_assert (r == (a % b),
+                   "C compiler modulo failure in 0x%llx, 0x%llx", (long long) a, (long long) b);
+#endif
+}
+
+static void
+div_test (void)
+{
+  grub_uint64_t a = 404, b = 7;
+  grub_size_t i;
+
+  for (i = 0; i < ARRAY_SIZE (vectors); i++)
+    {
+      test64 (vectors[i][0], vectors[i][1]);
+      test32 (vectors[i][0], vectors[i][1]);
+    }
+  for (i = 0; i < 40000; i++)
+    {
+      a = 17 * a + 13 * b;
+      b = 23 * a + 29 * b;
+      if (b == 0)
+       b = 1;
+      if (a == 0)
+       a = 1;
+      test64 (a, b);
+      test32 (a, b);
+
+    }
+}
+
+/* Register example_test method as a functional test.  */
+GRUB_FUNCTIONAL_TEST (div_test, div_test);
index a41fb978df965724b0e892133875506112537c7b..cb02f8f79e29aa63ad4acd834800ef7366277c8d 100644 (file)
@@ -58,6 +58,7 @@ grub_functional_all_tests (grub_extcmd_context_t ctxt __attribute__ ((unused)),
   grub_dl_load ("gfxterm_menu");
   grub_dl_load ("setjmp_test");
   grub_dl_load ("cmdline_cat_test");
+  grub_dl_load ("div_test");
 
   FOR_LIST_ELEMENTS (test, grub_test_list)
     ok = !grub_test_run (test) && ok;