+2012-02-14 Kenichi Ishibashi <bashi@chromium.org>
+
+ [WebSocket] Add deflater/inflater classes
+ https://bugs.webkit.org/show_bug.cgi?id=78449
+
+ Add WebSocketDeflater/WebSocketInflater classes which wrap zlib
+ functions. These classes are not used yet, but will be used for
+ supporting WebSocket deflate-frame extension.
+
+ Reviewed by Kent Tamura.
+
+ No new tests except for chromium port. Behavior is unchanged.
+
+ * GNUmakefile.list.am: Added.WebSocketDeflater.(cpp|h).
+ * WebCore.gypi: Ditto.
+ * WebCore.vcproj/WebCore.vcproj: Ditto.
+ * WebCore.xcodeproj/project.pbxproj: Ditto.
+ * websockets/WebSocketDeflater.cpp: Added.
+ (WebCore):
+ (WebCore::WebSocketDeflater::create):
+ (WebCore::WebSocketDeflater::WebSocketDeflater):
+ (WebCore::WebSocketDeflater::initialize):
+ (WebCore::WebSocketDeflater::~WebSocketDeflater):
+ (WebCore::WebSocketDeflater::addBytes):
+ (WebCore::WebSocketDeflater::finish):
+ (WebCore::WebSocketDeflater::reset):
+ (WebCore::WebSocketInflater::create):
+ (WebCore::WebSocketInflater::WebSocketInflater):
+ (WebCore::WebSocketInflater::initialize):
+ (WebCore::WebSocketInflater::~WebSocketInflater):
+ (WebCore::WebSocketInflater::addBytes):
+ (WebCore::WebSocketInflater::finish):
+ (WebCore::WebSocketInflater::reset):
+ * websockets/WebSocketDeflater.h: Added.
+ (WebCore):
+ (WebSocketDeflater):
+ (WebCore::WebSocketDeflater::data):
+ (WebCore::WebSocketDeflater::size):
+ (WebSocketInflater):
+ (WebCore::WebSocketInflater::data):
+ (WebCore::WebSocketInflater::size):
+
2012-02-14 Dana Jansens <danakj@chromium.org>
[chromium] Compare filters on impl thread when setting them, and test setting in unit tests
Source/WebCore/websockets/WebSocketChannel.h \
Source/WebCore/websockets/WebSocket.cpp \
Source/WebCore/websockets/WebSocket.h \
+ Source/WebCore/websockets/WebSocketDeflater.cpp \
+ Source/WebCore/websockets/WebSocketDeflater.h \
Source/WebCore/websockets/WebSocketExtensionDispatcher.cpp \
Source/WebCore/websockets/WebSocketExtensionDispatcher.h \
Source/WebCore/websockets/WebSocketExtensionProcessor.h \
'websockets/WebSocketChannel.cpp',
'websockets/WebSocketChannel.h',
'websockets/WebSocketChannelClient.h',
+ 'websockets/WebSocketDeflater.cpp',
+ 'websockets/WebSocketDeflater.h',
'websockets/WebSocketExtensionDispatcher.cpp',
'websockets/WebSocketExtensionDispatcher.h',
'websockets/WebSocketExtensionProcessor.h',
>
</File>
<File
+ RelativePath="..\websockets\WebSocketDeflater.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\websockets\WebSocketDeflater.h"
+ >
+ </File>
+ <File
RelativePath="..\websockets\WebSocketExtensionDispatcher.cpp"
>
</File>
4AD0173C127E82860015035F /* JSHTMLOutputElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4AD0173A127E82860015035F /* JSHTMLOutputElement.cpp */; };
4AD0173D127E82860015035F /* JSHTMLOutputElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 4AD0173B127E82860015035F /* JSHTMLOutputElement.h */; };
4ADE25FA14E3BB4C004C2213 /* WebSocketExtensionProcessor.h in Headers */ = {isa = PBXBuildFile; fileRef = 4ADE25F914E3BB4C004C2213 /* WebSocketExtensionProcessor.h */; };
+ 4AE02ABD14E8A9D200BC3BA7 /* WebSocketDeflater.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4AE02ABB14E8A9D200BC3BA7 /* WebSocketDeflater.cpp */; };
+ 4AE02ABE14E8A9D200BC3BA7 /* WebSocketDeflater.h in Headers */ = {isa = PBXBuildFile; fileRef = 4AE02ABC14E8A9D200BC3BA7 /* WebSocketDeflater.h */; };
4AF1AD3E13FD23A400AA9590 /* EventDispatchMediator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4AF1AD3C13FD23A400AA9590 /* EventDispatchMediator.cpp */; };
4AF1AD3F13FD23A400AA9590 /* EventDispatchMediator.h in Headers */ = {isa = PBXBuildFile; fileRef = 4AF1AD3D13FD23A400AA9590 /* EventDispatchMediator.h */; settings = {ATTRIBUTES = (Private, ); }; };
4B2708C70AF19EE40065127F /* Pasteboard.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B2708C50AF19EE40065127F /* Pasteboard.h */; };
4AD0173A127E82860015035F /* JSHTMLOutputElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSHTMLOutputElement.cpp; sourceTree = "<group>"; };
4AD0173B127E82860015035F /* JSHTMLOutputElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSHTMLOutputElement.h; sourceTree = "<group>"; };
4ADE25F914E3BB4C004C2213 /* WebSocketExtensionProcessor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebSocketExtensionProcessor.h; sourceTree = "<group>"; };
+ 4AE02ABB14E8A9D200BC3BA7 /* WebSocketDeflater.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebSocketDeflater.cpp; sourceTree = "<group>"; };
+ 4AE02ABC14E8A9D200BC3BA7 /* WebSocketDeflater.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebSocketDeflater.h; sourceTree = "<group>"; };
4AF1AD3C13FD23A400AA9590 /* EventDispatchMediator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EventDispatchMediator.cpp; sourceTree = "<group>"; };
4AF1AD3D13FD23A400AA9590 /* EventDispatchMediator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EventDispatchMediator.h; sourceTree = "<group>"; };
4B2708C50AF19EE40065127F /* Pasteboard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Pasteboard.h; sourceTree = "<group>"; };
518A34BD1026C831001B6896 /* websockets */ = {
isa = PBXGroup;
children = (
- 4ADE25F914E3BB4C004C2213 /* WebSocketExtensionProcessor.h */,
51FB54F4113E364200821176 /* CloseEvent.h */,
51FB54F6113E365900821176 /* CloseEvent.idl */,
5112247110CFB8C6008099D7 /* ThreadableWebSocketChannel.cpp */,
510D4A47103177A20049EA54 /* WebSocketChannel.cpp */,
510D4A48103177A20049EA54 /* WebSocketChannel.h */,
510D4A49103177A20049EA54 /* WebSocketChannelClient.h */,
+ 4AE02ABB14E8A9D200BC3BA7 /* WebSocketDeflater.cpp */,
+ 4AE02ABC14E8A9D200BC3BA7 /* WebSocketDeflater.h */,
4A957F0314E241100049DBFB /* WebSocketExtensionDispatcher.cpp */,
4A957F0414E241100049DBFB /* WebSocketExtensionDispatcher.h */,
+ 4ADE25F914E3BB4C004C2213 /* WebSocketExtensionProcessor.h */,
51ABAE421043AB4A008C5260 /* WebSocketHandshake.cpp */,
51ABAE431043AB4A008C5260 /* WebSocketHandshake.h */,
7637C540112E7B74003D6CDC /* WebSocketHandshakeRequest.cpp */,
97CC3AE314E8E4A200894988 /* NavigatorSupplement.h in Headers */,
C598905714E9C28000E8D18B /* PasteboardStrategy.h in Headers */,
C598905814E9C29900E8D18B /* PlatformPasteboard.h in Headers */,
+ 4AE02ABE14E8A9D200BC3BA7 /* WebSocketDeflater.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
572E92FB14E540580087FFBA /* ShadowRootList.cpp in Sources */,
97CC3AE214E8E4A200894988 /* NavigatorSupplement.cpp in Sources */,
C598902E14E9B0F800E8D18B /* PlatformPasteboardMac.mm in Sources */,
+ 4AE02ABD14E8A9D200BC3BA7 /* WebSocketDeflater.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
--- /dev/null
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(WEB_SOCKETS)
+
+#include "WebSocketDeflater.h"
+
+#include "Logging.h"
+#include <wtf/FastMalloc.h>
+#include <wtf/HashMap.h>
+#include <wtf/StdLibExtras.h>
+#include <wtf/StringExtras.h>
+#include <wtf/text/StringHash.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+static const int defaultMemLevel = 1;
+static const size_t bufferIncrementUnit = 4096;
+
+PassOwnPtr<WebSocketDeflater> WebSocketDeflater::create(int windowBits, ContextTakeOverMode contextTakeOverMode)
+{
+ return adoptPtr(new WebSocketDeflater(windowBits, contextTakeOverMode));
+}
+
+WebSocketDeflater::WebSocketDeflater(int windowBits, ContextTakeOverMode contextTakeOverMode)
+ : m_windowBits(windowBits)
+ , m_contextTakeOverMode(contextTakeOverMode)
+{
+ ASSERT(m_windowBits >= 8);
+ ASSERT(m_windowBits <= 15);
+ memset(&m_stream, 0, sizeof(z_stream));
+}
+
+bool WebSocketDeflater::initialize()
+{
+ return deflateInit2(&m_stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -m_windowBits, defaultMemLevel, Z_DEFAULT_STRATEGY) == Z_OK;
+}
+
+WebSocketDeflater::~WebSocketDeflater()
+{
+ int result = deflateEnd(&m_stream);
+ if (result != Z_OK)
+ LOG(Network, "deflateEnd() failed: %d", result);
+}
+
+static void setStreamParameter(z_stream& stream, const char* inputData, size_t inputLength, char* outputData, size_t outputLength)
+{
+ stream.next_in = reinterpret_cast<Bytef*>(const_cast<char*>(inputData));
+ stream.avail_in = inputLength;
+ stream.next_out = reinterpret_cast<Bytef*>(outputData);
+ stream.avail_out = outputLength;
+}
+
+bool WebSocketDeflater::addBytes(const char* data, size_t length)
+{
+ if (!length)
+ return false;
+
+ size_t maxLength = deflateBound(&m_stream, length);
+ size_t writePosition = m_buffer.size();
+ m_buffer.grow(writePosition + maxLength);
+ setStreamParameter(m_stream, data, length, m_buffer.data() + writePosition, maxLength);
+ int result = deflate(&m_stream, Z_NO_FLUSH);
+ if (result != Z_OK || m_stream.avail_in > 0)
+ return false;
+
+ m_buffer.shrink(writePosition + maxLength - m_stream.avail_out);
+ return true;
+}
+
+bool WebSocketDeflater::finish()
+{
+ while (true) {
+ size_t writePosition = m_buffer.size();
+ m_buffer.grow(writePosition + bufferIncrementUnit);
+ size_t availableCapacity = m_buffer.size() - writePosition;
+ setStreamParameter(m_stream, 0, 0, m_buffer.data() + writePosition, availableCapacity);
+ int result = deflate(&m_stream, Z_SYNC_FLUSH);
+ m_buffer.shrink(writePosition + availableCapacity - m_stream.avail_out);
+ if (result == Z_OK)
+ break;
+ if (result != Z_BUF_ERROR)
+ return false;
+ }
+ // Remove 4 octets from the tail as the specification requires.
+ if (m_buffer.size() <= 4)
+ return false;
+ m_buffer.resize(m_buffer.size() - 4);
+ return true;
+}
+
+void WebSocketDeflater::reset()
+{
+ m_buffer.clear();
+ if (m_contextTakeOverMode == DoNotTakeOverContext)
+ deflateReset(&m_stream);
+}
+
+PassOwnPtr<WebSocketInflater> WebSocketInflater::create(int windowBits)
+{
+ return adoptPtr(new WebSocketInflater(windowBits));
+}
+
+WebSocketInflater::WebSocketInflater(int windowBits)
+ : m_windowBits(windowBits)
+{
+ memset(&m_stream, 0, sizeof(z_stream));
+}
+
+bool WebSocketInflater::initialize()
+{
+ return inflateInit2(&m_stream, -m_windowBits) == Z_OK;
+}
+
+WebSocketInflater::~WebSocketInflater()
+{
+ int result = inflateEnd(&m_stream);
+ if (result != Z_OK)
+ LOG(Network, "inflateEnd() failed: %d", result);
+}
+
+bool WebSocketInflater::addBytes(const char* data, size_t length)
+{
+ if (!length)
+ return false;
+
+ size_t consumedSoFar = 0;
+ while (consumedSoFar < length) {
+ size_t writePosition = m_buffer.size();
+ m_buffer.grow(writePosition + bufferIncrementUnit);
+ size_t availableCapacity = m_buffer.size() - writePosition;
+ size_t remainingLength = length - consumedSoFar;
+ setStreamParameter(m_stream, data + consumedSoFar, remainingLength, m_buffer.data() + writePosition, availableCapacity);
+ int result = inflate(&m_stream, Z_NO_FLUSH);
+ consumedSoFar += remainingLength - m_stream.avail_in;
+ m_buffer.shrink(writePosition + availableCapacity - m_stream.avail_out);
+ if (result == Z_BUF_ERROR)
+ continue;
+ if (result != Z_OK)
+ return false;
+ }
+ ASSERT(consumedSoFar == length);
+ return true;
+}
+
+bool WebSocketInflater::finish()
+{
+ static const char* strippedFields = "\0\0\xff\xff";
+ static const size_t strippedLength = 4;
+
+ // Appends 4 octests of 0x00 0x00 0xff 0xff
+ size_t consumedSoFar = 0;
+ while (consumedSoFar < strippedLength) {
+ size_t writePosition = m_buffer.size();
+ m_buffer.grow(writePosition + bufferIncrementUnit);
+ size_t availableCapacity = m_buffer.size() - writePosition;
+ size_t remainingLength = strippedLength - consumedSoFar;
+ setStreamParameter(m_stream, strippedFields + consumedSoFar, remainingLength, m_buffer.data() + writePosition, availableCapacity);
+ int result = inflate(&m_stream, Z_FINISH);
+ consumedSoFar += remainingLength - m_stream.avail_in;
+ m_buffer.shrink(writePosition + availableCapacity - m_stream.avail_out);
+ if (result == Z_BUF_ERROR)
+ continue;
+ if (result != Z_OK && result != Z_STREAM_END)
+ return false;
+ }
+ ASSERT(consumedSoFar == strippedLength);
+
+ return true;
+}
+
+void WebSocketInflater::reset()
+{
+ m_buffer.clear();
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(WEB_SOCKETS)
--- /dev/null
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef WebSocketDeflater_h
+#define WebSocketDeflater_h
+
+#if ENABLE(WEB_SOCKETS)
+
+#include <wtf/Noncopyable.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/Vector.h>
+#include <zlib.h>
+
+namespace WebCore {
+
+class WebSocketDeflater {
+public:
+ enum ContextTakeOverMode {
+ DoNotTakeOverContext,
+ TakeOverContext
+ };
+ static PassOwnPtr<WebSocketDeflater> create(int windowBits, ContextTakeOverMode = TakeOverContext);
+
+ ~WebSocketDeflater();
+
+ bool initialize();
+ bool addBytes(const char*, size_t);
+ bool finish();
+ const char* data() { return m_buffer.data(); }
+ size_t size() const { return m_buffer.size(); }
+ void reset();
+
+private:
+ WebSocketDeflater(int windowBits, ContextTakeOverMode);
+
+ int m_windowBits;
+ ContextTakeOverMode m_contextTakeOverMode;
+ Vector<char> m_buffer;
+ z_stream m_stream;
+};
+
+class WebSocketInflater {
+public:
+ static PassOwnPtr<WebSocketInflater> create(int windowBits = 15);
+
+ ~WebSocketInflater();
+
+ bool initialize();
+ bool addBytes(const char*, size_t);
+ bool finish();
+ const char* data() { return m_buffer.data(); }
+ size_t size() const { return m_buffer.size(); }
+ void reset();
+
+private:
+ explicit WebSocketInflater(int windowBits);
+
+ int m_windowBits;
+ Vector<char> m_buffer;
+ z_stream m_stream;
+};
+
+}
+
+#endif // ENABLE(WEB_SOCKETS)
+
+#endif // WebSocketDeflater_h
+2012-02-14 Kenichi Ishibashi <bashi@chromium.org>
+
+ [WebSocket] Add deflater/inflater classes.
+ https://bugs.webkit.org/show_bug.cgi?id=78449
+
+ Add tests which ensure WebSocketDeflater/WebSocketInflater can
+ compress/decompress data correctly.
+
+ Reviewed by Kent Tamura.
+
+ * WebKit.gypi:
+ * tests/WebSocketDeflaterTest.cpp: Added.
+ (WebCore):
+ (WebCore::TEST):
+
2012-02-14 Dana Jansens <danakj@chromium.org>
[chromium] Compare filters on impl thread when setting them, and test setting in unit tests
'tests/WebLayerTest.cpp',
'tests/WebPageNewSerializerTest.cpp',
'tests/WebPageSerializerTest.cpp',
+ 'tests/WebSocketDeflaterTest.cpp',
'tests/WebSocketExtensionDispatcherTest.cpp',
'tests/WebURLRequestTest.cpp',
'tests/WebViewTest.cpp',
--- /dev/null
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "WebSocketDeflater.h"
+
+#include <gtest/gtest.h>
+#include <wtf/Vector.h>
+
+using namespace WebCore;
+
+namespace {
+
+TEST(WebSocketDeflaterTest, TestCompressHello)
+{
+ // Test the first example on section 4.3 of the specification.
+ OwnPtr<WebSocketDeflater> deflater = WebSocketDeflater::create(15);
+ ASSERT_TRUE(deflater->initialize());
+ OwnPtr<WebSocketInflater> inflater = WebSocketInflater::create();
+ ASSERT_TRUE(inflater->initialize());
+ const char* inputData = "Hello";
+ const size_t inputLength = strlen(inputData);
+
+ ASSERT_TRUE(deflater->addBytes(inputData, inputLength));
+ ASSERT_TRUE(deflater->finish());
+ const char expectedFirst[] = {0xf2, 0x48, 0xcd, 0xc9, 0xc9, 0x07, 0x00};
+ EXPECT_EQ(sizeof(expectedFirst), deflater->size());
+ EXPECT_EQ(0, memcmp(expectedFirst, deflater->data(), deflater->size()));
+ ASSERT_TRUE(inflater->addBytes(deflater->data(), deflater->size()));
+ ASSERT_TRUE(inflater->finish());
+ EXPECT_EQ(inputLength, inflater->size());
+ EXPECT_EQ(0, memcmp(inputData, inflater->data(), inflater->size()));
+
+ deflater->reset();
+ inflater->reset();
+
+ ASSERT_TRUE(deflater->addBytes(inputData, inputLength));
+ ASSERT_TRUE(deflater->finish());
+ const char expectedSecond[] = {0xf2, 0x00, 0x11, 0x00, 0x00};
+ EXPECT_EQ(sizeof(expectedSecond), deflater->size());
+ EXPECT_EQ(0, memcmp(expectedSecond, deflater->data(), deflater->size()));
+ ASSERT_TRUE(inflater->addBytes(deflater->data(), deflater->size()));
+ ASSERT_TRUE(inflater->finish());
+ EXPECT_EQ(inputLength, inflater->size());
+ EXPECT_EQ(0, memcmp(inputData, inflater->data(), inflater->size()));
+}
+
+TEST(WebSocketDeflaterTest, TestMultipleAddBytesCalls)
+{
+ OwnPtr<WebSocketDeflater> deflater = WebSocketDeflater::create(15);
+ ASSERT_TRUE(deflater->initialize());
+ OwnPtr<WebSocketInflater> inflater = WebSocketInflater::create();
+ ASSERT_TRUE(inflater->initialize());
+ Vector<char> inputData(32);
+ inputData.fill('a');
+
+ for (size_t i = 0; i < inputData.size(); ++i)
+ ASSERT_TRUE(deflater->addBytes(inputData.data() + i, 1));
+ ASSERT_TRUE(deflater->finish());
+ for (size_t i = 0; i < deflater->size(); ++i)
+ ASSERT_TRUE(inflater->addBytes(deflater->data() + i, 1));
+ ASSERT_TRUE(inflater->finish());
+ EXPECT_EQ(inputData.size(), inflater->size());
+ EXPECT_EQ(0, memcmp(inputData.data(), inflater->data(), inflater->size()));
+}
+
+TEST(WebSocketDeflaterTest, TestNoContextTakeOver)
+{
+ OwnPtr<WebSocketDeflater> deflater = WebSocketDeflater::create(15, WebSocketDeflater::DoNotTakeOverContext);
+ ASSERT_TRUE(deflater->initialize());
+ OwnPtr<WebSocketInflater> inflater = WebSocketInflater::create();
+ ASSERT_TRUE(inflater->initialize());
+ const char expected[] = {0xf2, 0x48, 0xcd, 0xc9, 0xc9, 0x07, 0x00};
+ const char* inputData = "Hello";
+ const size_t inputLength = strlen(inputData);
+
+ // If we don't take over context, the second result should be the identical
+ // with the first one.
+ for (size_t i = 0; i < 2; ++i) {
+ ASSERT_TRUE(deflater->addBytes(inputData, inputLength));
+ ASSERT_TRUE(deflater->finish());
+ EXPECT_EQ(sizeof(expected), deflater->size());
+ EXPECT_EQ(0, memcmp(expected, deflater->data(), deflater->size()));
+ ASSERT_TRUE(inflater->addBytes(deflater->data(), deflater->size()));
+ ASSERT_TRUE(inflater->finish());
+ EXPECT_EQ(inputLength, inflater->size());
+ EXPECT_EQ(0, memcmp(inputData, inflater->data(), inflater->size()));
+ deflater->reset();
+ inflater->reset();
+ }
+}
+
+TEST(WebSocketDeflaterTest, TestWindowBits)
+{
+ Vector<char> inputData(1024 + 64 * 2);
+ inputData.fill('a');
+ // Modify the head and tail of the inputData so that back-reference
+ // can be used if the window size is sufficiently-large.
+ for (size_t j = 0; j < 64; ++j) {
+ inputData[j] = 'b';
+ inputData[inputData.size() - j - 1] = 'b';
+ }
+
+ OwnPtr<WebSocketDeflater> deflater = WebSocketDeflater::create(8);
+ ASSERT_TRUE(deflater->initialize());
+ ASSERT_TRUE(deflater->addBytes(inputData.data(), inputData.size()));
+ ASSERT_TRUE(deflater->finish());
+
+ OwnPtr<WebSocketInflater> inflater = WebSocketInflater::create(8);
+ ASSERT_TRUE(inflater->initialize());
+ ASSERT_TRUE(inflater->addBytes(deflater->data(), deflater->size()));
+ ASSERT_TRUE(inflater->finish());
+ EXPECT_EQ(inputData.size(), inflater->size());
+ EXPECT_EQ(0, memcmp(inputData.data(), inflater->data(), inflater->size()));
+}
+
+TEST(WebSocketDeflaterTest, TestLargeData)
+{
+ OwnPtr<WebSocketDeflater> deflater = WebSocketDeflater::create(15);
+ ASSERT_TRUE(deflater->initialize());
+ OwnPtr<WebSocketInflater> inflater = WebSocketInflater::create();
+ ASSERT_TRUE(inflater->initialize());
+ Vector<char> inputData(16 * 1024 * 1024);
+ inputData.fill('a');
+
+ ASSERT_TRUE(deflater->addBytes(inputData.data(), inputData.size()));
+ ASSERT_TRUE(deflater->finish());
+ ASSERT_TRUE(inflater->addBytes(deflater->data(), deflater->size()));
+ ASSERT_TRUE(inflater->finish());
+ EXPECT_EQ(inputData.size(), inflater->size());
+ EXPECT_EQ(0, memcmp(inputData.data(), inflater->data(), inflater->size()));
+}
+
+}