diff options
author | tkent@chromium.org <tkent@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-09-20 05:37:56 +0000 |
---|---|---|
committer | tkent@chromium.org <tkent@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-09-20 05:37:56 +0000 |
commit | ef530750f967bd5e606dae380d0c230bf586b522 (patch) | |
tree | 781f4cf8c230dc11fc050725d73a9451ca114a63 /net/websockets | |
parent | a41b4e1e294a336a0e9589b432bb02d76121daca (diff) | |
download | chromium_src-ef530750f967bd5e606dae380d0c230bf586b522.zip chromium_src-ef530750f967bd5e606dae380d0c230bf586b522.tar.gz chromium_src-ef530750f967bd5e606dae380d0c230bf586b522.tar.bz2 |
Revert 224271 "Introduce WebSocketInflater."
The new test WebSocketInflaterTest.LargeRandomDeflateInflate failed on XP Tests
(dbg) and Win7 Tests (dbg).
http://build.chromium.org/p/chromium.win/builders/Win7%20Tests%20%28dbg%29%282%29/builds/17568/steps/net_unittests/logs/stdio
> [6994/6994] 376.29s WebSocketInflaterTest.LargeRandomDeflateInflate (0.73s) - retry #2
> Note: Google Test filter = WebSocketInflaterTest.LargeRandomDeflateInflate
> [==========] Running 1 test from 1 test case.
> [----------] Global test environment set-up.
> [----------] 1 test from WebSocketInflaterTest
> [ RUN ] WebSocketInflaterTest.LargeRandomDeflateInflate
> c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\vector(932) : Assertion failed: vector subscript out of range
> c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\vector(933) : Assertion failed: "Standard C++ Libraries Out of Range" && 0
> Introduce WebSocketInflater.
>
> Implement WebSocketInflater, a utility class for the permessage-deflate WebSocket extension.
>
> BUG=280910
> R=ricea, tyoshino
>
> Review URL: https://chromiumcodereview.appspot.com/23480049
TBR=yhirano@chromium.org
Review URL: https://codereview.chromium.org/24078027
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@224292 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/websockets')
-rw-r--r-- | net/websockets/README | 3 | ||||
-rw-r--r-- | net/websockets/websocket_inflater.cc | 280 | ||||
-rw-r--r-- | net/websockets/websocket_inflater.h | 130 | ||||
-rw-r--r-- | net/websockets/websocket_inflater_test.cc | 245 |
4 files changed, 0 insertions, 658 deletions
diff --git a/net/websockets/README b/net/websockets/README index e9fd214f..1d1e1c3 100644 --- a/net/websockets/README +++ b/net/websockets/README @@ -53,9 +53,6 @@ websocket_frame_parser.cc websocket_frame_parser.h websocket_frame_parser_test.cc websocket_frame_test.cc -websocket_inflater.cc -websocket_inflater.h -websocket_inflater_test.cc websocket_mux.h websocket_stream_base.h websocket_stream.cc diff --git a/net/websockets/websocket_inflater.cc b/net/websockets/websocket_inflater.cc deleted file mode 100644 index fbfb079..0000000 --- a/net/websockets/websocket_inflater.cc +++ /dev/null @@ -1,280 +0,0 @@ -// Copyright 2013 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 "net/websockets/websocket_inflater.h" - -#include <algorithm> -#include <deque> -#include <vector> - -#include "base/logging.h" -#include "net/base/io_buffer.h" -#include "third_party/zlib/zlib.h" - -namespace net { - -namespace { - -class ShrinkableIOBufferWithSize : public IOBufferWithSize { - public: - explicit ShrinkableIOBufferWithSize(int size) - : IOBufferWithSize(size) {} - - void Shrink(int new_size) { - DCHECK_LE(new_size, size_); - size_ = new_size; - } - - private: - virtual ~ShrinkableIOBufferWithSize() {} -}; - -} // namespace - -WebSocketInflater::WebSocketInflater() - : input_queue_(kDefaultInputIOBufferCapacity), - output_buffer_(kDefaultBufferCapacity) {} - -WebSocketInflater::WebSocketInflater(size_t input_queue_capacity, - size_t output_buffer_capacity) - : input_queue_(input_queue_capacity), - output_buffer_(output_buffer_capacity) { - DCHECK_GT(input_queue_capacity, 0u); - DCHECK_GT(output_buffer_capacity, 0u); -} - -bool WebSocketInflater::Initialize(int window_bits) { - DCHECK_LE(8, window_bits); - DCHECK_GE(15, window_bits); - stream_.reset(new z_stream); - memset(stream_.get(), 0, sizeof(*stream_)); - int result = inflateInit2(stream_.get(), -window_bits); - if (result != Z_OK) { - inflateEnd(stream_.get()); - stream_.reset(); - return false; - } - return true; -} - -WebSocketInflater::~WebSocketInflater() { - if (stream_) { - inflateEnd(stream_.get()); - stream_.reset(); - } -} - -bool WebSocketInflater::AddBytes(const char* data, size_t size) { - if (!size) - return true; - - if (!input_queue_.IsEmpty()) { - // choked - input_queue_.Push(data, size); - return true; - } - - int result = InflateWithFlush(data, size); - if (stream_->avail_in > 0) - input_queue_.Push(&data[size - stream_->avail_in], stream_->avail_in); - - return result == Z_OK || result == Z_BUF_ERROR; -} - -bool WebSocketInflater::Finish() { - return AddBytes("\x00\x00\xff\xff", 4); -} - -scoped_refptr<IOBufferWithSize> WebSocketInflater::GetOutput(size_t size) { - scoped_refptr<ShrinkableIOBufferWithSize> buffer = - new ShrinkableIOBufferWithSize(size); - size_t num_bytes_copied = 0; - - while (num_bytes_copied < size && output_buffer_.Size() > 0) { - size_t num_bytes_to_copy = - std::min(output_buffer_.Size(), size - num_bytes_copied); - output_buffer_.Read(&buffer->data()[num_bytes_copied], num_bytes_to_copy); - num_bytes_copied += num_bytes_to_copy; - int result = InflateChokedInput(); - if (result != Z_OK && result != Z_BUF_ERROR) - return NULL; - } - buffer->Shrink(num_bytes_copied); - return buffer; -} - -int WebSocketInflater::InflateWithFlush(const char* next_in, size_t avail_in) { - int result = Inflate(next_in, avail_in, Z_NO_FLUSH); - if (result != Z_OK && result != Z_BUF_ERROR) - return result; - - if (CurrentOutputSize() > 0) - return result; - // CurrentOutputSize() == 0 means there is no data to be output, - // so we should make sure it by using Z_SYNC_FLUSH. - return Inflate(reinterpret_cast<const char*>(stream_->next_in), - stream_->avail_in, - Z_SYNC_FLUSH); -} - -int WebSocketInflater::Inflate(const char* next_in, - size_t avail_in, - int flush) { - stream_->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(next_in)); - stream_->avail_in = avail_in; - - int result = Z_BUF_ERROR; - do { - std::pair<char*, size_t> tail = output_buffer_.GetTail(); - if (!tail.second) - break; - - stream_->next_out = reinterpret_cast<Bytef*>(tail.first); - stream_->avail_out = tail.second; - result = inflate(stream_.get(), flush); - output_buffer_.AdvanceTail(tail.second - stream_->avail_out); - if (result == Z_STREAM_END) { - // Received a block with BFINAL set to 1. Reset the decompression state. - result = inflateReset(stream_.get()); - } else if (tail.second == stream_->avail_out) { - break; - } - } while (result == Z_OK || result == Z_BUF_ERROR); - return result; -} - -int WebSocketInflater::InflateChokedInput() { - if (input_queue_.IsEmpty()) - return InflateWithFlush(NULL, 0); - - int result = Z_BUF_ERROR; - while (!input_queue_.IsEmpty()) { - std::pair<char*, size_t> top = input_queue_.Top(); - - result = InflateWithFlush(top.first, top.second); - input_queue_.Consume(top.second - stream_->avail_in); - - if (result != Z_OK && result != Z_BUF_ERROR) - return result; - - if (stream_->avail_in > 0) { - // There are some data which are not consumed. - break; - } - } - return result; -} - -WebSocketInflater::OutputBuffer::OutputBuffer(size_t capacity) - : capacity_(capacity), - buffer_(capacity_ + 1), // 1 for sentinel - head_(0), - tail_(0) {} - -WebSocketInflater::OutputBuffer::~OutputBuffer() {} - -size_t WebSocketInflater::OutputBuffer::Size() const { - return (tail_ + buffer_.size() - head_) % buffer_.size(); -} - -std::pair<char*, size_t> WebSocketInflater::OutputBuffer::GetTail() { - return std::make_pair(&buffer_[tail_], - std::min(capacity_ - Size(), buffer_.size() - tail_)); -} - -void WebSocketInflater::OutputBuffer::Read(char* dest, size_t size) { - DCHECK_LE(size, Size()); - - size_t num_bytes_copied = 0; - if (tail_ < head_) { - size_t num_bytes_to_copy = std::min(size, buffer_.size() - head_); - memcpy(&dest[num_bytes_copied], &buffer_[head_], num_bytes_to_copy); - AdvanceHead(num_bytes_to_copy); - num_bytes_copied += num_bytes_to_copy; - } - - if (num_bytes_copied == size) - return; - DCHECK_LE(head_, tail_); - size_t num_bytes_to_copy = size - num_bytes_copied; - DCHECK_LE(num_bytes_to_copy, tail_ - head_); - memcpy(&dest[num_bytes_copied], &buffer_[head_], num_bytes_to_copy); - AdvanceHead(num_bytes_to_copy); - num_bytes_copied += num_bytes_to_copy; - DCHECK_EQ(size, num_bytes_copied); - return; -} - -void WebSocketInflater::OutputBuffer::AdvanceHead(size_t advance) { - DCHECK_LE(advance, Size()); - head_ = (head_ + advance) % buffer_.size(); -} - -void WebSocketInflater::OutputBuffer::AdvanceTail(size_t advance) { - DCHECK_LE(advance + Size(), capacity_); - tail_ = (tail_ + advance) % buffer_.size(); -} - -WebSocketInflater::InputQueue::InputQueue(size_t capacity) - : capacity_(capacity), head_of_first_buffer_(0), tail_of_last_buffer_(0) {} - -WebSocketInflater::InputQueue::~InputQueue() {} - -std::pair<char*, size_t> WebSocketInflater::InputQueue::Top() { - DCHECK(!IsEmpty()); - if (buffers_.size() == 1) { - return std::make_pair(&buffers_.front()->data()[head_of_first_buffer_], - tail_of_last_buffer_ - head_of_first_buffer_); - } - return std::make_pair(&buffers_.front()->data()[head_of_first_buffer_], - capacity_ - head_of_first_buffer_); -} - -void WebSocketInflater::InputQueue::Push(const char* data, size_t size) { - if (!size) - return; - - size_t num_copied_bytes = 0; - if (!IsEmpty()) - num_copied_bytes += PushToLastBuffer(data, size); - - while (num_copied_bytes < size) { - DCHECK(IsEmpty() || tail_of_last_buffer_ == capacity_); - - buffers_.push_back(new IOBufferWithSize(capacity_)); - tail_of_last_buffer_ = 0; - num_copied_bytes += - PushToLastBuffer(&data[num_copied_bytes], size - num_copied_bytes); - } -} - -void WebSocketInflater::InputQueue::Consume(size_t size) { - DCHECK(!IsEmpty()); - DCHECK_LE(size + head_of_first_buffer_, capacity_); - - head_of_first_buffer_ += size; - if (head_of_first_buffer_ == capacity_) { - buffers_.pop_front(); - head_of_first_buffer_ = 0; - } - if (buffers_.size() == 1 && head_of_first_buffer_ == tail_of_last_buffer_) { - buffers_.pop_front(); - head_of_first_buffer_ = 0; - tail_of_last_buffer_ = 0; - } -} - -size_t WebSocketInflater::InputQueue::PushToLastBuffer(const char* data, - size_t size) { - DCHECK(!IsEmpty()); - size_t num_bytes_to_copy = std::min(size, capacity_ - tail_of_last_buffer_); - if (!num_bytes_to_copy) - return 0; - IOBufferWithSize* buffer = buffers_.back().get(); - memcpy(&buffer->data()[tail_of_last_buffer_], data, num_bytes_to_copy); - tail_of_last_buffer_ += num_bytes_to_copy; - return num_bytes_to_copy; -} - -} // namespace net diff --git a/net/websockets/websocket_inflater.h b/net/websockets/websocket_inflater.h deleted file mode 100644 index e57317f..0000000 --- a/net/websockets/websocket_inflater.h +++ /dev/null @@ -1,130 +0,0 @@ -// Copyright 2013 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. - -#ifndef NET_WEBSOCKETS_WEBSOCKET_INFLATER_H_ -#define NET_WEBSOCKETS_WEBSOCKET_INFLATER_H_ - -#include <deque> -#include <utility> -#include <vector> - -#include "base/basictypes.h" -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "net/base/net_export.h" - -extern "C" struct z_stream_s; - -namespace net { - -class IOBufferWithSize; - -// WebSocketInflater uncompresses data compressed by DEFLATE algorithm. -class NET_EXPORT_PRIVATE WebSocketInflater { - public: - WebSocketInflater(); - // |input_queue_capacity| is a capacity for each contiguous block in the - // input queue. The input queue can grow without limit. - WebSocketInflater(size_t input_queue_capacity, size_t output_buffer_capacity); - ~WebSocketInflater(); - - // Returns true if there is no error. - // |window_bits| must be between 8 and 15 (both inclusive). - // This function must be called exactly once before calling any of the - // following functions. - bool Initialize(int window_bits); - - // Adds bytes to |stream_|. - // Returns true if there is no error. - // If the size of the output data reaches the capacity of the output buffer, - // the following input data will be "choked", i.e. stored in the input queue, - // staying compressed. - bool AddBytes(const char* data, size_t size); - - // Flushes the input. - // Returns true if there is no error. - bool Finish(); - - // Returns up to |size| bytes of the decompressed output. - // Returns null if there is an inflation error. - // The returned bytes will be dropped from the current output and never be - // returned again. - // If some input data is choked, calling this function may restart the - // inflation process. - // This means that even if you call |Finish()| and call |GetOutput()| with - // size = |CurrentOutputSize()|, the inflater may have some remaining data. - // To confirm the inflater emptiness, you should check whether - // |CurrentOutputSize()| is zero. - scoped_refptr<IOBufferWithSize> GetOutput(size_t size); - - // Returns the size of the current inflated output. - size_t CurrentOutputSize() const { return output_buffer_.Size(); } - - static const size_t kDefaultBufferCapacity = 512; - static const size_t kDefaultInputIOBufferCapacity = 512; - - private: - // Ring buffer with fixed capacity. - class OutputBuffer { - public: - explicit OutputBuffer(size_t capacity); - ~OutputBuffer(); - - size_t Size() const; - // Returns (tail pointer, availabe size). - // A user can push data to the queue by writing the data to - // the area returned by this function and calling AdvanceTail. - std::pair<char*, size_t> GetTail(); - void Read(char* dest, size_t size); - void AdvanceTail(size_t advance); - - private: - void AdvanceHead(size_t advance); - - const size_t capacity_; - std::vector<char> buffer_; - size_t head_; - size_t tail_; - }; - - class InputQueue { - public: - // |capacity| is used for the capacity of each IOBuffer in this queue. - // this queue itself can grow without limit. - explicit InputQueue(size_t capacity); - ~InputQueue(); - - // Returns (data pointer, size), the first component of unconsumed data. - // The type of data pointer is non-const because |inflate| function - // requires so. - std::pair<char*, size_t> Top(); - bool IsEmpty() const { return buffers_.empty(); } - void Push(const char* data, size_t size); - // Consumes the topmost |size| bytes. - // |size| must be less than or equal to the first buffer size. - void Consume(size_t size); - - private: - size_t PushToLastBuffer(const char* data, size_t size); - - const size_t capacity_; - size_t head_of_first_buffer_; - size_t tail_of_last_buffer_; - std::deque<scoped_refptr<IOBufferWithSize> > buffers_; - }; - - int InflateWithFlush(const char* next_in, size_t avail_in); - int Inflate(const char* next_in, size_t avail_in, int flush); - int InflateChokedInput(); - - scoped_ptr<z_stream_s> stream_; - InputQueue input_queue_; - OutputBuffer output_buffer_; - - DISALLOW_COPY_AND_ASSIGN(WebSocketInflater); -}; - -} // namespace net - -#endif // NET_WEBSOCKETS_WEBSOCKET_INFLATER_H_ diff --git a/net/websockets/websocket_inflater_test.cc b/net/websockets/websocket_inflater_test.cc deleted file mode 100644 index 722e29e8..0000000 --- a/net/websockets/websocket_inflater_test.cc +++ /dev/null @@ -1,245 +0,0 @@ -// Copyright 2013 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 "net/websockets/websocket_inflater.h" - -#include <stdint.h> -#include <string> -#include <vector> - -#include "base/memory/ref_counted.h" -#include "net/base/io_buffer.h" -#include "net/websockets/websocket_deflater.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace net { - -namespace { - -std::string ToString(IOBufferWithSize* buffer) { - return std::string(buffer->data(), buffer->size()); -} - -class LinearCongruentialGenerator { - public: - explicit LinearCongruentialGenerator(uint32_t seed); - uint32_t Generate(); - - private: - uint32_t current_; - - static const uint32_t a_ = 1103515245; - static const uint32_t c_ = 12345; - static const uint32_t m_ = 1 << 31; -}; - -LinearCongruentialGenerator::LinearCongruentialGenerator(uint32_t seed) - : current_(seed) {} - -uint32_t LinearCongruentialGenerator::Generate() { - uint32_t result = current_; - current_ = (current_ * a_ + c_) % m_; - return result; -} - -TEST(WebSocketInflaterTest, Construct) { - WebSocketInflater inflater; - ASSERT_TRUE(inflater.Initialize(15)); - - EXPECT_EQ(0u, inflater.CurrentOutputSize()); -} - -TEST(WebSocketInflaterTest, InflateHelloTakeOverContext) { - WebSocketInflater inflater; - ASSERT_TRUE(inflater.Initialize(15)); - scoped_refptr<IOBufferWithSize> actual1, actual2; - - ASSERT_TRUE(inflater.AddBytes("\xf2\x48\xcd\xc9\xc9\x07\x00", 7)); - ASSERT_TRUE(inflater.Finish()); - actual1 = inflater.GetOutput(inflater.CurrentOutputSize()); - ASSERT_TRUE(actual1); - EXPECT_EQ("Hello", ToString(actual1.get())); - EXPECT_EQ(0u, inflater.CurrentOutputSize()); - - ASSERT_TRUE(inflater.AddBytes("\xf2\x00\x11\x00\x00", 5)); - ASSERT_TRUE(inflater.Finish()); - actual2 = inflater.GetOutput(inflater.CurrentOutputSize()); - ASSERT_TRUE(actual2); - EXPECT_EQ("Hello", ToString(actual2.get())); - EXPECT_EQ(0u, inflater.CurrentOutputSize()); -} - -TEST(WebSocketInflaterTest, InflateHelloSmallCapacity) { - WebSocketInflater inflater(1, 1); - ASSERT_TRUE(inflater.Initialize(15)); - std::string actual; - - ASSERT_TRUE(inflater.AddBytes("\xf2\x48\xcd\xc9\xc9\x07\x00", 7)); - ASSERT_TRUE(inflater.Finish()); - for (size_t i = 0; i < 5; ++i) { - ASSERT_EQ(1u, inflater.CurrentOutputSize()); - scoped_refptr<IOBufferWithSize> buffer = inflater.GetOutput(1); - ASSERT_TRUE(buffer); - ASSERT_EQ(1, buffer->size()); - actual += ToString(buffer.get()); - } - EXPECT_EQ("Hello", actual); - EXPECT_EQ(0u, inflater.CurrentOutputSize()); -} - -TEST(WebSocketInflaterTest, InflateHelloSmallCapacityGetTotalOutput) { - WebSocketInflater inflater(1, 1); - ASSERT_TRUE(inflater.Initialize(15)); - scoped_refptr<IOBufferWithSize> actual; - - ASSERT_TRUE(inflater.AddBytes("\xf2\x48\xcd\xc9\xc9\x07\x00", 7)); - ASSERT_TRUE(inflater.Finish()); - ASSERT_EQ(1u, inflater.CurrentOutputSize()); - actual = inflater.GetOutput(1024); - EXPECT_EQ("Hello", ToString(actual)); - EXPECT_EQ(0u, inflater.CurrentOutputSize()); -} - -TEST(WebSocketInflaterTest, InflateInvalidData) { - WebSocketInflater inflater; - ASSERT_TRUE(inflater.Initialize(15)); - EXPECT_FALSE(inflater.AddBytes("\xf2\x48\xcd\xc9INVALID DATA", 16)); -} - -TEST(WebSocketInflaterTest, ChokedInvalidData) { - WebSocketInflater inflater(1, 1); - ASSERT_TRUE(inflater.Initialize(15)); - - EXPECT_TRUE(inflater.AddBytes("\xf2\x48\xcd\xc9INVALID DATA", 16)); - EXPECT_TRUE(inflater.Finish()); - EXPECT_EQ(1u, inflater.CurrentOutputSize()); - EXPECT_FALSE(inflater.GetOutput(1024)); -} - -TEST(WebSocketInflaterTest, MultipleAddBytesCalls) { - WebSocketInflater inflater; - ASSERT_TRUE(inflater.Initialize(15)); - std::string input("\xf2\x48\xcd\xc9\xc9\x07\x00", 7); - scoped_refptr<IOBufferWithSize> actual; - - for (size_t i = 0; i < input.size(); ++i) { - ASSERT_TRUE(inflater.AddBytes(&input[i], 1)); - } - ASSERT_TRUE(inflater.Finish()); - actual = inflater.GetOutput(5); - ASSERT_TRUE(actual); - EXPECT_EQ("Hello", ToString(actual.get())); -} - -TEST(WebSocketInflaterTest, Reset) { - WebSocketInflater inflater; - ASSERT_TRUE(inflater.Initialize(15)); - scoped_refptr<IOBufferWithSize> actual1, actual2; - - ASSERT_TRUE(inflater.AddBytes("\xf2\x48\xcd\xc9\xc9\x07\x00", 7)); - ASSERT_TRUE(inflater.Finish()); - actual1 = inflater.GetOutput(inflater.CurrentOutputSize()); - ASSERT_TRUE(actual1); - EXPECT_EQ("Hello", ToString(actual1.get())); - EXPECT_EQ(0u, inflater.CurrentOutputSize()); - - // Reset the stream with a block [BFINAL = 1, BTYPE = 00, LEN = 0] - ASSERT_TRUE(inflater.AddBytes("\x01", 1)); - ASSERT_TRUE(inflater.Finish()); - ASSERT_EQ(0u, inflater.CurrentOutputSize()); - - ASSERT_TRUE(inflater.AddBytes("\xf2\x48\xcd\xc9\xc9\x07\x00", 7)); - ASSERT_TRUE(inflater.Finish()); - actual2 = inflater.GetOutput(inflater.CurrentOutputSize()); - ASSERT_TRUE(actual2); - EXPECT_EQ("Hello", ToString(actual2.get())); - EXPECT_EQ(0u, inflater.CurrentOutputSize()); -} - -TEST(WebSocketInflaterTest, ResetAndLostContext) { - WebSocketInflater inflater; - scoped_refptr<IOBufferWithSize> actual1, actual2; - ASSERT_TRUE(inflater.Initialize(15)); - - ASSERT_TRUE(inflater.AddBytes("\xf2\x48\xcd\xc9\xc9\x07\x00", 7)); - ASSERT_TRUE(inflater.Finish()); - actual1 = inflater.GetOutput(inflater.CurrentOutputSize()); - ASSERT_TRUE(actual1); - EXPECT_EQ("Hello", ToString(actual1.get())); - EXPECT_EQ(0u, inflater.CurrentOutputSize()); - - // Reset the stream with a block [BFINAL = 1, BTYPE = 00, LEN = 0] - ASSERT_TRUE(inflater.AddBytes("\x01", 1)); - ASSERT_TRUE(inflater.Finish()); - ASSERT_EQ(0u, inflater.CurrentOutputSize()); - - // The context is already reset. - ASSERT_FALSE(inflater.AddBytes("\xf2\x00\x11\x00\x00", 5)); -} - -TEST(WebSocketInflaterTest, CallAddBytesAndFinishWithoutGetOutput) { - WebSocketInflater inflater; - scoped_refptr<IOBufferWithSize> actual1, actual2; - ASSERT_TRUE(inflater.Initialize(15)); - - ASSERT_TRUE(inflater.AddBytes("\xf2\x48\xcd\xc9\xc9\x07\x00", 7)); - ASSERT_TRUE(inflater.Finish()); - EXPECT_EQ(5u, inflater.CurrentOutputSize()); - - // This is a test for detecting memory leaks with valgrind. -} - -TEST(WebSocketInflaterTest, CallAddBytesAndFinishWithoutGetOutputChoked) { - WebSocketInflater inflater(1, 1); - scoped_refptr<IOBufferWithSize> actual1, actual2; - ASSERT_TRUE(inflater.Initialize(15)); - - ASSERT_TRUE(inflater.AddBytes("\xf2\x48\xcd\xc9\xc9\x07\x00", 7)); - ASSERT_TRUE(inflater.Finish()); - EXPECT_EQ(1u, inflater.CurrentOutputSize()); - - // This is a test for detecting memory leaks with valgrind. -} - -TEST(WebSocketInflaterTest, LargeRandomDeflateInflate) { - const size_t size = 64 * 1024; - LinearCongruentialGenerator generator(133); - std::vector<char> input; - std::vector<char> output; - scoped_refptr<IOBufferWithSize> compressed; - - WebSocketDeflater deflater(WebSocketDeflater::TAKE_OVER_CONTEXT); - ASSERT_TRUE(deflater.Initialize(8)); - WebSocketInflater inflater(256, 256); - ASSERT_TRUE(inflater.Initialize(8)); - - for (size_t i = 0; i < size; ++i) - input.push_back(static_cast<char>(generator.Generate())); - - ASSERT_TRUE(deflater.AddBytes(&input[0], input.size())); - ASSERT_TRUE(deflater.Finish()); - - compressed = deflater.GetOutput(deflater.CurrentOutputSize()); - - ASSERT_TRUE(compressed); - ASSERT_EQ(0u, deflater.CurrentOutputSize()); - - ASSERT_TRUE(inflater.AddBytes(compressed->data(), compressed->size())); - ASSERT_TRUE(inflater.Finish()); - - while (inflater.CurrentOutputSize() > 0) { - scoped_refptr<IOBufferWithSize> uncompressed = - inflater.GetOutput(inflater.CurrentOutputSize()); - ASSERT_TRUE(uncompressed); - output.insert(output.end(), - uncompressed->data(), - uncompressed->data() + uncompressed->size()); - } - - EXPECT_EQ(output, input); -} - -} // unnamed namespace - -} // namespace net |