Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(100)

Unified Diff: net/filter/brotli_source_stream_unittest.cc

Issue 2329973003: Add net::BrotliSourceStream (Closed)
Patch Set: Sync-ed to 92104a0503b2862f54d60473b59dd1ae145eb22b Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/filter/brotli_source_stream_disabled.cc ('k') | net/net.gypi » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/filter/brotli_source_stream_unittest.cc
diff --git a/net/filter/brotli_source_stream_unittest.cc b/net/filter/brotli_source_stream_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..4a0fd1e70f320f6c9b19a934a04de65b3336e327
--- /dev/null
+++ b/net/filter/brotli_source_stream_unittest.cc
@@ -0,0 +1,275 @@
+// Copyright 2016 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 <string>
+
+#include "base/bind.h"
+#include "base/bit_cast.h"
+#include "base/callback.h"
+#include "base/files/file_util.h"
+#include "base/path_service.h"
+#include "base/run_loop.h"
+#include "net/base/io_buffer.h"
+#include "net/base/test_completion_callback.h"
+#include "net/filter/brotli_source_stream.h"
+#include "net/filter/mock_source_stream.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/platform_test.h"
+
+namespace net {
+
+namespace {
+
+const size_t kDefaultBufferSize = 4096;
+const size_t kSmallBufferSize = 128;
+
+} // namespace
+
+class BrotliSourceStreamTest : public PlatformTest {
+ protected:
+ void SetUp() override {
+ PlatformTest::SetUp();
+
+ // Get the path of data directory.
+ base::FilePath data_dir;
+ PathService::Get(base::DIR_SOURCE_ROOT, &data_dir);
+ data_dir = data_dir.AppendASCII("net");
+ data_dir = data_dir.AppendASCII("data");
+ data_dir = data_dir.AppendASCII("filter_unittests");
+
+ // Read data from the original file into buffer.
+ base::FilePath file_path;
+ file_path = data_dir.AppendASCII("google.txt");
+ ASSERT_TRUE(base::ReadFileToString(file_path, &source_data_));
+ ASSERT_GE(kDefaultBufferSize, source_data_.size());
+
+ // Read data from the encoded file into buffer.
+ base::FilePath encoded_file_path;
+ encoded_file_path = data_dir.AppendASCII("google.br");
+ ASSERT_TRUE(base::ReadFileToString(encoded_file_path, &encoded_buffer_));
+ ASSERT_GE(kDefaultBufferSize, encoded_buffer_.size());
+
+ std::unique_ptr<MockSourceStream> source(new MockSourceStream);
+ source_ = source.get();
+ brotli_stream_ = CreateBrotliSourceStream(std::move(source));
+ }
+
+ int ReadStream(const TestCompletionCallback& callback) {
+ return brotli_stream_->Read(out_buffer(), out_data_size(),
+ callback.callback());
+ }
+
+ IOBuffer* out_buffer() { return out_buffer_.get(); }
+ char* out_data() { return out_buffer_->data(); }
+ size_t out_data_size() { return out_buffer_->size(); }
+
+ std::string source_data() { return source_data_; }
+
+ size_t source_data_len() { return source_data_.length(); }
+
+ char* encoded_buffer() { return &encoded_buffer_[0]; }
+
+ size_t encoded_len() { return encoded_buffer_.length(); }
+
+ MockSourceStream* source() { return source_; }
+ SourceStream* brotli_stream() { return brotli_stream_.get(); }
+ scoped_refptr<IOBufferWithSize> out_buffer_;
+
+ private:
+ MockSourceStream* source_;
+ std::unique_ptr<SourceStream> brotli_stream_;
+ std::unique_ptr<base::RunLoop> loop_;
+
+ std::string source_data_;
+ std::string encoded_buffer_;
+};
+
+// Basic scenario: decoding brotli data with big enough buffer.
+TEST_F(BrotliSourceStreamTest, DecodeBrotliOneBlockSync) {
+ source()->AddReadResult(encoded_buffer(), encoded_len(), OK,
+ MockSourceStream::SYNC);
+ out_buffer_ = new IOBufferWithSize(kDefaultBufferSize);
+ TestCompletionCallback callback;
+ int bytes_read = ReadStream(callback);
+
+ EXPECT_EQ(static_cast<int>(source_data_len()), bytes_read);
+ EXPECT_EQ(0, memcmp(out_data(), source_data().c_str(), source_data_len()));
+ EXPECT_EQ("BROTLI", brotli_stream()->Description());
+}
+
+// Basic scenario: decoding brotli data with big enough buffer.
+TEST_F(BrotliSourceStreamTest, DecodeBrotliTwoBlockSync) {
+ source()->AddReadResult(encoded_buffer(), 10, OK, MockSourceStream::SYNC);
+ source()->AddReadResult(encoded_buffer() + 10, encoded_len() - 10, OK,
+ MockSourceStream::SYNC);
+ out_buffer_ = new IOBufferWithSize(kDefaultBufferSize);
+ TestCompletionCallback callback;
+ int bytes_read = ReadStream(callback);
+ EXPECT_EQ(static_cast<int>(source_data_len()), bytes_read);
+ EXPECT_EQ(0, memcmp(out_data(), source_data().c_str(), source_data_len()));
+ EXPECT_EQ("BROTLI", brotli_stream()->Description());
+}
+
+// Basic scenario: decoding brotli data with big enough buffer.
+TEST_F(BrotliSourceStreamTest, DecodeBrotliOneBlockAsync) {
+ source()->AddReadResult(encoded_buffer(), encoded_len(), OK,
+ MockSourceStream::ASYNC);
+ out_buffer_ = new IOBufferWithSize(kDefaultBufferSize);
+ TestCompletionCallback callback;
+ int bytes_read = ReadStream(callback);
+
+ EXPECT_EQ(ERR_IO_PENDING, bytes_read);
+ source()->CompleteNextRead();
+ int rv = callback.WaitForResult();
+ EXPECT_EQ(static_cast<int>(source_data_len()), rv);
+ EXPECT_EQ(0, memcmp(out_data(), source_data().c_str(), source_data_len()));
+ EXPECT_EQ("BROTLI", brotli_stream()->Description());
+}
+
+// Tests we can call filter repeatedly to get all the data decoded.
+// To do that, we create a filter with a small buffer that can not hold all
+// the input data.
+TEST_F(BrotliSourceStreamTest, DecodeWithSmallBufferSync) {
+ source()->AddReadResult(encoded_buffer(), encoded_len(), OK,
+ MockSourceStream::SYNC);
+ // Add a 0 byte read to signal EOF.
+ source()->AddReadResult(encoded_buffer(), 0, OK, MockSourceStream::SYNC);
+
+ out_buffer_ = new IOBufferWithSize(kSmallBufferSize);
+
+ scoped_refptr<IOBuffer> buffer = new IOBufferWithSize(source_data_len());
+ size_t total_bytes_read = 0;
+ int bytes_read = 0;
+ TestCompletionCallback callback;
+ do {
+ bytes_read = ReadStream(callback);
+ EXPECT_LE(OK, bytes_read);
+ EXPECT_GE(kSmallBufferSize, static_cast<size_t>(bytes_read));
+ memcpy(buffer->data() + total_bytes_read, out_data(), bytes_read);
+ total_bytes_read += bytes_read;
+ } while (bytes_read > 0);
+ EXPECT_EQ(source_data_len(), total_bytes_read);
+ EXPECT_EQ(0, memcmp(buffer->data(), source_data().c_str(), total_bytes_read));
+ EXPECT_EQ("BROTLI", brotli_stream()->Description());
+}
+
+// Tests we can call filter repeatedly to get all the data decoded.
+// To do that, we create a filter with a small buffer that can not hold all
+// the input data.
+TEST_F(BrotliSourceStreamTest, DecodeWithSmallBufferAsync) {
+ source()->AddReadResult(encoded_buffer(), encoded_len(), OK,
+ MockSourceStream::ASYNC);
+ // Add a 0 byte read to signal EOF.
+ source()->AddReadResult(encoded_buffer(), 0, OK, MockSourceStream::ASYNC);
+
+ out_buffer_ = new IOBufferWithSize(kSmallBufferSize);
+
+ scoped_refptr<IOBuffer> buffer = new IOBufferWithSize(source_data_len());
+ size_t total_bytes_read = 0;
+ int bytes_read = 0;
+ do {
+ TestCompletionCallback callback;
+ bytes_read = ReadStream(callback);
+ if (bytes_read == ERR_IO_PENDING) {
+ source()->CompleteNextRead();
+ bytes_read = callback.WaitForResult();
+ }
+ EXPECT_GE(static_cast<int>(kSmallBufferSize), bytes_read);
+ memcpy(buffer->data() + total_bytes_read, out_data(), bytes_read);
+ total_bytes_read += bytes_read;
+ } while (bytes_read > 0);
+ EXPECT_EQ(source_data_len(), total_bytes_read);
+ EXPECT_EQ(0, memcmp(buffer->data(), source_data().c_str(), total_bytes_read));
+ EXPECT_EQ("BROTLI", brotli_stream()->Description());
+}
+
+// Tests we can still decode with just 1 byte buffer in the filter.
+// The purpose of this test: sometimes the filter will consume input without
+// generating output. Verify filter can handle it correctly.
+TEST_F(BrotliSourceStreamTest, DecodeWithOneByteBuffer) {
+ source()->AddReadResult(encoded_buffer(), encoded_len(), OK,
+ MockSourceStream::SYNC);
+ // Add a 0 byte read to signal EOF.
+ source()->AddReadResult(encoded_buffer(), 0, OK, MockSourceStream::SYNC);
+ out_buffer_ = new IOBufferWithSize(1);
+ scoped_refptr<IOBuffer> buffer = new IOBufferWithSize(source_data_len());
+ size_t total_bytes_read = 0;
+ int bytes_read = 0;
+ do {
+ TestCompletionCallback callback;
+ bytes_read = ReadStream(callback);
+ EXPECT_NE(ERR_IO_PENDING, bytes_read);
+ EXPECT_GE(1, bytes_read);
+ memcpy(buffer->data() + total_bytes_read, out_data(), bytes_read);
+ total_bytes_read += bytes_read;
+ } while (bytes_read > 0);
+ EXPECT_EQ(source_data_len(), total_bytes_read);
+ EXPECT_EQ(0,
+ memcmp(buffer->data(), source_data().c_str(), source_data_len()));
+ EXPECT_EQ("BROTLI", brotli_stream()->Description());
+}
+
+// Decoding deflate stream with corrupted data.
+TEST_F(BrotliSourceStreamTest, DecodeCorruptedData) {
+ char corrupt_data[kDefaultBufferSize];
+ int corrupt_data_len = encoded_len();
+ memcpy(corrupt_data, encoded_buffer(), encoded_len());
+ int pos = corrupt_data_len / 2;
+ corrupt_data[pos] = !corrupt_data[pos];
+
+ source()->AddReadResult(corrupt_data, corrupt_data_len, OK,
+ MockSourceStream::SYNC);
+ out_buffer_ = new IOBufferWithSize(kDefaultBufferSize);
+ int error = OK;
+ do {
+ TestCompletionCallback callback;
+ error = ReadStream(callback);
+ EXPECT_NE(ERR_IO_PENDING, error);
+ } while (error > 0);
+ // Expect failures
+ EXPECT_EQ(ERR_CONTENT_DECODING_FAILED, error);
+ EXPECT_EQ("BROTLI", brotli_stream()->Description());
+}
+
+// Decoding deflate stream with missing data.
+TEST_F(BrotliSourceStreamTest, DecodeMissingData) {
+ char corrupt_data[kDefaultBufferSize];
+ int corrupt_data_len = encoded_len();
+ memcpy(corrupt_data, encoded_buffer(), encoded_len());
+
+ int pos = corrupt_data_len / 2;
+ int len = corrupt_data_len - pos - 1;
+ memmove(&corrupt_data[pos], &corrupt_data[pos + 1], len);
+ --corrupt_data_len;
+
+ // Decode the corrupted data with filter
+ source()->AddReadResult(corrupt_data, corrupt_data_len, OK,
+ MockSourceStream::SYNC);
+ out_buffer_ = new IOBufferWithSize(kDefaultBufferSize);
+ int error = OK;
+ do {
+ TestCompletionCallback callback;
+ error = ReadStream(callback);
+ EXPECT_NE(ERR_IO_PENDING, error);
+ } while (error > 0);
+ // Expect failures
+ EXPECT_EQ(ERR_CONTENT_DECODING_FAILED, error);
+ EXPECT_EQ("BROTLI", brotli_stream()->Description());
+}
+
+// Decoding brotli stream with empty output data.
+TEST_F(BrotliSourceStreamTest, DecodeEmptyData) {
+ char data[1] = {6}; // WBITS = 16, ISLAST = 1, ISLASTEMPTY = 1
+ int data_len = 1;
+
+ source()->AddReadResult(data, data_len, OK, MockSourceStream::SYNC);
+ source()->AddReadResult(data, 0, OK, MockSourceStream::SYNC);
+ out_buffer_ = new IOBufferWithSize(kDefaultBufferSize);
+ TestCompletionCallback callback;
+ int bytes_read = ReadStream(callback);
+ EXPECT_EQ(OK, bytes_read);
+ EXPECT_EQ("BROTLI", brotli_stream()->Description());
+}
+
+} // namespace net
« no previous file with comments | « net/filter/brotli_source_stream_disabled.cc ('k') | net/net.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698