1 // Copyright 2013 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.
5 #include "net/websockets/websocket_inflater.h"
11 #include "base/memory/ref_counted.h"
12 #include "net/base/io_buffer.h"
13 #include "net/websockets/websocket_deflater.h"
14 #include "testing/gtest/include/gtest/gtest.h"
20 std::string
ToString(IOBufferWithSize
* buffer
) {
21 return std::string(buffer
->data(), buffer
->size());
24 class LinearCongruentialGenerator
{
26 explicit LinearCongruentialGenerator(uint32_t seed
);
32 static const uint32_t a_
= 1103515245;
33 static const uint32_t c_
= 12345;
34 static const uint32_t m_
= 1 << 31;
37 LinearCongruentialGenerator::LinearCongruentialGenerator(uint32_t seed
)
40 uint32_t LinearCongruentialGenerator::Generate() {
41 uint32_t result
= current_
;
42 current_
= (current_
* a_
+ c_
) % m_
;
46 TEST(WebSocketInflaterTest
, Construct
) {
47 WebSocketInflater inflater
;
48 ASSERT_TRUE(inflater
.Initialize(15));
50 EXPECT_EQ(0u, inflater
.CurrentOutputSize());
53 TEST(WebSocketInflaterTest
, InflateHelloTakeOverContext
) {
54 WebSocketInflater inflater
;
55 ASSERT_TRUE(inflater
.Initialize(15));
56 scoped_refptr
<IOBufferWithSize
> actual1
, actual2
;
58 ASSERT_TRUE(inflater
.AddBytes("\xf2\x48\xcd\xc9\xc9\x07\x00", 7));
59 ASSERT_TRUE(inflater
.Finish());
60 actual1
= inflater
.GetOutput(inflater
.CurrentOutputSize());
62 EXPECT_EQ("Hello", ToString(actual1
.get()));
63 EXPECT_EQ(0u, inflater
.CurrentOutputSize());
65 ASSERT_TRUE(inflater
.AddBytes("\xf2\x00\x11\x00\x00", 5));
66 ASSERT_TRUE(inflater
.Finish());
67 actual2
= inflater
.GetOutput(inflater
.CurrentOutputSize());
69 EXPECT_EQ("Hello", ToString(actual2
.get()));
70 EXPECT_EQ(0u, inflater
.CurrentOutputSize());
73 TEST(WebSocketInflaterTest
, InflateHelloSmallCapacity
) {
74 WebSocketInflater
inflater(1, 1);
75 ASSERT_TRUE(inflater
.Initialize(15));
78 ASSERT_TRUE(inflater
.AddBytes("\xf2\x48\xcd\xc9\xc9\x07\x00", 7));
79 ASSERT_TRUE(inflater
.Finish());
80 for (size_t i
= 0; i
< 5; ++i
) {
81 ASSERT_EQ(1u, inflater
.CurrentOutputSize());
82 scoped_refptr
<IOBufferWithSize
> buffer
= inflater
.GetOutput(1);
84 ASSERT_EQ(1, buffer
->size());
85 actual
+= ToString(buffer
.get());
87 EXPECT_EQ("Hello", actual
);
88 EXPECT_EQ(0u, inflater
.CurrentOutputSize());
91 TEST(WebSocketInflaterTest
, InflateHelloSmallCapacityGetTotalOutput
) {
92 WebSocketInflater
inflater(1, 1);
93 ASSERT_TRUE(inflater
.Initialize(15));
94 scoped_refptr
<IOBufferWithSize
> actual
;
96 ASSERT_TRUE(inflater
.AddBytes("\xf2\x48\xcd\xc9\xc9\x07\x00", 7));
97 ASSERT_TRUE(inflater
.Finish());
98 ASSERT_EQ(1u, inflater
.CurrentOutputSize());
99 actual
= inflater
.GetOutput(1024);
100 EXPECT_EQ("Hello", ToString(actual
));
101 EXPECT_EQ(0u, inflater
.CurrentOutputSize());
104 TEST(WebSocketInflaterTest
, InflateInvalidData
) {
105 WebSocketInflater inflater
;
106 ASSERT_TRUE(inflater
.Initialize(15));
107 EXPECT_FALSE(inflater
.AddBytes("\xf2\x48\xcd\xc9INVALID DATA", 16));
110 TEST(WebSocketInflaterTest
, ChokedInvalidData
) {
111 WebSocketInflater
inflater(1, 1);
112 ASSERT_TRUE(inflater
.Initialize(15));
114 EXPECT_TRUE(inflater
.AddBytes("\xf2\x48\xcd\xc9INVALID DATA", 16));
115 EXPECT_TRUE(inflater
.Finish());
116 EXPECT_EQ(1u, inflater
.CurrentOutputSize());
117 EXPECT_FALSE(inflater
.GetOutput(1024));
120 TEST(WebSocketInflaterTest
, MultipleAddBytesCalls
) {
121 WebSocketInflater inflater
;
122 ASSERT_TRUE(inflater
.Initialize(15));
123 std::string
input("\xf2\x48\xcd\xc9\xc9\x07\x00", 7);
124 scoped_refptr
<IOBufferWithSize
> actual
;
126 for (size_t i
= 0; i
< input
.size(); ++i
) {
127 ASSERT_TRUE(inflater
.AddBytes(&input
[i
], 1));
129 ASSERT_TRUE(inflater
.Finish());
130 actual
= inflater
.GetOutput(5);
132 EXPECT_EQ("Hello", ToString(actual
.get()));
135 TEST(WebSocketInflaterTest
, Reset
) {
136 WebSocketInflater inflater
;
137 ASSERT_TRUE(inflater
.Initialize(15));
138 scoped_refptr
<IOBufferWithSize
> actual1
, actual2
;
140 ASSERT_TRUE(inflater
.AddBytes("\xf2\x48\xcd\xc9\xc9\x07\x00", 7));
141 ASSERT_TRUE(inflater
.Finish());
142 actual1
= inflater
.GetOutput(inflater
.CurrentOutputSize());
143 ASSERT_TRUE(actual1
);
144 EXPECT_EQ("Hello", ToString(actual1
.get()));
145 EXPECT_EQ(0u, inflater
.CurrentOutputSize());
147 // Reset the stream with a block [BFINAL = 1, BTYPE = 00, LEN = 0]
148 ASSERT_TRUE(inflater
.AddBytes("\x01", 1));
149 ASSERT_TRUE(inflater
.Finish());
150 ASSERT_EQ(0u, inflater
.CurrentOutputSize());
152 ASSERT_TRUE(inflater
.AddBytes("\xf2\x48\xcd\xc9\xc9\x07\x00", 7));
153 ASSERT_TRUE(inflater
.Finish());
154 actual2
= inflater
.GetOutput(inflater
.CurrentOutputSize());
155 ASSERT_TRUE(actual2
);
156 EXPECT_EQ("Hello", ToString(actual2
.get()));
157 EXPECT_EQ(0u, inflater
.CurrentOutputSize());
160 TEST(WebSocketInflaterTest
, ResetAndLostContext
) {
161 WebSocketInflater inflater
;
162 scoped_refptr
<IOBufferWithSize
> actual1
, actual2
;
163 ASSERT_TRUE(inflater
.Initialize(15));
165 ASSERT_TRUE(inflater
.AddBytes("\xf2\x48\xcd\xc9\xc9\x07\x00", 7));
166 ASSERT_TRUE(inflater
.Finish());
167 actual1
= inflater
.GetOutput(inflater
.CurrentOutputSize());
168 ASSERT_TRUE(actual1
);
169 EXPECT_EQ("Hello", ToString(actual1
.get()));
170 EXPECT_EQ(0u, inflater
.CurrentOutputSize());
172 // Reset the stream with a block [BFINAL = 1, BTYPE = 00, LEN = 0]
173 ASSERT_TRUE(inflater
.AddBytes("\x01", 1));
174 ASSERT_TRUE(inflater
.Finish());
175 ASSERT_EQ(0u, inflater
.CurrentOutputSize());
177 // The context is already reset.
178 ASSERT_FALSE(inflater
.AddBytes("\xf2\x00\x11\x00\x00", 5));
181 TEST(WebSocketInflaterTest
, CallAddBytesAndFinishWithoutGetOutput
) {
182 WebSocketInflater inflater
;
183 scoped_refptr
<IOBufferWithSize
> actual1
, actual2
;
184 ASSERT_TRUE(inflater
.Initialize(15));
186 ASSERT_TRUE(inflater
.AddBytes("\xf2\x48\xcd\xc9\xc9\x07\x00", 7));
187 ASSERT_TRUE(inflater
.Finish());
188 EXPECT_EQ(5u, inflater
.CurrentOutputSize());
190 // This is a test for detecting memory leaks with valgrind.
193 TEST(WebSocketInflaterTest
, CallAddBytesAndFinishWithoutGetOutputChoked
) {
194 WebSocketInflater
inflater(1, 1);
195 scoped_refptr
<IOBufferWithSize
> actual1
, actual2
;
196 ASSERT_TRUE(inflater
.Initialize(15));
198 ASSERT_TRUE(inflater
.AddBytes("\xf2\x48\xcd\xc9\xc9\x07\x00", 7));
199 ASSERT_TRUE(inflater
.Finish());
200 EXPECT_EQ(1u, inflater
.CurrentOutputSize());
202 // This is a test for detecting memory leaks with valgrind.
205 TEST(WebSocketInflaterTest
, LargeRandomDeflateInflate
) {
206 const size_t size
= 64 * 1024;
207 LinearCongruentialGenerator
generator(133);
208 std::vector
<char> input
;
209 std::vector
<char> output
;
210 scoped_refptr
<IOBufferWithSize
> compressed
;
212 WebSocketDeflater
deflater(WebSocketDeflater::TAKE_OVER_CONTEXT
);
213 ASSERT_TRUE(deflater
.Initialize(8));
214 WebSocketInflater
inflater(256, 256);
215 ASSERT_TRUE(inflater
.Initialize(8));
217 for (size_t i
= 0; i
< size
; ++i
)
218 input
.push_back(static_cast<char>(generator
.Generate()));
220 ASSERT_TRUE(deflater
.AddBytes(&input
[0], input
.size()));
221 ASSERT_TRUE(deflater
.Finish());
223 compressed
= deflater
.GetOutput(deflater
.CurrentOutputSize());
225 ASSERT_TRUE(compressed
);
226 ASSERT_EQ(0u, deflater
.CurrentOutputSize());
228 ASSERT_TRUE(inflater
.AddBytes(compressed
->data(), compressed
->size()));
229 ASSERT_TRUE(inflater
.Finish());
231 while (inflater
.CurrentOutputSize() > 0) {
232 scoped_refptr
<IOBufferWithSize
> uncompressed
=
233 inflater
.GetOutput(inflater
.CurrentOutputSize());
234 ASSERT_TRUE(uncompressed
);
235 output
.insert(output
.end(),
236 uncompressed
->data(),
237 uncompressed
->data() + uncompressed
->size());
240 EXPECT_EQ(output
, input
);
243 } // unnamed namespace