• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

randombit / botan / 5123321399

30 May 2023 04:06PM UTC coverage: 92.213% (+0.004%) from 92.209%
5123321399

Pull #3558

github

web-flow
Merge dd72f7389 into 057bcbc35
Pull Request #3558: Add braces around all if/else statements

75602 of 81986 relevant lines covered (92.21%)

11859779.3 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.2
/src/tests/test_utils.cpp
1
/*
2
* (C) 2015,2018 Jack Lloyd
3
* (C) 2016 Daniel Neus, Rohde & Schwarz Cybersecurity
4
* (C) 2017 René Korthaus, Rohde & Schwarz Cybersecurity
5
*
6
* Botan is released under the Simplified BSD License (see license.txt)
7
*/
8

9
#include "tests.h"
10
#include <botan/version.h>
11
#include <botan/internal/bit_ops.h>
12
#include <botan/internal/calendar.h>
13
#include <botan/internal/charset.h>
14
#include <botan/internal/cpuid.h>
15
#include <botan/internal/ct_utils.h>
16
#include <botan/internal/fmt.h>
17
#include <botan/internal/loadstor.h>
18
#include <botan/internal/parsing.h>
19
#include <botan/internal/rounding.h>
20
#include <ctime>
21
#include <functional>
22

23
#if defined(BOTAN_HAS_POLY_DBL)
24
   #include <botan/internal/poly_dbl.h>
25
#endif
26

27
#if defined(BOTAN_HAS_UUID)
28
   #include <botan/uuid.h>
29
#endif
30

31
namespace Botan_Tests {
32

33
namespace {
34

35
class Utility_Function_Tests final : public Text_Based_Test {
×
36
   public:
37
      Utility_Function_Tests() : Text_Based_Test("util.vec", "In1,In2,Out") {}
2✔
38

39
      Test::Result run_one_test(const std::string& algo, const VarMap& vars) override {
14✔
40
         Test::Result result("Util " + algo);
14✔
41

42
         if(algo == "round_up") {
14✔
43
            const size_t x = vars.get_req_sz("In1");
11✔
44
            const size_t to = vars.get_req_sz("In2");
11✔
45

46
            result.test_eq(algo, Botan::round_up(x, to), vars.get_req_sz("Out"));
22✔
47

48
            try {
11✔
49
               Botan::round_up(x, 0);
11✔
50
               result.test_failure("round_up did not reject invalid input");
51
            } catch(std::exception&) {}
11✔
52
         } else if(algo == "round_down") {
3✔
53
            const size_t x = vars.get_req_sz("In1");
3✔
54
            const size_t to = vars.get_req_sz("In2");
3✔
55

56
            result.test_eq(algo, Botan::round_down<size_t>(x, to), vars.get_req_sz("Out"));
6✔
57
            result.test_eq(algo, Botan::round_down<size_t>(x, 0), x);
3✔
58
         }
59

60
         return result;
14✔
61
      }
×
62

63
      std::vector<Test::Result> run_final_tests() override {
1✔
64
         std::vector<Test::Result> results;
1✔
65

66
         results.push_back(test_loadstore());
2✔
67

68
         return results;
1✔
69
      }
×
70

71
      static Test::Result test_loadstore() {
1✔
72
         Test::Result result("Util load/store");
1✔
73

74
         const std::vector<uint8_t> membuf = Botan::hex_decode("00112233445566778899AABBCCDDEEFF");
1✔
75
         const uint8_t* mem = membuf.data();
1✔
76

77
         const uint16_t in16 = 0x1234;
1✔
78
         const uint32_t in32 = 0xA0B0C0D0;
1✔
79
         const uint64_t in64 = 0xABCDEF0123456789;
1✔
80

81
         result.test_is_eq<uint8_t>(Botan::get_byte<0>(in32), 0xA0);
1✔
82
         result.test_is_eq<uint8_t>(Botan::get_byte<1>(in32), 0xB0);
1✔
83
         result.test_is_eq<uint8_t>(Botan::get_byte<2>(in32), 0xC0);
1✔
84
         result.test_is_eq<uint8_t>(Botan::get_byte<3>(in32), 0xD0);
1✔
85

86
         result.test_is_eq<uint16_t>(Botan::make_uint16(0xAA, 0xBB), 0xAABB);
1✔
87
         result.test_is_eq<uint32_t>(Botan::make_uint32(0x01, 0x02, 0x03, 0x04), 0x01020304);
1✔
88

89
         result.test_is_eq<uint16_t>(Botan::load_be<uint16_t>(mem, 0), 0x0011);
1✔
90
         result.test_is_eq<uint16_t>(Botan::load_be<uint16_t>(mem, 1), 0x2233);
1✔
91
         result.test_is_eq<uint16_t>(Botan::load_be<uint16_t>(mem, 2), 0x4455);
1✔
92
         result.test_is_eq<uint16_t>(Botan::load_be<uint16_t>(mem, 3), 0x6677);
1✔
93

94
         result.test_is_eq<uint16_t>(Botan::load_le<uint16_t>(mem, 0), 0x1100);
1✔
95
         result.test_is_eq<uint16_t>(Botan::load_le<uint16_t>(mem, 1), 0x3322);
1✔
96
         result.test_is_eq<uint16_t>(Botan::load_le<uint16_t>(mem, 2), 0x5544);
1✔
97
         result.test_is_eq<uint16_t>(Botan::load_le<uint16_t>(mem, 3), 0x7766);
1✔
98

99
         result.test_is_eq<uint32_t>(Botan::load_be<uint32_t>(mem, 0), 0x00112233);
1✔
100
         result.test_is_eq<uint32_t>(Botan::load_be<uint32_t>(mem, 1), 0x44556677);
1✔
101
         result.test_is_eq<uint32_t>(Botan::load_be<uint32_t>(mem, 2), 0x8899AABB);
1✔
102
         result.test_is_eq<uint32_t>(Botan::load_be<uint32_t>(mem, 3), 0xCCDDEEFF);
1✔
103

104
         result.test_is_eq<uint32_t>(Botan::load_le<uint32_t>(mem, 0), 0x33221100);
1✔
105
         result.test_is_eq<uint32_t>(Botan::load_le<uint32_t>(mem, 1), 0x77665544);
1✔
106
         result.test_is_eq<uint32_t>(Botan::load_le<uint32_t>(mem, 2), 0xBBAA9988);
1✔
107
         result.test_is_eq<uint32_t>(Botan::load_le<uint32_t>(mem, 3), 0xFFEEDDCC);
1✔
108

109
         result.test_is_eq<uint64_t>(Botan::load_be<uint64_t>(mem, 0), 0x0011223344556677);
1✔
110
         result.test_is_eq<uint64_t>(Botan::load_be<uint64_t>(mem, 1), 0x8899AABBCCDDEEFF);
1✔
111

112
         result.test_is_eq<uint64_t>(Botan::load_le<uint64_t>(mem, 0), 0x7766554433221100);
1✔
113
         result.test_is_eq<uint64_t>(Botan::load_le<uint64_t>(mem, 1), 0xFFEEDDCCBBAA9988);
1✔
114

115
         // Check misaligned loads:
116
         result.test_is_eq<uint16_t>(Botan::load_be<uint16_t>(mem + 1, 0), 0x1122);
1✔
117
         result.test_is_eq<uint16_t>(Botan::load_le<uint16_t>(mem + 3, 0), 0x4433);
1✔
118

119
         result.test_is_eq<uint32_t>(Botan::load_be<uint32_t>(mem + 1, 1), 0x55667788);
1✔
120
         result.test_is_eq<uint32_t>(Botan::load_le<uint32_t>(mem + 3, 1), 0xAA998877);
1✔
121

122
         result.test_is_eq<uint64_t>(Botan::load_be<uint64_t>(mem + 1, 0), 0x1122334455667788);
1✔
123
         result.test_is_eq<uint64_t>(Botan::load_le<uint64_t>(mem + 7, 0), 0xEEDDCCBBAA998877);
1✔
124
         result.test_is_eq<uint64_t>(Botan::load_le<uint64_t>(mem + 5, 0), 0xCCBBAA9988776655);
1✔
125

126
         uint8_t outbuf[16] = {0};
1✔
127

128
         for(size_t offset = 0; offset != 7; ++offset) {
8✔
129
            uint8_t* out = outbuf + offset;
7✔
130

131
            Botan::store_be(in16, out);
7✔
132
            result.test_is_eq<uint8_t>(out[0], 0x12);
7✔
133
            result.test_is_eq<uint8_t>(out[1], 0x34);
7✔
134

135
            Botan::store_le(in16, out);
7✔
136
            result.test_is_eq<uint8_t>(out[0], 0x34);
7✔
137
            result.test_is_eq<uint8_t>(out[1], 0x12);
7✔
138

139
            Botan::store_be(in32, out);
7✔
140
            result.test_is_eq<uint8_t>(out[0], 0xA0);
7✔
141
            result.test_is_eq<uint8_t>(out[1], 0xB0);
7✔
142
            result.test_is_eq<uint8_t>(out[2], 0xC0);
7✔
143
            result.test_is_eq<uint8_t>(out[3], 0xD0);
7✔
144

145
            Botan::store_le(in32, out);
7✔
146
            result.test_is_eq<uint8_t>(out[0], 0xD0);
7✔
147
            result.test_is_eq<uint8_t>(out[1], 0xC0);
7✔
148
            result.test_is_eq<uint8_t>(out[2], 0xB0);
7✔
149
            result.test_is_eq<uint8_t>(out[3], 0xA0);
7✔
150

151
            Botan::store_be(in64, out);
7✔
152
            result.test_is_eq<uint8_t>(out[0], 0xAB);
7✔
153
            result.test_is_eq<uint8_t>(out[1], 0xCD);
7✔
154
            result.test_is_eq<uint8_t>(out[2], 0xEF);
7✔
155
            result.test_is_eq<uint8_t>(out[3], 0x01);
7✔
156
            result.test_is_eq<uint8_t>(out[4], 0x23);
7✔
157
            result.test_is_eq<uint8_t>(out[5], 0x45);
7✔
158
            result.test_is_eq<uint8_t>(out[6], 0x67);
7✔
159
            result.test_is_eq<uint8_t>(out[7], 0x89);
7✔
160

161
            Botan::store_le(in64, out);
7✔
162
            result.test_is_eq<uint8_t>(out[0], 0x89);
7✔
163
            result.test_is_eq<uint8_t>(out[1], 0x67);
7✔
164
            result.test_is_eq<uint8_t>(out[2], 0x45);
7✔
165
            result.test_is_eq<uint8_t>(out[3], 0x23);
7✔
166
            result.test_is_eq<uint8_t>(out[4], 0x01);
7✔
167
            result.test_is_eq<uint8_t>(out[5], 0xEF);
7✔
168
            result.test_is_eq<uint8_t>(out[6], 0xCD);
7✔
169
            result.test_is_eq<uint8_t>(out[7], 0xAB);
7✔
170
         }
171

172
         return result;
1✔
173
      }
1✔
174
};
175

176
BOTAN_REGISTER_SMOKE_TEST("utils", "util", Utility_Function_Tests);
177

178
class CT_Mask_Tests final : public Test {
×
179
   public:
180
      std::vector<Test::Result> run() override {
1✔
181
         Test::Result result("CT utils");
1✔
182

183
         result.test_eq_sz("CT::is_zero8", Botan::CT::Mask<uint8_t>::is_zero(0).value(), 0xFF);
1✔
184
         result.test_eq_sz("CT::is_zero8", Botan::CT::Mask<uint8_t>::is_zero(1).value(), 0x00);
1✔
185
         result.test_eq_sz("CT::is_zero8", Botan::CT::Mask<uint8_t>::is_zero(0xFF).value(), 0x00);
1✔
186

187
         result.test_eq_sz("CT::is_zero16", Botan::CT::Mask<uint16_t>::is_zero(0).value(), 0xFFFF);
1✔
188
         result.test_eq_sz("CT::is_zero16", Botan::CT::Mask<uint16_t>::is_zero(1).value(), 0x0000);
1✔
189
         result.test_eq_sz("CT::is_zero16", Botan::CT::Mask<uint16_t>::is_zero(0xFF).value(), 0x0000);
1✔
190

191
         result.test_eq_sz("CT::is_zero32", Botan::CT::Mask<uint32_t>::is_zero(0).value(), 0xFFFFFFFF);
1✔
192
         result.test_eq_sz("CT::is_zero32", Botan::CT::Mask<uint32_t>::is_zero(1).value(), 0x00000000);
1✔
193
         result.test_eq_sz("CT::is_zero32", Botan::CT::Mask<uint32_t>::is_zero(0xFF).value(), 0x00000000);
1✔
194

195
         result.test_eq_sz("CT::is_less8", Botan::CT::Mask<uint8_t>::is_lt(0, 1).value(), 0xFF);
1✔
196
         result.test_eq_sz("CT::is_less8", Botan::CT::Mask<uint8_t>::is_lt(1, 0).value(), 0x00);
1✔
197
         result.test_eq_sz("CT::is_less8", Botan::CT::Mask<uint8_t>::is_lt(0xFF, 5).value(), 0x00);
1✔
198

199
         result.test_eq_sz("CT::is_less16", Botan::CT::Mask<uint16_t>::is_lt(0, 1).value(), 0xFFFF);
1✔
200
         result.test_eq_sz("CT::is_less16", Botan::CT::Mask<uint16_t>::is_lt(1, 0).value(), 0x0000);
1✔
201
         result.test_eq_sz("CT::is_less16", Botan::CT::Mask<uint16_t>::is_lt(0xFFFF, 5).value(), 0x0000);
1✔
202

203
         result.test_eq_sz("CT::is_less32", Botan::CT::Mask<uint32_t>::is_lt(0, 1).value(), 0xFFFFFFFF);
1✔
204
         result.test_eq_sz("CT::is_less32", Botan::CT::Mask<uint32_t>::is_lt(1, 0).value(), 0x00000000);
1✔
205
         result.test_eq_sz("CT::is_less32", Botan::CT::Mask<uint32_t>::is_lt(0xFFFF5, 5).value(), 0x00000000);
1✔
206
         result.test_eq_sz("CT::is_less32", Botan::CT::Mask<uint32_t>::is_lt(0xFFFFFFFF, 5).value(), 0x00000000);
1✔
207
         result.test_eq_sz("CT::is_less32", Botan::CT::Mask<uint32_t>::is_lt(5, 0xFFFFFFFF).value(), 0xFFFFFFFF);
1✔
208

209
         for(auto bad_input : {0, 1}) {
3✔
210
            for(size_t input_length : {0, 1, 2, 32}) {
10✔
211
               for(size_t offset = 0; offset != input_length + 1; ++offset) {
86✔
212
                  const auto mask = Botan::CT::Mask<uint8_t>::expand(static_cast<uint8_t>(bad_input));
78✔
213

214
                  std::vector<uint8_t> input(input_length);
78✔
215
                  rng().randomize(input.data(), input.size());
78✔
216

217
                  auto output = Botan::CT::copy_output(mask, input.data(), input.size(), offset);
78✔
218

219
                  result.test_eq_sz("CT::copy_output capacity", output.capacity(), input.size());
78✔
220

221
                  if(bad_input) {
78✔
222
                     result.confirm("If bad input, no output", output.empty());
117✔
223
                  } else {
224
                     if(offset >= input_length) {
39✔
225
                        result.confirm("If offset is too large, output is empty", output.empty());
12✔
226
                     } else {
227
                        result.test_eq_sz("CT::copy_output length", output.size(), input.size() - offset);
35✔
228

229
                        for(size_t i = 0; i != output.size(); ++i) {
567✔
230
                           result.test_eq_sz("CT::copy_output offset", output[i], input[i + offset]);
1,064✔
231
                        }
232
                     }
233
                  }
234
               }
154✔
235
            }
236
         }
237

238
         return {result};
3✔
239
      }
1✔
240
};
241

242
BOTAN_REGISTER_TEST("utils", "ct_utils", CT_Mask_Tests);
243

244
class BitOps_Tests final : public Test {
×
245
   public:
246
      std::vector<Test::Result> run() override {
1✔
247
         std::vector<Test::Result> results;
1✔
248

249
         results.push_back(test_power_of_2());
2✔
250
         results.push_back(test_ctz());
2✔
251
         results.push_back(test_sig_bytes());
2✔
252

253
         return results;
1✔
254
      }
×
255

256
   private:
257
      template <typename T>
258
      void test_ctz(Test::Result& result, T val, size_t expected) {
6✔
259
         result.test_eq("ctz(" + std::to_string(val) + ")", Botan::ctz<T>(val), expected);
12✔
260
      }
6✔
261

262
      Test::Result test_ctz() {
1✔
263
         Test::Result result("ctz");
1✔
264
         test_ctz<uint32_t>(result, 0, 32);
1✔
265
         test_ctz<uint32_t>(result, 1, 0);
1✔
266
         test_ctz<uint32_t>(result, 0x80, 7);
1✔
267
         test_ctz<uint32_t>(result, 0x8000000, 27);
1✔
268
         test_ctz<uint32_t>(result, 0x8100000, 20);
1✔
269
         test_ctz<uint32_t>(result, 0x80000000, 31);
1✔
270

271
         return result;
1✔
272
      }
×
273

274
      template <typename T>
275
      void test_sig_bytes(Test::Result& result, T val, size_t expected) {
14✔
276
         result.test_eq("significant_bytes(" + std::to_string(val) + ")", Botan::significant_bytes<T>(val), expected);
28✔
277
      }
14✔
278

279
      Test::Result test_sig_bytes() {
1✔
280
         Test::Result result("significant_bytes");
1✔
281
         test_sig_bytes<uint32_t>(result, 0, 0);
1✔
282
         test_sig_bytes<uint32_t>(result, 1, 1);
1✔
283
         test_sig_bytes<uint32_t>(result, 0x80, 1);
1✔
284
         test_sig_bytes<uint32_t>(result, 255, 1);
1✔
285
         test_sig_bytes<uint32_t>(result, 256, 2);
1✔
286
         test_sig_bytes<uint32_t>(result, 65535, 2);
1✔
287
         test_sig_bytes<uint32_t>(result, 65536, 3);
1✔
288
         test_sig_bytes<uint32_t>(result, 0x80000000, 4);
1✔
289

290
         test_sig_bytes<uint64_t>(result, 0, 0);
1✔
291
         test_sig_bytes<uint64_t>(result, 1, 1);
1✔
292
         test_sig_bytes<uint64_t>(result, 0x80, 1);
1✔
293
         test_sig_bytes<uint64_t>(result, 256, 2);
1✔
294
         test_sig_bytes<uint64_t>(result, 0x80000000, 4);
1✔
295
         test_sig_bytes<uint64_t>(result, 0x100000000, 5);
1✔
296

297
         return result;
1✔
298
      }
×
299

300
      template <typename T>
301
      void test_power_of_2(Test::Result& result, T val, bool expected) {
15✔
302
         result.test_eq("power_of_2(" + std::to_string(val) + ")", Botan::is_power_of_2<T>(val), expected);
45✔
303
      }
15✔
304

305
      Test::Result test_power_of_2() {
1✔
306
         Test::Result result("is_power_of_2");
1✔
307

308
         test_power_of_2<uint32_t>(result, 0, false);
1✔
309
         test_power_of_2<uint32_t>(result, 1, false);
1✔
310
         test_power_of_2<uint32_t>(result, 2, true);
1✔
311
         test_power_of_2<uint32_t>(result, 3, false);
1✔
312
         test_power_of_2<uint32_t>(result, 0x8000, true);
1✔
313
         test_power_of_2<uint32_t>(result, 0x8001, false);
1✔
314
         test_power_of_2<uint32_t>(result, 0x8000000, true);
1✔
315

316
         test_power_of_2<uint64_t>(result, 0, false);
1✔
317
         test_power_of_2<uint64_t>(result, 1, false);
1✔
318
         test_power_of_2<uint64_t>(result, 2, true);
1✔
319
         test_power_of_2<uint64_t>(result, 3, false);
1✔
320
         test_power_of_2<uint64_t>(result, 0x8000, true);
1✔
321
         test_power_of_2<uint64_t>(result, 0x8001, false);
1✔
322
         test_power_of_2<uint64_t>(result, 0x8000000, true);
1✔
323
         test_power_of_2<uint64_t>(result, 0x100000000000, true);
1✔
324

325
         return result;
1✔
326
      }
×
327
};
328

329
BOTAN_REGISTER_TEST("utils", "bit_ops", BitOps_Tests);
330

331
#if defined(BOTAN_HAS_POLY_DBL)
332

333
class Poly_Double_Tests final : public Text_Based_Test {
×
334
   public:
335
      Poly_Double_Tests() : Text_Based_Test("poly_dbl.vec", "In,Out") {}
2✔
336

337
      Test::Result run_one_test(const std::string& /*header*/, const VarMap& vars) override {
82✔
338
         Test::Result result("Polynomial doubling");
82✔
339
         const std::vector<uint8_t> in = vars.get_req_bin("In");
82✔
340
         const std::vector<uint8_t> out = vars.get_req_bin("Out");
82✔
341

342
         std::vector<uint8_t> b = in;
82✔
343
         Botan::poly_double_n(b.data(), b.size());
82✔
344

345
         result.test_eq("Expected value", b, out);
82✔
346
         return result;
82✔
347
      }
246✔
348
};
349

350
BOTAN_REGISTER_TEST("utils", "poly_dbl", Poly_Double_Tests);
351

352
#endif
353

354
class Version_Tests final : public Test {
×
355
   public:
356
      std::vector<Test::Result> run() override {
1✔
357
         Test::Result result("Versions");
1✔
358

359
         result.confirm("Version datestamp matches macro", Botan::version_datestamp() == BOTAN_VERSION_DATESTAMP);
2✔
360

361
         const char* version_cstr = Botan::version_cstr();
1✔
362
         std::string version_str = Botan::version_string();
1✔
363
         result.test_eq("Same version string", version_str, std::string(version_cstr));
2✔
364

365
         const char* sversion_cstr = Botan::short_version_cstr();
1✔
366
         std::string sversion_str = Botan::short_version_string();
1✔
367
         result.test_eq("Same short version string", sversion_str, std::string(sversion_cstr));
2✔
368

369
         std::string expected_sversion = std::to_string(BOTAN_VERSION_MAJOR) + "." +
2✔
370
                                         std::to_string(BOTAN_VERSION_MINOR) + "." +
4✔
371
                                         std::to_string(BOTAN_VERSION_PATCH);
2✔
372

373
#if defined(BOTAN_VERSION_SUFFIX)
374
         expected_sversion += BOTAN_VERSION_SUFFIX_STR;
375
#endif
376

377
         result.test_eq("Short version string has expected format", sversion_str, expected_sversion);
1✔
378

379
         const std::string version_check_ok =
1✔
380
            Botan::runtime_version_check(BOTAN_VERSION_MAJOR, BOTAN_VERSION_MINOR, BOTAN_VERSION_PATCH);
1✔
381

382
         result.confirm("Correct version no warning", version_check_ok.empty());
2✔
383

384
         const std::string version_check_bad = Botan::runtime_version_check(1, 19, 42);
1✔
385

386
         const std::string expected_error =
1✔
387
            "Warning: linked version (" + sversion_str + ") does not match version built against (1.19.42)\n";
1✔
388

389
         result.test_eq("Expected warning text", version_check_bad, expected_error);
1✔
390

391
         return {result};
3✔
392
      }
3✔
393
};
394

395
BOTAN_REGISTER_TEST("utils", "versioning", Version_Tests);
396

397
class Date_Format_Tests final : public Text_Based_Test {
×
398
   public:
399
      Date_Format_Tests() : Text_Based_Test("dates.vec", "Date") {}
2✔
400

401
      static std::vector<uint32_t> parse_date(const std::string& s) {
8✔
402
         const std::vector<std::string> parts = Botan::split_on(s, ',');
8✔
403
         if(parts.size() != 6) {
8✔
404
            throw Test_Error("Bad date format '" + s + "'");
×
405
         }
406

407
         std::vector<uint32_t> u32s;
8✔
408
         u32s.reserve(parts.size());
8✔
409
         for(const auto& sub : parts) {
56✔
410
            u32s.push_back(Botan::to_u32bit(sub));
48✔
411
         }
412
         return u32s;
8✔
413
      }
8✔
414

415
      Test::Result run_one_test(const std::string& type, const VarMap& vars) override {
8✔
416
         const std::string date_str = vars.get_req_str("Date");
8✔
417
         Test::Result result("Date parsing");
8✔
418

419
         const std::vector<uint32_t> d = parse_date(date_str);
8✔
420

421
         if(type == "valid" || type == "valid.not_std" || type == "valid.64_bit_time_t") {
8✔
422
            Botan::calendar_point c(d[0], d[1], d[2], d[3], d[4], d[5]);
8✔
423
            result.test_is_eq(date_str + " year", c.year(), d[0]);
8✔
424
            result.test_is_eq(date_str + " month", c.month(), d[1]);
8✔
425
            result.test_is_eq(date_str + " day", c.day(), d[2]);
8✔
426
            result.test_is_eq(date_str + " hour", c.hour(), d[3]);
8✔
427
            result.test_is_eq(date_str + " minute", c.minutes(), d[4]);
8✔
428
            result.test_is_eq(date_str + " second", c.seconds(), d[5]);
8✔
429

430
            if(type == "valid.not_std" ||
8✔
431
               (type == "valid.64_bit_time_t" && c.year() > 2037 && sizeof(std::time_t) == 4)) {
5✔
432
               result.test_throws("valid but out of std::timepoint range", [c]() { c.to_std_timepoint(); });
12✔
433
            } else {
434
               Botan::calendar_point c2(c.to_std_timepoint());
5✔
435
               result.test_is_eq(date_str + " year", c2.year(), d[0]);
5✔
436
               result.test_is_eq(date_str + " month", c2.month(), d[1]);
5✔
437
               result.test_is_eq(date_str + " day", c2.day(), d[2]);
5✔
438
               result.test_is_eq(date_str + " hour", c2.hour(), d[3]);
5✔
439
               result.test_is_eq(date_str + " minute", c2.minutes(), d[4]);
5✔
440
               result.test_is_eq(date_str + " second", c2.seconds(), d[5]);
10✔
441
            }
442
         } else if(type == "invalid") {
×
443
            result.test_throws("invalid date", [d]() { Botan::calendar_point c(d[0], d[1], d[2], d[3], d[4], d[5]); });
×
444
         } else {
445
            throw Test_Error("Unexpected header '" + type + "' in date format tests");
×
446
         }
447

448
         return result;
8✔
449
      }
16✔
450

451
      std::vector<Test::Result> run_final_tests() override {
1✔
452
         Test::Result result("calendar_point::to_string");
1✔
453
         Botan::calendar_point d(2008, 5, 15, 9, 30, 33);
1✔
454
         // desired format: <YYYY>-<MM>-<dd>T<HH>:<mm>:<ss>
455
         result.test_eq("calendar_point::to_string", d.to_string(), "2008-05-15T09:30:33");
3✔
456
         return {result};
3✔
457
      }
1✔
458
};
459

460
BOTAN_REGISTER_TEST("utils", "util_dates", Date_Format_Tests);
461

462
class Charset_Tests final : public Text_Based_Test {
×
463
   public:
464
      Charset_Tests() : Text_Based_Test("charset.vec", "In,Out") {}
2✔
465

466
      Test::Result run_one_test(const std::string& type, const VarMap& vars) override {
8✔
467
         Test::Result result("Charset");
8✔
468

469
         const std::vector<uint8_t> in = vars.get_req_bin("In");
8✔
470
         const std::vector<uint8_t> expected = vars.get_req_bin("Out");
8✔
471

472
         const std::string in_str(in.begin(), in.end());
8✔
473

474
         std::string converted;
8✔
475

476
         if(type == "UCS2-UTF8") {
8✔
477
            converted = Botan::ucs2_to_utf8(in.data(), in.size());
4✔
478
         } else if(type == "UCS4-UTF8") {
4✔
479
            converted = Botan::ucs4_to_utf8(in.data(), in.size());
1✔
480
         } else if(type == "LATIN1-UTF8") {
3✔
481
            converted = Botan::latin1_to_utf8(in.data(), in.size());
3✔
482
         } else {
483
            throw Test_Error("Unexpected header '" + type + "' in charset tests");
×
484
         }
485

486
         result.test_eq(
16✔
487
            "string converted successfully", std::vector<uint8_t>(converted.begin(), converted.end()), expected);
8✔
488

489
         return result;
8✔
490
      }
28✔
491
};
492

493
BOTAN_REGISTER_TEST("utils", "charset", Charset_Tests);
494

495
class Hostname_Tests final : public Text_Based_Test {
×
496
   public:
497
      Hostname_Tests() : Text_Based_Test("hostnames.vec", "Issued,Hostname") {}
2✔
498

499
      Test::Result run_one_test(const std::string& type, const VarMap& vars) override {
44✔
500
         Test::Result result("Hostname Matching");
44✔
501

502
         const std::string issued = vars.get_req_str("Issued");
44✔
503
         const std::string hostname = vars.get_req_str("Hostname");
44✔
504
         const bool expected = (type == "Invalid") ? false : true;
44✔
505

506
         const std::string what = hostname + ((expected == true) ? " matches " : " does not match ") + issued;
44✔
507
         result.test_eq(what, Botan::host_wildcard_match(issued, hostname), expected);
44✔
508

509
         return result;
44✔
510
      }
71✔
511
};
512

513
BOTAN_REGISTER_TEST("utils", "hostname", Hostname_Tests);
514

515
class ReadKV_Tests final : public Text_Based_Test {
×
516
   public:
517
      ReadKV_Tests() : Text_Based_Test("utils/read_kv.vec", "Input,Expected") {}
2✔
518

519
      Test::Result run_one_test(const std::string& status, const VarMap& vars) override {
16✔
520
         Test::Result result("read_kv");
16✔
521

522
         const bool is_valid = (status == "Valid");
16✔
523

524
         const std::string input = vars.get_req_str("Input");
16✔
525
         const std::string expected = vars.get_req_str("Expected");
16✔
526

527
         if(is_valid) {
16✔
528
            confirm_kv(result, Botan::read_kv(input), split_group(expected));
14✔
529
         } else {
530
            // In this case "expected" is the expected exception message
531
            result.test_throws("Invalid key value input throws exception", expected, [&]() { Botan::read_kv(input); });
36✔
532
         }
533
         return result;
16✔
534
      }
21✔
535

536
   private:
537
      static std::vector<std::string> split_group(const std::string& str) {
7✔
538
         std::vector<std::string> elems;
7✔
539
         if(str.empty()) {
7✔
540
            return elems;
541
         }
542

543
         std::string substr;
6✔
544
         for(auto i = str.begin(); i != str.end(); ++i) {
115✔
545
            if(*i == '|') {
109✔
546
               elems.push_back(substr);
16✔
547
               substr.clear();
16✔
548
            } else {
549
               substr += *i;
202✔
550
            }
551
         }
552

553
         if(!substr.empty()) {
6✔
554
            elems.push_back(substr);
6✔
555
         }
556

557
         return elems;
6✔
558
      }
7✔
559

560
      static void confirm_kv(Test::Result& result,
7✔
561
                             const std::map<std::string, std::string>& kv,
562
                             const std::vector<std::string>& expected) {
563
         if(!result.test_eq("expected size", expected.size() % 2, size_t(0))) {
7✔
564
            return;
565
         }
566

567
         for(size_t i = 0; i != expected.size(); i += 2) {
18✔
568
            auto j = kv.find(expected[i]);
11✔
569
            if(result.confirm("Found key", j != kv.end())) {
22✔
570
               result.test_eq("Matching value", j->second, expected[i + 1]);
22✔
571
            }
572
         }
573

574
         result.test_eq("KV has same size as expected", kv.size(), expected.size() / 2);
14✔
575
      }
576
};
577

578
BOTAN_REGISTER_TEST("utils", "util_read_kv", ReadKV_Tests);
579

580
class CPUID_Tests final : public Test {
×
581
   public:
582
      std::vector<Test::Result> run() override {
1✔
583
         Test::Result result("CPUID");
1✔
584

585
         result.confirm("Endian is either little or big",
2✔
586
                        Botan::CPUID::is_big_endian() || Botan::CPUID::is_little_endian());
587

588
         if(Botan::CPUID::is_little_endian()) {
1✔
589
            result.test_eq("If endian is little, it is not also big endian", Botan::CPUID::is_big_endian(), false);
1✔
590
         } else {
591
            result.test_eq("If endian is big, it is not also little endian", Botan::CPUID::is_little_endian(), false);
592
         }
593

594
         const std::string cpuid_string = Botan::CPUID::to_string();
1✔
595
         result.test_success("CPUID::to_string doesn't crash");
1✔
596

597
#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
598

599
         if(Botan::CPUID::has_sse2()) {
1✔
600
            result.confirm("Output string includes sse2", cpuid_string.find("sse2") != std::string::npos);
2✔
601

602
            Botan::CPUID::clear_cpuid_bit(Botan::CPUID::CPUID_SSE2_BIT);
1✔
603

604
            result.test_eq("After clearing cpuid bit, has_sse2 returns false", Botan::CPUID::has_sse2(), false);
1✔
605

606
            Botan::CPUID::initialize();  // reset state
1✔
607
            result.test_eq("After reinitializing, has_sse2 returns true", Botan::CPUID::has_sse2(), true);
2✔
608
         }
609
#endif
610

611
         return {result};
3✔
612
      }
1✔
613
};
614

615
BOTAN_REGISTER_TEST("utils", "cpuid", CPUID_Tests);
616

617
#if defined(BOTAN_HAS_UUID)
618

619
class UUID_Tests : public Test {
×
620
   public:
621
      std::vector<Test::Result> run() override {
1✔
622
         Test::Result result("UUID");
1✔
623

624
         const Botan::UUID empty_uuid;
1✔
625
         const Botan::UUID random_uuid1(Test::rng());
1✔
626
         const Botan::UUID random_uuid2(Test::rng());
1✔
627
         const Botan::UUID loaded_uuid(std::vector<uint8_t>(16, 4));
1✔
628

629
         result.test_throws("Cannot load wrong number of bytes", []() { Botan::UUID u(std::vector<uint8_t>(15)); });
3✔
630

631
         result.test_eq("Empty UUID is empty", empty_uuid.is_valid(), false);
1✔
632
         result.confirm("Empty UUID equals another empty UUID", empty_uuid == Botan::UUID());
3✔
633

634
         result.test_throws("Empty UUID cannot become a string", [&]() { empty_uuid.to_string(); });
3✔
635

636
         result.test_eq("Random UUID not empty", random_uuid1.is_valid(), true);
1✔
637
         result.test_eq("Random UUID not empty", random_uuid2.is_valid(), true);
1✔
638

639
         result.confirm("Random UUIDs are distinct", random_uuid1 != random_uuid2);
2✔
640
         result.confirm("Random UUIDs not equal to empty", random_uuid1 != empty_uuid);
2✔
641

642
         const std::string uuid4_str = loaded_uuid.to_string();
1✔
643
         result.test_eq("String matches expected", uuid4_str, "04040404-0404-0404-0404-040404040404");
2✔
644

645
         const std::string uuid_r1_str = random_uuid1.to_string();
1✔
646
         result.confirm("UUID from string matches", Botan::UUID(uuid_r1_str) == random_uuid1);
3✔
647

648
         class AllSame_RNG : public Botan::RandomNumberGenerator {
×
649
            public:
650
               explicit AllSame_RNG(uint8_t b) : m_val(b) {}
2✔
651

652
               void fill_bytes_with_input(std::span<uint8_t> output, std::span<const uint8_t> /* ignored */) override {
2✔
653
                  for(auto& byte : output) {
34✔
654
                     byte = m_val;
32✔
655
                  }
656
               }
2✔
657

658
               std::string name() const override { return "zeros"; }
×
659

660
               bool accepts_input() const override { return false; }
×
661

662
               void clear() override {}
×
663

664
               bool is_seeded() const override { return true; }
×
665

666
            private:
667
               uint8_t m_val;
668
         };
669

670
         AllSame_RNG zeros(0x00);
1✔
671
         const Botan::UUID zero_uuid(zeros);
1✔
672
         result.test_eq("Zero UUID matches expected", zero_uuid.to_string(), "00000000-0000-4000-8000-000000000000");
3✔
673

674
         AllSame_RNG ones(0xFF);
1✔
675
         const Botan::UUID ones_uuid(ones);
1✔
676
         result.test_eq("Ones UUID matches expected", ones_uuid.to_string(), "FFFFFFFF-FFFF-4FFF-BFFF-FFFFFFFFFFFF");
3✔
677

678
         return {result};
3✔
679
      }
7✔
680
};
681

682
BOTAN_REGISTER_TEST("utils", "uuid", UUID_Tests);
683

684
class Formatter_Tests : public Test {
×
685
   public:
686
      std::vector<Test::Result> run() override {
1✔
687
         Test::Result result("Format utility");
1✔
688

689
         /*
690
         In a number of these tests, we are not strictly depending on the
691
         behavior, for instance checking `fmt("{}") == "{}"` is more about
692
         checking that we don't crash, rather than we return that precise string.
693
         */
694

695
         result.test_eq("test 1", Botan::fmt("hi"), "hi");
2✔
696
         result.test_eq("test 2", Botan::fmt("ignored", 5), "ignored");
2✔
697
         result.test_eq("test 3", Botan::fmt("answer is {}", 42), "answer is 42");
2✔
698
         result.test_eq("test 4", Botan::fmt("{", 5), "{");
2✔
699
         result.test_eq("test 4", Botan::fmt("{}"), "{}");
2✔
700
         result.test_eq("test 5", Botan::fmt("{} == '{}'", 5, "five"), "5 == 'five'");
2✔
701

702
         return {result};
3✔
703
      }
1✔
704
};
705

706
BOTAN_REGISTER_TEST("utils", "fmt", Formatter_Tests);
707

708
#endif
709

710
}  // namespace
711

712
}  // namespace Botan_Tests
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc