|  | /* | 
|  | *  Copyright (c) 2025 The WebRTC project authors. All Rights Reserved. | 
|  | * | 
|  | *  Use of this source code is governed by a BSD-style license | 
|  | *  that can be found in the LICENSE file in the root of the source | 
|  | *  tree. An additional intellectual property rights grant can be found | 
|  | *  in the file PATENTS.  All contributing project authors may | 
|  | *  be found in the AUTHORS file in the root of the source tree. | 
|  | */ | 
|  |  | 
|  | #include "rtc_base/base64.h" | 
|  |  | 
|  | #include <optional> | 
|  | #include <string> | 
|  |  | 
|  | #include "absl/strings/string_view.h" | 
|  | #include "test/gmock.h" | 
|  | #include "test/gtest.h" | 
|  |  | 
|  | namespace webrtc { | 
|  | namespace { | 
|  |  | 
|  | using ::testing::Eq; | 
|  | using ::testing::Optional; | 
|  | using ::testing::SizeIs; | 
|  | using ::testing::TestWithParam; | 
|  |  | 
|  | TEST(Base64Test, Encode) { | 
|  | std::string data{0x64, 0x65, 0x66}; | 
|  | EXPECT_THAT(Base64Encode(data), Eq("ZGVm")); | 
|  | } | 
|  |  | 
|  | TEST(Base64Test, EncodeDecode) { | 
|  | std::string data{0x01, 0x02, 0x03, 0x04, 0x05}; | 
|  | EXPECT_THAT(Base64Decode(Base64Encode(data)), Optional(Eq(data))); | 
|  | } | 
|  |  | 
|  | TEST(Base64Test, DecodeCertificate) { | 
|  | // Certificate data often contains newlines, which are not valid base64 | 
|  | // characters but parsable using the forgiving option. | 
|  | constexpr absl::string_view kExampleCertificateData = | 
|  | "MIIB6TCCAVICAQYwDQYJKoZIhvcNAQEEBQAwWzELMAkGA1UEBhMCQVUxEzARBgNV\n" | 
|  | "BAgTClF1ZWVuc2xhbmQxGjAYBgNVBAoTEUNyeXB0U29mdCBQdHkgTHRkMRswGQYD\n" | 
|  | "VQQDExJUZXN0IENBICgxMDI0IGJpdCkwHhcNMDAxMDE2MjIzMTAzWhcNMDMwMTE0\n" | 
|  | "MjIzMTAzWjBjMQswCQYDVQQGEwJBVTETMBEGA1UECBMKUXVlZW5zbGFuZDEaMBgG\n" | 
|  | "A1UEChMRQ3J5cHRTb2Z0IFB0eSBMdGQxIzAhBgNVBAMTGlNlcnZlciB0ZXN0IGNl\n" | 
|  | "cnQgKDUxMiBiaXQpMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJ+zw4Qnlf8SMVIP\n" | 
|  | "Fe9GEcStgOY2Ww/dgNdhjeD8ckUJNP5VZkVDTGiXav6ooKXfX3j/7tdkuD8Ey2//\n" | 
|  | "Kv7+ue0CAwEAATANBgkqhkiG9w0BAQQFAAOBgQCT0grFQeZaqYb5EYfk20XixZV4\n" | 
|  | "GmyAbXMftG1Eo7qGiMhYzRwGNWxEYojf5PZkYZXvSqZ/ZXHXa4g59jK/rJNnaVGM\n" | 
|  | "k+xIX8mxQvlV0n5O9PIha5BX5teZnkHKgL8aKKLKW1BK7YTngsfSzzaeame5iKfz\n" | 
|  | "itAE+OjGF+PFKbwX8Q==\n"; | 
|  |  | 
|  | EXPECT_THAT( | 
|  | Base64Decode(kExampleCertificateData, Base64DecodeOptions::kForgiving), | 
|  | Optional(SizeIs(493))); | 
|  | EXPECT_THAT( | 
|  | Base64Decode(kExampleCertificateData, Base64DecodeOptions::kStrict), | 
|  | Eq(std::nullopt)); | 
|  | } | 
|  |  | 
|  | struct Base64DecodeTestCase { | 
|  | std::string name; | 
|  | std::string data; | 
|  | std::optional<std::string> result; | 
|  | }; | 
|  |  | 
|  | const Base64DecodeTestCase kBase64DecodeTestCases[] = { | 
|  | {"InvalidCharacters", "invalid;;;", std::nullopt}, | 
|  | {"InvalidLength", "abcde", std::nullopt}, | 
|  | {"ValidInput", "abcd", "i\xB7\x1D"}, | 
|  | {"ValidInputPadding", "abc=", "i\xB7"}, | 
|  | {"EmptyInput", "", ""}, | 
|  | }; | 
|  |  | 
|  | using Base64DecodeTest = TestWithParam<Base64DecodeTestCase>; | 
|  | INSTANTIATE_TEST_SUITE_P( | 
|  | Base64DecodeTest, | 
|  | Base64DecodeTest, | 
|  | testing::ValuesIn<Base64DecodeTestCase>(kBase64DecodeTestCases), | 
|  | [](const auto& info) { return info.param.name; }); | 
|  |  | 
|  | TEST_P(Base64DecodeTest, TestDecodeStrict) { | 
|  | absl::string_view data = GetParam().data; | 
|  | EXPECT_THAT(Base64Decode(data, Base64DecodeOptions::kStrict), | 
|  | Eq(GetParam().result)); | 
|  | } | 
|  |  | 
|  | TEST_P(Base64DecodeTest, TestDecodeForgiving) { | 
|  | // Test default value is strict. | 
|  | EXPECT_THAT(Base64Decode(GetParam().data), Eq(GetParam().result)); | 
|  | } | 
|  |  | 
|  | const Base64DecodeTestCase kBase64DecodeForgivingTestCases[] = { | 
|  | { | 
|  | "ForgivingPadding", | 
|  | "abc", | 
|  | "i\xB7", | 
|  | }, | 
|  | { | 
|  | "WhitespaceForgivenTab", | 
|  | "ab\tcd", | 
|  | "i\xB7\x1D", | 
|  | }, | 
|  | { | 
|  | "WhitespaceForgivenSpace", | 
|  | "a bc d", | 
|  | "i\xB7\x1D", | 
|  | }, | 
|  | { | 
|  | "WhitespaceForgivenNewline", | 
|  | "a\nbc\nd", | 
|  | "i\xB7\x1D", | 
|  | }, | 
|  | { | 
|  | "WhitespaceForgivenCarriageReturn", | 
|  | "a\r\nbc\rd", | 
|  | "i\xB7\x1D", | 
|  | }, | 
|  | {"WhitespaceForgivenLineFeed", "a\fbcd", "i\xB7\x1D"}, | 
|  | }; | 
|  |  | 
|  | using Base64DecodeForgivingTest = TestWithParam<Base64DecodeTestCase>; | 
|  | INSTANTIATE_TEST_SUITE_P( | 
|  | Base64DecodeTest, | 
|  | Base64DecodeForgivingTest, | 
|  | testing::ValuesIn<Base64DecodeTestCase>(kBase64DecodeForgivingTestCases), | 
|  | [](const auto& info) { return info.param.name; }); | 
|  |  | 
|  | TEST_P(Base64DecodeForgivingTest, TestDecodeForgiving) { | 
|  | EXPECT_THAT(Base64Decode(GetParam().data, Base64DecodeOptions::kForgiving), | 
|  | Eq(GetParam().result)); | 
|  | } | 
|  |  | 
|  | TEST_P(Base64DecodeForgivingTest, TestDecodeStrictFails) { | 
|  | // Test default value is strict. | 
|  | EXPECT_THAT(Base64Decode(GetParam().data), Eq(std::nullopt)); | 
|  | } | 
|  |  | 
|  | }  // namespace | 
|  | }  // namespace webrtc |