openMSX
unittest/sha1.cc
Go to the documentation of this file.
1#include "catch.hpp"
2
3#include "sha1.hh"
4
5#include "ranges.hh"
6#include "xrange.hh"
7
8#include <bit>
9#include <cstring>
10#include <sstream>
11
12using namespace openmsx;
13
14TEST_CASE("Sha1Sum: constructors")
15{
16 SECTION("default") {
18 CHECK(sum.empty());
19 CHECK(sum.toString() == "0000000000000000000000000000000000000000");
20 }
21
22 SECTION("from string, ok") {
23 Sha1Sum sum("1234567890123456789012345678901234567890");
24 CHECK(!sum.empty());
25 CHECK(sum.toString() == "1234567890123456789012345678901234567890");
26 }
27 SECTION("from string, too short") {
28 CHECK_THROWS(Sha1Sum("123456789012345678901234567890123456789"));
29 }
30 SECTION("from string, too long") {
31 CHECK_THROWS(Sha1Sum("12345678901234567890123456789012345678901"));
32 }
33 SECTION("from string, invalid char") {
34 CHECK_THROWS(Sha1Sum("g234567890123456789012345678901234567890"));
35 }
36}
37
38TEST_CASE("Sha1Sum: parse")
39{
41
42 // precondition: string must be 40 chars long
43 SECTION("ok") {
44 sum.parse40(subspan<40>("abcdabcdabcdabcdabcdabcdabcdabcdabcdabcd"));
45 CHECK(sum.toString() == "abcdabcdabcdabcdabcdabcdabcdabcdabcdabcd");
46 }
47 SECTION("invalid char") {
48 CHECK_THROWS(sum.parse40(subspan<40>("abcdabcdabcdabcdabcdabcdabcdabcd-bcdabcd")));
49 }
50}
51
52TEST_CASE("Sha1Sum: clear")
53{
54 Sha1Sum sum("1111111111111111111111111111111111111111");
55 REQUIRE(!sum.empty());
56 REQUIRE(sum.toString() != "0000000000000000000000000000000000000000");
57
58 sum.clear();
59 CHECK(sum.empty());
60 CHECK(sum.toString() == "0000000000000000000000000000000000000000");
61}
62
63static void testCompare(const Sha1Sum& x, const Sha1Sum& y, bool expectEqual, bool expectLess)
64{
65 if (expectEqual) {
66 REQUIRE(!expectLess);
67 CHECK( x == y ); CHECK( y == x );
68 CHECK(!(x != y)); CHECK(!(y != x));
69
70 CHECK(!(x < y)); CHECK(!(y < x));
71 CHECK( x <= y ); CHECK( y <= x );
72 CHECK(!(x > y)); CHECK(!(y > x));
73 CHECK( x >= y ); CHECK( y >= x );
74 } else {
75 CHECK(!(x == y)); CHECK(!(y == x));
76 CHECK( x != y ); CHECK( y != x );
77 if (expectLess) {
78 CHECK( x < y ); CHECK(!(y < x));
79 CHECK( x <= y ); CHECK(!(y <= x));
80 CHECK(!(x > y)); CHECK( y > x );
81 CHECK(!(x >= y)); CHECK( y >= x );
82 } else {
83 CHECK(!(x < y)); CHECK( y < x );
84 CHECK(!(x <= y)); CHECK( y <= x );
85 CHECK( x > y ); CHECK(!(y > x));
86 CHECK( x >= y ); CHECK(!(y >= x));
87 }
88 }
89}
90
91TEST_CASE("Sha1Sum: comparisons")
92{
93 Sha1Sum sumA ("0000000000000000000000000000000000000000");
94 Sha1Sum sumB ("0000000000000000000000000000000000000001");
95 Sha1Sum sumB2("0000000000000000000000000000000000000001");
96 Sha1Sum sumC ("0000000000100000000000000000000000000001");
97
98 testCompare(sumB, sumB2, true, false);
99 testCompare(sumA, sumB, false, true);
100 testCompare(sumC, sumB, false, false);
101}
102
103TEST_CASE("Sha1Sum: stream")
104{
105 Sha1Sum sum("abcdef0123ABCDEF0123abcdef0123ABCDEF0123");
106 std::stringstream ss;
107 ss << sum;
108 CHECK(ss.str() == "abcdef0123abcdef0123abcdef0123abcdef0123");
109}
110
111
112TEST_CASE("sha1: calc")
113{
114 const char* in = "abc";
115 Sha1Sum output = SHA1::calc({std::bit_cast<const uint8_t*>(in), strlen(in)});
116 CHECK(output.toString() == "a9993e364706816aba3e25717850c26c9cd0d89d");
117}
118
119TEST_CASE("sha1: update,digest")
120{
121 SHA1 sha1;
122 SECTION("single block") {
123 const char* in = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
124 sha1.update({std::bit_cast<const uint8_t*>(in), strlen(in)});
125 Sha1Sum sum1 = sha1.digest();
126 Sha1Sum sum2 = sha1.digest(); // call 2nd time is ok
127 CHECK(sum1 == sum2);
128 CHECK(sum1.toString() == "84983e441c3bd26ebaae4aa1f95129e5e54670f1");
129 }
130 SECTION("multiple blocks") {
131 const char* in = "aaaaaaaaaaaaaaaaaaaaaaaaa";
132 REQUIRE(strlen(in) == 25);
133 repeat(40000, [&] {
134 sha1.update({std::bit_cast<const uint8_t*>(in), strlen(in)});
135 });
136 // 25 * 40'000 = 1'000'000 repetitions of "a"
137 Sha1Sum sum = sha1.digest();
138 CHECK(sum.toString() == "34aa973cd4c4daa4f61eeb2bdbad27316534016f");
139 }
140}
141
142TEST_CASE("sha1: finalize")
143{
144 // white-box test for boundary cases in finalize()
145 SHA1 sha1;
146 const char* in = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
147 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
148 SECTION("0") {
149 sha1.update({std::bit_cast<const uint8_t*>(in), size_t(0)});
150 auto sum = sha1.digest();
151 CHECK(sum.toString() == "da39a3ee5e6b4b0d3255bfef95601890afd80709");
152 }
153 SECTION("25") {
154 sha1.update({std::bit_cast<const uint8_t*>(in), 25});
155 auto sum = sha1.digest();
156 CHECK(sum.toString() == "44f4647e1542a79d7d68ceb7f75d1dbf77fdebfc");
157 }
158 SECTION("55") {
159 sha1.update({std::bit_cast<const uint8_t*>(in), 55});
160 auto sum = sha1.digest();
161 CHECK(sum.toString() == "c1c8bbdc22796e28c0e15163d20899b65621d65a");
162 }
163 SECTION("56") {
164 sha1.update({std::bit_cast<const uint8_t*>(in), 56});
165 auto sum = sha1.digest();
166 CHECK(sum.toString() == "c2db330f6083854c99d4b5bfb6e8f29f201be699");
167 }
168 SECTION("60") {
169 sha1.update({std::bit_cast<const uint8_t*>(in), 60});
170 auto sum = sha1.digest();
171 CHECK(sum.toString() == "13d956033d9af449bfe2c4ef78c17c20469c4bf1");
172 }
173 SECTION("63") {
174 sha1.update({std::bit_cast<const uint8_t*>(in), 63});
175 auto sum = sha1.digest();
176 CHECK(sum.toString() == "03f09f5b158a7a8cdad920bddc29b81c18a551f5");
177 }
178 SECTION("64") {
179 sha1.update({std::bit_cast<const uint8_t*>(in), 64});
180 auto sum = sha1.digest();
181 CHECK(sum.toString() == "0098ba824b5c16427bd7a1122a5a442a25ec644d");
182 }
183}
Helper class to perform a sha1 calculation.
Definition sha1.hh:81
Sha1Sum digest()
Get the final hash.
void update(std::span< const uint8_t > data)
Incrementally calculate the hash value.
static Sha1Sum calc(std::span< const uint8_t > data)
Easier to use interface, if you can pass all data in one go.
This class represents the result of a sha1 calculation (a 160-bit value).
Definition sha1.hh:24
void parse40(std::span< const char, 40 > str)
Parse from a 40-character long buffer.
std::string toString() const
CHECK(m3==m3)
This file implemented 3 utility functions:
Definition Autofire.cc:11
auto sum(InputRange &&range, Proj proj={})
Definition stl.hh:245
TEST_CASE("Sha1Sum: constructors")
constexpr void repeat(T n, Op op)
Repeat the given operation 'op' 'n' times.
Definition xrange.hh:147