From: Jacob Lifshay Date: Thu, 30 Nov 2023 22:54:05 +0000 (-0800) Subject: test_caller_svp64_powmod: rename to test_aaa_caller_svp64_powmod so pytest tries... X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=795cd9cba2882b0dd80c4fb93c984501e9f30cf4;p=openpower-isa.git test_caller_svp64_powmod: rename to test_aaa_caller_svp64_powmod so pytest tries to run it earlier --- diff --git a/src/openpower/decoder/isa/test_aaa_caller_svp64_powmod.py b/src/openpower/decoder/isa/test_aaa_caller_svp64_powmod.py new file mode 100644 index 00000000..4ca16db5 --- /dev/null +++ b/src/openpower/decoder/isa/test_aaa_caller_svp64_powmod.py @@ -0,0 +1,139 @@ +# SPDX-License-Identifier: LGPL-3-or-later +# Copyright 2023 Jacob Lifshay programmerjake@gmail.com + +# Funded by NLnet Assure Programme 2021-02-052, https://nlnet.nl/assure part +# of Horizon 2020 EU Programme 957073. + +""" modular exponentiation (`pow(x, y, z)`) tests + +related bugs: + + * https://bugs.libre-soc.org/show_bug.cgi?id=1044 +""" + +import unittest +from functools import lru_cache +import os +from openpower.test.bigint.powmod import ( + PowModCases, python_divmod_shift_sub_algorithm, + DivModKnuthAlgorithmD, python_powmod_256_algorithm) +from openpower.test.runner import TestRunnerBase + + +class TestPythonAlgorithms(unittest.TestCase): + def test_python_divmod_shift_sub_algorithm(self): + for n, d in PowModCases.divmod_512x256_to_256x256_test_inputs(): + q, r = divmod(n, d) + with self.subTest(n=f"{n:#_x}", d=f"{d:#_x}", + q=f"{q:#_x}", r=f"{r:#_x}"): + log_regex = n == 2 ** 511 - 1 and d == 2 ** 256 - 1 + out_q, out_r = python_divmod_shift_sub_algorithm( + n, d, log_regex=log_regex) + with self.subTest(out_q=f"{out_q:#_x}", out_r=f"{out_r:#_x}"): + self.assertEqual(out_q, q) + self.assertEqual(out_r, r) + + def test_python_divmod_knuth_algorithm_d(self): + seen_corner_cases = set() + algo = DivModKnuthAlgorithmD() + for n, d in PowModCases.divmod_512x256_to_256x256_test_inputs(): + log_regex = n == 2 ** 511 - 1 and d == 2 ** 256 - 1 + q, r = divmod(n, d) + n = [(n >> 64 * i) % 2 ** 64 for i in range(8)] + d = [(d >> 64 * i) % 2 ** 64 for i in range(4)] + q = [(q >> 64 * i) % 2 ** 64 for i in range(4)] + r = [(r >> 64 * i) % 2 ** 64 for i in range(4)] + with self.subTest(n=[f"{i:#_x}" for i in n], + d=[f"{i:#_x}" for i in d], + q=[f"{i:#_x}" for i in q], + r=[f"{i:#_x}" for i in r]): + out_q, out_r = algo.python( + n, d, log_regex=log_regex, + on_corner_case=seen_corner_cases.add) + with self.subTest(out_q=[f"{i:#_x}" for i in out_q], + out_r=[f"{i:#_x}" for i in out_r]): + self.assertEqual(out_q, q) + self.assertEqual(out_r, r) + + # ensure our testing actually covers all the corner cases + self.assertEqual(seen_corner_cases, { + "single-word divisor", + "non-zero shift", + "qhat overflows word", + "qhat adjustment", + "add back", + }) + + def test_python_powmod_algorithm(self): + for base, exp, mod in PowModCases.powmod_256_test_inputs(): + expected = pow(base, exp, mod) + with self.subTest(base=f"{base:#_x}", exp=f"{exp:#_x}", + mod=f"{mod:#_x}", expected=f"{expected:#_x}"): + out = python_powmod_256_algorithm(base, exp, mod) + with self.subTest(out=f"{out:#_x}"): + self.assertEqual(expected, out) + + +# writing the test_caller invocation this way makes it work with pytest + + +@lru_cache() +def make_cases(): + # cache globally, so we only have to create test_data once per process + return PowModCases().test_data + + +class TestPowModBase(TestRunnerBase): + __test__ = False + + # split up test cases into SPLIT_COUNT tests, so we get some parallelism + SPLIT_COUNT = 64 + SPLIT_INDEX = -1 + + def __init__(self, test): + assert test == 'test', f"test={test!r}" + self.__old_silence_log = os.environ.get("SILENCELOG") + cases = make_cases() + assert self.SPLIT_INDEX != -1, "must be overridden" + # split cases evenly over tests + start = (len(cases) * self.SPLIT_INDEX) // self.SPLIT_COUNT + end = (len(cases) * (self.SPLIT_INDEX + 1)) // self.SPLIT_COUNT + # if we have less cases than tests, move them all to the beginning, + # making finding failures faster + if len(cases) < self.SPLIT_COUNT: + start = 0 + end = 0 + if self.SPLIT_INDEX < len(cases): + start = self.SPLIT_INDEX + end = start + 1 + # can't do raise SkipTest if `start == end`, it makes unittest break + super().__init__(cases[start:end]) + + def setUp(self): + super().setUp() + if self.__old_silence_log is None: + os.environ["SILENCELOG"] = "!*,default" + + def tearDown(self): + super().tearDown() + if self.__old_silence_log is None: + del os.environ["SILENCELOG"] + + @classmethod + def make_split_classes(cls): + for i in range(cls.SPLIT_COUNT): + exec(f""" +class TestPowMod{i}(TestPowModBase): + __test__ = True + SPLIT_INDEX = {i} + + def test(self): + # dummy function to make unittest try to test this class + pass + """, globals()) + + +TestPowModBase.make_split_classes() + +if __name__ == "__main__": + unittest.main() diff --git a/src/openpower/decoder/isa/test_caller_svp64_powmod.py b/src/openpower/decoder/isa/test_caller_svp64_powmod.py deleted file mode 100644 index 4ca16db5..00000000 --- a/src/openpower/decoder/isa/test_caller_svp64_powmod.py +++ /dev/null @@ -1,139 +0,0 @@ -# SPDX-License-Identifier: LGPL-3-or-later -# Copyright 2023 Jacob Lifshay programmerjake@gmail.com - -# Funded by NLnet Assure Programme 2021-02-052, https://nlnet.nl/assure part -# of Horizon 2020 EU Programme 957073. - -""" modular exponentiation (`pow(x, y, z)`) tests - -related bugs: - - * https://bugs.libre-soc.org/show_bug.cgi?id=1044 -""" - -import unittest -from functools import lru_cache -import os -from openpower.test.bigint.powmod import ( - PowModCases, python_divmod_shift_sub_algorithm, - DivModKnuthAlgorithmD, python_powmod_256_algorithm) -from openpower.test.runner import TestRunnerBase - - -class TestPythonAlgorithms(unittest.TestCase): - def test_python_divmod_shift_sub_algorithm(self): - for n, d in PowModCases.divmod_512x256_to_256x256_test_inputs(): - q, r = divmod(n, d) - with self.subTest(n=f"{n:#_x}", d=f"{d:#_x}", - q=f"{q:#_x}", r=f"{r:#_x}"): - log_regex = n == 2 ** 511 - 1 and d == 2 ** 256 - 1 - out_q, out_r = python_divmod_shift_sub_algorithm( - n, d, log_regex=log_regex) - with self.subTest(out_q=f"{out_q:#_x}", out_r=f"{out_r:#_x}"): - self.assertEqual(out_q, q) - self.assertEqual(out_r, r) - - def test_python_divmod_knuth_algorithm_d(self): - seen_corner_cases = set() - algo = DivModKnuthAlgorithmD() - for n, d in PowModCases.divmod_512x256_to_256x256_test_inputs(): - log_regex = n == 2 ** 511 - 1 and d == 2 ** 256 - 1 - q, r = divmod(n, d) - n = [(n >> 64 * i) % 2 ** 64 for i in range(8)] - d = [(d >> 64 * i) % 2 ** 64 for i in range(4)] - q = [(q >> 64 * i) % 2 ** 64 for i in range(4)] - r = [(r >> 64 * i) % 2 ** 64 for i in range(4)] - with self.subTest(n=[f"{i:#_x}" for i in n], - d=[f"{i:#_x}" for i in d], - q=[f"{i:#_x}" for i in q], - r=[f"{i:#_x}" for i in r]): - out_q, out_r = algo.python( - n, d, log_regex=log_regex, - on_corner_case=seen_corner_cases.add) - with self.subTest(out_q=[f"{i:#_x}" for i in out_q], - out_r=[f"{i:#_x}" for i in out_r]): - self.assertEqual(out_q, q) - self.assertEqual(out_r, r) - - # ensure our testing actually covers all the corner cases - self.assertEqual(seen_corner_cases, { - "single-word divisor", - "non-zero shift", - "qhat overflows word", - "qhat adjustment", - "add back", - }) - - def test_python_powmod_algorithm(self): - for base, exp, mod in PowModCases.powmod_256_test_inputs(): - expected = pow(base, exp, mod) - with self.subTest(base=f"{base:#_x}", exp=f"{exp:#_x}", - mod=f"{mod:#_x}", expected=f"{expected:#_x}"): - out = python_powmod_256_algorithm(base, exp, mod) - with self.subTest(out=f"{out:#_x}"): - self.assertEqual(expected, out) - - -# writing the test_caller invocation this way makes it work with pytest - - -@lru_cache() -def make_cases(): - # cache globally, so we only have to create test_data once per process - return PowModCases().test_data - - -class TestPowModBase(TestRunnerBase): - __test__ = False - - # split up test cases into SPLIT_COUNT tests, so we get some parallelism - SPLIT_COUNT = 64 - SPLIT_INDEX = -1 - - def __init__(self, test): - assert test == 'test', f"test={test!r}" - self.__old_silence_log = os.environ.get("SILENCELOG") - cases = make_cases() - assert self.SPLIT_INDEX != -1, "must be overridden" - # split cases evenly over tests - start = (len(cases) * self.SPLIT_INDEX) // self.SPLIT_COUNT - end = (len(cases) * (self.SPLIT_INDEX + 1)) // self.SPLIT_COUNT - # if we have less cases than tests, move them all to the beginning, - # making finding failures faster - if len(cases) < self.SPLIT_COUNT: - start = 0 - end = 0 - if self.SPLIT_INDEX < len(cases): - start = self.SPLIT_INDEX - end = start + 1 - # can't do raise SkipTest if `start == end`, it makes unittest break - super().__init__(cases[start:end]) - - def setUp(self): - super().setUp() - if self.__old_silence_log is None: - os.environ["SILENCELOG"] = "!*,default" - - def tearDown(self): - super().tearDown() - if self.__old_silence_log is None: - del os.environ["SILENCELOG"] - - @classmethod - def make_split_classes(cls): - for i in range(cls.SPLIT_COUNT): - exec(f""" -class TestPowMod{i}(TestPowModBase): - __test__ = True - SPLIT_INDEX = {i} - - def test(self): - # dummy function to make unittest try to test this class - pass - """, globals()) - - -TestPowModBase.make_split_classes() - -if __name__ == "__main__": - unittest.main()