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

Side by Side Diff: net/filter/brotli_filter_unittest.cc

Issue 1431723002: Add brotli content-encoding filter. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Add brotli reference link Created 5 years, 1 month 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 unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <fstream>
6 #include <ostream>
7
8 #include "base/files/file_util.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/path_service.h"
11 #include "net/base/io_buffer.h"
12 #include "net/filter/brotli_filter.h"
13 #include "net/filter/mock_filter_context.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15 #include "testing/platform_test.h"
16
17 namespace {
18 const int kDefaultBufferSize = 4096;
19 const int kSmallBufferSize = 128;
20 } // namespace
21
22 namespace net {
23
24 // These tests use the path service, which uses autoreleased objects on the
25 // Mac, so this needs to be a PlatformTest.
26 class BrotliUnitTest : public PlatformTest {
27 protected:
28 void SetUp() override {
29 PlatformTest::SetUp();
30
31 filter_context_.SetBrotliEnabled(true);
32
33 // Get the path of data directory.
34 base::FilePath data_dir;
35 PathService::Get(base::DIR_SOURCE_ROOT, &data_dir);
36 data_dir = data_dir.AppendASCII("net");
37 data_dir = data_dir.AppendASCII("data");
38 data_dir = data_dir.AppendASCII("filter_unittests");
39
40 // Read data from the original file into buffer.
41 base::FilePath file_path;
42 file_path = data_dir.AppendASCII("google.txt");
43 ASSERT_TRUE(base::ReadFileToString(file_path, &source_buffer_));
44
45 // Read data from the encoded file into buffer.
46 base::FilePath encoded_file_path;
47 encoded_file_path = data_dir.AppendASCII("google.br");
48 ASSERT_TRUE(base::ReadFileToString(encoded_file_path, &encoded_buffer_));
49 ASSERT_TRUE(encoded_buffer_.size() <= kDefaultBufferSize);
50 }
51
52 void TearDown() override { PlatformTest::TearDown(); }
53
54 // Use filter to decode compressed data, and compare the decoding result with
55 // the orginal Data.
56 // Parameters: Source and source_len are original data and its size.
57 // Encoded_source and encoded_source_len are compressed data and its size.
58 // Output_buffer_size specifies the size of buffer to read out data from
59 // filter.
60 void DecodeAndCompareWithFilter(Filter* filter,
61 const char* source,
62 int source_len,
63 const char* encoded_source,
64 int encoded_source_len,
65 int output_buffer_size) {
66 // Make sure we have enough space to hold the decoding output.
67 ASSERT_TRUE(source_len <= kDefaultBufferSize);
68 ASSERT_TRUE(output_buffer_size <= kDefaultBufferSize);
69
70 char decode_buffer[kDefaultBufferSize];
71 char* decode_next = decode_buffer;
72 int decode_avail_size = kDefaultBufferSize;
73
74 const char* encode_next = encoded_source;
75 int encode_avail_size = encoded_source_len;
76
77 int code = Filter::FILTER_OK;
78 while (code != Filter::FILTER_DONE) {
79 int encode_data_len;
80 encode_data_len =
81 std::min(encode_avail_size, filter->stream_buffer_size());
82 memcpy(filter->stream_buffer()->data(), encode_next, encode_data_len);
83 filter->FlushStreamBuffer(encode_data_len);
84 encode_next += encode_data_len;
85 encode_avail_size -= encode_data_len;
86
87 while (1) {
88 int decode_data_len = std::min(decode_avail_size, output_buffer_size);
89
90 code = filter->ReadData(decode_next, &decode_data_len);
91 decode_next += decode_data_len;
92 decode_avail_size -= decode_data_len;
93
94 ASSERT_TRUE(code != Filter::FILTER_ERROR);
95
96 if (code == Filter::FILTER_NEED_MORE_DATA ||
97 code == Filter::FILTER_DONE) {
98 break;
99 }
100 }
101 }
102
103 // Compare the decoding result with source data
104 int decode_total_data_len = kDefaultBufferSize - decode_avail_size;
105 EXPECT_TRUE(decode_total_data_len == source_len);
106 EXPECT_EQ(memcmp(source, decode_buffer, source_len), 0);
107 }
108
109 // Unsafe function to use filter to decode compressed data.
110 // Parameters: Source and source_len are compressed data and its size.
111 // Dest is the buffer for decoding results. Upon entry, *dest_len is the size
112 // of the dest buffer. Upon exit, *dest_len is the number of chars written
113 // into the buffer.
114 int DecodeAllWithFilter(Filter* filter,
115 const char* source,
116 int source_len,
117 char* dest,
118 int* dest_len) {
119 memcpy(filter->stream_buffer()->data(), source, source_len);
120 filter->FlushStreamBuffer(source_len);
121 return filter->ReadData(dest, dest_len);
122 }
123
124 void InitFilter() {
125 std::vector<Filter::FilterType> filter_types;
126 filter_types.push_back(Filter::FILTER_TYPE_BROTLI);
127 filter_.reset(Filter::Factory(filter_types, filter_context_));
128 ASSERT_TRUE(filter_.get());
129 ASSERT_GE(filter_->stream_buffer_size(), kDefaultBufferSize);
130 }
131
132 void InitFilterWithBufferSize(int buffer_size) {
133 std::vector<Filter::FilterType> filter_types;
134 filter_types.push_back(Filter::FILTER_TYPE_BROTLI);
135 filter_.reset(
136 Filter::FactoryForTests(filter_types, filter_context_, buffer_size));
137 ASSERT_TRUE(filter_.get());
138 }
139
140 const char* source_buffer() const { return source_buffer_.data(); }
141 int source_len() const { return static_cast<int>(source_buffer_.size()); }
142
143 const char* encoded_buffer() const { return encoded_buffer_.data(); }
144 int encoded_len() const { return static_cast<int>(encoded_buffer_.size()); }
145
146 scoped_ptr<Filter> filter_;
147
148 std::string source_buffer_;
149 std::string encoded_buffer_;
150
151 private:
152 MockFilterContext filter_context_;
153 };
154
155 // Basic scenario: decoding gzip data with big enough buffer.
156 TEST_F(BrotliUnitTest, DecodeBrotli) {
157 InitFilter();
158 memcpy(filter_->stream_buffer()->data(), encoded_buffer(), encoded_len());
159 filter_->FlushStreamBuffer(encoded_len());
160
161 char decode_buffer[kDefaultBufferSize];
162 int decode_size = kDefaultBufferSize;
163 filter_->ReadData(decode_buffer, &decode_size);
164
165 // Compare the decoding result with source data
166 EXPECT_TRUE(decode_size == source_len());
167 EXPECT_EQ(memcmp(source_buffer(), decode_buffer, source_len()), 0);
168 }
169
170 // Tests we can call filter repeatedly to get all the data decoded.
171 // To do that, we create a filter with a small buffer that can not hold all
172 // the input data.
173 TEST_F(BrotliUnitTest, DecodeWithSmallBuffer) {
174 InitFilterWithBufferSize(kSmallBufferSize);
175 EXPECT_EQ(kSmallBufferSize, filter_->stream_buffer_size());
176 DecodeAndCompareWithFilter(filter_.get(), source_buffer(), source_len(),
177 encoded_buffer(), encoded_len(),
178 kDefaultBufferSize);
179 }
180
181 // Tests we can still decode with just 1 byte buffer in the filter.
182 // The purpose of this test: sometimes the filter will consume input without
183 // generating output. Verify filter can handle it correctly.
184 TEST_F(BrotliUnitTest, DecodeWithOneByteBuffer) {
185 InitFilterWithBufferSize(1);
186 EXPECT_EQ(1, filter_->stream_buffer_size());
187 DecodeAndCompareWithFilter(filter_.get(), source_buffer(), source_len(),
188 encoded_buffer(), encoded_len(),
189 kDefaultBufferSize);
190 }
191
192 // Tests we can decode when caller has small buffer to read out from filter.
193 TEST_F(BrotliUnitTest, DecodeWithSmallOutputBuffer) {
194 InitFilter();
195 DecodeAndCompareWithFilter(filter_.get(), source_buffer(), source_len(),
196 encoded_buffer(), encoded_len(), kSmallBufferSize);
197 }
198
199 // Tests we can still decode with just 1 byte buffer in the filter and just 1
200 // byte buffer in the caller.
201 TEST_F(BrotliUnitTest, DecodeWithOneByteInputAndOutputBuffer) {
202 InitFilterWithBufferSize(1);
203 EXPECT_EQ(1, filter_->stream_buffer_size());
204 DecodeAndCompareWithFilter(filter_.get(), source_buffer(), source_len(),
205 encoded_buffer(), encoded_len(), 1);
206 }
207
208 // Decoding deflate stream with corrupted data.
209 TEST_F(BrotliUnitTest, DecodeCorruptedData) {
210 char corrupt_data[kDefaultBufferSize];
211 int corrupt_data_len = encoded_len();
212 memcpy(corrupt_data, encoded_buffer(), encoded_len());
213
214 int pos = corrupt_data_len / 2;
215 corrupt_data[pos] = !corrupt_data[pos];
216
217 // Decode the corrupted data with filter
218 InitFilter();
219 char corrupt_decode_buffer[kDefaultBufferSize];
220 int corrupt_decode_size = kDefaultBufferSize;
221
222 int code = DecodeAllWithFilter(filter_.get(), corrupt_data, corrupt_data_len,
223 corrupt_decode_buffer, &corrupt_decode_size);
224
225 // Expect failures
226 EXPECT_TRUE(code == Filter::FILTER_ERROR);
227 }
228
229 // Decoding deflate stream with missing data.
230 TEST_F(BrotliUnitTest, DecodeMissingData) {
231 char corrupt_data[kDefaultBufferSize];
232 int corrupt_data_len = encoded_len();
233 memcpy(corrupt_data, encoded_buffer(), encoded_len());
234
235 int pos = corrupt_data_len / 2;
236 int len = corrupt_data_len - pos - 1;
237 memmove(&corrupt_data[pos], &corrupt_data[pos + 1], len);
238 --corrupt_data_len;
239
240 // Decode the corrupted data with filter
241 InitFilter();
242 char corrupt_decode_buffer[kDefaultBufferSize];
243 int corrupt_decode_size = kDefaultBufferSize;
244
245 int code = DecodeAllWithFilter(filter_.get(), corrupt_data, corrupt_data_len,
246 corrupt_decode_buffer, &corrupt_decode_size);
247
248 // Expect failures
249 EXPECT_EQ(Filter::FILTER_ERROR, code);
250 }
251 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698