• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "net/websockets/websocket_inflater.h"
6 
7 #include <stdint.h>
8 #include <string>
9 #include <vector>
10 
11 #include "base/memory/ref_counted.h"
12 #include "net/base/io_buffer.h"
13 #include "net/websockets/websocket_deflater.h"
14 #include "net/websockets/websocket_test_util.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16 
17 namespace net {
18 
19 namespace {
20 
ToString(IOBufferWithSize * buffer)21 std::string ToString(IOBufferWithSize* buffer) {
22   return std::string(buffer->data(), buffer->size());
23 }
24 
TEST(WebSocketInflaterTest,Construct)25 TEST(WebSocketInflaterTest, Construct) {
26   WebSocketInflater inflater;
27   ASSERT_TRUE(inflater.Initialize(15));
28 
29   EXPECT_EQ(0u, inflater.CurrentOutputSize());
30 }
31 
TEST(WebSocketInflaterTest,InflateHelloTakeOverContext)32 TEST(WebSocketInflaterTest, InflateHelloTakeOverContext) {
33   WebSocketInflater inflater;
34   ASSERT_TRUE(inflater.Initialize(15));
35   scoped_refptr<IOBufferWithSize> actual1, actual2;
36 
37   ASSERT_TRUE(inflater.AddBytes("\xf2\x48\xcd\xc9\xc9\x07\x00", 7));
38   ASSERT_TRUE(inflater.Finish());
39   actual1 = inflater.GetOutput(inflater.CurrentOutputSize());
40   ASSERT_TRUE(actual1.get());
41   EXPECT_EQ("Hello", ToString(actual1.get()));
42   EXPECT_EQ(0u, inflater.CurrentOutputSize());
43 
44   ASSERT_TRUE(inflater.AddBytes("\xf2\x00\x11\x00\x00", 5));
45   ASSERT_TRUE(inflater.Finish());
46   actual2 = inflater.GetOutput(inflater.CurrentOutputSize());
47   ASSERT_TRUE(actual2.get());
48   EXPECT_EQ("Hello", ToString(actual2.get()));
49   EXPECT_EQ(0u, inflater.CurrentOutputSize());
50 }
51 
TEST(WebSocketInflaterTest,InflateHelloSmallCapacity)52 TEST(WebSocketInflaterTest, InflateHelloSmallCapacity) {
53   WebSocketInflater inflater(1, 1);
54   ASSERT_TRUE(inflater.Initialize(15));
55   std::string actual;
56 
57   ASSERT_TRUE(inflater.AddBytes("\xf2\x48\xcd\xc9\xc9\x07\x00", 7));
58   ASSERT_TRUE(inflater.Finish());
59   for (size_t i = 0; i < 5; ++i) {
60     ASSERT_EQ(1u, inflater.CurrentOutputSize());
61     scoped_refptr<IOBufferWithSize> buffer = inflater.GetOutput(1);
62     ASSERT_TRUE(buffer.get());
63     ASSERT_EQ(1, buffer->size());
64     actual += ToString(buffer.get());
65   }
66   EXPECT_EQ("Hello", actual);
67   EXPECT_EQ(0u, inflater.CurrentOutputSize());
68 }
69 
TEST(WebSocketInflaterTest,InflateHelloSmallCapacityGetTotalOutput)70 TEST(WebSocketInflaterTest, InflateHelloSmallCapacityGetTotalOutput) {
71   WebSocketInflater inflater(1, 1);
72   ASSERT_TRUE(inflater.Initialize(15));
73   scoped_refptr<IOBufferWithSize> actual;
74 
75   ASSERT_TRUE(inflater.AddBytes("\xf2\x48\xcd\xc9\xc9\x07\x00", 7));
76   ASSERT_TRUE(inflater.Finish());
77   ASSERT_EQ(1u, inflater.CurrentOutputSize());
78   actual = inflater.GetOutput(1024);
79   EXPECT_EQ("Hello", ToString(actual.get()));
80   EXPECT_EQ(0u, inflater.CurrentOutputSize());
81 }
82 
TEST(WebSocketInflaterTest,InflateInvalidData)83 TEST(WebSocketInflaterTest, InflateInvalidData) {
84   WebSocketInflater inflater;
85   ASSERT_TRUE(inflater.Initialize(15));
86   EXPECT_FALSE(inflater.AddBytes("\xf2\x48\xcd\xc9INVALID DATA", 16));
87 }
88 
TEST(WebSocketInflaterTest,ChokedInvalidData)89 TEST(WebSocketInflaterTest, ChokedInvalidData) {
90   WebSocketInflater inflater(1, 1);
91   ASSERT_TRUE(inflater.Initialize(15));
92 
93   EXPECT_TRUE(inflater.AddBytes("\xf2\x48\xcd\xc9INVALID DATA", 16));
94   EXPECT_TRUE(inflater.Finish());
95   EXPECT_EQ(1u, inflater.CurrentOutputSize());
96   EXPECT_FALSE(inflater.GetOutput(1024).get());
97 }
98 
TEST(WebSocketInflaterTest,MultipleAddBytesCalls)99 TEST(WebSocketInflaterTest, MultipleAddBytesCalls) {
100   WebSocketInflater inflater;
101   ASSERT_TRUE(inflater.Initialize(15));
102   std::string input("\xf2\x48\xcd\xc9\xc9\x07\x00", 7);
103   scoped_refptr<IOBufferWithSize> actual;
104 
105   for (size_t i = 0; i < input.size(); ++i) {
106     ASSERT_TRUE(inflater.AddBytes(&input[i], 1));
107   }
108   ASSERT_TRUE(inflater.Finish());
109   actual = inflater.GetOutput(5);
110   ASSERT_TRUE(actual.get());
111   EXPECT_EQ("Hello", ToString(actual.get()));
112 }
113 
TEST(WebSocketInflaterTest,Reset)114 TEST(WebSocketInflaterTest, Reset) {
115   WebSocketInflater inflater;
116   ASSERT_TRUE(inflater.Initialize(15));
117   scoped_refptr<IOBufferWithSize> actual1, actual2;
118 
119   ASSERT_TRUE(inflater.AddBytes("\xf2\x48\xcd\xc9\xc9\x07\x00", 7));
120   ASSERT_TRUE(inflater.Finish());
121   actual1 = inflater.GetOutput(inflater.CurrentOutputSize());
122   ASSERT_TRUE(actual1.get());
123   EXPECT_EQ("Hello", ToString(actual1.get()));
124   EXPECT_EQ(0u, inflater.CurrentOutputSize());
125 
126   // Reset the stream with a block [BFINAL = 1, BTYPE = 00, LEN = 0]
127   ASSERT_TRUE(inflater.AddBytes("\x01", 1));
128   ASSERT_TRUE(inflater.Finish());
129   ASSERT_EQ(0u, inflater.CurrentOutputSize());
130 
131   ASSERT_TRUE(inflater.AddBytes("\xf2\x48\xcd\xc9\xc9\x07\x00", 7));
132   ASSERT_TRUE(inflater.Finish());
133   actual2 = inflater.GetOutput(inflater.CurrentOutputSize());
134   ASSERT_TRUE(actual2.get());
135   EXPECT_EQ("Hello", ToString(actual2.get()));
136   EXPECT_EQ(0u, inflater.CurrentOutputSize());
137 }
138 
TEST(WebSocketInflaterTest,ResetAndLostContext)139 TEST(WebSocketInflaterTest, ResetAndLostContext) {
140   WebSocketInflater inflater;
141   scoped_refptr<IOBufferWithSize> actual1, actual2;
142   ASSERT_TRUE(inflater.Initialize(15));
143 
144   ASSERT_TRUE(inflater.AddBytes("\xf2\x48\xcd\xc9\xc9\x07\x00", 7));
145   ASSERT_TRUE(inflater.Finish());
146   actual1 = inflater.GetOutput(inflater.CurrentOutputSize());
147   ASSERT_TRUE(actual1.get());
148   EXPECT_EQ("Hello", ToString(actual1.get()));
149   EXPECT_EQ(0u, inflater.CurrentOutputSize());
150 
151   // Reset the stream with a block [BFINAL = 1, BTYPE = 00, LEN = 0]
152   ASSERT_TRUE(inflater.AddBytes("\x01", 1));
153   ASSERT_TRUE(inflater.Finish());
154   ASSERT_EQ(0u, inflater.CurrentOutputSize());
155 
156   // The context is already reset.
157   ASSERT_FALSE(inflater.AddBytes("\xf2\x00\x11\x00\x00", 5));
158 }
159 
TEST(WebSocketInflaterTest,CallAddBytesAndFinishWithoutGetOutput)160 TEST(WebSocketInflaterTest, CallAddBytesAndFinishWithoutGetOutput) {
161   WebSocketInflater inflater;
162   scoped_refptr<IOBufferWithSize> actual1, actual2;
163   ASSERT_TRUE(inflater.Initialize(15));
164 
165   ASSERT_TRUE(inflater.AddBytes("\xf2\x48\xcd\xc9\xc9\x07\x00", 7));
166   ASSERT_TRUE(inflater.Finish());
167   EXPECT_EQ(5u, inflater.CurrentOutputSize());
168 
169   // This is a test for detecting memory leaks with valgrind.
170 }
171 
TEST(WebSocketInflaterTest,CallAddBytesAndFinishWithoutGetOutputChoked)172 TEST(WebSocketInflaterTest, CallAddBytesAndFinishWithoutGetOutputChoked) {
173   WebSocketInflater inflater(1, 1);
174   scoped_refptr<IOBufferWithSize> actual1, actual2;
175   ASSERT_TRUE(inflater.Initialize(15));
176 
177   ASSERT_TRUE(inflater.AddBytes("\xf2\x48\xcd\xc9\xc9\x07\x00", 7));
178   ASSERT_TRUE(inflater.Finish());
179   EXPECT_EQ(1u, inflater.CurrentOutputSize());
180 
181   // This is a test for detecting memory leaks with valgrind.
182 }
183 
TEST(WebSocketInflaterTest,LargeRandomDeflateInflate)184 TEST(WebSocketInflaterTest, LargeRandomDeflateInflate) {
185   const size_t size = 64 * 1024;
186   LinearCongruentialGenerator generator(133);
187   std::vector<char> input;
188   std::vector<char> output;
189   scoped_refptr<IOBufferWithSize> compressed;
190 
191   WebSocketDeflater deflater(WebSocketDeflater::TAKE_OVER_CONTEXT);
192   ASSERT_TRUE(deflater.Initialize(8));
193   WebSocketInflater inflater(256, 256);
194   ASSERT_TRUE(inflater.Initialize(8));
195 
196   for (size_t i = 0; i < size; ++i)
197     input.push_back(static_cast<char>(generator.Generate()));
198 
199   ASSERT_TRUE(deflater.AddBytes(&input[0], input.size()));
200   ASSERT_TRUE(deflater.Finish());
201 
202   compressed = deflater.GetOutput(deflater.CurrentOutputSize());
203 
204   ASSERT_TRUE(compressed.get());
205   ASSERT_EQ(0u, deflater.CurrentOutputSize());
206 
207   ASSERT_TRUE(inflater.AddBytes(compressed->data(), compressed->size()));
208   ASSERT_TRUE(inflater.Finish());
209 
210   while (inflater.CurrentOutputSize() > 0) {
211     scoped_refptr<IOBufferWithSize> uncompressed =
212         inflater.GetOutput(inflater.CurrentOutputSize());
213     ASSERT_TRUE(uncompressed.get());
214     output.insert(output.end(),
215                   uncompressed->data(),
216                   uncompressed->data() + uncompressed->size());
217   }
218 
219   EXPECT_EQ(output, input);
220 }
221 
222 }  // unnamed namespace
223 
224 }  // namespace net
225