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