mirror of
https://github.com/m5stack/M5Utility.git
synced 2026-05-20 11:27:29 -07:00
1036 lines
53 KiB
C++
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);
|
|
}
|
|
}
|