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

randombit / botan / 37723301502

07 Oct 2026 01:16PM UTC coverage: 89.903% (-0.01%) from 89.915%
37723301502

push

github

web-flow
Merge pull request #5999 from randombit/jack/base64-avx512

Add a AVX-512 path for base64 encoding and decoding

131000 of 145712 relevant lines covered (89.9%)

9262170.72 hits per line

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

84.07
/src/tests/test_codec.cpp
1
/*
2
* (C) 2015,2018,2021 Jack Lloyd
3
*
4
* Botan is released under the Simplified BSD License (see license.txt)
5
*/
6

7
#include "tests.h"
8

9
#include <botan/exceptn.h>
10
#include <botan/hex.h>
11

12
#if defined(BOTAN_HAS_BASE64_CODEC)
13
   #include <botan/base64.h>
14
#endif
15

16
#if defined(BOTAN_HAS_BASE32_CODEC)
17
   #include <botan/base32.h>
18
#endif
19

20
#if defined(BOTAN_HAS_BASE58_CODEC)
21
   #include <botan/base58.h>
22
#endif
23

24
namespace Botan_Tests {
25

26
namespace {
27

28
#if defined(BOTAN_HAS_BASE32_CODEC)
29

30
class Base32_Tests final : public Text_Based_Test {
×
31
   public:
32
      Base32_Tests() : Text_Based_Test("codec/base32.vec", "Base32", "Binary") {}
2 ✔
33

34
      Test::Result run_one_test(const std::string& type, const VarMap& vars) override {
33 ✔
35
         Test::Result result("Base32");
33 ✔
36

37
         const bool is_valid = (type == "valid");
33 ✔
38
         const std::string base32 = vars.get_req_str("Base32");
33 ✔
39

40
         try {
33 ✔
41
            if(is_valid) {
33 ✔
42
               const std::vector<uint8_t> binary = vars.get_req_bin("Binary");
24 ✔
43
               result.test_bin_eq("base32 decoding", Botan::base32_decode(base32), binary);
24 ✔
44
               result.test_str_eq("base32 encoding", Botan::base32_encode(binary), base32);
24 ✔
45
            } else {
24 ✔
46
               auto res = Botan::base32_decode(base32);
9 ✔
47
               result.test_failure("decoded invalid base32 to " + Botan::hex_encode(res));
×
48
            }
×
49
         } catch(std::exception& e) {
9 ✔
50
            if(is_valid) {
9 ✔
51
               result.test_failure("rejected valid base32", e.what());
×
52
            } else {
53
               result.test_note("rejected invalid base32");
9 ✔
54
            }
55
         }
9 ✔
56

57
         return result;
33 ✔
58
      }
33 ✔
59

60
      std::vector<Test::Result> run_final_tests() override {
1 ✔
61
         Test::Result result("Base32");
1 ✔
62
         const std::string valid_b32 = "MY======";
1 ✔
63

64
         for(const char ws_char : {' ', '\t', '\r', '\n'}) {
5 ✔
65
            for(size_t i = 0; i <= valid_b32.size(); ++i) {
40 ✔
66
               std::string b32_ws = valid_b32;
36 ✔
67
               b32_ws.insert(i, 1, ws_char);
36 ✔
68

69
               try {
36 ✔
70
                  result.test_failure("decoded whitespace base32", Botan::base32_decode(b32_ws, false));
36 ✔
71
               } catch(std::exception&) {}
36 ✔
72

73
               try {
36 ✔
74
                  result.test_bin_eq("base32 decoding with whitespace", Botan::base32_decode(b32_ws, true), "66");
72 ✔
75
               } catch(std::exception& e) {
×
76
                  result.test_failure(b32_ws, e.what());
×
77
               }
×
78
            }
36 ✔
79
         }
80

81
         return {result};
3 ✔
82
      }
2 ✔
83
};
84

85
BOTAN_REGISTER_TEST("codec", "base32", Base32_Tests);
86

87
#endif
88

89
#if defined(BOTAN_HAS_BASE58_CODEC)
90

91
class Base58_Tests final : public Text_Based_Test {
×
92
   public:
93
      Base58_Tests() : Text_Based_Test("codec/base58.vec", "Base58", "Binary") {}
2 ✔
94

95
      Test::Result run_one_test(const std::string& type, const VarMap& vars) override {
60 ✔
96
         Test::Result result("Base58");
60 ✔
97

98
         const bool is_valid = (type == "valid");
60 ✔
99
         const std::string base58 = vars.get_req_str("Base58");
60 ✔
100

101
         try {
60 ✔
102
            if(is_valid) {
60 ✔
103
               const std::vector<uint8_t> binary = vars.get_req_bin("Binary");
36 ✔
104
               result.test_bin_eq("base58 decoding", Botan::base58_decode(base58), binary);
36 ✔
105
               result.test_str_eq("base58 encoding", Botan::base58_encode(binary), base58);
36 ✔
106
            } else {
36 ✔
107
               auto res = Botan::base58_decode(base58);
24 ✔
108
               result.test_failure("decoded invalid base58 to " + Botan::hex_encode(res));
×
109
            }
×
110
         } catch(std::exception& e) {
24 ✔
111
            if(is_valid) {
24 ✔
112
               result.test_failure("rejected valid base58", e.what());
×
113
            } else {
114
               result.test_note("rejected invalid base58");
24 ✔
115
            }
116
         }
24 ✔
117

118
         return result;
60 ✔
119
      }
60 ✔
120

121
      std::vector<Test::Result> run_final_tests() override {
1 ✔
122
         Test::Result result("Base58");
1 ✔
123

124
         // Whitespace is ignored wherever it appears, including inside a block of 8 characters
125
         const std::vector<uint8_t> expected =
1 ✔
126
            Botan::hex_decode("6162636465666768696a6b6c6d6e6f707172737475767778797a");
1 ✔
127

128
         const std::vector<std::string> with_ws = {
1 ✔
129
            "3yxU3u1igY8WkgtjK92fbJQCd4BZiiT1v25f\n",
130
            " 3yxU3u1igY8WkgtjK92fbJQCd4BZiiT1v25f",
131
            "3yxU 3u1igY8WkgtjK92fbJQCd4BZiiT1v25f",
132
            "3yxU3u1i\ngY8Wkgtj\nK92fbJQC\nd4BZiiT1\nv25f",
133
            "3yxU3u1igY8Wkgtj K92fbJQCd4BZiiT1v25f",
134
            "3yxU3u1igY8WkgtjK92fbJ  QCd4BZiiT1v25f",
135
            "3 y x U 3 u 1 i g Y 8 W k g t j K 9 2 f b J Q C d 4 B Z i i T 1 v 2 5 f",
136
         };
1 ✔
137

138
         for(const auto& b58 : with_ws) {
8 ✔
139
            try {
7 ✔
140
               result.test_bin_eq("base58 decoding with whitespace", Botan::base58_decode(b58), expected);
14 ✔
141
            } catch(std::exception& e) {
×
142
               result.test_failure("rejected valid base58 with whitespace", e.what());
×
143
            }
×
144
         }
145

146
         return {result};
3 ✔
147
      }
3 ✔
148
};
149

150
BOTAN_REGISTER_TEST("codec", "base58", Base58_Tests);
151

152
class Base58_Check_Tests final : public Text_Based_Test {
×
153
   public:
154
      Base58_Check_Tests() : Text_Based_Test("codec/base58c.vec", "Base58", "Binary") {}
2 ✔
155

156
      Test::Result run_one_test(const std::string& type, const VarMap& vars) override {
9 ✔
157
         Test::Result result("Base58 Check");
9 ✔
158

159
         const bool is_valid = (type == "valid");
9 ✔
160
         const std::string base58 = vars.get_req_str("Base58");
9 ✔
161

162
         try {
9 ✔
163
            if(is_valid) {
9 ✔
164
               const std::vector<uint8_t> binary = vars.get_req_bin("Binary");
4 ✔
165
               result.test_bin_eq("base58 decoding", Botan::base58_check_decode(base58), binary);
4 ✔
166
               result.test_str_eq("base58 encoding", Botan::base58_check_encode(binary), base58);
4 ✔
167
            } else {
4 ✔
168
               auto res = Botan::base58_check_decode(base58);
5 ✔
169
               result.test_failure("decoded invalid base58c to " + Botan::hex_encode(res));
×
170
            }
×
171
         } catch(std::exception& e) {
5 ✔
172
            if(is_valid) {
5 ✔
173
               result.test_failure("rejected valid base58c", e.what());
×
174
            } else {
175
               result.test_note("rejected invalid base58c");
5 ✔
176
            }
177
         }
5 ✔
178

179
         return result;
9 ✔
180
      }
9 ✔
181
};
182

183
BOTAN_REGISTER_TEST("codec", "base58c", Base58_Check_Tests);
184

185
#endif
186

187
#if defined(BOTAN_HAS_BASE64_CODEC)
188

189
class Base64_Tests final : public Text_Based_Test {
×
190
   public:
191
      Base64_Tests() : Text_Based_Test("codec/base64.vec", "Base64", "Binary") {}
2 ✔
192

193
      Test::Result run_one_test(const std::string& type, const VarMap& vars) override {
39 ✔
194
         Test::Result result("Base64");
39 ✔
195

196
         const bool is_valid = (type == "valid");
39 ✔
197
         const std::string base64 = vars.get_req_str("Base64");
39 ✔
198

199
         try {
39 ✔
200
            if(is_valid) {
39 ✔
201
               const std::vector<uint8_t> binary = vars.get_req_bin("Binary");
27 ✔
202
               result.test_bin_eq("base64 decoding", Botan::base64_decode(base64), binary);
27 ✔
203
               result.test_str_eq("base64 encoding", Botan::base64_encode(binary), base64);
27 ✔
204
            } else {
27 ✔
205
               auto res = Botan::base64_decode(base64);
12 ✔
206
               result.test_failure("decoded invalid base64 to " + Botan::hex_encode(res));
×
207
            }
×
208
         } catch(std::exception& e) {
12 ✔
209
            if(is_valid) {
12 ✔
210
               result.test_failure("rejected valid base64", e.what());
×
211
            } else {
212
               result.test_note("rejected invalid base64");
12 ✔
213
            }
214
         }
12 ✔
215

216
         return result;
39 ✔
217
      }
39 ✔
218

219
      std::vector<Test::Result> run_final_tests() override {
1 ✔
220
         Test::Result result("Base64");
1 ✔
221
         const std::string valid_b64 = "Zg==";
1 ✔
222

223
         for(const char ws_char : {' ', '\t', '\r', '\n'}) {
5 ✔
224
            for(size_t i = 0; i <= valid_b64.size(); ++i) {
24 ✔
225
               std::string b64_ws = valid_b64;
20 ✔
226
               b64_ws.insert(i, 1, ws_char);
20 ✔
227

228
               try {
20 ✔
229
                  result.test_failure("decoded whitespace base64", Botan::base64_decode(b64_ws, false));
20 ✔
230
               } catch(std::exception&) {}
20 ✔
231

232
               try {
20 ✔
233
                  result.test_bin_eq("base64 decoding with whitespace", Botan::base64_decode(b64_ws, true), "66");
40 ✔
234
               } catch(std::exception& e) {
×
235
                  result.test_failure(b64_ws, e.what());
×
236
               }
×
237
            }
20 ✔
238
         }
239

240
         // Long inputs exercise the SIMD bulk paths in some build configurations
241
         std::vector<uint8_t> long_bin(3000);
1 ✔
242
         for(size_t i = 0; i != long_bin.size(); ++i) {
3,001 ✔
243
            long_bin[i] = static_cast<uint8_t>(i * 7 + i / 251);
3,000 ✔
244
         }
245

246
         const std::string long_b64 = Botan::base64_encode(long_bin);
1 ✔
247

248
         // PEM style line wrapping
249
         std::string long_b64_ws;
1 ✔
250
         for(size_t i = 0; i != long_b64.size(); ++i) {
4,001 ✔
251
            if(i > 0 && i % 64 == 0) {
4,000 ✔
252
               long_b64_ws += '\n';
62 ✔
253
            }
254
            long_b64_ws += long_b64[i];
8,000 ✔
255
         }
256

257
         try {
1 ✔
258
            result.test_bin_eq("long base64 decoding", Botan::base64_decode(long_b64, false), long_bin);
1 ✔
259
            result.test_bin_eq("long base64 decoding with newlines", Botan::base64_decode(long_b64_ws, true), long_bin);
2 ✔
260
         } catch(std::exception& e) {
×
261
            result.test_failure("long base64 roundtrip", e.what());
×
262
         }
×
263

264
         try {
1 ✔
265
            std::string corrupted = long_b64;
1 ✔
266
            corrupted[corrupted.size() / 2] = '!';
1 ✔
267
            result.test_failure("decoded corrupted base64", Botan::base64_decode(corrupted));
1 ✔
268
         } catch(std::exception&) {
1 ✔
269
            result.test_note("rejected corrupted base64");
1 ✔
270
         }
1 ✔
271

272
         return {result};
3 ✔
273
      }
3 ✔
274
};
275

276
BOTAN_REGISTER_TEST("codec", "base64", Base64_Tests);
277

278
#endif
279

280
class Codec_Error_Char_Display_Tests final : public Test {
1 ✔
281
   public:
282
      std::vector<Test::Result> run() override {
1 ✔
283
         Test::Result result("Codec error message character display");
1 ✔
284

285
         const std::vector<std::pair<char, std::string>> cases = {
1 ✔
286
            {'\x1b', "\\x1B"},
1 ✔
287
            {'\x00', "\\x00"},
1 ✔
288
            {'\n', "\\n"},
1 ✔
289
            {'\r', "\\r"},
1 ✔
290
            {'\t', "\\t"},
1 ✔
291
            {'\x7f', "\\x7F"},
1 ✔
292
            {static_cast<char>(0xFF), "\\xFF"},
1 ✔
293
         };
8 ✔
294

295
         for(const auto& [bad, expect] : cases) {
8 ✔
296
            try {
7 ✔
297
               Botan::hex_decode(std::string(1, bad), false);
14 ✔
298
               result.test_failure("hex_decode accepted invalid byte");
×
299
            } catch(const Botan::Invalid_Argument& e) {
7 ✔
300
               const std::string msg = e.what();
7 ✔
301
               result.test_is_true("message uses escaped string", msg.find(expect) != std::string::npos);
7 ✔
302
            }
7 ✔
303
         }
304

305
         return {result};
3 ✔
306
      }
3 ✔
307
};
308

309
BOTAN_REGISTER_TEST("codec", "codec_error_char_display", Codec_Error_Char_Display_Tests);
310

311
}  // namespace
312

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

© 2026 Coveralls, Inc