| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <fstream> | 5 #include <fstream> |
| 6 #include <iostream> | 6 #include <iostream> |
| 7 | 7 |
| 8 #if defined(USE_SYSTEM_ZLIB) | 8 #if defined(USE_SYSTEM_ZLIB) |
| 9 // The code below uses the MOZ_Z_ forms of these functions in order that things | 9 // The code below uses the MOZ_Z_ forms of these functions in order that things |
| 10 // should work on Windows. In order to make this code cross platform, we map | 10 // should work on Windows. In order to make this code cross platform, we map |
| (...skipping 12 matching lines...) Expand all Loading... |
| 23 #include "net/base/gzip_filter.h" | 23 #include "net/base/gzip_filter.h" |
| 24 #include "net/base/mock_filter_context.h" | 24 #include "net/base/mock_filter_context.h" |
| 25 #include "net/base/io_buffer.h" | 25 #include "net/base/io_buffer.h" |
| 26 #include "testing/gtest/include/gtest/gtest.h" | 26 #include "testing/gtest/include/gtest/gtest.h" |
| 27 #include "testing/platform_test.h" | 27 #include "testing/platform_test.h" |
| 28 | 28 |
| 29 namespace { | 29 namespace { |
| 30 | 30 |
| 31 const int kDefaultBufferSize = 4096; | 31 const int kDefaultBufferSize = 4096; |
| 32 const int kSmallBufferSize = 128; | 32 const int kSmallBufferSize = 128; |
| 33 const int kMaxBufferSize = 1048576; // 1048576 == 2^20 == 1 MB | |
| 34 | 33 |
| 35 const char kApplicationOctetStream[] = "application/octet-stream"; | 34 const char kApplicationOctetStream[] = "application/octet-stream"; |
| 36 const char kApplicationXGzip[] = "application/x-gzip"; | 35 const char kApplicationXGzip[] = "application/x-gzip"; |
| 37 const char kApplicationGzip[] = "application/gzip"; | 36 const char kApplicationGzip[] = "application/gzip"; |
| 38 const char kApplicationXGunzip[] = "application/x-gunzip"; | 37 const char kApplicationXGunzip[] = "application/x-gunzip"; |
| 39 | 38 |
| 40 // The GZIP header (see RFC 1952): | 39 // The GZIP header (see RFC 1952): |
| 41 // +---+---+---+---+---+---+---+---+---+---+ | 40 // +---+---+---+---+---+---+---+---+---+---+ |
| 42 // |ID1|ID2|CM |FLG| MTIME |XFL|OS | | 41 // |ID1|ID2|CM |FLG| MTIME |XFL|OS | |
| 43 // +---+---+---+---+---+---+---+---+---+---+ | 42 // +---+---+---+---+---+---+---+---+---+---+ |
| (...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 236 | 235 |
| 237 char* gzip_encode_buffer_; | 236 char* gzip_encode_buffer_; |
| 238 int gzip_encode_len_; | 237 int gzip_encode_len_; |
| 239 }; | 238 }; |
| 240 | 239 |
| 241 // Basic scenario: decoding deflate data with big enough buffer. | 240 // Basic scenario: decoding deflate data with big enough buffer. |
| 242 TEST_F(GZipUnitTest, DecodeDeflate) { | 241 TEST_F(GZipUnitTest, DecodeDeflate) { |
| 243 // Decode the compressed data with filter | 242 // Decode the compressed data with filter |
| 244 std::vector<Filter::FilterType> filter_types; | 243 std::vector<Filter::FilterType> filter_types; |
| 245 filter_types.push_back(Filter::FILTER_TYPE_DEFLATE); | 244 filter_types.push_back(Filter::FILTER_TYPE_DEFLATE); |
| 246 net::MockFilterContext filter_context(kDefaultBufferSize); | 245 net::MockFilterContext filter_context; |
| 247 scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); | 246 scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); |
| 248 ASSERT_TRUE(filter.get()); | 247 ASSERT_TRUE(filter.get()); |
| 249 memcpy(filter->stream_buffer()->data(), deflate_encode_buffer_, | 248 memcpy(filter->stream_buffer()->data(), deflate_encode_buffer_, |
| 250 deflate_encode_len_); | 249 deflate_encode_len_); |
| 251 filter->FlushStreamBuffer(deflate_encode_len_); | 250 filter->FlushStreamBuffer(deflate_encode_len_); |
| 252 | 251 |
| 253 char deflate_decode_buffer[kDefaultBufferSize]; | 252 char deflate_decode_buffer[kDefaultBufferSize]; |
| 254 int deflate_decode_size = kDefaultBufferSize; | 253 int deflate_decode_size = kDefaultBufferSize; |
| 255 filter->ReadData(deflate_decode_buffer, &deflate_decode_size); | 254 filter->ReadData(deflate_decode_buffer, &deflate_decode_size); |
| 256 | 255 |
| 257 // Compare the decoding result with source data | 256 // Compare the decoding result with source data |
| 258 EXPECT_TRUE(deflate_decode_size == source_len()); | 257 EXPECT_TRUE(deflate_decode_size == source_len()); |
| 259 EXPECT_EQ(memcmp(source_buffer(), deflate_decode_buffer, source_len()), 0); | 258 EXPECT_EQ(memcmp(source_buffer(), deflate_decode_buffer, source_len()), 0); |
| 260 } | 259 } |
| 261 | 260 |
| 262 // Basic scenario: decoding gzip data with big enough buffer. | 261 // Basic scenario: decoding gzip data with big enough buffer. |
| 263 TEST_F(GZipUnitTest, DecodeGZip) { | 262 TEST_F(GZipUnitTest, DecodeGZip) { |
| 264 // Decode the compressed data with filter | 263 // Decode the compressed data with filter |
| 265 std::vector<Filter::FilterType> filter_types; | 264 std::vector<Filter::FilterType> filter_types; |
| 266 filter_types.push_back(Filter::FILTER_TYPE_GZIP); | 265 filter_types.push_back(Filter::FILTER_TYPE_GZIP); |
| 267 net::MockFilterContext filter_context(kDefaultBufferSize); | 266 net::MockFilterContext filter_context; |
| 268 scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); | 267 scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); |
| 269 ASSERT_TRUE(filter.get()); | 268 ASSERT_TRUE(filter.get()); |
| 270 memcpy(filter->stream_buffer()->data(), gzip_encode_buffer_, | 269 memcpy(filter->stream_buffer()->data(), gzip_encode_buffer_, |
| 271 gzip_encode_len_); | 270 gzip_encode_len_); |
| 272 filter->FlushStreamBuffer(gzip_encode_len_); | 271 filter->FlushStreamBuffer(gzip_encode_len_); |
| 273 | 272 |
| 274 char gzip_decode_buffer[kDefaultBufferSize]; | 273 char gzip_decode_buffer[kDefaultBufferSize]; |
| 275 int gzip_decode_size = kDefaultBufferSize; | 274 int gzip_decode_size = kDefaultBufferSize; |
| 276 filter->ReadData(gzip_decode_buffer, &gzip_decode_size); | 275 filter->ReadData(gzip_decode_buffer, &gzip_decode_size); |
| 277 | 276 |
| 278 // Compare the decoding result with source data | 277 // Compare the decoding result with source data |
| 279 EXPECT_TRUE(gzip_decode_size == source_len()); | 278 EXPECT_TRUE(gzip_decode_size == source_len()); |
| 280 EXPECT_EQ(memcmp(source_buffer(), gzip_decode_buffer, source_len()), 0); | 279 EXPECT_EQ(memcmp(source_buffer(), gzip_decode_buffer, source_len()), 0); |
| 281 } | 280 } |
| 282 | 281 |
| 283 // Tests we can call filter repeatedly to get all the data decoded. | 282 // Tests we can call filter repeatedly to get all the data decoded. |
| 284 // To do that, we create a filter with a small buffer that can not hold all | 283 // To do that, we create a filter with a small buffer that can not hold all |
| 285 // the input data. | 284 // the input data. |
| 286 TEST_F(GZipUnitTest, DecodeWithSmallBuffer) { | 285 TEST_F(GZipUnitTest, DecodeWithSmallBuffer) { |
| 287 std::vector<Filter::FilterType> filter_types; | 286 std::vector<Filter::FilterType> filter_types; |
| 288 filter_types.push_back(Filter::FILTER_TYPE_DEFLATE); | 287 filter_types.push_back(Filter::FILTER_TYPE_DEFLATE); |
| 289 net::MockFilterContext filter_context(kSmallBufferSize); | 288 net::MockFilterContext filter_context; |
| 290 scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); | 289 scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); |
| 291 ASSERT_TRUE(filter.get()); | 290 ASSERT_TRUE(filter.get()); |
| 291 filter->ResetInputBufferForTest(kSmallBufferSize); |
| 292 DecodeAndCompareWithFilter(filter.get(), source_buffer(), source_len(), | 292 DecodeAndCompareWithFilter(filter.get(), source_buffer(), source_len(), |
| 293 deflate_encode_buffer_, deflate_encode_len_, | 293 deflate_encode_buffer_, deflate_encode_len_, |
| 294 kDefaultBufferSize); | 294 kDefaultBufferSize); |
| 295 } | 295 } |
| 296 | 296 |
| 297 // Tests we can still decode with just 1 byte buffer in the filter. | 297 // Tests we can still decode with just 1 byte buffer in the filter. |
| 298 // The purpose of this tests are two: (1) Verify filter can parse partial GZip | 298 // The purpose of this tests are two: (1) Verify filter can parse partial GZip |
| 299 // header correctly. (2) Sometimes the filter will consume input without | 299 // header correctly. (2) Sometimes the filter will consume input without |
| 300 // generating output. Verify filter can handle it correctly. | 300 // generating output. Verify filter can handle it correctly. |
| 301 TEST_F(GZipUnitTest, DecodeWithOneByteBuffer) { | 301 TEST_F(GZipUnitTest, DecodeWithOneByteBuffer) { |
| 302 std::vector<Filter::FilterType> filter_types; | 302 std::vector<Filter::FilterType> filter_types; |
| 303 filter_types.push_back(Filter::FILTER_TYPE_GZIP); | 303 filter_types.push_back(Filter::FILTER_TYPE_GZIP); |
| 304 net::MockFilterContext filter_context(1); | 304 net::MockFilterContext filter_context; |
| 305 scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); | 305 scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); |
| 306 ASSERT_TRUE(filter.get()); | 306 ASSERT_TRUE(filter.get()); |
| 307 filter->ResetInputBufferForTest(1); |
| 307 DecodeAndCompareWithFilter(filter.get(), source_buffer(), source_len(), | 308 DecodeAndCompareWithFilter(filter.get(), source_buffer(), source_len(), |
| 308 gzip_encode_buffer_, gzip_encode_len_, | 309 gzip_encode_buffer_, gzip_encode_len_, |
| 309 kDefaultBufferSize); | 310 kDefaultBufferSize); |
| 310 } | 311 } |
| 311 | 312 |
| 312 // Tests we can decode when caller has small buffer to read out from filter. | 313 // Tests we can decode when caller has small buffer to read out from filter. |
| 313 TEST_F(GZipUnitTest, DecodeWithSmallOutputBuffer) { | 314 TEST_F(GZipUnitTest, DecodeWithSmallOutputBuffer) { |
| 314 std::vector<Filter::FilterType> filter_types; | 315 std::vector<Filter::FilterType> filter_types; |
| 315 filter_types.push_back(Filter::FILTER_TYPE_DEFLATE); | 316 filter_types.push_back(Filter::FILTER_TYPE_DEFLATE); |
| 316 net::MockFilterContext filter_context(kDefaultBufferSize); | 317 net::MockFilterContext filter_context; |
| 317 scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); | 318 scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); |
| 318 ASSERT_TRUE(filter.get()); | 319 ASSERT_TRUE(filter.get()); |
| 319 DecodeAndCompareWithFilter(filter.get(), source_buffer(), source_len(), | 320 DecodeAndCompareWithFilter(filter.get(), source_buffer(), source_len(), |
| 320 deflate_encode_buffer_, deflate_encode_len_, | 321 deflate_encode_buffer_, deflate_encode_len_, |
| 321 kSmallBufferSize); | 322 kSmallBufferSize); |
| 322 } | 323 } |
| 323 | 324 |
| 324 // Tests we can still decode with just 1 byte buffer in the filter and just 1 | 325 // Tests we can still decode with just 1 byte buffer in the filter and just 1 |
| 325 // byte buffer in the caller. | 326 // byte buffer in the caller. |
| 326 TEST_F(GZipUnitTest, DecodeWithOneByteInputAndOutputBuffer) { | 327 TEST_F(GZipUnitTest, DecodeWithOneByteInputAndOutputBuffer) { |
| 327 std::vector<Filter::FilterType> filter_types; | 328 std::vector<Filter::FilterType> filter_types; |
| 328 filter_types.push_back(Filter::FILTER_TYPE_GZIP); | 329 filter_types.push_back(Filter::FILTER_TYPE_GZIP); |
| 329 net::MockFilterContext filter_context(1); | 330 net::MockFilterContext filter_context; |
| 330 scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); | 331 scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); |
| 331 ASSERT_TRUE(filter.get()); | 332 ASSERT_TRUE(filter.get()); |
| 333 filter->ResetInputBufferForTest(1); |
| 332 DecodeAndCompareWithFilter(filter.get(), source_buffer(), source_len(), | 334 DecodeAndCompareWithFilter(filter.get(), source_buffer(), source_len(), |
| 333 gzip_encode_buffer_, gzip_encode_len_, 1); | 335 gzip_encode_buffer_, gzip_encode_len_, 1); |
| 334 } | 336 } |
| 335 | 337 |
| 336 // Decoding deflate stream with corrupted data. | 338 // Decoding deflate stream with corrupted data. |
| 337 TEST_F(GZipUnitTest, DecodeCorruptedData) { | 339 TEST_F(GZipUnitTest, DecodeCorruptedData) { |
| 338 char corrupt_data[kDefaultBufferSize]; | 340 char corrupt_data[kDefaultBufferSize]; |
| 339 int corrupt_data_len = deflate_encode_len_; | 341 int corrupt_data_len = deflate_encode_len_; |
| 340 memcpy(corrupt_data, deflate_encode_buffer_, deflate_encode_len_); | 342 memcpy(corrupt_data, deflate_encode_buffer_, deflate_encode_len_); |
| 341 | 343 |
| 342 int pos = corrupt_data_len / 2; | 344 int pos = corrupt_data_len / 2; |
| 343 corrupt_data[pos] = !corrupt_data[pos]; | 345 corrupt_data[pos] = !corrupt_data[pos]; |
| 344 | 346 |
| 345 // Decode the corrupted data with filter | 347 // Decode the corrupted data with filter |
| 346 std::vector<Filter::FilterType> filter_types; | 348 std::vector<Filter::FilterType> filter_types; |
| 347 filter_types.push_back(Filter::FILTER_TYPE_DEFLATE); | 349 filter_types.push_back(Filter::FILTER_TYPE_DEFLATE); |
| 348 net::MockFilterContext filter_context(kDefaultBufferSize); | 350 net::MockFilterContext filter_context; |
| 349 scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); | 351 scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); |
| 350 ASSERT_TRUE(filter.get()); | 352 ASSERT_TRUE(filter.get()); |
| 351 char corrupt_decode_buffer[kDefaultBufferSize]; | 353 char corrupt_decode_buffer[kDefaultBufferSize]; |
| 352 int corrupt_decode_size = kDefaultBufferSize; | 354 int corrupt_decode_size = kDefaultBufferSize; |
| 353 | 355 |
| 354 int code = DecodeAllWithFilter(filter.get(), corrupt_data, corrupt_data_len, | 356 int code = DecodeAllWithFilter(filter.get(), corrupt_data, corrupt_data_len, |
| 355 corrupt_decode_buffer, &corrupt_decode_size); | 357 corrupt_decode_buffer, &corrupt_decode_size); |
| 356 | 358 |
| 357 // Expect failures | 359 // Expect failures |
| 358 EXPECT_TRUE(code == Filter::FILTER_ERROR); | 360 EXPECT_TRUE(code == Filter::FILTER_ERROR); |
| 359 } | 361 } |
| 360 | 362 |
| 361 // Decoding deflate stream with missing data. | 363 // Decoding deflate stream with missing data. |
| 362 TEST_F(GZipUnitTest, DecodeMissingData) { | 364 TEST_F(GZipUnitTest, DecodeMissingData) { |
| 363 char corrupt_data[kDefaultBufferSize]; | 365 char corrupt_data[kDefaultBufferSize]; |
| 364 int corrupt_data_len = deflate_encode_len_; | 366 int corrupt_data_len = deflate_encode_len_; |
| 365 memcpy(corrupt_data, deflate_encode_buffer_, deflate_encode_len_); | 367 memcpy(corrupt_data, deflate_encode_buffer_, deflate_encode_len_); |
| 366 | 368 |
| 367 int pos = corrupt_data_len / 2; | 369 int pos = corrupt_data_len / 2; |
| 368 int len = corrupt_data_len - pos - 1; | 370 int len = corrupt_data_len - pos - 1; |
| 369 memmove(&corrupt_data[pos], &corrupt_data[pos+1], len); | 371 memmove(&corrupt_data[pos], &corrupt_data[pos+1], len); |
| 370 --corrupt_data_len; | 372 --corrupt_data_len; |
| 371 | 373 |
| 372 // Decode the corrupted data with filter | 374 // Decode the corrupted data with filter |
| 373 std::vector<Filter::FilterType> filter_types; | 375 std::vector<Filter::FilterType> filter_types; |
| 374 filter_types.push_back(Filter::FILTER_TYPE_DEFLATE); | 376 filter_types.push_back(Filter::FILTER_TYPE_DEFLATE); |
| 375 net::MockFilterContext filter_context(kDefaultBufferSize); | 377 net::MockFilterContext filter_context; |
| 376 scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); | 378 scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); |
| 377 ASSERT_TRUE(filter.get()); | 379 ASSERT_TRUE(filter.get()); |
| 378 char corrupt_decode_buffer[kDefaultBufferSize]; | 380 char corrupt_decode_buffer[kDefaultBufferSize]; |
| 379 int corrupt_decode_size = kDefaultBufferSize; | 381 int corrupt_decode_size = kDefaultBufferSize; |
| 380 | 382 |
| 381 int code = DecodeAllWithFilter(filter.get(), corrupt_data, corrupt_data_len, | 383 int code = DecodeAllWithFilter(filter.get(), corrupt_data, corrupt_data_len, |
| 382 corrupt_decode_buffer, &corrupt_decode_size); | 384 corrupt_decode_buffer, &corrupt_decode_size); |
| 383 | 385 |
| 384 // Expect failures | 386 // Expect failures |
| 385 EXPECT_EQ(Filter::FILTER_ERROR, code); | 387 EXPECT_EQ(Filter::FILTER_ERROR, code); |
| 386 } | 388 } |
| 387 | 389 |
| 388 // Decoding gzip stream with corrupted header. | 390 // Decoding gzip stream with corrupted header. |
| 389 TEST_F(GZipUnitTest, DecodeCorruptedHeader) { | 391 TEST_F(GZipUnitTest, DecodeCorruptedHeader) { |
| 390 char corrupt_data[kDefaultBufferSize]; | 392 char corrupt_data[kDefaultBufferSize]; |
| 391 int corrupt_data_len = gzip_encode_len_; | 393 int corrupt_data_len = gzip_encode_len_; |
| 392 memcpy(corrupt_data, gzip_encode_buffer_, gzip_encode_len_); | 394 memcpy(corrupt_data, gzip_encode_buffer_, gzip_encode_len_); |
| 393 | 395 |
| 394 corrupt_data[2] = !corrupt_data[2]; | 396 corrupt_data[2] = !corrupt_data[2]; |
| 395 | 397 |
| 396 // Decode the corrupted data with filter | 398 // Decode the corrupted data with filter |
| 397 std::vector<Filter::FilterType> filter_types; | 399 std::vector<Filter::FilterType> filter_types; |
| 398 filter_types.push_back(Filter::FILTER_TYPE_GZIP); | 400 filter_types.push_back(Filter::FILTER_TYPE_GZIP); |
| 399 net::MockFilterContext filter_context(kDefaultBufferSize); | 401 net::MockFilterContext filter_context; |
| 400 scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); | 402 scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); |
| 401 ASSERT_TRUE(filter.get()); | 403 ASSERT_TRUE(filter.get()); |
| 402 char corrupt_decode_buffer[kDefaultBufferSize]; | 404 char corrupt_decode_buffer[kDefaultBufferSize]; |
| 403 int corrupt_decode_size = kDefaultBufferSize; | 405 int corrupt_decode_size = kDefaultBufferSize; |
| 404 | 406 |
| 405 int code = DecodeAllWithFilter(filter.get(), corrupt_data, corrupt_data_len, | 407 int code = DecodeAllWithFilter(filter.get(), corrupt_data, corrupt_data_len, |
| 406 corrupt_decode_buffer, &corrupt_decode_size); | 408 corrupt_decode_buffer, &corrupt_decode_size); |
| 407 | 409 |
| 408 // Expect failures | 410 // Expect failures |
| 409 EXPECT_TRUE(code == Filter::FILTER_ERROR); | 411 EXPECT_TRUE(code == Filter::FILTER_ERROR); |
| 410 } | 412 } |
| 411 | 413 |
| 412 } // namespace | 414 } // namespace |
| OLD | NEW |