1 // Copyright (c) 2011 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 <iostream> 7 8 #if defined(USE_SYSTEM_ZLIB) 9 #include <zlib.h> 10 #else 11 #include "third_party/zlib/zlib.h" 12 #endif 13 14 #include "base/file_util.h" 15 #include "base/memory/scoped_ptr.h" 16 #include "base/path_service.h" 17 #include "net/base/gzip_filter.h" 18 #include "net/base/mock_filter_context.h" 19 #include "net/base/io_buffer.h" 20 #include "testing/gtest/include/gtest/gtest.h" 21 #include "testing/platform_test.h" 22 23 namespace { 24 25 const int kDefaultBufferSize = 4096; 26 const int kSmallBufferSize = 128; 27 28 const char kApplicationOctetStream[] = "application/octet-stream"; 29 const char kApplicationXGzip[] = "application/x-gzip"; 30 const char kApplicationGzip[] = "application/gzip"; 31 const char kApplicationXGunzip[] = "application/x-gunzip"; 32 33 // The GZIP header (see RFC 1952): 34 // +---+---+---+---+---+---+---+---+---+---+ 35 // |ID1|ID2|CM |FLG| MTIME |XFL|OS | 36 // +---+---+---+---+---+---+---+---+---+---+ 37 // ID1 \037 38 // ID2 \213 39 // CM \010 (compression method == DEFLATE) 40 // FLG \000 (special flags that we do not support) 41 // MTIME Unix format modification time (0 means not available) 42 // XFL 2-4? DEFLATE flags 43 // OS ???? Operating system indicator (255 means unknown) 44 // 45 // Header value we generate: 46 const char kGZipHeader[] = { '\037', '\213', '\010', '\000', '\000', 47 '\000', '\000', '\000', '\002', '\377' }; 48 49 enum EncodeMode { 50 ENCODE_GZIP, // Wrap the deflate with a GZip header. 51 ENCODE_DEFLATE // Raw deflate. 52 }; 53 54 } // namespace 55 56 namespace net { 57 58 // These tests use the path service, which uses autoreleased objects on the 59 // Mac, so this needs to be a PlatformTest. 60 class GZipUnitTest : public PlatformTest { 61 protected: 62 virtual void SetUp() { 63 PlatformTest::SetUp(); 64 65 deflate_encode_buffer_ = NULL; 66 gzip_encode_buffer_ = NULL; 67 68 // Get the path of source data file. 69 FilePath file_path; 70 PathService::Get(base::DIR_SOURCE_ROOT, &file_path); 71 file_path = file_path.AppendASCII("net"); 72 file_path = file_path.AppendASCII("data"); 73 file_path = file_path.AppendASCII("filter_unittests"); 74 file_path = file_path.AppendASCII("google.txt"); 75 76 // Read data from the file into buffer. 77 ASSERT_TRUE(file_util::ReadFileToString(file_path, &source_buffer_)); 78 79 // Encode the data with deflate 80 deflate_encode_buffer_ = new char[kDefaultBufferSize]; 81 ASSERT_TRUE(deflate_encode_buffer_ != NULL); 82 83 deflate_encode_len_ = kDefaultBufferSize; 84 int code = CompressAll(ENCODE_DEFLATE , source_buffer(), source_len(), 85 deflate_encode_buffer_, &deflate_encode_len_); 86 ASSERT_TRUE(code == Z_STREAM_END); 87 ASSERT_GT(deflate_encode_len_, 0); 88 ASSERT_TRUE(deflate_encode_len_ <= kDefaultBufferSize); 89 90 // Encode the data with gzip 91 gzip_encode_buffer_ = new char[kDefaultBufferSize]; 92 ASSERT_TRUE(gzip_encode_buffer_ != NULL); 93 94 gzip_encode_len_ = kDefaultBufferSize; 95 code = CompressAll(ENCODE_GZIP, source_buffer(), source_len(), 96 gzip_encode_buffer_, &gzip_encode_len_); 97 ASSERT_TRUE(code == Z_STREAM_END); 98 ASSERT_GT(gzip_encode_len_, 0); 99 ASSERT_TRUE(gzip_encode_len_ <= kDefaultBufferSize); 100 } 101 102 virtual void TearDown() { 103 delete[] deflate_encode_buffer_; 104 deflate_encode_buffer_ = NULL; 105 106 delete[] gzip_encode_buffer_; 107 gzip_encode_buffer_ = NULL; 108 109 PlatformTest::TearDown(); 110 } 111 112 // Compress the data in source with deflate encoding and write output to the 113 // buffer provided by dest. The function returns Z_OK if success, and returns 114 // other zlib error code if fail. 115 // The parameter mode specifies the encoding mechanism. 116 // The dest buffer should be large enough to hold all the output data. 117 int CompressAll(EncodeMode mode, const char* source, int source_size, 118 char* dest, int* dest_len) { 119 z_stream zlib_stream; 120 memset(&zlib_stream, 0, sizeof(zlib_stream)); 121 int code; 122 123 // Initialize zlib 124 if (mode == ENCODE_GZIP) { 125 code = deflateInit2(&zlib_stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 126 -MAX_WBITS, 127 8, // DEF_MEM_LEVEL 128 Z_DEFAULT_STRATEGY); 129 } else { 130 code = deflateInit(&zlib_stream, Z_DEFAULT_COMPRESSION); 131 } 132 133 if (code != Z_OK) 134 return code; 135 136 // Fill in zlib control block 137 zlib_stream.next_in = bit_cast<Bytef*>(source); 138 zlib_stream.avail_in = source_size; 139 zlib_stream.next_out = bit_cast<Bytef*>(dest); 140 zlib_stream.avail_out = *dest_len; 141 142 // Write header if needed 143 if (mode == ENCODE_GZIP) { 144 if (zlib_stream.avail_out < sizeof(kGZipHeader)) 145 return Z_BUF_ERROR; 146 memcpy(zlib_stream.next_out, kGZipHeader, sizeof(kGZipHeader)); 147 zlib_stream.next_out += sizeof(kGZipHeader); 148 zlib_stream.avail_out -= sizeof(kGZipHeader); 149 } 150 151 // Do deflate 152 code = deflate(&zlib_stream, Z_FINISH); 153 *dest_len = *dest_len - zlib_stream.avail_out; 154 155 deflateEnd(&zlib_stream); 156 return code; 157 } 158 159 // Use filter to decode compressed data, and compare the decoding result with 160 // the orginal Data. 161 // Parameters: Source and source_len are original data and its size. 162 // Encoded_source and encoded_source_len are compressed data and its size. 163 // Output_buffer_size specifies the size of buffer to read out data from 164 // filter. 165 void DecodeAndCompareWithFilter(Filter* filter, 166 const char* source, 167 int source_len, 168 const char* encoded_source, 169 int encoded_source_len, 170 int output_buffer_size) { 171 // Make sure we have enough space to hold the decoding output. 172 ASSERT_TRUE(source_len <= kDefaultBufferSize); 173 ASSERT_TRUE(output_buffer_size <= kDefaultBufferSize); 174 175 char decode_buffer[kDefaultBufferSize]; 176 char* decode_next = decode_buffer; 177 int decode_avail_size = kDefaultBufferSize; 178 179 const char* encode_next = encoded_source; 180 int encode_avail_size = encoded_source_len; 181 182 int code = Filter::FILTER_OK; 183 while (code != Filter::FILTER_DONE) { 184 int encode_data_len; 185 encode_data_len = std::min(encode_avail_size, 186 filter->stream_buffer_size()); 187 memcpy(filter->stream_buffer()->data(), encode_next, encode_data_len); 188 filter->FlushStreamBuffer(encode_data_len); 189 encode_next += encode_data_len; 190 encode_avail_size -= encode_data_len; 191 192 while (1) { 193 int decode_data_len = std::min(decode_avail_size, output_buffer_size); 194 195 code = filter->ReadData(decode_next, &decode_data_len); 196 decode_next += decode_data_len; 197 decode_avail_size -= decode_data_len; 198 199 ASSERT_TRUE(code != Filter::FILTER_ERROR); 200 201 if (code == Filter::FILTER_NEED_MORE_DATA || 202 code == Filter::FILTER_DONE) { 203 break; 204 } 205 } 206 } 207 208 // Compare the decoding result with source data 209 int decode_total_data_len = kDefaultBufferSize - decode_avail_size; 210 EXPECT_TRUE(decode_total_data_len == source_len); 211 EXPECT_EQ(memcmp(source, decode_buffer, source_len), 0); 212 } 213 214 // Unsafe function to use filter to decode compressed data. 215 // Parameters: Source and source_len are compressed data and its size. 216 // Dest is the buffer for decoding results. Upon entry, *dest_len is the size 217 // of the dest buffer. Upon exit, *dest_len is the number of chars written 218 // into the buffer. 219 int DecodeAllWithFilter(Filter* filter, const char* source, int source_len, 220 char* dest, int* dest_len) { 221 memcpy(filter->stream_buffer()->data(), source, source_len); 222 filter->FlushStreamBuffer(source_len); 223 return filter->ReadData(dest, dest_len); 224 } 225 226 void InitFilter(Filter::FilterType type) { 227 std::vector<Filter::FilterType> filter_types; 228 filter_types.push_back(type); 229 filter_.reset(Filter::Factory(filter_types, filter_context_)); 230 ASSERT_TRUE(filter_.get()); 231 ASSERT_GE(filter_->stream_buffer_size(), kDefaultBufferSize); 232 } 233 234 void InitFilterWithBufferSize(Filter::FilterType type, int buffer_size) { 235 std::vector<Filter::FilterType> filter_types; 236 filter_types.push_back(type); 237 filter_.reset(Filter::FactoryForTests(filter_types, filter_context_, 238 buffer_size)); 239 ASSERT_TRUE(filter_.get()); 240 } 241 242 const char* source_buffer() const { return source_buffer_.data(); } 243 int source_len() const { return static_cast<int>(source_buffer_.size()); } 244 245 scoped_ptr<Filter> filter_; 246 247 std::string source_buffer_; 248 249 char* deflate_encode_buffer_; 250 int deflate_encode_len_; 251 252 char* gzip_encode_buffer_; 253 int gzip_encode_len_; 254 255 private: 256 MockFilterContext filter_context_; 257 }; 258 259 // Basic scenario: decoding deflate data with big enough buffer. 260 TEST_F(GZipUnitTest, DecodeDeflate) { 261 // Decode the compressed data with filter 262 InitFilter(Filter::FILTER_TYPE_DEFLATE); 263 memcpy(filter_->stream_buffer()->data(), deflate_encode_buffer_, 264 deflate_encode_len_); 265 filter_->FlushStreamBuffer(deflate_encode_len_); 266 267 char deflate_decode_buffer[kDefaultBufferSize]; 268 int deflate_decode_size = kDefaultBufferSize; 269 filter_->ReadData(deflate_decode_buffer, &deflate_decode_size); 270 271 // Compare the decoding result with source data 272 EXPECT_TRUE(deflate_decode_size == source_len()); 273 EXPECT_EQ(memcmp(source_buffer(), deflate_decode_buffer, source_len()), 0); 274 } 275 276 // Basic scenario: decoding gzip data with big enough buffer. 277 TEST_F(GZipUnitTest, DecodeGZip) { 278 // Decode the compressed data with filter 279 InitFilter(Filter::FILTER_TYPE_GZIP); 280 memcpy(filter_->stream_buffer()->data(), gzip_encode_buffer_, 281 gzip_encode_len_); 282 filter_->FlushStreamBuffer(gzip_encode_len_); 283 284 char gzip_decode_buffer[kDefaultBufferSize]; 285 int gzip_decode_size = kDefaultBufferSize; 286 filter_->ReadData(gzip_decode_buffer, &gzip_decode_size); 287 288 // Compare the decoding result with source data 289 EXPECT_TRUE(gzip_decode_size == source_len()); 290 EXPECT_EQ(memcmp(source_buffer(), gzip_decode_buffer, source_len()), 0); 291 } 292 293 // Tests we can call filter repeatedly to get all the data decoded. 294 // To do that, we create a filter with a small buffer that can not hold all 295 // the input data. 296 TEST_F(GZipUnitTest, DecodeWithSmallBuffer) { 297 InitFilterWithBufferSize(Filter::FILTER_TYPE_DEFLATE, kSmallBufferSize); 298 EXPECT_EQ(kSmallBufferSize, filter_->stream_buffer_size()); 299 DecodeAndCompareWithFilter(filter_.get(), source_buffer(), source_len(), 300 deflate_encode_buffer_, deflate_encode_len_, 301 kDefaultBufferSize); 302 } 303 304 // Tests we can still decode with just 1 byte buffer in the filter. 305 // The purpose of this tests are two: (1) Verify filter can parse partial GZip 306 // header correctly. (2) Sometimes the filter will consume input without 307 // generating output. Verify filter can handle it correctly. 308 TEST_F(GZipUnitTest, DecodeWithOneByteBuffer) { 309 InitFilterWithBufferSize(Filter::FILTER_TYPE_GZIP, 1); 310 EXPECT_EQ(1, filter_->stream_buffer_size()); 311 DecodeAndCompareWithFilter(filter_.get(), source_buffer(), source_len(), 312 gzip_encode_buffer_, gzip_encode_len_, 313 kDefaultBufferSize); 314 } 315 316 // Tests we can decode when caller has small buffer to read out from filter. 317 TEST_F(GZipUnitTest, DecodeWithSmallOutputBuffer) { 318 InitFilter(Filter::FILTER_TYPE_DEFLATE); 319 DecodeAndCompareWithFilter(filter_.get(), source_buffer(), source_len(), 320 deflate_encode_buffer_, deflate_encode_len_, 321 kSmallBufferSize); 322 } 323 324 // Tests we can still decode with just 1 byte buffer in the filter and just 1 325 // byte buffer in the caller. 326 TEST_F(GZipUnitTest, DecodeWithOneByteInputAndOutputBuffer) { 327 InitFilterWithBufferSize(Filter::FILTER_TYPE_GZIP, 1); 328 EXPECT_EQ(1, filter_->stream_buffer_size()); 329 DecodeAndCompareWithFilter(filter_.get(), source_buffer(), source_len(), 330 gzip_encode_buffer_, gzip_encode_len_, 1); 331 } 332 333 // Decoding deflate stream with corrupted data. 334 TEST_F(GZipUnitTest, DecodeCorruptedData) { 335 char corrupt_data[kDefaultBufferSize]; 336 int corrupt_data_len = deflate_encode_len_; 337 memcpy(corrupt_data, deflate_encode_buffer_, deflate_encode_len_); 338 339 int pos = corrupt_data_len / 2; 340 corrupt_data[pos] = !corrupt_data[pos]; 341 342 // Decode the corrupted data with filter 343 InitFilter(Filter::FILTER_TYPE_DEFLATE); 344 char corrupt_decode_buffer[kDefaultBufferSize]; 345 int corrupt_decode_size = kDefaultBufferSize; 346 347 int code = DecodeAllWithFilter(filter_.get(), corrupt_data, corrupt_data_len, 348 corrupt_decode_buffer, &corrupt_decode_size); 349 350 // Expect failures 351 EXPECT_TRUE(code == Filter::FILTER_ERROR); 352 } 353 354 // Decoding deflate stream with missing data. 355 TEST_F(GZipUnitTest, DecodeMissingData) { 356 char corrupt_data[kDefaultBufferSize]; 357 int corrupt_data_len = deflate_encode_len_; 358 memcpy(corrupt_data, deflate_encode_buffer_, deflate_encode_len_); 359 360 int pos = corrupt_data_len / 2; 361 int len = corrupt_data_len - pos - 1; 362 memmove(&corrupt_data[pos], &corrupt_data[pos+1], len); 363 --corrupt_data_len; 364 365 // Decode the corrupted data with filter 366 InitFilter(Filter::FILTER_TYPE_DEFLATE); 367 char corrupt_decode_buffer[kDefaultBufferSize]; 368 int corrupt_decode_size = kDefaultBufferSize; 369 370 int code = DecodeAllWithFilter(filter_.get(), corrupt_data, corrupt_data_len, 371 corrupt_decode_buffer, &corrupt_decode_size); 372 373 // Expect failures 374 EXPECT_EQ(Filter::FILTER_ERROR, code); 375 } 376 377 // Decoding gzip stream with corrupted header. 378 TEST_F(GZipUnitTest, DecodeCorruptedHeader) { 379 char corrupt_data[kDefaultBufferSize]; 380 int corrupt_data_len = gzip_encode_len_; 381 memcpy(corrupt_data, gzip_encode_buffer_, gzip_encode_len_); 382 383 corrupt_data[2] = !corrupt_data[2]; 384 385 // Decode the corrupted data with filter 386 InitFilter(Filter::FILTER_TYPE_GZIP); 387 char corrupt_decode_buffer[kDefaultBufferSize]; 388 int corrupt_decode_size = kDefaultBufferSize; 389 390 int code = DecodeAllWithFilter(filter_.get(), corrupt_data, corrupt_data_len, 391 corrupt_decode_buffer, &corrupt_decode_size); 392 393 // Expect failures 394 EXPECT_TRUE(code == Filter::FILTER_ERROR); 395 } 396 397 } // namespace net 398