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