Files
2026-01-09 18:37:34 +09:00

1036 lines
53 KiB
C++

/*
* SPDX-FileCopyrightText: 2025 M5Stack Technology CO LTD
*
* SPDX-License-Identifier: MIT
*/
/*
UnitTest for utility functions
*/
#include <gtest/gtest.h>
#include <M5Unified.h>
#include <M5Utility.h>
using namespace m5::utility;
namespace {
// Base64
struct Base64TestData {
const uint8_t* input;
const uint32_t ilen;
const char* expected;
const uint32_t expected_len;
};
constexpr Base64TestData nolinebreak_std_padding_table[] = {
{(const uint8_t[]){}, 0, "", 0},
{(const uint8_t[]){0x00}, 1, "AA==", 4},
{(const uint8_t[]){0x00, 0x00}, 2, "AAA=", 4},
{(const uint8_t[]){0x00, 0x00, 0x00}, 3, "AAAA", 4},
{(const uint8_t[]){0xFF}, 1, "/w==", 4},
{(const uint8_t[]){0xFF, 0xFF}, 2, "//8=", 4},
{(const uint8_t[]){0xFF, 0xFF, 0xFF}, 3, "////", 4},
{(const uint8_t[]){0xDE, 0xAD, 0xBE, 0xEF}, 4, "3q2+7w==", 8},
{(const uint8_t[]){0x48, 0x65, 0x6C, 0x6C, 0x6F}, 5, "SGVsbG8=", 8},
{(const uint8_t[]){0x4D, 0x61, 0x73, 0x74, 0x65, 0x72}, 6, "TWFzdGVy", 8},
{(const uint8_t[]){0x00, 0x01, 0x02, 0x03, 0x04}, 5, "AAECAwQ=", 8},
{(const uint8_t[]){0x7E, 0xBA, 0x90, 0x33, 0x8B}, 5, "frqQM4s=", 8},
{(const uint8_t[]){0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41},
63, "QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFB", 84},
{(const uint8_t[]){0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
48, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", 64},
{(const uint8_t[]){0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
64, "/////////////////////////////////////////////////////////////////////////////////////w==", 88},
{(const uint8_t[]){0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F},
64, "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+Pw==", 88},
{(const uint8_t[]){0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42,
0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41,
0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43,
0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42,
0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43},
66, "QUJDQUJDQUJDQUJDQUJDQUJDQUJDQUJDQUJDQUJDQUJDQUJDQUJDQUJDQUJDQUJDQUJDQUJDQUJDQUJDQUJDQUJD", 88},
};
constexpr Base64TestData nolinebreak_std_nopad_table[] = {
{(const uint8_t[]){}, 0, "", 0},
{(const uint8_t[]){0x00}, 1, "AA", 2},
{(const uint8_t[]){0x00, 0x00}, 2, "AAA", 3},
{(const uint8_t[]){0x00, 0x00, 0x00}, 3, "AAAA", 4},
{(const uint8_t[]){0xFF}, 1, "/w", 2},
{(const uint8_t[]){0xFF, 0xFF}, 2, "//8", 3},
{(const uint8_t[]){0xFF, 0xFF, 0xFF}, 3, "////", 4},
{(const uint8_t[]){0xDE, 0xAD, 0xBE, 0xEF}, 4, "3q2+7w", 6},
{(const uint8_t[]){0x48, 0x65, 0x6C, 0x6C, 0x6F}, 5, "SGVsbG8", 7},
{(const uint8_t[]){0x4D, 0x61, 0x73, 0x74, 0x65, 0x72}, 6, "TWFzdGVy", 8},
{(const uint8_t[]){0x00, 0x01, 0x02, 0x03, 0x04}, 5, "AAECAwQ", 7},
{(const uint8_t[]){0x7E, 0xBA, 0x90, 0x33, 0x8B}, 5, "frqQM4s", 7},
{(const uint8_t[]){0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41},
63, "QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFB", 84},
{(const uint8_t[]){0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
48, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", 64},
{(const uint8_t[]){0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
64, "/////////////////////////////////////////////////////////////////////////////////////w", 86},
{(const uint8_t[]){0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F},
64, "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+Pw", 86},
{(const uint8_t[]){0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42,
0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41,
0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43,
0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42,
0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43},
66, "QUJDQUJDQUJDQUJDQUJDQUJDQUJDQUJDQUJDQUJDQUJDQUJDQUJDQUJDQUJDQUJDQUJDQUJDQUJDQUJDQUJDQUJD", 88},
};
constexpr Base64TestData nolinebreak_url_padding_table[] = {
{(const uint8_t[]){}, 0, "", 0},
{(const uint8_t[]){0x00}, 1, "AA==", 4},
{(const uint8_t[]){0x00, 0x00}, 2, "AAA=", 4},
{(const uint8_t[]){0x00, 0x00, 0x00}, 3, "AAAA", 4},
{(const uint8_t[]){0xFF}, 1, "_w==", 4},
{(const uint8_t[]){0xFF, 0xFF}, 2, "__8=", 4},
{(const uint8_t[]){0xFF, 0xFF, 0xFF}, 3, "____", 4},
{(const uint8_t[]){0xDE, 0xAD, 0xBE, 0xEF}, 4, "3q2-7w==", 8},
{(const uint8_t[]){0x48, 0x65, 0x6C, 0x6C, 0x6F}, 5, "SGVsbG8=", 8},
{(const uint8_t[]){0x4D, 0x61, 0x73, 0x74, 0x65, 0x72}, 6, "TWFzdGVy", 8},
{(const uint8_t[]){0x00, 0x01, 0x02, 0x03, 0x04}, 5, "AAECAwQ=", 8},
{(const uint8_t[]){0x7E, 0xBA, 0x90, 0x33, 0x8B}, 5, "frqQM4s=", 8},
{(const uint8_t[]){0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41},
63, "QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFB", 84},
{(const uint8_t[]){0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
48, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", 64},
{(const uint8_t[]){0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
64, "_____________________________________________________________________________________w==", 88},
{(const uint8_t[]){0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F},
64, "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0-Pw==", 88},
{(const uint8_t[]){0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42,
0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41,
0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43,
0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42,
0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43},
66, "QUJDQUJDQUJDQUJDQUJDQUJDQUJDQUJDQUJDQUJDQUJDQUJDQUJDQUJDQUJDQUJDQUJDQUJDQUJDQUJDQUJDQUJD", 88},
};
constexpr Base64TestData nolinebreak_url_nopad_table[] = {
{(const uint8_t[]){}, 0, "", 0},
{(const uint8_t[]){0x00}, 1, "AA", 2},
{(const uint8_t[]){0x00, 0x00}, 2, "AAA", 3},
{(const uint8_t[]){0x00, 0x00, 0x00}, 3, "AAAA", 4},
{(const uint8_t[]){0xFF}, 1, "_w", 2},
{(const uint8_t[]){0xFF, 0xFF}, 2, "__8", 3},
{(const uint8_t[]){0xFF, 0xFF, 0xFF}, 3, "____", 4},
{(const uint8_t[]){0xDE, 0xAD, 0xBE, 0xEF}, 4, "3q2-7w", 6},
{(const uint8_t[]){0x48, 0x65, 0x6C, 0x6C, 0x6F}, 5, "SGVsbG8", 7},
{(const uint8_t[]){0x4D, 0x61, 0x73, 0x74, 0x65, 0x72}, 6, "TWFzdGVy", 8},
{(const uint8_t[]){0x00, 0x01, 0x02, 0x03, 0x04}, 5, "AAECAwQ", 7},
{(const uint8_t[]){0x7E, 0xBA, 0x90, 0x33, 0x8B}, 5, "frqQM4s", 7},
{(const uint8_t[]){0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41},
63, "QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFB", 84},
{(const uint8_t[]){0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
48, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", 64},
{(const uint8_t[]){0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
64, "_____________________________________________________________________________________w", 86},
{(const uint8_t[]){0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F},
64, "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0-Pw", 86},
{(const uint8_t[]){0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42,
0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41,
0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43,
0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42,
0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43},
66, "QUJDQUJDQUJDQUJDQUJDQUJDQUJDQUJDQUJDQUJDQUJDQUJDQUJDQUJDQUJDQUJDQUJDQUJDQUJDQUJDQUJDQUJD", 88},
};
//
constexpr Base64TestData linebreak_std_padding_table[] = {
{(const uint8_t[]){}, 0, "", 0},
{(const uint8_t[]){0x00}, 1, "AA==", 4},
{(const uint8_t[]){0x00, 0x00}, 2, "AAA=", 4},
{(const uint8_t[]){0x00, 0x00, 0x00}, 3, "AAAA", 4},
{(const uint8_t[]){0xFF}, 1, "/w==", 4},
{(const uint8_t[]){0xFF, 0xFF}, 2, "//8=", 4},
{(const uint8_t[]){0xFF, 0xFF, 0xFF}, 3, "////", 4},
{(const uint8_t[]){0xDE, 0xAD, 0xBE, 0xEF}, 4, "3q2+7\nw==", 9},
{(const uint8_t[]){0x48, 0x65, 0x6C, 0x6C, 0x6F}, 5, "SGVsb\nG8=", 9},
{(const uint8_t[]){0x4D, 0x61, 0x73, 0x74, 0x65, 0x72}, 6, "TWFzd\nGVy", 9},
{(const uint8_t[]){0x00, 0x01, 0x02, 0x03, 0x04}, 5, "AAECA\nwQ=", 9},
{(const uint8_t[]){0x7E, 0xBA, 0x90, 0x33, 0x8B}, 5, "frqQM\n4s=", 9},
{(const uint8_t[]){0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41},
63,
"QUFBQ\nUFBQU\nFBQUF\nBQUFB\nQUFBQ\nUFBQU\nFBQUF\nBQUFB\nQUFBQ\nUFBQU\nFBQUF\nBQUFB\nQUFBQ\nUFBQU\nFBQUF\nBQUFB\nQ"
"UFB",
100},
{(const uint8_t[]){0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
48, "AAAAA\nAAAAA\nAAAAA\nAAAAA\nAAAAA\nAAAAA\nAAAAA\nAAAAA\nAAAAA\nAAAAA\nAAAAA\nAAAAA\nAAAA", 76},
{(const uint8_t[]){0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
64,
"/////\n/////\n/////\n/////\n/////\n/////\n/////\n/////\n/////\n/////\n/////\n/////\n/////\n/////\n/////\n/////\n/"
"////\nw==",
105},
{(const uint8_t[]){0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F},
64,
"AAECA\nwQFBg\ncICQo\nLDA0O\nDxARE\nhMUFR\nYXGBk\naGxwd\nHh8gI\nSIjJC\nUmJyg\npKiss\nLS4vM\nDEyMz\nQ1Njc\n4OTo7\nP"
"D0+P\nw==",
105},
{(const uint8_t[]){0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42,
0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41,
0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43,
0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42,
0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43},
66,
"QUJDQ\nUJDQU\nJDQUJ\nDQUJD\nQUJDQ\nUJDQU\nJDQUJ\nDQUJD\nQUJDQ\nUJDQU\nJDQUJ\nDQUJD\nQUJDQ\nUJDQU\nJDQUJ\nDQUJD\nQ"
"UJDQ\nUJD",
105},
};
constexpr Base64TestData linebreak_std_nopad_table[] = {
{(const uint8_t[]){}, 0, "", 0},
{(const uint8_t[]){0x00}, 1, "AA", 2},
{(const uint8_t[]){0x00, 0x00}, 2, "AAA", 3},
{(const uint8_t[]){0x00, 0x00, 0x00}, 3, "AAAA", 4},
{(const uint8_t[]){0xFF}, 1, "/w", 2},
{(const uint8_t[]){0xFF, 0xFF}, 2, "//8", 3},
{(const uint8_t[]){0xFF, 0xFF, 0xFF}, 3, "////", 4},
{(const uint8_t[]){0xDE, 0xAD, 0xBE, 0xEF}, 4, "3q2+7\nw", 7},
{(const uint8_t[]){0x48, 0x65, 0x6C, 0x6C, 0x6F}, 5, "SGVsb\nG8", 8},
{(const uint8_t[]){0x4D, 0x61, 0x73, 0x74, 0x65, 0x72}, 6, "TWFzd\nGVy", 9},
{(const uint8_t[]){0x00, 0x01, 0x02, 0x03, 0x04}, 5, "AAECA\nwQ", 8},
{(const uint8_t[]){0x7E, 0xBA, 0x90, 0x33, 0x8B}, 5, "frqQM\n4s", 8},
{(const uint8_t[]){0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41},
63,
"QUFBQ\nUFBQU\nFBQUF\nBQUFB\nQUFBQ\nUFBQU\nFBQUF\nBQUFB\nQUFBQ\nUFBQU\nFBQUF\nBQUFB\nQUFBQ\nUFBQU\nFBQUF\nBQUFB\nQ"
"UFB",
100},
{(const uint8_t[]){0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
48, "AAAAA\nAAAAA\nAAAAA\nAAAAA\nAAAAA\nAAAAA\nAAAAA\nAAAAA\nAAAAA\nAAAAA\nAAAAA\nAAAAA\nAAAA", 76},
{(const uint8_t[]){0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
64,
"/////\n/////\n/////\n/////\n/////\n/////\n/////\n/////\n/////\n/////\n/////\n/////\n/////\n/////\n/////\n/////\n/"
"////\nw",
103},
{(const uint8_t[]){0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F},
64,
"AAECA\nwQFBg\ncICQo\nLDA0O\nDxARE\nhMUFR\nYXGBk\naGxwd\nHh8gI\nSIjJC\nUmJyg\npKiss\nLS4vM\nDEyMz\nQ1Njc\n4OTo7\nP"
"D0+P\nw",
103},
{(const uint8_t[]){0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42,
0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41,
0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43,
0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42,
0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43},
66,
"QUJDQ\nUJDQU\nJDQUJ\nDQUJD\nQUJDQ\nUJDQU\nJDQUJ\nDQUJD\nQUJDQ\nUJDQU\nJDQUJ\nDQUJD\nQUJDQ\nUJDQU\nJDQUJ\nDQUJD\nQ"
"UJDQ\nUJD",
105},
};
constexpr Base64TestData linebreak_url_padding_table[] = {
{(const uint8_t[]){}, 0, "", 0},
{(const uint8_t[]){0x00}, 1, "AA==", 4},
{(const uint8_t[]){0x00, 0x00}, 2, "AAA=", 4},
{(const uint8_t[]){0x00, 0x00, 0x00}, 3, "AAAA", 4},
{(const uint8_t[]){0xFF}, 1, "_w==", 4},
{(const uint8_t[]){0xFF, 0xFF}, 2, "__8=", 4},
{(const uint8_t[]){0xFF, 0xFF, 0xFF}, 3, "____", 4},
{(const uint8_t[]){0xDE, 0xAD, 0xBE, 0xEF}, 4, "3q2-7\nw==", 9},
{(const uint8_t[]){0x48, 0x65, 0x6C, 0x6C, 0x6F}, 5, "SGVsb\nG8=", 9},
{(const uint8_t[]){0x4D, 0x61, 0x73, 0x74, 0x65, 0x72}, 6, "TWFzd\nGVy", 9},
{(const uint8_t[]){0x00, 0x01, 0x02, 0x03, 0x04}, 5, "AAECA\nwQ=", 9},
{(const uint8_t[]){0x7E, 0xBA, 0x90, 0x33, 0x8B}, 5, "frqQM\n4s=", 9},
{(const uint8_t[]){0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41},
63,
"QUFBQ\nUFBQU\nFBQUF\nBQUFB\nQUFBQ\nUFBQU\nFBQUF\nBQUFB\nQUFBQ\nUFBQU\nFBQUF\nBQUFB\nQUFBQ\nUFBQU\nFBQUF\nBQUFB\nQ"
"UFB",
100},
{(const uint8_t[]){0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
48, "AAAAA\nAAAAA\nAAAAA\nAAAAA\nAAAAA\nAAAAA\nAAAAA\nAAAAA\nAAAAA\nAAAAA\nAAAAA\nAAAAA\nAAAA", 76},
{(const uint8_t[]){0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
64,
"_____\n_____\n_____\n_____\n_____\n_____\n_____\n_____\n_____\n_____\n_____\n_____\n_____\n_____\n_____\n_____\n_"
"____\nw==",
105},
{(const uint8_t[]){0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F},
64,
"AAECA\nwQFBg\ncICQo\nLDA0O\nDxARE\nhMUFR\nYXGBk\naGxwd\nHh8gI\nSIjJC\nUmJyg\npKiss\nLS4vM\nDEyMz\nQ1Njc\n4OTo7\nP"
"D0-P\nw==",
105},
{(const uint8_t[]){0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42,
0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41,
0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43,
0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42,
0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43},
66,
"QUJDQ\nUJDQU\nJDQUJ\nDQUJD\nQUJDQ\nUJDQU\nJDQUJ\nDQUJD\nQUJDQ\nUJDQU\nJDQUJ\nDQUJD\nQUJDQ\nUJDQU\nJDQUJ\nDQUJD\nQ"
"UJDQ\nUJD",
105},
};
constexpr Base64TestData linebreak_url_nopad_table[] = {
{(const uint8_t[]){}, 0, "", 0},
{(const uint8_t[]){0x00}, 1, "AA", 2},
{(const uint8_t[]){0x00, 0x00}, 2, "AAA", 3},
{(const uint8_t[]){0x00, 0x00, 0x00}, 3, "AAAA", 4},
{(const uint8_t[]){0xFF}, 1, "_w", 2},
{(const uint8_t[]){0xFF, 0xFF}, 2, "__8", 3},
{(const uint8_t[]){0xFF, 0xFF, 0xFF}, 3, "____", 4},
{(const uint8_t[]){0xDE, 0xAD, 0xBE, 0xEF}, 4, "3q2-7\nw", 7},
{(const uint8_t[]){0x48, 0x65, 0x6C, 0x6C, 0x6F}, 5, "SGVsb\nG8", 8},
{(const uint8_t[]){0x4D, 0x61, 0x73, 0x74, 0x65, 0x72}, 6, "TWFzd\nGVy", 9},
{(const uint8_t[]){0x00, 0x01, 0x02, 0x03, 0x04}, 5, "AAECA\nwQ", 8},
{(const uint8_t[]){0x7E, 0xBA, 0x90, 0x33, 0x8B}, 5, "frqQM\n4s", 8},
{(const uint8_t[]){0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41},
63,
"QUFBQ\nUFBQU\nFBQUF\nBQUFB\nQUFBQ\nUFBQU\nFBQUF\nBQUFB\nQUFBQ\nUFBQU\nFBQUF\nBQUFB\nQUFBQ\nUFBQU\nFBQUF\nBQUFB\nQ"
"UFB",
100},
{(const uint8_t[]){0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
48, "AAAAA\nAAAAA\nAAAAA\nAAAAA\nAAAAA\nAAAAA\nAAAAA\nAAAAA\nAAAAA\nAAAAA\nAAAAA\nAAAAA\nAAAA", 76},
{(const uint8_t[]){0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
64,
"_____\n_____\n_____\n_____\n_____\n_____\n_____\n_____\n_____\n_____\n_____\n_____\n_____\n_____\n_____\n_____\n_"
"____\nw",
103},
{(const uint8_t[]){0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F},
64,
"AAECA\nwQFBg\ncICQo\nLDA0O\nDxARE\nhMUFR\nYXGBk\naGxwd\nHh8gI\nSIjJC\nUmJyg\npKiss\nLS4vM\nDEyMz\nQ1Njc\n4OTo7\nP"
"D0-P\nw",
103},
{(const uint8_t[]){0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42,
0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41,
0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43,
0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42,
0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43, 0x41, 0x42, 0x43},
66,
"QUJDQ\nUJDQU\nJDQUJ\nDQUJD\nQUJDQ\nUJDQU\nJDQUJ\nDQUJD\nQUJDQ\nUJDQU\nJDQUJ\nDQUJD\nQUJDQ\nUJDQU\nJDQUJ\nDQUJD\nQ"
"UJDQ\nUJD",
105},
};
// Line width used in linebreak test data tables
constexpr uint8_t TEST_LINE_WIDTH = 5;
} // namespace
TEST(Utility, Base64)
{
SCOPED_TRACE("Base64");
char output[128]{};
uint32_t olen{};
{ // no linebraek, std, padding
SCOPED_TRACE("nolinebreak, std, padding");
for (uint32_t i = 0; i < m5::stl::size(nolinebreak_std_padding_table); ++i) {
auto& e = nolinebreak_std_padding_table[i];
olen = sizeof(output);
auto written = encode_base64(output, olen, e.input, e.ilen, 0, false, true);
EXPECT_EQ(written, e.expected_len) << "idx:" << i;
EXPECT_TRUE(memcmp(output, e.expected, written) == 0)
<< "idx:" << i << "\nO:[" << output << "]\nE:[" << e.expected << "]";
}
}
{ // no linebreak, std, no padding
SCOPED_TRACE("nolinebreak, std, nopad");
for (uint32_t i = 0; i < m5::stl::size(nolinebreak_std_nopad_table); ++i) {
auto& e = nolinebreak_std_nopad_table[i];
olen = sizeof(output);
auto written = encode_base64(output, olen, e.input, e.ilen, 0, false, false);
EXPECT_EQ(written, e.expected_len) << "idx:" << i;
EXPECT_TRUE(memcmp(output, e.expected, written) == 0)
<< "idx:" << i << "\nO:[" << output << "]\nE:[" << e.expected << "]";
}
}
{ // no linebreak, url, padding
SCOPED_TRACE("nolinebreak, url, padding");
for (uint32_t i = 0; i < m5::stl::size(nolinebreak_url_padding_table); ++i) {
auto& e = nolinebreak_url_padding_table[i];
olen = sizeof(output);
auto written = encode_base64(output, olen, e.input, e.ilen, 0, true, true);
EXPECT_EQ(written, e.expected_len) << "idx:" << i;
EXPECT_TRUE(memcmp(output, e.expected, written) == 0)
<< "idx:" << i << "\nO:[" << output << "]\nE:[" << e.expected << "]";
}
}
{ // no linebreak, url, no padding
SCOPED_TRACE("nolinebreak, url, nopad");
for (uint32_t i = 0; i < m5::stl::size(nolinebreak_url_nopad_table); ++i) {
auto& e = nolinebreak_url_nopad_table[i];
olen = sizeof(output);
auto written = encode_base64(output, olen, e.input, e.ilen, 0, true, false);
EXPECT_EQ(written, e.expected_len) << "idx:" << i;
EXPECT_TRUE(memcmp(output, e.expected, written) == 0)
<< "idx:" << i << "\nO:[" << output << "]\nE:[" << e.expected << "]";
}
}
//
{ // linebraek, std, padding
SCOPED_TRACE("linebreak, std, padding");
for (uint32_t i = 0; i < m5::stl::size(linebreak_std_padding_table); ++i) {
auto& e = linebreak_std_padding_table[i];
olen = sizeof(output);
auto written = encode_base64(output, olen, e.input, e.ilen, TEST_LINE_WIDTH, false, true);
EXPECT_EQ(written, e.expected_len) << "idx:" << i;
EXPECT_TRUE(memcmp(output, e.expected, written) == 0)
<< "idx:" << i << "\nO:[" << output << "]\nE:[" << e.expected << "]";
}
}
{ // linebreak, std, no padding
SCOPED_TRACE("linebreak, std, nopad");
for (uint32_t i = 0; i < m5::stl::size(linebreak_std_nopad_table); ++i) {
auto& e = linebreak_std_nopad_table[i];
olen = sizeof(output);
auto written = encode_base64(output, olen, e.input, e.ilen, TEST_LINE_WIDTH, false, false);
EXPECT_EQ(written, e.expected_len) << "idx:" << i;
EXPECT_TRUE(memcmp(output, e.expected, written) == 0)
<< "idx:" << i << "\nO:[" << output << "]\nE:[" << e.expected << "]";
}
}
{ // linebreak, url, padding
SCOPED_TRACE("linebreak, url, padding");
for (uint32_t i = 0; i < m5::stl::size(linebreak_url_padding_table); ++i) {
auto& e = linebreak_url_padding_table[i];
olen = sizeof(output);
auto written = encode_base64(output, olen, e.input, e.ilen, TEST_LINE_WIDTH, true, true);
EXPECT_EQ(written, e.expected_len) << "idx:" << i;
EXPECT_TRUE(memcmp(output, e.expected, written) == 0)
<< "idx:" << i << "\nO:[" << output << "]\nE:[" << e.expected << "]";
}
}
{ // linebreak, url, no padding
SCOPED_TRACE("linebreak, url, nopad");
for (uint32_t i = 0; i < m5::stl::size(linebreak_url_nopad_table); ++i) {
auto& e = linebreak_url_nopad_table[i];
olen = sizeof(output);
auto written = encode_base64(output, olen, e.input, e.ilen, TEST_LINE_WIDTH, true, false);
EXPECT_EQ(written, e.expected_len) << "idx:" << i;
EXPECT_TRUE(memcmp(output, e.expected, written) == 0)
<< "idx:" << i << "\nO:[" << output << "]\nE:[" << e.expected << "]";
}
}
}
TEST(Utility, Base64Decode)
{
SCOPED_TRACE("Base64Decode");
uint8_t output[128]{};
// Decode: nolinebreak, std, padding
{
SCOPED_TRACE("decode: nolinebreak, std, padding");
for (uint32_t i = 0; i < m5::stl::size(nolinebreak_std_padding_table); ++i) {
auto& e = nolinebreak_std_padding_table[i];
if (e.ilen == 0) continue; // skip empty input
auto written = decode_base64(output, sizeof(output), e.expected, e.expected_len, false, true);
EXPECT_EQ(written, e.ilen) << "idx:" << i;
EXPECT_TRUE(memcmp(output, e.input, written) == 0) << "idx:" << i;
}
}
// Decode: nolinebreak, std, no padding
{
SCOPED_TRACE("decode: nolinebreak, std, nopad");
for (uint32_t i = 0; i < m5::stl::size(nolinebreak_std_nopad_table); ++i) {
auto& e = nolinebreak_std_nopad_table[i];
if (e.ilen == 0) continue;
auto written = decode_base64(output, sizeof(output), e.expected, e.expected_len, false, false);
EXPECT_EQ(written, e.ilen) << "idx:" << i;
EXPECT_TRUE(memcmp(output, e.input, written) == 0) << "idx:" << i;
}
}
// Decode: nolinebreak, url, padding
{
SCOPED_TRACE("decode: nolinebreak, url, padding");
for (uint32_t i = 0; i < m5::stl::size(nolinebreak_url_padding_table); ++i) {
auto& e = nolinebreak_url_padding_table[i];
if (e.ilen == 0) continue;
auto written = decode_base64(output, sizeof(output), e.expected, e.expected_len, true, true);
EXPECT_EQ(written, e.ilen) << "idx:" << i;
EXPECT_TRUE(memcmp(output, e.input, written) == 0) << "idx:" << i;
}
}
// Decode: nolinebreak, url, no padding
{
SCOPED_TRACE("decode: nolinebreak, url, nopad");
for (uint32_t i = 0; i < m5::stl::size(nolinebreak_url_nopad_table); ++i) {
auto& e = nolinebreak_url_nopad_table[i];
if (e.ilen == 0) continue;
auto written = decode_base64(output, sizeof(output), e.expected, e.expected_len, true, false);
EXPECT_EQ(written, e.ilen) << "idx:" << i;
EXPECT_TRUE(memcmp(output, e.input, written) == 0) << "idx:" << i;
}
}
// Decode with linebreaks: std, padding
{
SCOPED_TRACE("decode: linebreak, std, padding");
for (uint32_t i = 0; i < m5::stl::size(linebreak_std_padding_table); ++i) {
auto& e = linebreak_std_padding_table[i];
if (e.ilen == 0) continue;
auto written = decode_base64(output, sizeof(output), e.expected, e.expected_len, false, true);
EXPECT_EQ(written, e.ilen) << "idx:" << i;
EXPECT_TRUE(memcmp(output, e.input, written) == 0) << "idx:" << i;
}
}
// Decode with linebreaks: url, padding
{
SCOPED_TRACE("decode: linebreak, url, padding");
for (uint32_t i = 0; i < m5::stl::size(linebreak_url_padding_table); ++i) {
auto& e = linebreak_url_padding_table[i];
if (e.ilen == 0) continue;
auto written = decode_base64(output, sizeof(output), e.expected, e.expected_len, true, true);
EXPECT_EQ(written, e.ilen) << "idx:" << i;
EXPECT_TRUE(memcmp(output, e.input, written) == 0) << "idx:" << i;
}
}
}
TEST(Utility, Base64DecodeErrors)
{
SCOPED_TRACE("Base64DecodeErrors");
uint8_t output[128]{};
// Invalid characters in standard base64
{
SCOPED_TRACE("invalid char in std");
const char* invalid_std = "SGVs#G8="; // '#' is invalid
auto written = decode_base64(output, sizeof(output), invalid_std, 8, false, true);
EXPECT_EQ(written, 0u);
}
// URL-safe chars in standard mode should fail
{
SCOPED_TRACE("url char in std mode");
const char* url_in_std = "3q2-7w=="; // '-' is URL-safe, not standard
auto written = decode_base64(output, sizeof(output), url_in_std, 8, false, true);
EXPECT_EQ(written, 0u);
}
// Standard chars in URL mode should fail
{
SCOPED_TRACE("std char in url mode");
const char* std_in_url = "3q2+7w=="; // '+' is standard, not URL-safe
auto written = decode_base64(output, sizeof(output), std_in_url, 8, true, true);
EXPECT_EQ(written, 0u);
}
// Padding when padding=false should fail
{
SCOPED_TRACE("padding when disabled");
const char* with_padding = "AA==";
auto written = decode_base64(output, sizeof(output), with_padding, 4, false, false);
EXPECT_EQ(written, 0u);
}
// Incomplete group with padding=true should fail (expects '=' in input)
{
SCOPED_TRACE("incomplete group with padding=true");
const char* incomplete = "AAA"; // 3 chars, needs '=' padding char when padding=true
auto written = decode_base64(output, sizeof(output), incomplete, 3, false, true);
EXPECT_EQ(written, 0u);
}
// Incomplete group with padding=false should succeed (auto-pad)
{
SCOPED_TRACE("incomplete group with padding=false");
const char* incomplete = "AAA"; // 3 chars, will be auto-padded
auto written = decode_base64(output, sizeof(output), incomplete, 3, false, false);
EXPECT_EQ(written, 2u);
}
// NULL output buffer
{
SCOPED_TRACE("null output");
const char* valid = "SGVsbG8=";
auto written = decode_base64(nullptr, 128, valid, 8, false, true);
EXPECT_EQ(written, 0u);
}
// Zero output length
{
SCOPED_TRACE("zero output length");
const char* valid = "SGVsbG8=";
auto written = decode_base64(output, 0, valid, 8, false, true);
EXPECT_EQ(written, 0u);
}
// NULL input buffer
{
SCOPED_TRACE("null input");
auto written = decode_base64(output, sizeof(output), nullptr, 8, false, true);
EXPECT_EQ(written, 0u);
}
// Zero input length
{
SCOPED_TRACE("zero input length");
const char* valid = "SGVsbG8=";
auto written = decode_base64(output, sizeof(output), valid, 0, false, true);
EXPECT_EQ(written, 0u);
}
// Output buffer too small
{
SCOPED_TRACE("output buffer too small");
const char* valid = "SGVsbG8="; // decodes to "Hello" (5 bytes)
auto written = decode_base64(output, 3, valid, 8, false, true);
EXPECT_EQ(written, 0u);
}
}
TEST(Utility, Base64Roundtrip)
{
SCOPED_TRACE("Base64Roundtrip");
// Test roundtrip: encode then decode should return original
const uint8_t original[] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF};
char encoded[64]{};
uint8_t decoded[64]{};
// Standard with padding
{
SCOPED_TRACE("roundtrip: std, padding");
auto enc_len = encode_base64(encoded, sizeof(encoded), original, sizeof(original), 0, false, true);
EXPECT_GT(enc_len, 0u);
auto dec_len = decode_base64(decoded, sizeof(decoded), encoded, enc_len, false, true);
EXPECT_EQ(dec_len, sizeof(original));
EXPECT_TRUE(memcmp(decoded, original, sizeof(original)) == 0);
}
// Standard without padding
{
SCOPED_TRACE("roundtrip: std, nopad");
auto enc_len = encode_base64(encoded, sizeof(encoded), original, sizeof(original), 0, false, false);
EXPECT_GT(enc_len, 0u);
auto dec_len = decode_base64(decoded, sizeof(decoded), encoded, enc_len, false, false);
EXPECT_EQ(dec_len, sizeof(original));
EXPECT_TRUE(memcmp(decoded, original, sizeof(original)) == 0);
}
// URL with padding
{
SCOPED_TRACE("roundtrip: url, padding");
auto enc_len = encode_base64(encoded, sizeof(encoded), original, sizeof(original), 0, true, true);
EXPECT_GT(enc_len, 0u);
auto dec_len = decode_base64(decoded, sizeof(decoded), encoded, enc_len, true, true);
EXPECT_EQ(dec_len, sizeof(original));
EXPECT_TRUE(memcmp(decoded, original, sizeof(original)) == 0);
}
// URL without padding
{
SCOPED_TRACE("roundtrip: url, nopad");
auto enc_len = encode_base64(encoded, sizeof(encoded), original, sizeof(original), 0, true, false);
EXPECT_GT(enc_len, 0u);
auto dec_len = decode_base64(decoded, sizeof(decoded), encoded, enc_len, true, false);
EXPECT_EQ(dec_len, sizeof(original));
EXPECT_TRUE(memcmp(decoded, original, sizeof(original)) == 0);
}
// With linebreaks
{
SCOPED_TRACE("roundtrip: with linebreaks");
auto enc_len = encode_base64(encoded, sizeof(encoded), original, sizeof(original), 8, false, true);
EXPECT_GT(enc_len, 0u);
auto dec_len = decode_base64(decoded, sizeof(decoded), encoded, enc_len, false, true);
EXPECT_EQ(dec_len, sizeof(original));
EXPECT_TRUE(memcmp(decoded, original, sizeof(original)) == 0);
}
// Various input sizes (1 to 16 bytes)
{
SCOPED_TRACE("roundtrip: various sizes");
for (uint32_t size = 1; size <= 16; ++size) {
auto enc_len = encode_base64(encoded, sizeof(encoded), original, size, 0, false, true);
EXPECT_GT(enc_len, 0u) << "size:" << size;
auto dec_len = decode_base64(decoded, sizeof(decoded), encoded, enc_len, false, true);
EXPECT_EQ(dec_len, size) << "size:" << size;
EXPECT_TRUE(memcmp(decoded, original, size) == 0) << "size:" << size;
}
}
}
TEST(Utility, Base64LineBreakPositions)
{
SCOPED_TRACE("Base64LineBreakPositions");
// Helper to check line break positions
auto verify_linebreaks = [](const char* encoded, uint32_t len, uint8_t line_len) {
uint32_t char_count = 0; // characters since last line break
uint32_t line_count = 0; // number of complete lines
for (uint32_t i = 0; i < len; ++i) {
if (encoded[i] == '\n') {
// Line break should occur exactly at line_len
EXPECT_EQ(char_count, line_len) << "Line break at wrong position. Expected after " << (int)line_len
<< " chars, got after " << char_count << " at index " << i;
char_count = 0;
++line_count;
} else {
++char_count;
// Should not exceed line_len before a line break
EXPECT_LE(char_count, line_len)
<< "Too many characters (" << char_count << ") without line break at index " << i;
}
}
// Last line should NOT end with a newline (already stripped by encode)
if (len > 0) {
EXPECT_NE(encoded[len - 1], '\n') << "Output should not end with newline";
}
};
char output[256]{};
// Test with line_len = 4
{
SCOPED_TRACE("line_len=4");
// 12 bytes input -> 16 base64 chars -> 4 lines of 4 chars with 3 newlines
const uint8_t input[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B};
auto written = encode_base64(output, sizeof(output), input, sizeof(input), 4, false, true);
EXPECT_GT(written, 0u);
// Expected: "AAEC\nAwQF\nBgcI\nCQoL" (16 chars + 3 newlines = 19)
verify_linebreaks(output, written, 4);
// Count newlines
uint32_t newline_count = 0;
for (uint32_t i = 0; i < written; ++i) {
if (output[i] == '\n') ++newline_count;
}
EXPECT_EQ(newline_count, 3u); // 16/4 - 1 = 3 newlines
}
// Test with line_len = 8
{
SCOPED_TRACE("line_len=8");
// 12 bytes input -> 16 base64 chars -> 2 lines of 8 chars with 1 newline
const uint8_t input[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B};
auto written = encode_base64(output, sizeof(output), input, sizeof(input), 8, false, true);
EXPECT_GT(written, 0u);
verify_linebreaks(output, written, 8);
uint32_t newline_count = 0;
for (uint32_t i = 0; i < written; ++i) {
if (output[i] == '\n') ++newline_count;
}
EXPECT_EQ(newline_count, 1u); // 16/8 - 1 = 1 newline
}
// Test with line_len = 64 (PEM standard)
{
SCOPED_TRACE("line_len=64 (PEM)");
// 48 bytes input -> 64 base64 chars -> exactly 1 line, no newlines
const uint8_t input[48] = {0};
auto written = encode_base64(output, sizeof(output), input, sizeof(input), 64, false, true);
EXPECT_GT(written, 0u);
EXPECT_EQ(written, 64u); // exactly 64 chars, no newline
uint32_t newline_count = 0;
for (uint32_t i = 0; i < written; ++i) {
if (output[i] == '\n') ++newline_count;
}
EXPECT_EQ(newline_count, 0u); // exactly fits, no newline needed
}
// Test with line_len = 64, input slightly larger
{
SCOPED_TRACE("line_len=64, overflow");
// 49 bytes input -> 68 base64 chars (with padding) -> 1 line of 64 + 1 line of 4
const uint8_t input[49] = {0};
auto written = encode_base64(output, sizeof(output), input, sizeof(input), 64, false, true);
EXPECT_GT(written, 0u);
verify_linebreaks(output, written, 64);
uint32_t newline_count = 0;
for (uint32_t i = 0; i < written; ++i) {
if (output[i] == '\n') ++newline_count;
}
EXPECT_EQ(newline_count, 1u); // one newline after first 64 chars
}
// Test short input (less than line_len)
{
SCOPED_TRACE("short input");
// 3 bytes input -> 4 base64 chars -> no newlines needed
const uint8_t input[] = {0x01, 0x02, 0x03};
auto written = encode_base64(output, sizeof(output), input, sizeof(input), 64, false, true);
EXPECT_EQ(written, 4u);
uint32_t newline_count = 0;
for (uint32_t i = 0; i < written; ++i) {
if (output[i] == '\n') ++newline_count;
}
EXPECT_EQ(newline_count, 0u);
}
// Test with padding and line breaks
{
SCOPED_TRACE("padding with linebreak");
// 5 bytes -> 8 chars (with ==) -> with line_len=4: "AQID\nBAU=" (4+1+4=9)
const uint8_t input[] = {0x01, 0x02, 0x03, 0x04, 0x05};
auto written = encode_base64(output, sizeof(output), input, sizeof(input), 4, false, true);
EXPECT_GT(written, 0u);
verify_linebreaks(output, written, 4);
// Check padding is present
EXPECT_EQ(output[written - 1], '=');
}
}
TEST(Utility, Base64EncodeErrors)
{
SCOPED_TRACE("Base64EncodeErrors");
char output[128]{};
// NULL output buffer
{
SCOPED_TRACE("null output");
const uint8_t input[] = {0x01, 0x02, 0x03};
auto written = encode_base64(nullptr, 128, input, sizeof(input), 0, false, true);
EXPECT_EQ(written, 0u);
}
// Zero output length
{
SCOPED_TRACE("zero output length");
const uint8_t input[] = {0x01, 0x02, 0x03};
auto written = encode_base64(output, 0, input, sizeof(input), 0, false, true);
EXPECT_EQ(written, 0u);
}
// NULL input buffer
{
SCOPED_TRACE("null input");
auto written = encode_base64(output, sizeof(output), nullptr, 3, 0, false, true);
EXPECT_EQ(written, 0u);
}
// Zero input length
{
SCOPED_TRACE("zero input length");
const uint8_t input[] = {0x01, 0x02, 0x03};
auto written = encode_base64(output, sizeof(output), input, 0, 0, false, true);
EXPECT_EQ(written, 0u);
}
// Output buffer too small for minimal output (1 byte -> 4 chars + null)
{
SCOPED_TRACE("buffer too small for 1 byte");
const uint8_t input[] = {0x00};
// 1 byte input needs 4 chars ("AA==") + null terminator
// Buffer size 4 should fail (need 5 for null)
auto written = encode_base64(output, 4, input, 1, 0, false, true);
EXPECT_EQ(written, 0u);
}
// Output buffer exactly enough
{
SCOPED_TRACE("buffer exactly enough");
const uint8_t input[] = {0x00};
// 1 byte needs 4 chars + null = 5 bytes
auto written = encode_base64(output, 5, input, 1, 0, false, true);
EXPECT_EQ(written, 4u);
EXPECT_STREQ(output, "AA==");
}
// Output buffer too small for longer input
{
SCOPED_TRACE("buffer too small for 3 bytes");
const uint8_t input[] = {0x01, 0x02, 0x03};
// 3 bytes -> 4 chars, needs 5 bytes for null
auto written = encode_base64(output, 4, input, sizeof(input), 0, false, true);
EXPECT_EQ(written, 0u);
}
// Output buffer too small with linebreaks
{
SCOPED_TRACE("buffer too small with linebreaks");
const uint8_t input[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06};
// 6 bytes -> 8 chars, with line_len=4: "AQID\nBAYG" = 9 chars
// First verify actual output length
auto actual_len = encode_base64(output, sizeof(output), input, sizeof(input), 4, false, true);
EXPECT_GT(actual_len, 0u);
// Buffer one byte too small should fail
auto written = encode_base64(output, actual_len, input, sizeof(input), 4, false, true);
EXPECT_EQ(written, 0u);
}
// Buffer just enough with linebreaks
// Note: encode_base64 needs extra space for potential trailing newline
// (which gets removed), so we need actual_len + 2
{
SCOPED_TRACE("buffer just enough with linebreaks");
const uint8_t input[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06};
// First get actual length needed
auto actual_len = encode_base64(output, sizeof(output), input, sizeof(input), 4, false, true);
EXPECT_GT(actual_len, 0u);
// Buffer one short of minimum should fail
auto written = encode_base64(output, actual_len + 1, input, sizeof(input), 4, false, true);
EXPECT_EQ(written, 0u);
// Buffer with extra space for temp newline should succeed
written = encode_base64(output, actual_len + 2, input, sizeof(input), 4, false, true);
EXPECT_EQ(written, actual_len);
}
// Output buffer too small for padding
{
SCOPED_TRACE("buffer too small for padding");
const uint8_t input[] = {0x01, 0x02}; // 2 bytes -> "AQI=" (4 chars with padding)
auto written = encode_base64(output, 4, input, sizeof(input), 0, false, true);
EXPECT_EQ(written, 0u); // needs 5 for null
}
// Without padding, shorter output
{
SCOPED_TRACE("without padding shorter");
const uint8_t input[] = {0x01, 0x02}; // 2 bytes -> "AQI" (3 chars without padding)
auto written = encode_base64(output, 4, input, sizeof(input), 0, false, false);
EXPECT_EQ(written, 3u);
EXPECT_STREQ(output, "AQI");
}
// Large input, buffer boundary
{
SCOPED_TRACE("large input buffer boundary");
const uint8_t input[48] = {0}; // 48 bytes -> 64 chars + null = 65 bytes needed
auto written = encode_base64(output, 64, input, sizeof(input), 0, false, true);
EXPECT_EQ(written, 0u); // needs 65
written = encode_base64(output, 65, input, sizeof(input), 0, false, true);
EXPECT_EQ(written, 64u);
}
}