• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2013 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 are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  *     * Neither the name of Google Inc. nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #include "config.h"
32 #include "modules/websockets/WebSocketPerMessageDeflate.h"
33 
34 #include "wtf/Vector.h"
35 #include "wtf/text/StringHash.h"
36 
37 #include <algorithm>
38 #include <gtest/gtest.h>
39 #include <iterator>
40 
41 using namespace WebCore;
42 
43 namespace {
44 
TEST(WebSocketPerMessageDeflateTest,TestDeflateHelloTakeOver)45 TEST(WebSocketPerMessageDeflateTest, TestDeflateHelloTakeOver)
46 {
47     WebSocketPerMessageDeflate c;
48     c.enable(8, WebSocketDeflater::TakeOverContext);
49     WebSocketFrame::OpCode opcode = WebSocketFrame::OpCodeText;
50     WebSocketFrame f1(opcode, "Hello", 5, WebSocketFrame::Final);
51     WebSocketFrame f2(opcode, "Hello", 5, WebSocketFrame::Final);
52 
53     ASSERT_TRUE(c.deflate(f1));
54     EXPECT_EQ(7u, f1.payloadLength);
55     EXPECT_EQ(0, memcmp("\xf2\x48\xcd\xc9\xc9\x07\x00", f1.payload, f1.payloadLength));
56     EXPECT_TRUE(f1.compress);
57     EXPECT_TRUE(f1.final);
58 
59     c.resetDeflateBuffer();
60     ASSERT_TRUE(c.deflate(f2));
61     EXPECT_EQ(5u, f2.payloadLength);
62     EXPECT_EQ(0, memcmp("\xf2\x00\x11\x00\x00", f2.payload, f2.payloadLength));
63     EXPECT_TRUE(f2.compress);
64     EXPECT_TRUE(f2.final);
65 }
66 
TEST(WebSocketPerMessageTest,TestDeflateHelloNoTakeOver)67 TEST(WebSocketPerMessageTest, TestDeflateHelloNoTakeOver)
68 {
69     WebSocketPerMessageDeflate c;
70     c.enable(8, WebSocketDeflater::DoNotTakeOverContext);
71     WebSocketFrame::OpCode opcode = WebSocketFrame::OpCodeText;
72     WebSocketFrame f1(opcode, "Hello", 5, WebSocketFrame::Final);
73     WebSocketFrame f2(opcode, "Hello", 5, WebSocketFrame::Final);
74 
75     ASSERT_TRUE(c.deflate(f1));
76     EXPECT_EQ(7u, f1.payloadLength);
77     EXPECT_EQ(0, memcmp("\xf2\x48\xcd\xc9\xc9\x07\x00", f1.payload, f1.payloadLength));
78     EXPECT_TRUE(f1.compress);
79     EXPECT_TRUE(f1.final);
80 
81     c.resetDeflateBuffer();
82     ASSERT_TRUE(c.deflate(f2));
83     EXPECT_EQ(7u, f2.payloadLength);
84     EXPECT_EQ(0, memcmp("\xf2\x48\xcd\xc9\xc9\x07\x00", f2.payload, f2.payloadLength));
85     EXPECT_TRUE(f2.compress);
86     EXPECT_TRUE(f2.final);
87 }
88 
TEST(WebSocketPerMessageDeflateTest,TestDeflateInflateMultipleFrame)89 TEST(WebSocketPerMessageDeflateTest, TestDeflateInflateMultipleFrame)
90 {
91     WebSocketPerMessageDeflate c;
92     WebSocketFrame::OpCode text = WebSocketFrame::OpCodeText;
93     c.enable(8, WebSocketDeflater::DoNotTakeOverContext);
94     size_t length = 64 * 1024;
95     std::string payload;
96     std::string expected;
97     std::string actual;
98     std::string inflated;
99     // Generate string by a linear congruential generator.
100     uint64_t r = 0;
101     for (size_t i = 0; i < length; ++i) {
102         payload += 'a' + (r % 25);
103         r = (r * 12345 + 1103515245) % (static_cast<uint64_t>(1) << 31);
104     }
105 
106     WebSocketFrame frame(text, &payload[0], payload.size(), WebSocketFrame::Final);
107     ASSERT_TRUE(c.deflate(frame));
108     ASSERT_TRUE(frame.final);
109     ASSERT_TRUE(frame.compress);
110     expected = std::string(frame.payload, frame.payloadLength);
111     for (size_t i = 0; i < length; ++i) {
112         WebSocketFrame::OpCode opcode = !i ? text : WebSocketFrame::OpCodeContinuation;
113         c.resetDeflateBuffer();
114         WebSocketFrame frame(opcode, &payload[i], 1);
115         frame.final = (i == length - 1);
116 
117         ASSERT_TRUE(c.deflate(frame));
118         ASSERT_EQ(i == length - 1, frame.final);
119         ASSERT_EQ(!i, frame.compress);
120         actual += std::string(frame.payload, frame.payloadLength);
121     }
122     EXPECT_EQ(expected, actual);
123 
124     for (size_t i = 0; i < actual.size(); ++i) {
125         WebSocketFrame::OpCode opcode = !i ? text : WebSocketFrame::OpCodeContinuation;
126         c.resetInflateBuffer();
127         WebSocketFrame frame(opcode, &actual[i], 1);
128         frame.final = (i == actual.size() - 1);
129         frame.compress = !i;
130 
131         ASSERT_TRUE(c.inflate(frame));
132         ASSERT_EQ(i == actual.size() - 1, frame.final);
133         ASSERT_FALSE(frame.compress);
134         inflated += std::string(frame.payload, frame.payloadLength);
135     }
136     EXPECT_EQ(payload, inflated);
137 }
138 
TEST(WebSocketPerMessageDeflateTest,TestDeflateBinary)139 TEST(WebSocketPerMessageDeflateTest, TestDeflateBinary)
140 {
141     WebSocketPerMessageDeflate c;
142     c.enable(8, WebSocketDeflater::TakeOverContext);
143     WebSocketFrame::OpCode opcode = WebSocketFrame::OpCodeBinary;
144     WebSocketFrame f1(opcode, "Hello", 5, WebSocketFrame::Final);
145 
146     ASSERT_TRUE(c.deflate(f1));
147     EXPECT_EQ(7u, f1.payloadLength);
148     EXPECT_EQ(0, memcmp("\xf2\x48\xcd\xc9\xc9\x07\x00", f1.payload, f1.payloadLength));
149     EXPECT_EQ(opcode, f1.opCode);
150     EXPECT_TRUE(f1.compress);
151     EXPECT_TRUE(f1.final);
152 }
153 
TEST(WebSocketPerMessageDeflateTest,TestDeflateEmptyFrame)154 TEST(WebSocketPerMessageDeflateTest, TestDeflateEmptyFrame)
155 {
156     WebSocketPerMessageDeflate c;
157     c.enable(8, WebSocketDeflater::TakeOverContext);
158     WebSocketFrame f1(WebSocketFrame::OpCodeText, "Hello", 5);
159     WebSocketFrame f2(WebSocketFrame::OpCodeContinuation, "", 0, WebSocketFrame::Final);
160 
161     ASSERT_TRUE(c.deflate(f1));
162     EXPECT_EQ(0u, f1.payloadLength);
163     EXPECT_FALSE(f1.final);
164     EXPECT_TRUE(f1.compress);
165 
166     c.resetDeflateBuffer();
167     ASSERT_TRUE(c.deflate(f2));
168     EXPECT_EQ(7u, f2.payloadLength);
169     EXPECT_EQ(0, memcmp("\xf2\x48\xcd\xc9\xc9\x07\x00", f2.payload, f2.payloadLength));
170     EXPECT_TRUE(f2.final);
171     EXPECT_FALSE(f2.compress);
172 }
173 
TEST(WebSocketPerMessageDeflateTest,TestDeflateEmptyMessages)174 TEST(WebSocketPerMessageDeflateTest, TestDeflateEmptyMessages)
175 {
176     WebSocketPerMessageDeflate c;
177     c.enable(8, WebSocketDeflater::TakeOverContext);
178     WebSocketFrame f1(WebSocketFrame::OpCodeText, "", 0);
179     WebSocketFrame f2(WebSocketFrame::OpCodeContinuation, "", 0, WebSocketFrame::Final);
180     WebSocketFrame f3(WebSocketFrame::OpCodeText, "", 0, WebSocketFrame::Final);
181     WebSocketFrame f4(WebSocketFrame::OpCodeText, "", 0, WebSocketFrame::Final);
182     WebSocketFrame f5(WebSocketFrame::OpCodeText, "Hello", 5, WebSocketFrame::Final);
183 
184     ASSERT_TRUE(c.deflate(f1));
185     EXPECT_EQ(0u, f1.payloadLength);
186     EXPECT_FALSE(f1.final);
187     EXPECT_TRUE(f1.compress);
188 
189     c.resetDeflateBuffer();
190     ASSERT_TRUE(c.deflate(f2));
191     EXPECT_EQ(2u, f2.payloadLength);
192     EXPECT_EQ(0, memcmp("\x02\x00", f2.payload, f2.payloadLength));
193     EXPECT_TRUE(f2.final);
194     EXPECT_FALSE(f2.compress);
195 
196     c.resetDeflateBuffer();
197     ASSERT_TRUE(c.deflate(f3));
198     EXPECT_EQ(0u, f3.payloadLength);
199     EXPECT_TRUE(f3.final);
200     EXPECT_FALSE(f3.compress);
201 
202     c.resetDeflateBuffer();
203     ASSERT_TRUE(c.deflate(f4));
204     EXPECT_EQ(0u, f4.payloadLength);
205     EXPECT_TRUE(f4.final);
206     EXPECT_FALSE(f4.compress);
207 
208     c.resetDeflateBuffer();
209     ASSERT_TRUE(c.deflate(f5));
210     EXPECT_EQ(7u, f5.payloadLength);
211     EXPECT_EQ(0, memcmp("\xf2\x48\xcd\xc9\xc9\x07\x00", f5.payload, f5.payloadLength));
212     EXPECT_TRUE(f5.final);
213     EXPECT_TRUE(f5.compress);
214 }
215 
TEST(WebSocketPerMessageDeflateTest,TestControlMessage)216 TEST(WebSocketPerMessageDeflateTest, TestControlMessage)
217 {
218     WebSocketPerMessageDeflate c;
219     c.enable(8, WebSocketDeflater::TakeOverContext);
220     WebSocketFrame::OpCode opcode = WebSocketFrame::OpCodeClose;
221     WebSocketFrame f1(opcode, "Hello", 5, WebSocketFrame::Final);
222 
223     ASSERT_TRUE(c.deflate(f1));
224     EXPECT_TRUE(f1.final);
225     EXPECT_FALSE(f1.compress);
226     EXPECT_EQ(std::string("Hello"), std::string(f1.payload, f1.payloadLength));
227 }
228 
TEST(WebSocketPerMessageDeflateTest,TestDeflateControlMessageBetweenTextFrames)229 TEST(WebSocketPerMessageDeflateTest, TestDeflateControlMessageBetweenTextFrames)
230 {
231     WebSocketPerMessageDeflate c;
232     c.enable(8, WebSocketDeflater::TakeOverContext);
233     WebSocketFrame::OpCode close = WebSocketFrame::OpCodeClose;
234     WebSocketFrame::OpCode text = WebSocketFrame::OpCodeText;
235     WebSocketFrame::OpCode continuation = WebSocketFrame::OpCodeContinuation;
236     WebSocketFrame f1(text, "Hello", 5);
237     WebSocketFrame f2(close, "close", 5, WebSocketFrame::Final);
238     WebSocketFrame f3(continuation, "", 0, WebSocketFrame::Final);
239 
240     std::vector<char> compressed;
241     ASSERT_TRUE(c.deflate(f1));
242     EXPECT_FALSE(f1.final);
243     EXPECT_TRUE(f1.compress);
244     std::copy(&f1.payload[0], &f1.payload[f1.payloadLength], std::inserter(compressed, compressed.end()));
245 
246     c.resetDeflateBuffer();
247     ASSERT_TRUE(c.deflate(f2));
248     EXPECT_TRUE(f2.final);
249     EXPECT_FALSE(f2.compress);
250     EXPECT_EQ(std::string("close"), std::string(f2.payload, f2.payloadLength));
251 
252     c.resetDeflateBuffer();
253     ASSERT_TRUE(c.deflate(f3));
254     EXPECT_TRUE(f3.final);
255     EXPECT_FALSE(f3.compress);
256     std::copy(&f3.payload[0], &f3.payload[f3.payloadLength], std::inserter(compressed, compressed.end()));
257 
258     EXPECT_EQ(7u, compressed.size());
259     EXPECT_EQ(0, memcmp("\xf2\x48\xcd\xc9\xc9\x07\x00", &compressed[0], compressed.size()));
260 }
261 
TEST(WebSocketPerMessageDeflateTest,TestInflate)262 TEST(WebSocketPerMessageDeflateTest, TestInflate)
263 {
264     WebSocketPerMessageDeflate c;
265     c.enable(8, WebSocketDeflater::TakeOverContext);
266     WebSocketFrame::OpCode opcode = WebSocketFrame::OpCodeText;
267     WebSocketFrame::OpCode continuation = WebSocketFrame::OpCodeContinuation;
268     std::string expected = "HelloHi!Hello";
269     std::string actual;
270     WebSocketFrame f1(opcode, "\xf2\x48\xcd\xc9\xc9\x07\x00", 7, WebSocketFrame::Final | WebSocketFrame::Compress);
271     WebSocketFrame f2(continuation, "Hi!", 3, WebSocketFrame::Final);
272     WebSocketFrame f3(opcode, "\xf2\x00\x11\x00\x00", 5, WebSocketFrame::Final | WebSocketFrame::Compress);
273 
274     ASSERT_TRUE(c.inflate(f1));
275     EXPECT_EQ(5u, f1.payloadLength);
276     EXPECT_EQ(std::string("Hello"), std::string(f1.payload, f1.payloadLength));
277     EXPECT_FALSE(f1.compress);
278     EXPECT_TRUE(f1.final);
279 
280     c.resetInflateBuffer();
281     ASSERT_TRUE(c.inflate(f2));
282     EXPECT_EQ(3u, f2.payloadLength);
283     EXPECT_EQ(std::string("Hi!"), std::string(f2.payload, f2.payloadLength));
284     EXPECT_FALSE(f2.compress);
285     EXPECT_TRUE(f2.final);
286 
287     c.resetInflateBuffer();
288     ASSERT_TRUE(c.inflate(f3));
289     EXPECT_EQ(5u, f3.payloadLength);
290     EXPECT_EQ(std::string("Hello"), std::string(f3.payload, f3.payloadLength));
291     EXPECT_FALSE(f3.compress);
292     EXPECT_TRUE(f3.final);
293 }
294 
TEST(WebSocketPerMessageDeflateTest,TestInflateEmptyFrame)295 TEST(WebSocketPerMessageDeflateTest, TestInflateEmptyFrame)
296 {
297     WebSocketPerMessageDeflate c;
298     c.enable(8, WebSocketDeflater::TakeOverContext);
299     WebSocketFrame::OpCode opcode = WebSocketFrame::OpCodeText;
300     WebSocketFrame::OpCode continuation = WebSocketFrame::OpCodeContinuation;
301     WebSocketFrame f1(opcode, "", 0, WebSocketFrame::Compress);
302     WebSocketFrame f2(continuation, "\xf2\x48\xcd\xc9\xc9\x07\x00", 7, WebSocketFrame::Final);
303 
304     ASSERT_TRUE(c.inflate(f1));
305     EXPECT_EQ(0u, f1.payloadLength);
306     EXPECT_FALSE(f1.compress);
307     EXPECT_FALSE(f1.final);
308 
309     c.resetInflateBuffer();
310     ASSERT_TRUE(c.inflate(f2));
311     EXPECT_EQ(5u, f2.payloadLength);
312     EXPECT_EQ(std::string("Hello"), std::string(f2.payload, f2.payloadLength));
313     EXPECT_FALSE(f2.compress);
314     EXPECT_TRUE(f2.final);
315 }
316 
TEST(WebSocketPerMessageDeflateTest,TestInflateControlMessageBetweenTextFrames)317 TEST(WebSocketPerMessageDeflateTest, TestInflateControlMessageBetweenTextFrames)
318 {
319     WebSocketPerMessageDeflate c;
320     c.enable(8, WebSocketDeflater::TakeOverContext);
321     WebSocketFrame::OpCode close = WebSocketFrame::OpCodeClose;
322     WebSocketFrame::OpCode text = WebSocketFrame::OpCodeText;
323     WebSocketFrame f1(text, "\xf2\x48", 2, WebSocketFrame::Compress);
324     WebSocketFrame f2(close, "close", 5, WebSocketFrame::Final);
325     WebSocketFrame f3(text, "\xcd\xc9\xc9\x07\x00", 5, WebSocketFrame::Final);
326 
327     std::vector<char> decompressed;
328     ASSERT_TRUE(c.inflate(f1));
329     EXPECT_FALSE(f1.final);
330     EXPECT_FALSE(f1.compress);
331     std::copy(&f1.payload[0], &f1.payload[f1.payloadLength], std::inserter(decompressed, decompressed.end()));
332 
333     c.resetInflateBuffer();
334     ASSERT_TRUE(c.inflate(f2));
335     EXPECT_TRUE(f2.final);
336     EXPECT_FALSE(f2.compress);
337     EXPECT_EQ(std::string("close"), std::string(f2.payload, f2.payloadLength));
338 
339     c.resetInflateBuffer();
340     ASSERT_TRUE(c.inflate(f3));
341     std::copy(&f3.payload[0], &f3.payload[f3.payloadLength], std::inserter(decompressed, decompressed.end()));
342     EXPECT_TRUE(f3.final);
343     EXPECT_FALSE(f3.compress);
344 
345     EXPECT_EQ(std::string("Hello"), std::string(&decompressed[0], decompressed.size()));
346 }
347 
TEST(WebSocketPerMessageDeflateTest,TestNotEnabled)348 TEST(WebSocketPerMessageDeflateTest, TestNotEnabled)
349 {
350     WebSocketPerMessageDeflate c;
351     WebSocketFrame::OpCode opcode = WebSocketFrame::OpCodeClose;
352     WebSocketFrame f1(opcode, "Hello", 5, WebSocketFrame::Final | WebSocketFrame::Compress);
353     WebSocketFrame f2(opcode, "\xf2\x48\xcd\xc9\xc9\x07\x00", 7, WebSocketFrame::Final | WebSocketFrame::Compress);
354 
355     // deflate and inflate return true and do nothing if it is not enabled.
356     ASSERT_TRUE(c.deflate(f1));
357     ASSERT_TRUE(f1.compress);
358     ASSERT_TRUE(c.inflate(f2));
359     ASSERT_TRUE(f2.compress);
360 }
361 
processResponse(const HashMap<String,String> & serverParameters)362 bool processResponse(const HashMap<String, String>& serverParameters)
363 {
364     return WebSocketPerMessageDeflate().createExtensionProcessor()->processResponse(serverParameters);
365 }
366 
TEST(WebSocketPerMessageDeflateTest,TestValidNegotiationResponse)367 TEST(WebSocketPerMessageDeflateTest, TestValidNegotiationResponse)
368 {
369     {
370         HashMap<String, String> params;
371         EXPECT_TRUE(processResponse(params));
372     }
373     {
374         HashMap<String, String> params;
375         params.add("client_max_window_bits", "15");
376         EXPECT_TRUE(processResponse(params));
377     }
378     {
379         HashMap<String, String> params;
380         params.add("client_max_window_bits", "8");
381         EXPECT_TRUE(processResponse(params));
382     }
383     {
384         HashMap<String, String> params;
385         params.add("client_max_window_bits", "15");
386         params.add("client_no_context_takeover", String());
387         EXPECT_TRUE(processResponse(params));
388     }
389     {
390         // Unsolicited server_no_context_takeover should be ignored.
391         HashMap<String, String> params;
392         params.add("server_no_context_takeover", String());
393         EXPECT_TRUE(processResponse(params));
394     }
395     {
396         // Unsolicited server_max_window_bits should be ignored.
397         HashMap<String, String> params;
398         params.add("server_max_window_bits", "15");
399         EXPECT_TRUE(processResponse(params));
400     }
401 }
402 
TEST(WebSocketPerMessageDeflateTest,TestInvalidNegotiationResponse)403 TEST(WebSocketPerMessageDeflateTest, TestInvalidNegotiationResponse)
404 {
405     {
406         HashMap<String, String> params;
407         params.add("method", "deflate");
408         EXPECT_FALSE(processResponse(params));
409     }
410     {
411         HashMap<String, String> params;
412         params.add("foo", "");
413         EXPECT_FALSE(processResponse(params));
414     }
415     {
416         HashMap<String, String> params;
417         params.add("foo", "bar");
418         EXPECT_FALSE(processResponse(params));
419     }
420     {
421         HashMap<String, String> params;
422         params.add("client_max_window_bits", "");
423         EXPECT_FALSE(processResponse(params));
424     }
425     {
426         HashMap<String, String> params;
427         params.add("client_max_window_bits", "16");
428         EXPECT_FALSE(processResponse(params));
429     }
430     {
431         HashMap<String, String> params;
432         params.add("client_max_window_bits", "7");
433         EXPECT_FALSE(processResponse(params));
434     }
435     {
436         HashMap<String, String> params;
437         params.add("client_max_window_bits", "+15");
438         EXPECT_FALSE(processResponse(params));
439     }
440     {
441         HashMap<String, String> params;
442         params.add("client_max_window_bits", "0x9");
443         EXPECT_FALSE(processResponse(params));
444     }
445     {
446         HashMap<String, String> params;
447         params.add("client_max_window_bits", "08");
448         EXPECT_FALSE(processResponse(params));
449     }
450     {
451         // Unsolicited server_no_context_takeover should be verified though it is not used.
452         HashMap<String, String> params;
453         params.add("server_no_context_takeover", "foo");
454         EXPECT_FALSE(processResponse(params));
455     }
456     {
457         // Unsolicited server_max_window_bits should be verified though it is not used.
458         HashMap<String, String> params;
459         params.add("server_max_window_bits", "7");
460         EXPECT_FALSE(processResponse(params));
461     }
462     {
463         // Unsolicited server_max_window_bits should be verified though it is not used.
464         HashMap<String, String> params;
465         params.add("server_max_window_bits", "bar");
466         EXPECT_FALSE(processResponse(params));
467     }
468     {
469         // Unsolicited server_max_window_bits should be verified though it is not used.
470         HashMap<String, String> params;
471         params.add("server_max_window_bits", "16");
472         EXPECT_FALSE(processResponse(params));
473     }
474     {
475         // Unsolicited server_max_window_bits should be verified though it is not used.
476         HashMap<String, String> params;
477         params.add("server_max_window_bits", "08");
478         EXPECT_FALSE(processResponse(params));
479     }
480 }
481 
TEST(WebSocketPerMessageDeflateTest,TestNegotiationRequest)482 TEST(WebSocketPerMessageDeflateTest, TestNegotiationRequest)
483 {
484     String actual = WebSocketPerMessageDeflate().createExtensionProcessor()->handshakeString();
485     EXPECT_EQ(String("permessage-deflate; client_max_window_bits"), actual);
486 }
487 } // namespace
488