generator_test.py 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. # vim: ts=8 sw=8 noexpandtab
  2. #
  3. # CRC code generator
  4. #
  5. # Copyright (c) 2020-2023 Michael Büsch <m@bues.ch>
  6. #
  7. # This program is free software; you can redistribute it and/or modify
  8. # it under the terms of the GNU General Public License as published by
  9. # the Free Software Foundation; either version 2 of the License, or
  10. # (at your option) any later version.
  11. #
  12. # This program is distributed in the hope that it will be useful,
  13. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. # GNU General Public License for more details.
  16. #
  17. # You should have received a copy of the GNU General Public License along
  18. # with this program; if not, write to the Free Software Foundation, Inc.,
  19. # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  20. #
  21. from libcrcgen.generator import *
  22. from libcrcgen.reference import *
  23. from libcrcgen.util import *
  24. __all__ = [
  25. "CrcGenTest",
  26. ]
  27. class CrcGenTest(CrcGen):
  28. def runTests(self, name=None, extra=None):
  29. tmpdir = None
  30. try:
  31. import random
  32. rng = random.Random()
  33. rng.seed(424242)
  34. print(f"Testing{(' ' + name) if name else ''} "
  35. f"P=0x{self._P:X}, "
  36. f"nrCrcBits={self._nrCrcBits}, "
  37. f"shiftRight={int(bool(self._shiftRight))}, "
  38. f"nrDataBits={self._nrDataBits}"
  39. f"{(', ' + extra) if extra else ''} ...")
  40. # Generate the CRC function as Python code.
  41. pyCode = self.genPython(funcName="crc_pyimpl")
  42. execEnv = {}
  43. exec(pyCode, execEnv)
  44. crc_pyimpl = execEnv["crc_pyimpl"]
  45. # Generate the CRC function as C code.
  46. import os, time, importlib, shutil
  47. from cffi import FFI
  48. ffibuilder = FFI()
  49. ffibuilder.set_source("testmod_crcgen", self.genC())
  50. ffibuilder.cdef(self.genC(declOnly=True,
  51. includeGuards=False,
  52. includes=False))
  53. tmpdir = f"tmp_{os.getpid()}_{int(time.time() * 1e6)}"
  54. ffibuilder.compile(tmpdir=tmpdir, verbose=False)
  55. testmod_crcgen = importlib.import_module(tmpdir + ".testmod_crcgen")
  56. crc_cimpl = testmod_crcgen.lib.crc
  57. # Compare the reference implementation to the Python and C code.
  58. crcMask = (1 << self._nrCrcBits) - 1
  59. dataMask = (1 << self._nrDataBits) - 1
  60. for i in range(32):
  61. if i == 0:
  62. crc = 0
  63. elif i == 1:
  64. crc = crcMask
  65. else:
  66. crc = rng.randint(1, crcMask - 1)
  67. for j in range(min(64, dataMask + 1)):
  68. if j == 0:
  69. data = 0
  70. elif j == 1:
  71. data = dataMask
  72. else:
  73. data = rng.randint(1, dataMask - 1)
  74. for k in range(3):
  75. ref = CrcReference.crc(
  76. crc=crc,
  77. data=data,
  78. polynomial=self._P,
  79. nrCrcBits=self._nrCrcBits,
  80. nrDataBits=self._nrDataBits,
  81. shiftRight=self._shiftRight)
  82. py = crc_pyimpl(crc, data)
  83. c = crc_cimpl(crc, data)
  84. if ref != py or ref != c:
  85. raise CrcGenError(
  86. f"Test failed: "
  87. f"P=0x{self._P:X}, "
  88. f"nrCrcBits={self._nrCrcBits}, "
  89. f"shiftRight={int(bool(self._shiftRight))}, "
  90. f"nrDataBits={self._nrDataBits}, "
  91. f"data=0x{data:X}, "
  92. f"ref=0x{ref:X}, "
  93. f"py=0x{py:X}, "
  94. f"c=0x{c:X}")
  95. crc = ref
  96. data = (data + 1) & dataMask
  97. finally:
  98. if tmpdir:
  99. shutil.rmtree(tmpdir, ignore_errors=True)