|  | // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #include <memory> | 
|  |  | 
|  | #include "android_webview/native/input_stream_impl.h" | 
|  | #include "base/android/jni_android.h" | 
|  | #include "base/android/scoped_java_ref.h" | 
|  | #include "jni/InputStreamUnittest_jni.h" | 
|  | #include "net/base/io_buffer.h" | 
|  | #include "net/base/net_errors.h" | 
|  | #include "net/http/http_byte_range.h" | 
|  | #include "testing/gmock/include/gmock/gmock.h" | 
|  | #include "testing/gtest/include/gtest/gtest.h" | 
|  |  | 
|  | using android_webview::InputStream; | 
|  | using android_webview::InputStreamImpl; | 
|  | using base::android::AttachCurrentThread; | 
|  | using base::android::ScopedJavaLocalRef; | 
|  | using net::IOBuffer; | 
|  | using testing::DoAll; | 
|  | using testing::Ge; | 
|  | using testing::InSequence; | 
|  | using testing::Lt; | 
|  | using testing::Ne; | 
|  | using testing::NotNull; | 
|  | using testing::Return; | 
|  | using testing::SetArgPointee; | 
|  | using testing::Test; | 
|  | using testing::_; | 
|  |  | 
|  | class InputStreamTest : public Test { | 
|  | public: | 
|  | InputStreamTest() { | 
|  | } | 
|  | protected: | 
|  | void SetUp() override { | 
|  | env_ = AttachCurrentThread(); | 
|  | ASSERT_THAT(env_, NotNull()); | 
|  | } | 
|  |  | 
|  | scoped_refptr<IOBuffer> DoReadCountedStreamTest(int stream_size, | 
|  | int bytes_requested, | 
|  | int* bytes_read) { | 
|  | ScopedJavaLocalRef<jobject> counting_jstream = | 
|  | Java_InputStreamUnittest_getCountingStream(env_, stream_size); | 
|  | EXPECT_FALSE(counting_jstream.is_null()); | 
|  |  | 
|  | std::unique_ptr<InputStream> input_stream( | 
|  | new InputStreamImpl(counting_jstream)); | 
|  | scoped_refptr<IOBuffer> buffer = new IOBuffer(bytes_requested); | 
|  |  | 
|  | EXPECT_TRUE(input_stream->Read(buffer.get(), bytes_requested, bytes_read)); | 
|  | return buffer; | 
|  | } | 
|  |  | 
|  | JNIEnv* env_; | 
|  | }; | 
|  |  | 
|  | TEST_F(InputStreamTest, ReadEmptyStream) { | 
|  | ScopedJavaLocalRef<jobject> empty_jstream = | 
|  | Java_InputStreamUnittest_getEmptyStream(env_); | 
|  | EXPECT_FALSE(empty_jstream.is_null()); | 
|  |  | 
|  | std::unique_ptr<InputStream> input_stream(new InputStreamImpl(empty_jstream)); | 
|  | const int bytes_requested = 10; | 
|  | int bytes_read = 0; | 
|  | scoped_refptr<IOBuffer> buffer = new IOBuffer(bytes_requested); | 
|  |  | 
|  | EXPECT_TRUE(input_stream->Read(buffer.get(), bytes_requested, &bytes_read)); | 
|  | EXPECT_EQ(0, bytes_read); | 
|  | } | 
|  |  | 
|  | TEST_F(InputStreamTest, ReadStreamPartial) { | 
|  | const int bytes_requested = 128; | 
|  | int bytes_read = 0; | 
|  | DoReadCountedStreamTest(bytes_requested * 2, bytes_requested, &bytes_read); | 
|  | EXPECT_EQ(bytes_requested, bytes_read); | 
|  | } | 
|  |  | 
|  | TEST_F(InputStreamTest, ReadStreamCompletely) { | 
|  | const int bytes_requested = 42; | 
|  | int bytes_read = 0; | 
|  | DoReadCountedStreamTest(bytes_requested, bytes_requested, &bytes_read); | 
|  | EXPECT_EQ(bytes_requested, bytes_read); | 
|  | } | 
|  |  | 
|  | TEST_F(InputStreamTest, TryReadMoreThanBuffer) { | 
|  | const int buffer_size = 3 * InputStreamImpl::kBufferSize; | 
|  | int bytes_read = 0; | 
|  | DoReadCountedStreamTest(buffer_size, buffer_size * 2, &bytes_read); | 
|  | EXPECT_EQ(buffer_size, bytes_read); | 
|  | } | 
|  |  | 
|  | TEST_F(InputStreamTest, CheckContentsReadCorrectly) { | 
|  | const int bytes_requested = 256; | 
|  | int bytes_read = 0; | 
|  | scoped_refptr<IOBuffer> buffer = | 
|  | DoReadCountedStreamTest(bytes_requested, bytes_requested, &bytes_read); | 
|  | EXPECT_EQ(bytes_requested, bytes_read); | 
|  | for (int i = 0; i < bytes_requested; ++i) { | 
|  | EXPECT_EQ(i, (unsigned char)buffer->data()[i]); | 
|  | } | 
|  | } | 
|  |  | 
|  | TEST_F(InputStreamTest, ReadLargeStreamPartial) { | 
|  | const int bytes_requested = 3 * InputStreamImpl::kBufferSize; | 
|  | int bytes_read = 0; | 
|  | DoReadCountedStreamTest(bytes_requested + 32, bytes_requested, &bytes_read); | 
|  | EXPECT_EQ(bytes_requested, bytes_read); | 
|  | } | 
|  |  | 
|  | TEST_F(InputStreamTest, ReadLargeStreamCompletely) { | 
|  | const int bytes_requested = 3 * InputStreamImpl::kBufferSize; | 
|  | int bytes_read = 0; | 
|  | DoReadCountedStreamTest(bytes_requested, bytes_requested, &bytes_read); | 
|  | EXPECT_EQ(bytes_requested, bytes_read); | 
|  | } | 
|  |  | 
|  | TEST_F(InputStreamTest, DoesNotCrashWhenExceptionThrown) { | 
|  | ScopedJavaLocalRef<jobject> throw_jstream = | 
|  | Java_InputStreamUnittest_getThrowingStream(env_); | 
|  | EXPECT_FALSE(throw_jstream.is_null()); | 
|  |  | 
|  | std::unique_ptr<InputStream> input_stream(new InputStreamImpl(throw_jstream)); | 
|  |  | 
|  | int64_t bytes_skipped; | 
|  | EXPECT_FALSE(input_stream->Skip(10, &bytes_skipped)); | 
|  |  | 
|  | int bytes_available; | 
|  | EXPECT_FALSE(input_stream->BytesAvailable(&bytes_available)); | 
|  |  | 
|  |  | 
|  | const int bytes_requested = 10; | 
|  | int bytes_read = 0; | 
|  | scoped_refptr<IOBuffer> buffer = new IOBuffer(bytes_requested); | 
|  | EXPECT_FALSE(input_stream->Read(buffer.get(), bytes_requested, &bytes_read)); | 
|  | EXPECT_EQ(0, bytes_read); | 
|  |  | 
|  | // This closes the stream. | 
|  | input_stream.reset(NULL); | 
|  | } |