openMSX
CRC16_test.cc
Go to the documentation of this file.
1#include "catch.hpp"
2#include "CRC16.hh"
3
4#include "narrow.hh"
5#include "xrange.hh"
6
7#include <array>
8#include <bit>
9
10using namespace openmsx;
11
12TEST_CASE("CRC16")
13{
14 CRC16 crc;
15 REQUIRE(crc.getValue() == 0xFFFF);
16
17 // Test a simple sequence
18 SECTION("'3 x A1' in a loop") {
19 repeat(3, [&] { crc.update(0xA1); });
20 CHECK(crc.getValue() == 0xCDB4);
21 }
22 SECTION("'3 x A1' in one chunk") {
23 static constexpr std::array<uint8_t, 3> buf = { 0xA1, 0xA1, 0xA1 };
24 crc.update(buf);
25 CHECK(crc.getValue() == 0xCDB4);
26 }
27 SECTION("'3 x A1' via init") {
28 crc.init({0xA1, 0xA1, 0xA1});
29 CHECK(crc.getValue() == 0xCDB4);
30 }
31
32 // Internally the block-update method works on chunks of 8 bytes,
33 // so also try a few bigger examples
34 // not (an integer) multiple of 8
35 SECTION("'123456789' in a loop") {
36 for (char c : {'1', '2', '3', '4', '5', '6', '7', '8', '9'}) crc.update(c);
37 CHECK(crc.getValue() == 0x29B1);
38 }
39 SECTION("'123456789' in one chunk") {
40 static constexpr const char* const digits = "123456789";
41 crc.update(std::span{std::bit_cast<const uint8_t*>(digits), 9});
42 CHECK(crc.getValue() == 0x29B1);
43 }
44 // same as disk sector size
45 SECTION("512 bytes") {
46 std::array<uint8_t, 512> buf;
47 for (auto i : xrange(512)) buf[i] = narrow_cast<uint8_t>(i & 255);
48 SECTION("in a loop") {
49 for (char c : buf) crc.update(c);
50 CHECK(crc.getValue() == 0x56EE);
51 }
52 SECTION("in one chunk") {
53 crc.update(buf);
54 CHECK(crc.getValue() == 0x56EE);
55 }
56 }
57
58 // Tests for init<..>()
59 // It's possible to pass up-to 4 parameters. Verify that this gives
60 // the same result as the other 2 CRC calculation methods.
61 SECTION("'11' in a loop") {
62 for (uint8_t c : {uint8_t(0x11)}) crc.update(c);
63 CHECK(crc.getValue() == 0xE3E0);
64 }
65 SECTION("'11' in one chunk") {
66 static constexpr std::array<uint8_t, 1> buf = {0x11};
67 crc.update(buf);
68 CHECK(crc.getValue() == 0xE3E0);
69 }
70 SECTION("'11' via init") {
71 crc.init({0x11});
72 CHECK(crc.getValue() == 0xE3E0);
73 }
74
75 SECTION("'11 22' in a loop") {
76 for (uint8_t c : {uint8_t(0x11), uint8_t(0x22)}) crc.update(c);
77 CHECK(crc.getValue() == 0x296D);
78 }
79 SECTION("'11 22' in one chunk") {
80 static constexpr std::array<uint8_t, 2> buf = {0x11, 0x22};
81 crc.update(buf);
82 CHECK(crc.getValue() == 0x296D);
83 }
84 SECTION("'11 22' via init") {
85 crc.init({0x11, 0x22});
86 CHECK(crc.getValue() == 0x296D);
87 }
88
89 SECTION("'11 22 33' in a loop") {
90 for (uint8_t c : {uint8_t(0x11), uint8_t(0x22), uint8_t(0x33)}) crc.update(c);
91 CHECK(crc.getValue() == 0xDE7B);
92 }
93 SECTION("'11 22 33' in one chunk") {
94 static constexpr std::array<uint8_t, 3> buf = {0x11, 0x22, 0x33};
95 crc.update(buf);
96 CHECK(crc.getValue() == 0xDE7B);
97 }
98 SECTION("'11 22 33' via init") {
99 crc.init({0x11, 0x22, 0x33});
100 CHECK(crc.getValue() == 0xDE7B);
101 }
102
103 SECTION("'11 22 33 44' in a loop") {
104 for (uint8_t c : {uint8_t(0x11), uint8_t(0x22), uint8_t(0x33), uint8_t(0x44)}) crc.update(c);
105 CHECK(crc.getValue() == 0x59F3);
106 }
107 SECTION("'11 22 33 44' in one chunk") {
108 static constexpr std::array<uint8_t, 4> buf = {0x11, 0x22, 0x33, 0x44};
109 crc.update(buf);
110 CHECK(crc.getValue() == 0x59F3);
111 }
112 SECTION("'11 22 33 44' via init") {
113 crc.init({0x11, 0x22, 0x33, 0x44});
114 CHECK(crc.getValue() == 0x59F3);
115 }
116}
117
118
119#if 0
120
121// Functions to inspect the quality of the generated code
122
123uint16_t test_init()
124{
125 // I verified that gcc is capable of optimizing this to 'return 0xcdb4'.
126 CRC16 crc;
127 crc.init({0xA1, 0xA1, 0xA1});
128 return crc.getValue();
129}
130
131#endif
TEST_CASE("CRC16")
Definition CRC16_test.cc:12
This class calculates CRC numbers for the polygon x^16 + x^12 + x^5 + 1.
Definition CRC16.hh:19
constexpr void update(uint8_t value)
Update CRC with one byte.
Definition CRC16.hh:45
constexpr uint16_t getValue() const
Get current CRC value.
Definition CRC16.hh:89
constexpr void init(uint16_t initialCRC)
(Re)initialize the current value
Definition CRC16.hh:30
CHECK(m3==m3)
This file implemented 3 utility functions:
Definition Autofire.cc:11
constexpr void repeat(T n, Op op)
Repeat the given operation 'op' 'n' times.
Definition xrange.hh:147
constexpr auto xrange(T e)
Definition xrange.hh:132