TestShortRead.cpp (3287B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this file, 5 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "gtest/gtest.h" 8 #include "mozilla/ErrorNames.h" 9 #include "nsCOMPtr.h" 10 #include "nsConverterInputStream.h" 11 #include "nsIInputStream.h" 12 #include "nsISupports.h" 13 #include "nsStringStream.h" 14 15 namespace { 16 17 class ShortReadWrapper final : public nsIInputStream { 18 public: 19 NS_DECL_THREADSAFE_ISUPPORTS 20 NS_DECL_NSIINPUTSTREAM 21 22 template <size_t N> 23 ShortReadWrapper(const uint32_t (&aShortReads)[N], 24 nsIInputStream* aBaseStream) 25 : mShortReadIter(std::begin(aShortReads)), 26 mShortReadEnd(std::end(aShortReads)), 27 mBaseStream(aBaseStream) {} 28 29 ShortReadWrapper(const ShortReadWrapper&) = delete; 30 ShortReadWrapper& operator=(const ShortReadWrapper&) = delete; 31 32 private: 33 ~ShortReadWrapper() = default; 34 35 const uint32_t* mShortReadIter; 36 const uint32_t* mShortReadEnd; 37 nsCOMPtr<nsIInputStream> mBaseStream; 38 }; 39 40 NS_IMPL_ISUPPORTS(ShortReadWrapper, nsIInputStream) 41 42 NS_IMETHODIMP 43 ShortReadWrapper::Close() { return mBaseStream->Close(); } 44 45 NS_IMETHODIMP 46 ShortReadWrapper::Available(uint64_t* aAvailable) { 47 nsresult rv = mBaseStream->Available(aAvailable); 48 NS_ENSURE_SUCCESS(rv, rv); 49 50 if (mShortReadIter != mShortReadEnd) { 51 *aAvailable = std::min(uint64_t(*mShortReadIter), *aAvailable); 52 } 53 return NS_OK; 54 } 55 56 NS_IMETHODIMP 57 ShortReadWrapper::StreamStatus() { return mBaseStream->StreamStatus(); } 58 59 NS_IMETHODIMP 60 ShortReadWrapper::Read(char* aBuf, uint32_t aCount, uint32_t* _retval) { 61 if (mShortReadIter != mShortReadEnd) { 62 aCount = std::min(*mShortReadIter, aCount); 63 } 64 65 nsresult rv = mBaseStream->Read(aBuf, aCount, _retval); 66 if (NS_SUCCEEDED(rv) && mShortReadIter != mShortReadEnd) { 67 ++mShortReadIter; 68 } 69 return rv; 70 } 71 72 NS_IMETHODIMP 73 ShortReadWrapper::ReadSegments(nsWriteSegmentFun aWriter, void* aClosure, 74 uint32_t aCount, uint32_t* _retval) { 75 return NS_ERROR_NOT_IMPLEMENTED; 76 } 77 78 NS_IMETHODIMP 79 ShortReadWrapper::IsNonBlocking(bool* _retval) { 80 return mBaseStream->IsNonBlocking(_retval); 81 } 82 83 } // namespace 84 85 TEST(ConverterStreamShortRead, ShortRead) 86 { 87 uint8_t bytes[] = {0xd8, 0x35, 0xdc, 0x20}; 88 nsCOMPtr<nsIInputStream> baseStream; 89 ASSERT_TRUE(NS_SUCCEEDED(NS_NewByteInputStream(getter_AddRefs(baseStream), 90 AsChars(mozilla::Span(bytes)), 91 NS_ASSIGNMENT_COPY))); 92 93 static const uint32_t kShortReads[] = {1, 2, 1}; 94 nsCOMPtr<nsIInputStream> shortStream = 95 new ShortReadWrapper(kShortReads, baseStream); 96 97 RefPtr<nsConverterInputStream> unicharStream = new nsConverterInputStream(); 98 ASSERT_TRUE(NS_SUCCEEDED( 99 unicharStream->Init(shortStream, "UTF-16BE", 4096, 100 nsIConverterInputStream::ERRORS_ARE_FATAL))); 101 102 uint32_t read; 103 nsAutoString result; 104 ASSERT_TRUE( 105 NS_SUCCEEDED(unicharStream->ReadString(UINT32_MAX, result, &read))); 106 107 ASSERT_EQ(read, 2u); 108 ASSERT_TRUE(result == u"\U0001d420"); 109 }