TestBase64Stream.cpp (3404B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 #include "gtest/gtest.h" 7 #include "mozilla/Base64.h" 8 #include "mozilla/gtest/MozAssertions.h" 9 #include "nsCOMPtr.h" 10 #include "nsIInputStream.h" 11 #include "nsStringStream.h" 12 13 namespace mozilla { 14 namespace net { 15 16 // An input stream whose ReadSegments method calls aWriter with writes of size 17 // aStep from the provided aInput in order to test edge-cases related to small 18 // buffers. 19 class TestStream final : public nsIInputStream { 20 public: 21 NS_DECL_ISUPPORTS; 22 23 TestStream(const nsACString& aInput, uint32_t aStep) 24 : mInput(aInput), mStep(aStep) {} 25 26 NS_IMETHOD Close() override { MOZ_CRASH("This should not be called"); } 27 28 NS_IMETHOD Available(uint64_t* aLength) override { 29 *aLength = mInput.Length() - mPos; 30 return NS_OK; 31 } 32 33 NS_IMETHOD StreamStatus() override { return NS_OK; } 34 35 NS_IMETHOD Read(char* aBuffer, uint32_t aCount, 36 uint32_t* aReadCount) override { 37 MOZ_CRASH("This should not be called"); 38 } 39 40 NS_IMETHOD ReadSegments(nsWriteSegmentFun aWriter, void* aClosure, 41 uint32_t aCount, uint32_t* aResult) override { 42 *aResult = 0; 43 44 if (mPos == mInput.Length()) { 45 return NS_OK; 46 } 47 48 while (aCount > 0) { 49 uint32_t amt = std::min(mStep, (uint32_t)(mInput.Length() - mPos)); 50 51 uint32_t read = 0; 52 nsresult rv = 53 aWriter(this, aClosure, mInput.get() + mPos, *aResult, amt, &read); 54 if (NS_WARN_IF(NS_FAILED(rv))) { 55 return rv; 56 } 57 58 *aResult += read; 59 aCount -= read; 60 mPos += read; 61 } 62 63 return NS_OK; 64 } 65 66 NS_IMETHOD IsNonBlocking(bool* aNonBlocking) override { 67 *aNonBlocking = true; 68 return NS_OK; 69 } 70 71 private: 72 ~TestStream() = default; 73 74 nsCString mInput; 75 const uint32_t mStep; 76 uint32_t mPos = 0; 77 }; 78 79 NS_IMPL_ISUPPORTS(TestStream, nsIInputStream) 80 81 // Test the base64 encoder with writer buffer sizes between 1 byte and the 82 // entire length of "Hello World!" in order to exercise various edge cases. 83 TEST(TestBase64Stream, Run) 84 { 85 nsCString input; 86 input.AssignLiteral("Hello World!"); 87 88 for (uint32_t step = 1; step <= input.Length(); ++step) { 89 RefPtr<TestStream> ts = new TestStream(input, step); 90 91 nsAutoString encodedData; 92 nsresult rv = Base64EncodeInputStream(ts, encodedData, input.Length()); 93 ASSERT_NS_SUCCEEDED(rv); 94 95 EXPECT_TRUE(encodedData.EqualsLiteral("SGVsbG8gV29ybGQh")); 96 } 97 } 98 99 TEST(TestBase64Stream, VaryingCount) 100 { 101 nsCString input; 102 input.AssignLiteral("Hello World!"); 103 104 std::pair<size_t, nsCString> tests[] = { 105 {0, "SGVsbG8gV29ybGQh"_ns}, {1, "SA=="_ns}, 106 {5, "SGVsbG8="_ns}, {11, "SGVsbG8gV29ybGQ="_ns}, 107 {12, "SGVsbG8gV29ybGQh"_ns}, {13, "SGVsbG8gV29ybGQh"_ns}, 108 }; 109 110 for (auto& [count, expected] : tests) { 111 nsCOMPtr<nsIInputStream> is; 112 nsresult rv = NS_NewCStringInputStream(getter_AddRefs(is), input); 113 ASSERT_NS_SUCCEEDED(rv); 114 115 nsAutoCString encodedData; 116 rv = Base64EncodeInputStream(is, encodedData, count); 117 ASSERT_NS_SUCCEEDED(rv); 118 EXPECT_EQ(encodedData, expected) << "count: " << count; 119 } 120 } 121 122 } // namespace net 123 } // namespace mozilla