brotli_source_stream_unittest.cc 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. // Copyright 2016 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. #include <string>
  5. #include <utility>
  6. #include "base/bind.h"
  7. #include "base/callback.h"
  8. #include "base/files/file_util.h"
  9. #include "base/memory/raw_ptr.h"
  10. #include "base/path_service.h"
  11. #include "base/run_loop.h"
  12. #include "net/base/io_buffer.h"
  13. #include "net/base/test_completion_callback.h"
  14. #include "net/filter/brotli_source_stream.h"
  15. #include "net/filter/mock_source_stream.h"
  16. #include "testing/gtest/include/gtest/gtest.h"
  17. #include "testing/platform_test.h"
  18. namespace net {
  19. namespace {
  20. const size_t kDefaultBufferSize = 4096;
  21. const size_t kSmallBufferSize = 128;
  22. } // namespace
  23. class BrotliSourceStreamTest : public PlatformTest {
  24. protected:
  25. void SetUp() override {
  26. PlatformTest::SetUp();
  27. // Get the path of data directory.
  28. base::FilePath data_dir;
  29. base::PathService::Get(base::DIR_SOURCE_ROOT, &data_dir);
  30. data_dir = data_dir.AppendASCII("net");
  31. data_dir = data_dir.AppendASCII("data");
  32. data_dir = data_dir.AppendASCII("filter_unittests");
  33. // Read data from the original file into buffer.
  34. base::FilePath file_path;
  35. file_path = data_dir.AppendASCII("google.txt");
  36. ASSERT_TRUE(base::ReadFileToString(file_path, &source_data_));
  37. ASSERT_GE(kDefaultBufferSize, source_data_.size());
  38. // Read data from the encoded file into buffer.
  39. base::FilePath encoded_file_path;
  40. encoded_file_path = data_dir.AppendASCII("google.br");
  41. ASSERT_TRUE(base::ReadFileToString(encoded_file_path, &encoded_buffer_));
  42. ASSERT_GE(kDefaultBufferSize, encoded_buffer_.size());
  43. auto source = std::make_unique<MockSourceStream>();
  44. source_ = source.get();
  45. brotli_stream_ = CreateBrotliSourceStream(std::move(source));
  46. }
  47. int ReadStream(net::CompletionOnceCallback callback) {
  48. return brotli_stream_->Read(out_buffer(), out_data_size(),
  49. std::move(callback));
  50. }
  51. IOBuffer* out_buffer() { return out_buffer_.get(); }
  52. char* out_data() { return out_buffer_->data(); }
  53. size_t out_data_size() { return out_buffer_->size(); }
  54. std::string source_data() { return source_data_; }
  55. size_t source_data_len() { return source_data_.length(); }
  56. char* encoded_buffer() { return &encoded_buffer_[0]; }
  57. size_t encoded_len() { return encoded_buffer_.length(); }
  58. MockSourceStream* source() { return source_; }
  59. SourceStream* brotli_stream() { return brotli_stream_.get(); }
  60. scoped_refptr<IOBufferWithSize> out_buffer_;
  61. private:
  62. raw_ptr<MockSourceStream> source_;
  63. std::unique_ptr<SourceStream> brotli_stream_;
  64. std::unique_ptr<base::RunLoop> loop_;
  65. std::string source_data_;
  66. std::string encoded_buffer_;
  67. };
  68. // Basic scenario: decoding brotli data with big enough buffer.
  69. TEST_F(BrotliSourceStreamTest, DecodeBrotliOneBlockSync) {
  70. source()->AddReadResult(encoded_buffer(), encoded_len(), OK,
  71. MockSourceStream::SYNC);
  72. out_buffer_ = base::MakeRefCounted<IOBufferWithSize>(kDefaultBufferSize);
  73. TestCompletionCallback callback;
  74. int bytes_read = ReadStream(callback.callback());
  75. EXPECT_EQ(static_cast<int>(source_data_len()), bytes_read);
  76. EXPECT_EQ(0, memcmp(out_data(), source_data().c_str(), source_data_len()));
  77. EXPECT_EQ("BROTLI", brotli_stream()->Description());
  78. }
  79. // Regression test for crbug.com/659311. The following example is taken out
  80. // of the bug report. For this specific example, Brotli will consume the first
  81. // byte in the 6 available bytes and return 0.
  82. TEST_F(BrotliSourceStreamTest, IgnoreExtraData) {
  83. const unsigned char kResponse[] = {0x1A, 0xDF, 0x6E, 0x74, 0x74, 0x68};
  84. source()->AddReadResult(reinterpret_cast<const char*>(kResponse),
  85. sizeof(kResponse), OK, MockSourceStream::SYNC);
  86. // Add an EOF.
  87. source()->AddReadResult(reinterpret_cast<const char*>(kResponse), 0, OK,
  88. MockSourceStream::SYNC);
  89. out_buffer_ = base::MakeRefCounted<IOBufferWithSize>(kDefaultBufferSize);
  90. std::string actual_output;
  91. TestCompletionCallback callback;
  92. int bytes_read = ReadStream(callback.callback());
  93. EXPECT_EQ(0, bytes_read);
  94. EXPECT_EQ("BROTLI", brotli_stream()->Description());
  95. }
  96. // If there are data after decoding is done, ignore the data. crbug.com/659311.
  97. TEST_F(BrotliSourceStreamTest, IgnoreExtraDataInOneRead) {
  98. std::string response_with_extra_data(encoded_buffer(), encoded_len());
  99. response_with_extra_data.append(1000, 'x');
  100. source()->AddReadResult(response_with_extra_data.c_str(),
  101. response_with_extra_data.length(), OK,
  102. MockSourceStream::SYNC);
  103. // Add an EOF.
  104. source()->AddReadResult(response_with_extra_data.c_str(), 0, OK,
  105. MockSourceStream::SYNC);
  106. out_buffer_ = base::MakeRefCounted<IOBufferWithSize>(kDefaultBufferSize);
  107. std::string actual_output;
  108. while (true) {
  109. TestCompletionCallback callback;
  110. int bytes_read = ReadStream(callback.callback());
  111. if (bytes_read == OK)
  112. break;
  113. ASSERT_GT(bytes_read, OK);
  114. actual_output.append(out_data(), bytes_read);
  115. }
  116. EXPECT_EQ(source_data_len(), actual_output.size());
  117. EXPECT_EQ(source_data(), actual_output);
  118. EXPECT_EQ("BROTLI", brotli_stream()->Description());
  119. }
  120. // Same as above but extra data is in a different read.
  121. TEST_F(BrotliSourceStreamTest, IgnoreExtraDataInDifferentRead) {
  122. std::string extra_data;
  123. extra_data.append(1000, 'x');
  124. source()->AddReadResult(encoded_buffer(), encoded_len(), OK,
  125. MockSourceStream::SYNC);
  126. source()->AddReadResult(extra_data.c_str(), extra_data.length(), OK,
  127. MockSourceStream::SYNC);
  128. // Add an EOF.
  129. source()->AddReadResult(extra_data.c_str(), 0, OK, MockSourceStream::SYNC);
  130. out_buffer_ = base::MakeRefCounted<IOBufferWithSize>(kDefaultBufferSize);
  131. std::string actual_output;
  132. while (true) {
  133. TestCompletionCallback callback;
  134. int bytes_read = ReadStream(callback.callback());
  135. if (bytes_read == OK)
  136. break;
  137. ASSERT_GT(bytes_read, OK);
  138. actual_output.append(out_data(), bytes_read);
  139. }
  140. EXPECT_EQ(source_data_len(), actual_output.size());
  141. EXPECT_EQ(source_data(), actual_output);
  142. EXPECT_EQ("BROTLI", brotli_stream()->Description());
  143. }
  144. // Basic scenario: decoding brotli data with big enough buffer.
  145. TEST_F(BrotliSourceStreamTest, DecodeBrotliTwoBlockSync) {
  146. source()->AddReadResult(encoded_buffer(), 10, OK, MockSourceStream::SYNC);
  147. source()->AddReadResult(encoded_buffer() + 10, encoded_len() - 10, OK,
  148. MockSourceStream::SYNC);
  149. out_buffer_ = base::MakeRefCounted<IOBufferWithSize>(kDefaultBufferSize);
  150. TestCompletionCallback callback;
  151. int bytes_read = ReadStream(callback.callback());
  152. EXPECT_EQ(static_cast<int>(source_data_len()), bytes_read);
  153. EXPECT_EQ(0, memcmp(out_data(), source_data().c_str(), source_data_len()));
  154. EXPECT_EQ("BROTLI", brotli_stream()->Description());
  155. }
  156. // Basic scenario: decoding brotli data with big enough buffer.
  157. TEST_F(BrotliSourceStreamTest, DecodeBrotliOneBlockAsync) {
  158. source()->AddReadResult(encoded_buffer(), encoded_len(), OK,
  159. MockSourceStream::ASYNC);
  160. out_buffer_ = base::MakeRefCounted<IOBufferWithSize>(kDefaultBufferSize);
  161. TestCompletionCallback callback;
  162. int bytes_read = ReadStream(callback.callback());
  163. EXPECT_EQ(ERR_IO_PENDING, bytes_read);
  164. source()->CompleteNextRead();
  165. int rv = callback.WaitForResult();
  166. EXPECT_EQ(static_cast<int>(source_data_len()), rv);
  167. EXPECT_EQ(0, memcmp(out_data(), source_data().c_str(), source_data_len()));
  168. EXPECT_EQ("BROTLI", brotli_stream()->Description());
  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(BrotliSourceStreamTest, DecodeWithSmallBufferSync) {
  174. source()->AddReadResult(encoded_buffer(), encoded_len(), OK,
  175. MockSourceStream::SYNC);
  176. // Add a 0 byte read to signal EOF.
  177. source()->AddReadResult(encoded_buffer(), 0, OK, MockSourceStream::SYNC);
  178. out_buffer_ = base::MakeRefCounted<IOBufferWithSize>(kSmallBufferSize);
  179. scoped_refptr<IOBuffer> buffer =
  180. base::MakeRefCounted<IOBufferWithSize>(source_data_len());
  181. size_t total_bytes_read = 0;
  182. int bytes_read = 0;
  183. do {
  184. TestCompletionCallback callback;
  185. bytes_read = ReadStream(callback.callback());
  186. EXPECT_LE(OK, bytes_read);
  187. EXPECT_GE(kSmallBufferSize, static_cast<size_t>(bytes_read));
  188. memcpy(buffer->data() + total_bytes_read, out_data(), bytes_read);
  189. total_bytes_read += bytes_read;
  190. } while (bytes_read > 0);
  191. EXPECT_EQ(source_data_len(), total_bytes_read);
  192. EXPECT_EQ(0, memcmp(buffer->data(), source_data().c_str(), total_bytes_read));
  193. EXPECT_EQ("BROTLI", brotli_stream()->Description());
  194. }
  195. // Tests we can call filter repeatedly to get all the data decoded.
  196. // To do that, we create a filter with a small buffer that can not hold all
  197. // the input data.
  198. TEST_F(BrotliSourceStreamTest, DecodeWithSmallBufferAsync) {
  199. source()->AddReadResult(encoded_buffer(), encoded_len(), OK,
  200. MockSourceStream::ASYNC);
  201. // Add a 0 byte read to signal EOF.
  202. source()->AddReadResult(encoded_buffer(), 0, OK, MockSourceStream::ASYNC);
  203. out_buffer_ = base::MakeRefCounted<IOBufferWithSize>(kSmallBufferSize);
  204. scoped_refptr<IOBuffer> buffer =
  205. base::MakeRefCounted<IOBufferWithSize>(source_data_len());
  206. size_t total_bytes_read = 0;
  207. int bytes_read = 0;
  208. do {
  209. TestCompletionCallback callback;
  210. bytes_read = ReadStream(callback.callback());
  211. if (bytes_read == ERR_IO_PENDING) {
  212. source()->CompleteNextRead();
  213. bytes_read = callback.WaitForResult();
  214. }
  215. EXPECT_GE(static_cast<int>(kSmallBufferSize), bytes_read);
  216. memcpy(buffer->data() + total_bytes_read, out_data(), bytes_read);
  217. total_bytes_read += bytes_read;
  218. } while (bytes_read > 0);
  219. EXPECT_EQ(source_data_len(), total_bytes_read);
  220. EXPECT_EQ(0, memcmp(buffer->data(), source_data().c_str(), total_bytes_read));
  221. EXPECT_EQ("BROTLI", brotli_stream()->Description());
  222. }
  223. // Tests we can still decode with just 1 byte buffer in the filter.
  224. // The purpose of this test: sometimes the filter will consume input without
  225. // generating output. Verify filter can handle it correctly.
  226. TEST_F(BrotliSourceStreamTest, DecodeWithOneByteBuffer) {
  227. source()->AddReadResult(encoded_buffer(), encoded_len(), OK,
  228. MockSourceStream::SYNC);
  229. // Add a 0 byte read to signal EOF.
  230. source()->AddReadResult(encoded_buffer(), 0, OK, MockSourceStream::SYNC);
  231. out_buffer_ = base::MakeRefCounted<IOBufferWithSize>(1);
  232. scoped_refptr<IOBuffer> buffer =
  233. base::MakeRefCounted<IOBufferWithSize>(source_data_len());
  234. size_t total_bytes_read = 0;
  235. int bytes_read = 0;
  236. do {
  237. TestCompletionCallback callback;
  238. bytes_read = ReadStream(callback.callback());
  239. EXPECT_NE(ERR_IO_PENDING, bytes_read);
  240. EXPECT_GE(1, bytes_read);
  241. memcpy(buffer->data() + total_bytes_read, out_data(), bytes_read);
  242. total_bytes_read += bytes_read;
  243. } while (bytes_read > 0);
  244. EXPECT_EQ(source_data_len(), total_bytes_read);
  245. EXPECT_EQ(0,
  246. memcmp(buffer->data(), source_data().c_str(), source_data_len()));
  247. EXPECT_EQ("BROTLI", brotli_stream()->Description());
  248. }
  249. // Decoding deflate stream with corrupted data.
  250. TEST_F(BrotliSourceStreamTest, DecodeCorruptedData) {
  251. char corrupt_data[kDefaultBufferSize];
  252. int corrupt_data_len = encoded_len();
  253. memcpy(corrupt_data, encoded_buffer(), encoded_len());
  254. int pos = corrupt_data_len / 2;
  255. corrupt_data[pos] = !corrupt_data[pos];
  256. source()->AddReadResult(corrupt_data, corrupt_data_len, OK,
  257. MockSourceStream::SYNC);
  258. out_buffer_ = base::MakeRefCounted<IOBufferWithSize>(kDefaultBufferSize);
  259. int error = OK;
  260. do {
  261. TestCompletionCallback callback;
  262. error = ReadStream(callback.callback());
  263. EXPECT_NE(ERR_IO_PENDING, error);
  264. } while (error > 0);
  265. // Expect failures
  266. EXPECT_EQ(ERR_CONTENT_DECODING_FAILED, error);
  267. // Calling Read again gives the same error.
  268. TestCompletionCallback callback;
  269. error = ReadStream(callback.callback());
  270. EXPECT_EQ(ERR_CONTENT_DECODING_FAILED, error);
  271. EXPECT_EQ("BROTLI", brotli_stream()->Description());
  272. }
  273. // Decoding deflate stream with missing data.
  274. TEST_F(BrotliSourceStreamTest, DecodeMissingData) {
  275. char corrupt_data[kDefaultBufferSize];
  276. int corrupt_data_len = encoded_len();
  277. memcpy(corrupt_data, encoded_buffer(), encoded_len());
  278. int pos = corrupt_data_len / 2;
  279. int len = corrupt_data_len - pos - 1;
  280. memmove(&corrupt_data[pos], &corrupt_data[pos + 1], len);
  281. --corrupt_data_len;
  282. // Decode the corrupted data with filter
  283. source()->AddReadResult(corrupt_data, corrupt_data_len, OK,
  284. MockSourceStream::SYNC);
  285. out_buffer_ = base::MakeRefCounted<IOBufferWithSize>(kDefaultBufferSize);
  286. int error = OK;
  287. do {
  288. TestCompletionCallback callback;
  289. error = ReadStream(callback.callback());
  290. EXPECT_NE(ERR_IO_PENDING, error);
  291. } while (error > 0);
  292. // Expect failures
  293. EXPECT_EQ(ERR_CONTENT_DECODING_FAILED, error);
  294. EXPECT_EQ("BROTLI", brotli_stream()->Description());
  295. }
  296. // Decoding brotli stream with empty output data.
  297. TEST_F(BrotliSourceStreamTest, DecodeEmptyData) {
  298. char data[1] = {6}; // WBITS = 16, ISLAST = 1, ISLASTEMPTY = 1
  299. int data_len = 1;
  300. source()->AddReadResult(data, data_len, OK, MockSourceStream::SYNC);
  301. source()->AddReadResult(data, 0, OK, MockSourceStream::SYNC);
  302. out_buffer_ = base::MakeRefCounted<IOBufferWithSize>(kDefaultBufferSize);
  303. TestCompletionCallback callback;
  304. int bytes_read = ReadStream(callback.callback());
  305. EXPECT_EQ(OK, bytes_read);
  306. EXPECT_EQ("BROTLI", brotli_stream()->Description());
  307. }
  308. } // namespace net