Skip to content

Commit 3573700

Browse files
committed
Add unit tests for Data class
1 parent 1f9ed4b commit 3573700

1 file changed

Lines changed: 161 additions & 0 deletions

File tree

tests/src/bkcrack/Data.test.cpp

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
#include <bkcrack/Data.hpp>
2+
#include <bkcrack/Keys.hpp>
3+
4+
#include <TestRunner.hpp>
5+
#include <string_view>
6+
7+
namespace
8+
{
9+
const auto plaintext = std::vector<std::uint8_t>{
10+
'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', '!',
11+
};
12+
const auto ciphertext = std::vector<std::uint8_t>{
13+
0x3e, 0xb4, 0xc5, 0x92, 0x58, 0x40, 0x9a, 0x6c, 0xed, 0x99, 0x65, 0x81,
14+
0x66, 0x1b, 0x1d, 0xda, 0x5d, 0x8a, 0x8c, 0x30, 0x07, 0x76, 0x50, 0xbb,
15+
};
16+
const auto keystream = std::vector<std::uint8_t>{
17+
0xee, 0x96, 0x22, 0x47, 0x78, 0xb8, 0x73, 0x54, 0x4c, 0xd7, 0x7d, 0x0d,
18+
0x2e, 0x7e, 0x71, 0xb6, 0x32, 0xaa, 0xdb, 0x5f, 0x75, 0x1a, 0x34, 0x9a,
19+
};
20+
21+
auto prefix(const std::vector<std::uint8_t>& vector, std::size_t length) -> std::vector<std::uint8_t>
22+
{
23+
return std::vector<std::uint8_t>{vector.begin(), vector.begin() + length};
24+
}
25+
auto slice(const std::vector<std::uint8_t>& vector, std::size_t begin, std::size_t end) -> std::vector<std::uint8_t>
26+
{
27+
return std::vector<std::uint8_t>{vector.begin() + begin, vector.begin() + end};
28+
}
29+
} // namespace
30+
31+
TEST("Data::Error")
32+
{
33+
const auto error = Data::Error{"description"};
34+
CHECK(error.what() == std::string_view{"Data error: description."});
35+
}
36+
37+
TEST("contiguous plaintext only")
38+
{
39+
const auto data = Data{ciphertext, plaintext, 0, {}};
40+
CHECK(data.ciphertext == ciphertext);
41+
CHECK(data.plaintext == plaintext);
42+
CHECK(data.offset == 12);
43+
CHECK(data.keystream == slice(keystream, 12, 24));
44+
CHECK(data.extraPlaintext.empty());
45+
}
46+
47+
TEST("contiguous plaintext and sparse extra plaintext")
48+
{
49+
const auto data = Data{ciphertext, prefix(plaintext, 8), 0, {{-3, 0x4e}, {-2, 0x18}, {10, 'd'}, {11, '!'}}};
50+
CHECK(data.ciphertext == ciphertext);
51+
CHECK(data.plaintext == prefix(plaintext, 8));
52+
CHECK(data.offset == 12);
53+
CHECK(data.keystream == slice(keystream, 12, 20));
54+
CHECK(data.extraPlaintext == decltype(data.extraPlaintext){{22, 'd'}, {23, '!'}, {10, 0x18}, {9, 0x4e}});
55+
}
56+
57+
TEST("merge extra plaintext after")
58+
{
59+
const auto data = Data{ciphertext, prefix(plaintext, 10), 0, {{10, 'd'}, {11, '!'}}};
60+
CHECK(data.ciphertext == ciphertext);
61+
CHECK(data.plaintext == plaintext);
62+
CHECK(data.offset == 12);
63+
CHECK(data.keystream == slice(keystream, 12, 24));
64+
CHECK(data.extraPlaintext.empty());
65+
}
66+
67+
TEST("merge extra plaintext before")
68+
{
69+
const auto data = Data{ciphertext, slice(plaintext, 2, 12), 2, {{0, 'H'}, {1, 'e'}}};
70+
CHECK(data.ciphertext == ciphertext);
71+
CHECK(data.plaintext == plaintext);
72+
CHECK(data.offset == 12);
73+
CHECK(data.keystream == slice(keystream, 12, 24));
74+
CHECK(data.extraPlaintext.empty());
75+
}
76+
77+
TEST("overwrite contiguous plaintext with extra plaintext")
78+
{
79+
auto overwrittenPlaintext = plaintext;
80+
overwrittenPlaintext[5] = '*';
81+
82+
auto overwrittenKeystream = keystream;
83+
overwrittenKeystream[17] = ciphertext[17] ^ '*';
84+
85+
const auto data = Data{ciphertext, plaintext, 0, {{5, '*'}}};
86+
CHECK(data.ciphertext == ciphertext);
87+
CHECK(data.plaintext == overwrittenPlaintext);
88+
CHECK(data.offset == 12);
89+
CHECK(data.keystream == slice(overwrittenKeystream, 12, 24));
90+
CHECK(data.extraPlaintext.empty());
91+
}
92+
93+
TEST("long contiguous extra plaintext after")
94+
{
95+
const auto data = Data{ciphertext,
96+
{0x8c, 'H', 'e', 'l'},
97+
-1,
98+
{{4, 'o'}, {5, ' '}, {6, 'W'}, {7, 'o'}, {8, 'r'}, {9, 'l'}, {10, 'd'}, {11, '!'}}};
99+
CHECK(data.ciphertext == ciphertext);
100+
CHECK(data.plaintext == slice(plaintext, 4, 12));
101+
CHECK(data.offset == 16);
102+
CHECK(data.keystream == slice(keystream, 16, 24));
103+
CHECK(data.extraPlaintext == decltype(data.extraPlaintext){{14, 'l'}, {13, 'e'}, {12, 'H'}, {11, 0x8c}});
104+
}
105+
106+
TEST("long contiguous extra plaintext before")
107+
{
108+
const auto data = Data{ciphertext,
109+
{'r', 'l', 'd', '!'},
110+
8,
111+
{{-1, 0x8c}, {0, 'H'}, {1, 'e'}, {2, 'l'}, {3, 'l'}, {4, 'o'}, {5, ' '}, {6, 'W'}}};
112+
CHECK(data.ciphertext == ciphertext);
113+
CHECK(data.plaintext == decltype(data.plaintext){0x8c, 'H', 'e', 'l', 'l', 'o', ' ', 'W'});
114+
CHECK(data.offset == 11);
115+
CHECK(data.keystream == slice(keystream, 11, 19));
116+
CHECK(data.extraPlaintext == decltype(data.extraPlaintext){{20, 'r'}, {21, 'l'}, {22, 'd'}, {23, '!'}});
117+
}
118+
119+
TEST("extra plaintext only")
120+
{
121+
const auto extraPlaintext = std::map<int, std::uint8_t>{
122+
{0, 'H'}, {1, 'e'}, {2, 'l'}, {3, 'l'}, {4, 'o'}, {5, ' '},
123+
{6, 'W'}, {7, 'o'}, {8, 'r'}, {9, 'l'}, {10, 'd'}, {11, '!'},
124+
};
125+
const auto data = Data{ciphertext, {}, -1, extraPlaintext};
126+
CHECK(data.ciphertext == ciphertext);
127+
CHECK(data.plaintext == plaintext);
128+
CHECK(data.offset == 12);
129+
CHECK(data.keystream == slice(keystream, 12, 24));
130+
CHECK(data.extraPlaintext.empty());
131+
}
132+
133+
TEST("not enough data")
134+
{
135+
// not enough ciphertext
136+
CHECK_THROWS(Data::Error, Data{prefix(ciphertext, 11), prefix(plaintext, 11), -12, {}});
137+
138+
// less ciphertext than plaintext
139+
CHECK_THROWS(Data::Error, Data{prefix(ciphertext, 12), std::vector<std::uint8_t>('A', 13), -12, {}});
140+
141+
// not enough contiguous plaintext
142+
CHECK_THROWS(Data::Error, Data{ciphertext, prefix(plaintext, 7), 0, {}});
143+
144+
// not enough contiguous + extra plaintext
145+
CHECK_THROWS(Data::Error, Data{ciphertext, prefix(plaintext, 9), 0, {{10, 'd'}, {11, '!'}}});
146+
}
147+
148+
TEST("invalid offset")
149+
{
150+
// offset is too small
151+
CHECK_THROWS(Data::Error, Data{ciphertext, plaintext, -13, {}});
152+
153+
// offset is too large
154+
CHECK_THROWS(Data::Error, Data{ciphertext, plaintext, 1, {}});
155+
156+
// extra plaintext offset is too small
157+
CHECK_THROWS(Data::Error, Data{ciphertext, plaintext, 0, {{-13, 0x00}}});
158+
159+
// extra plaintext offset is too large
160+
CHECK_THROWS(Data::Error, Data{ciphertext, plaintext, 0, {{12, 0x00}}});
161+
}

0 commit comments

Comments
 (0)