1/*
2 * Copyright (C) 2012 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1.  Redistributions of source code must retain the above copyright
9 *     notice, this list of conditions and the following disclaimer.
10 * 2.  Redistributions in binary form must reproduce the above copyright
11 *     notice, this list of conditions and the following disclaimer in the
12 *     documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
18 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "modules/websockets/WebSocketDeflater.h"
28
29#include "wtf/Vector.h"
30#include <gtest/gtest.h>
31
32namespace blink {
33namespace {
34
35TEST(WebSocketDeflaterTest, TestCompressHello)
36{
37    // Test the first example on section 4.3 of the specification.
38    OwnPtr<WebSocketDeflater> deflater = WebSocketDeflater::create(15);
39    ASSERT_TRUE(deflater->initialize());
40    OwnPtr<WebSocketInflater> inflater = WebSocketInflater::create();
41    ASSERT_TRUE(inflater->initialize());
42    const char* inputData = "Hello";
43    const size_t inputLength = strlen(inputData);
44
45    ASSERT_TRUE(deflater->addBytes(inputData, inputLength));
46    ASSERT_TRUE(deflater->finish());
47    const char* expectedFirst = "\xf2\x48\xcd\xc9\xc9\x07\x00";
48    EXPECT_EQ(7U, deflater->size());
49    EXPECT_EQ(0, memcmp(expectedFirst, deflater->data(), deflater->size()));
50    ASSERT_TRUE(inflater->addBytes(deflater->data(), deflater->size()));
51    ASSERT_TRUE(inflater->finish());
52    EXPECT_EQ(inputLength, inflater->size());
53    EXPECT_EQ(0, memcmp(inputData, inflater->data(), inflater->size()));
54
55    deflater->reset();
56    inflater->reset();
57
58    ASSERT_TRUE(deflater->addBytes(inputData, inputLength));
59    ASSERT_TRUE(deflater->finish());
60    const char* expectedSecond = "\xf2\x00\x11\x00\x00";
61    EXPECT_EQ(5U, deflater->size());
62    EXPECT_EQ(0, memcmp(expectedSecond, deflater->data(), deflater->size()));
63    ASSERT_TRUE(inflater->addBytes(deflater->data(), deflater->size()));
64    ASSERT_TRUE(inflater->finish());
65    EXPECT_EQ(inputLength, inflater->size());
66    EXPECT_EQ(0, memcmp(inputData, inflater->data(), inflater->size()));
67}
68
69TEST(WebSocketDeflaterTest, TestMultipleAddBytesCalls)
70{
71    OwnPtr<WebSocketDeflater> deflater = WebSocketDeflater::create(15);
72    ASSERT_TRUE(deflater->initialize());
73    OwnPtr<WebSocketInflater> inflater = WebSocketInflater::create();
74    ASSERT_TRUE(inflater->initialize());
75    Vector<char> inputData(32);
76    inputData.fill('a');
77
78    for (size_t i = 0; i < inputData.size(); ++i)
79        ASSERT_TRUE(deflater->addBytes(inputData.data() + i, 1));
80    ASSERT_TRUE(deflater->finish());
81    for (size_t i = 0; i < deflater->size(); ++i)
82        ASSERT_TRUE(inflater->addBytes(deflater->data() + i, 1));
83    ASSERT_TRUE(inflater->finish());
84    EXPECT_EQ(inputData.size(), inflater->size());
85    EXPECT_EQ(0, memcmp(inputData.data(), inflater->data(), inflater->size()));
86}
87
88TEST(WebSocketDeflaterTest, TestNoContextTakeOver)
89{
90    OwnPtr<WebSocketDeflater> deflater = WebSocketDeflater::create(15, WebSocketDeflater::DoNotTakeOverContext);
91    ASSERT_TRUE(deflater->initialize());
92    OwnPtr<WebSocketInflater> inflater = WebSocketInflater::create();
93    ASSERT_TRUE(inflater->initialize());
94    const char* expected = "\xf2\x48\xcd\xc9\xc9\x07\x00";
95    const char* inputData = "Hello";
96    const size_t inputLength = strlen(inputData);
97
98    // If we don't take over context, the second result should be the identical
99    // with the first one.
100    for (size_t i = 0; i < 2; ++i) {
101        ASSERT_TRUE(deflater->addBytes(inputData, inputLength));
102        ASSERT_TRUE(deflater->finish());
103        EXPECT_EQ(7U, deflater->size());
104        EXPECT_EQ(0, memcmp(expected, deflater->data(), deflater->size()));
105        ASSERT_TRUE(inflater->addBytes(deflater->data(), deflater->size()));
106        ASSERT_TRUE(inflater->finish());
107        EXPECT_EQ(inputLength, inflater->size());
108        EXPECT_EQ(0, memcmp(inputData, inflater->data(), inflater->size()));
109        deflater->reset();
110        inflater->reset();
111    }
112}
113
114TEST(WebSocketDeflaterTest, TestWindowBits)
115{
116    Vector<char> inputData(1024 + 64 * 2);
117    inputData.fill('a');
118    // Modify the head and tail of the inputData so that back-reference
119    // can be used if the window size is sufficiently-large.
120    for (size_t j = 0; j < 64; ++j) {
121        inputData[j] = 'b';
122        inputData[inputData.size() - j - 1] = 'b';
123    }
124
125    OwnPtr<WebSocketDeflater> deflater = WebSocketDeflater::create(8);
126    ASSERT_TRUE(deflater->initialize());
127    ASSERT_TRUE(deflater->addBytes(inputData.data(), inputData.size()));
128    ASSERT_TRUE(deflater->finish());
129
130    OwnPtr<WebSocketInflater> inflater = WebSocketInflater::create(8);
131    ASSERT_TRUE(inflater->initialize());
132    ASSERT_TRUE(inflater->addBytes(deflater->data(), deflater->size()));
133    ASSERT_TRUE(inflater->finish());
134    EXPECT_EQ(inputData.size(), inflater->size());
135    EXPECT_EQ(0, memcmp(inputData.data(), inflater->data(), inflater->size()));
136}
137
138TEST(WebSocketDeflaterTest, TestLargeData)
139{
140    OwnPtr<WebSocketDeflater> deflater = WebSocketDeflater::create(15);
141    ASSERT_TRUE(deflater->initialize());
142    OwnPtr<WebSocketInflater> inflater = WebSocketInflater::create();
143    ASSERT_TRUE(inflater->initialize());
144    Vector<char> inputData(16 * 1024 * 1024);
145    inputData.fill('a');
146
147    ASSERT_TRUE(deflater->addBytes(inputData.data(), inputData.size()));
148    ASSERT_TRUE(deflater->finish());
149    ASSERT_TRUE(inflater->addBytes(deflater->data(), deflater->size()));
150    ASSERT_TRUE(inflater->finish());
151    EXPECT_EQ(inputData.size(), inflater->size());
152    EXPECT_EQ(0, memcmp(inputData.data(), inflater->data(), inflater->size()));
153}
154
155} // namespace
156} // namespace blink
157