| /* | 
 |  *  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 |