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