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 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 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 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 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 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 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(1u, f2.payloadLength); 192 EXPECT_EQ(0, memcmp("\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 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 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 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 295 TEST(WebSocketPerMessageDeflateTest, TestInflateMultipleBlocksOverMultipleFrames) 296 { 297 WebSocketPerMessageDeflate c; 298 c.enable(8, WebSocketDeflater::TakeOverContext); 299 WebSocketFrame::OpCode opcode = WebSocketFrame::OpCodeText; 300 WebSocketFrame::OpCode continuation = WebSocketFrame::OpCodeContinuation; 301 std::string expected = "HelloHello"; 302 std::string actual; 303 WebSocketFrame f1(opcode, "\xf2\x48\xcd\xc9\xc9\x07\x00\x00\x00\xff\xff", 11, WebSocketFrame::Compress); 304 WebSocketFrame f2(continuation, "\xf2\x00\x11\x00\x00", 5, WebSocketFrame::Final); 305 306 ASSERT_TRUE(c.inflate(f1)); 307 EXPECT_FALSE(f1.compress); 308 EXPECT_FALSE(f1.final); 309 actual += std::string(f1.payload, f1.payloadLength); 310 311 c.resetInflateBuffer(); 312 ASSERT_TRUE(c.inflate(f2)); 313 EXPECT_FALSE(f2.compress); 314 EXPECT_TRUE(f2.final); 315 actual += std::string(f2.payload, f2.payloadLength); 316 317 EXPECT_EQ(expected, actual); 318 } 319 320 TEST(WebSocketPerMessageDeflateTest, TestInflateEmptyFrame) 321 { 322 WebSocketPerMessageDeflate c; 323 c.enable(8, WebSocketDeflater::TakeOverContext); 324 WebSocketFrame::OpCode opcode = WebSocketFrame::OpCodeText; 325 WebSocketFrame::OpCode continuation = WebSocketFrame::OpCodeContinuation; 326 WebSocketFrame f1(opcode, "", 0, WebSocketFrame::Compress); 327 WebSocketFrame f2(continuation, "\xf2\x48\xcd\xc9\xc9\x07\x00", 7, WebSocketFrame::Final); 328 329 ASSERT_TRUE(c.inflate(f1)); 330 EXPECT_EQ(0u, f1.payloadLength); 331 EXPECT_FALSE(f1.compress); 332 EXPECT_FALSE(f1.final); 333 334 c.resetInflateBuffer(); 335 ASSERT_TRUE(c.inflate(f2)); 336 EXPECT_EQ(5u, f2.payloadLength); 337 EXPECT_EQ(std::string("Hello"), std::string(f2.payload, f2.payloadLength)); 338 EXPECT_FALSE(f2.compress); 339 EXPECT_TRUE(f2.final); 340 } 341 342 TEST(WebSocketPerMessageDeflateTest, TestInflateControlMessageBetweenTextFrames) 343 { 344 WebSocketPerMessageDeflate c; 345 c.enable(8, WebSocketDeflater::TakeOverContext); 346 WebSocketFrame::OpCode close = WebSocketFrame::OpCodeClose; 347 WebSocketFrame::OpCode text = WebSocketFrame::OpCodeText; 348 WebSocketFrame f1(text, "\xf2\x48", 2, WebSocketFrame::Compress); 349 WebSocketFrame f2(close, "close", 5, WebSocketFrame::Final); 350 WebSocketFrame f3(text, "\xcd\xc9\xc9\x07\x00", 5, WebSocketFrame::Final); 351 352 std::vector<char> decompressed; 353 ASSERT_TRUE(c.inflate(f1)); 354 EXPECT_FALSE(f1.final); 355 EXPECT_FALSE(f1.compress); 356 std::copy(&f1.payload[0], &f1.payload[f1.payloadLength], std::inserter(decompressed, decompressed.end())); 357 358 c.resetInflateBuffer(); 359 ASSERT_TRUE(c.inflate(f2)); 360 EXPECT_TRUE(f2.final); 361 EXPECT_FALSE(f2.compress); 362 EXPECT_EQ(std::string("close"), std::string(f2.payload, f2.payloadLength)); 363 364 c.resetInflateBuffer(); 365 ASSERT_TRUE(c.inflate(f3)); 366 std::copy(&f3.payload[0], &f3.payload[f3.payloadLength], std::inserter(decompressed, decompressed.end())); 367 EXPECT_TRUE(f3.final); 368 EXPECT_FALSE(f3.compress); 369 370 EXPECT_EQ(std::string("Hello"), std::string(&decompressed[0], decompressed.size())); 371 } 372 373 TEST(WebSocketPerMessageDeflateTest, TestNotEnabled) 374 { 375 WebSocketPerMessageDeflate c; 376 WebSocketFrame::OpCode opcode = WebSocketFrame::OpCodeClose; 377 WebSocketFrame f1(opcode, "Hello", 5, WebSocketFrame::Final | WebSocketFrame::Compress); 378 WebSocketFrame f2(opcode, "\xf2\x48\xcd\xc9\xc9\x07\x00", 7, WebSocketFrame::Final | WebSocketFrame::Compress); 379 380 // deflate and inflate return true and do nothing if it is not enabled. 381 ASSERT_TRUE(c.deflate(f1)); 382 ASSERT_TRUE(f1.compress); 383 ASSERT_TRUE(c.inflate(f2)); 384 ASSERT_TRUE(f2.compress); 385 } 386 387 bool processResponse(const HashMap<String, String>& serverParameters) 388 { 389 return WebSocketPerMessageDeflate().createExtensionProcessor()->processResponse(serverParameters); 390 } 391 392 TEST(WebSocketPerMessageDeflateTest, TestValidNegotiationResponse) 393 { 394 { 395 HashMap<String, String> params; 396 EXPECT_TRUE(processResponse(params)); 397 } 398 { 399 HashMap<String, String> params; 400 params.add("client_max_window_bits", "15"); 401 EXPECT_TRUE(processResponse(params)); 402 } 403 { 404 HashMap<String, String> params; 405 params.add("client_max_window_bits", "8"); 406 EXPECT_TRUE(processResponse(params)); 407 } 408 { 409 HashMap<String, String> params; 410 params.add("client_max_window_bits", "15"); 411 params.add("client_no_context_takeover", String()); 412 EXPECT_TRUE(processResponse(params)); 413 } 414 { 415 // Unsolicited server_no_context_takeover should be ignored. 416 HashMap<String, String> params; 417 params.add("server_no_context_takeover", String()); 418 EXPECT_TRUE(processResponse(params)); 419 } 420 { 421 // Unsolicited server_max_window_bits should be ignored. 422 HashMap<String, String> params; 423 params.add("server_max_window_bits", "15"); 424 EXPECT_TRUE(processResponse(params)); 425 } 426 } 427 428 TEST(WebSocketPerMessageDeflateTest, TestInvalidNegotiationResponse) 429 { 430 { 431 HashMap<String, String> params; 432 params.add("method", "deflate"); 433 EXPECT_FALSE(processResponse(params)); 434 } 435 { 436 HashMap<String, String> params; 437 params.add("foo", ""); 438 EXPECT_FALSE(processResponse(params)); 439 } 440 { 441 HashMap<String, String> params; 442 params.add("foo", "bar"); 443 EXPECT_FALSE(processResponse(params)); 444 } 445 { 446 HashMap<String, String> params; 447 params.add("client_max_window_bits", ""); 448 EXPECT_FALSE(processResponse(params)); 449 } 450 { 451 HashMap<String, String> params; 452 params.add("client_max_window_bits", "16"); 453 EXPECT_FALSE(processResponse(params)); 454 } 455 { 456 HashMap<String, String> params; 457 params.add("client_max_window_bits", "7"); 458 EXPECT_FALSE(processResponse(params)); 459 } 460 { 461 HashMap<String, String> params; 462 params.add("client_max_window_bits", "+15"); 463 EXPECT_FALSE(processResponse(params)); 464 } 465 { 466 HashMap<String, String> params; 467 params.add("client_max_window_bits", "0x9"); 468 EXPECT_FALSE(processResponse(params)); 469 } 470 { 471 HashMap<String, String> params; 472 params.add("client_max_window_bits", "08"); 473 EXPECT_FALSE(processResponse(params)); 474 } 475 { 476 // Unsolicited server_no_context_takeover should be verified though it is not used. 477 HashMap<String, String> params; 478 params.add("server_no_context_takeover", "foo"); 479 EXPECT_FALSE(processResponse(params)); 480 } 481 { 482 // Unsolicited server_max_window_bits should be verified though it is not used. 483 HashMap<String, String> params; 484 params.add("server_max_window_bits", "7"); 485 EXPECT_FALSE(processResponse(params)); 486 } 487 { 488 // Unsolicited server_max_window_bits should be verified though it is not used. 489 HashMap<String, String> params; 490 params.add("server_max_window_bits", "bar"); 491 EXPECT_FALSE(processResponse(params)); 492 } 493 { 494 // Unsolicited server_max_window_bits should be verified though it is not used. 495 HashMap<String, String> params; 496 params.add("server_max_window_bits", "16"); 497 EXPECT_FALSE(processResponse(params)); 498 } 499 { 500 // Unsolicited server_max_window_bits should be verified though it is not used. 501 HashMap<String, String> params; 502 params.add("server_max_window_bits", "08"); 503 EXPECT_FALSE(processResponse(params)); 504 } 505 } 506 507 TEST(WebSocketPerMessageDeflateTest, TestNegotiationRequest) 508 { 509 String actual = WebSocketPerMessageDeflate().createExtensionProcessor()->handshakeString(); 510 EXPECT_EQ(String("permessage-deflate; client_max_window_bits"), actual); 511 } 512 } // namespace 513