From d061fda7e90c29f4f5c2f47e66db7acba6a7edbe Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko Date: Fri, 8 Nov 2013 15:01:59 +0100 Subject: [PATCH] * grub-core/tests/div_test.c: New test. --- ChangeLog | 4 + grub-core/Makefile.core.def | 5 ++ grub-core/tests/div_test.c | 124 ++++++++++++++++++++++++++ grub-core/tests/lib/functional_test.c | 1 + 4 files changed, 134 insertions(+) create mode 100644 grub-core/tests/div_test.c diff --git a/ChangeLog b/ChangeLog index f8a014880..201050f10 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2013-11-08 Vladimir Serbinenko + + * grub-core/tests/div_test.c: New test. + 2013-11-08 Vladimir Testov * grub-core/gfxmenu/gui_box.c: Updated to work with area status. diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 7f3bae3c6..8dd99260b 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -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 index 000000000..1928f8507 --- /dev/null +++ b/grub-core/tests/div_test.c @@ -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 . + */ + +#include +#include +#include + +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); diff --git a/grub-core/tests/lib/functional_test.c b/grub-core/tests/lib/functional_test.c index a41fb978d..cb02f8f79 100644 --- a/grub-core/tests/lib/functional_test.c +++ b/grub-core/tests/lib/functional_test.c @@ -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;