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/text/StringHash.h" 35 36#include <algorithm> 37#include <gtest/gtest.h> 38#include <iterator> 39 40namespace blink { 41namespace { 42 43TEST(WebSocketPerMessageDeflateTest, TestDeflateHelloTakeOver) 44{ 45 WebSocketPerMessageDeflate c; 46 c.enable(8, WebSocketDeflater::TakeOverContext); 47 WebSocketFrame::OpCode opcode = WebSocketFrame::OpCodeText; 48 WebSocketFrame f1(opcode, "Hello", 5, WebSocketFrame::Final); 49 WebSocketFrame f2(opcode, "Hello", 5, WebSocketFrame::Final); 50 51 ASSERT_TRUE(c.deflate(f1)); 52 EXPECT_EQ(7u, f1.payloadLength); 53 EXPECT_EQ(0, memcmp("\xf2\x48\xcd\xc9\xc9\x07\x00", f1.payload, f1.payloadLength)); 54 EXPECT_TRUE(f1.compress); 55 EXPECT_TRUE(f1.final); 56 57 c.resetDeflateBuffer(); 58 ASSERT_TRUE(c.deflate(f2)); 59 EXPECT_EQ(5u, f2.payloadLength); 60 EXPECT_EQ(0, memcmp("\xf2\x00\x11\x00\x00", f2.payload, f2.payloadLength)); 61 EXPECT_TRUE(f2.compress); 62 EXPECT_TRUE(f2.final); 63} 64 65TEST(WebSocketPerMessageTest, TestDeflateHelloNoTakeOver) 66{ 67 WebSocketPerMessageDeflate c; 68 c.enable(8, WebSocketDeflater::DoNotTakeOverContext); 69 WebSocketFrame::OpCode opcode = WebSocketFrame::OpCodeText; 70 WebSocketFrame f1(opcode, "Hello", 5, WebSocketFrame::Final); 71 WebSocketFrame f2(opcode, "Hello", 5, WebSocketFrame::Final); 72 73 ASSERT_TRUE(c.deflate(f1)); 74 EXPECT_EQ(7u, f1.payloadLength); 75 EXPECT_EQ(0, memcmp("\xf2\x48\xcd\xc9\xc9\x07\x00", f1.payload, f1.payloadLength)); 76 EXPECT_TRUE(f1.compress); 77 EXPECT_TRUE(f1.final); 78 79 c.resetDeflateBuffer(); 80 ASSERT_TRUE(c.deflate(f2)); 81 EXPECT_EQ(7u, f2.payloadLength); 82 EXPECT_EQ(0, memcmp("\xf2\x48\xcd\xc9\xc9\x07\x00", f2.payload, f2.payloadLength)); 83 EXPECT_TRUE(f2.compress); 84 EXPECT_TRUE(f2.final); 85} 86 87TEST(WebSocketPerMessageDeflateTest, TestDeflateInflateMultipleFrame) 88{ 89 WebSocketPerMessageDeflate c; 90 WebSocketFrame::OpCode text = WebSocketFrame::OpCodeText; 91 c.enable(8, WebSocketDeflater::DoNotTakeOverContext); 92 size_t length = 64 * 1024; 93 std::string payload; 94 std::string expected; 95 std::string actual; 96 std::string inflated; 97 // Generate string by a linear congruential generator. 98 uint64_t r = 0; 99 for (size_t i = 0; i < length; ++i) { 100 payload += 'a' + (r % 25); 101 r = (r * 12345 + 1103515245) % (static_cast<uint64_t>(1) << 31); 102 } 103 104 WebSocketFrame frame(text, &payload[0], payload.size(), WebSocketFrame::Final); 105 ASSERT_TRUE(c.deflate(frame)); 106 ASSERT_TRUE(frame.final); 107 ASSERT_TRUE(frame.compress); 108 expected = std::string(frame.payload, frame.payloadLength); 109 for (size_t i = 0; i < length; ++i) { 110 WebSocketFrame::OpCode opcode = !i ? text : WebSocketFrame::OpCodeContinuation; 111 c.resetDeflateBuffer(); 112 WebSocketFrame frame(opcode, &payload[i], 1); 113 frame.final = (i == length - 1); 114 115 ASSERT_TRUE(c.deflate(frame)); 116 ASSERT_EQ(i == length - 1, frame.final); 117 ASSERT_EQ(!i, frame.compress); 118 actual += std::string(frame.payload, frame.payloadLength); 119 } 120 EXPECT_EQ(expected, actual); 121 122 for (size_t i = 0; i < actual.size(); ++i) { 123 WebSocketFrame::OpCode opcode = !i ? text : WebSocketFrame::OpCodeContinuation; 124 c.resetInflateBuffer(); 125 WebSocketFrame frame(opcode, &actual[i], 1); 126 frame.final = (i == actual.size() - 1); 127 frame.compress = !i; 128 129 ASSERT_TRUE(c.inflate(frame)); 130 ASSERT_EQ(i == actual.size() - 1, frame.final); 131 ASSERT_FALSE(frame.compress); 132 inflated += std::string(frame.payload, frame.payloadLength); 133 } 134 EXPECT_EQ(payload, inflated); 135} 136 137TEST(WebSocketPerMessageDeflateTest, TestDeflateBinary) 138{ 139 WebSocketPerMessageDeflate c; 140 c.enable(8, WebSocketDeflater::TakeOverContext); 141 WebSocketFrame::OpCode opcode = WebSocketFrame::OpCodeBinary; 142 WebSocketFrame f1(opcode, "Hello", 5, WebSocketFrame::Final); 143 144 ASSERT_TRUE(c.deflate(f1)); 145 EXPECT_EQ(7u, f1.payloadLength); 146 EXPECT_EQ(0, memcmp("\xf2\x48\xcd\xc9\xc9\x07\x00", f1.payload, f1.payloadLength)); 147 EXPECT_EQ(opcode, f1.opCode); 148 EXPECT_TRUE(f1.compress); 149 EXPECT_TRUE(f1.final); 150} 151 152TEST(WebSocketPerMessageDeflateTest, TestDeflateEmptyFrame) 153{ 154 WebSocketPerMessageDeflate c; 155 c.enable(8, WebSocketDeflater::TakeOverContext); 156 WebSocketFrame f1(WebSocketFrame::OpCodeText, "Hello", 5); 157 WebSocketFrame f2(WebSocketFrame::OpCodeContinuation, "", 0, WebSocketFrame::Final); 158 159 ASSERT_TRUE(c.deflate(f1)); 160 EXPECT_EQ(0u, f1.payloadLength); 161 EXPECT_FALSE(f1.final); 162 EXPECT_TRUE(f1.compress); 163 164 c.resetDeflateBuffer(); 165 ASSERT_TRUE(c.deflate(f2)); 166 EXPECT_EQ(7u, f2.payloadLength); 167 EXPECT_EQ(0, memcmp("\xf2\x48\xcd\xc9\xc9\x07\x00", f2.payload, f2.payloadLength)); 168 EXPECT_TRUE(f2.final); 169 EXPECT_FALSE(f2.compress); 170} 171 172TEST(WebSocketPerMessageDeflateTest, TestDeflateEmptyMessages) 173{ 174 WebSocketPerMessageDeflate c; 175 c.enable(8, WebSocketDeflater::TakeOverContext); 176 WebSocketFrame f1(WebSocketFrame::OpCodeText, "", 0); 177 WebSocketFrame f2(WebSocketFrame::OpCodeContinuation, "", 0, WebSocketFrame::Final); 178 WebSocketFrame f3(WebSocketFrame::OpCodeText, "", 0, WebSocketFrame::Final); 179 WebSocketFrame f4(WebSocketFrame::OpCodeText, "", 0, WebSocketFrame::Final); 180 WebSocketFrame f5(WebSocketFrame::OpCodeText, "Hello", 5, WebSocketFrame::Final); 181 182 ASSERT_TRUE(c.deflate(f1)); 183 EXPECT_EQ(0u, f1.payloadLength); 184 EXPECT_FALSE(f1.final); 185 EXPECT_TRUE(f1.compress); 186 187 c.resetDeflateBuffer(); 188 ASSERT_TRUE(c.deflate(f2)); 189 EXPECT_EQ(1u, f2.payloadLength); 190 EXPECT_EQ(0, memcmp("\x00", f2.payload, f2.payloadLength)); 191 EXPECT_TRUE(f2.final); 192 EXPECT_FALSE(f2.compress); 193 194 c.resetDeflateBuffer(); 195 ASSERT_TRUE(c.deflate(f3)); 196 EXPECT_EQ(0u, f3.payloadLength); 197 EXPECT_TRUE(f3.final); 198 EXPECT_FALSE(f3.compress); 199 200 c.resetDeflateBuffer(); 201 ASSERT_TRUE(c.deflate(f4)); 202 EXPECT_EQ(0u, f4.payloadLength); 203 EXPECT_TRUE(f4.final); 204 EXPECT_FALSE(f4.compress); 205 206 c.resetDeflateBuffer(); 207 ASSERT_TRUE(c.deflate(f5)); 208 EXPECT_EQ(7u, f5.payloadLength); 209 EXPECT_EQ(0, memcmp("\xf2\x48\xcd\xc9\xc9\x07\x00", f5.payload, f5.payloadLength)); 210 EXPECT_TRUE(f5.final); 211 EXPECT_TRUE(f5.compress); 212} 213 214TEST(WebSocketPerMessageDeflateTest, TestControlMessage) 215{ 216 WebSocketPerMessageDeflate c; 217 c.enable(8, WebSocketDeflater::TakeOverContext); 218 WebSocketFrame::OpCode opcode = WebSocketFrame::OpCodeClose; 219 WebSocketFrame f1(opcode, "Hello", 5, WebSocketFrame::Final); 220 221 ASSERT_TRUE(c.deflate(f1)); 222 EXPECT_TRUE(f1.final); 223 EXPECT_FALSE(f1.compress); 224 EXPECT_EQ(std::string("Hello"), std::string(f1.payload, f1.payloadLength)); 225} 226 227TEST(WebSocketPerMessageDeflateTest, TestDeflateControlMessageBetweenTextFrames) 228{ 229 WebSocketPerMessageDeflate c; 230 c.enable(8, WebSocketDeflater::TakeOverContext); 231 WebSocketFrame::OpCode close = WebSocketFrame::OpCodeClose; 232 WebSocketFrame::OpCode text = WebSocketFrame::OpCodeText; 233 WebSocketFrame::OpCode continuation = WebSocketFrame::OpCodeContinuation; 234 WebSocketFrame f1(text, "Hello", 5); 235 WebSocketFrame f2(close, "close", 5, WebSocketFrame::Final); 236 WebSocketFrame f3(continuation, "", 0, WebSocketFrame::Final); 237 238 std::vector<char> compressed; 239 ASSERT_TRUE(c.deflate(f1)); 240 EXPECT_FALSE(f1.final); 241 EXPECT_TRUE(f1.compress); 242 std::copy(&f1.payload[0], &f1.payload[f1.payloadLength], std::inserter(compressed, compressed.end())); 243 244 c.resetDeflateBuffer(); 245 ASSERT_TRUE(c.deflate(f2)); 246 EXPECT_TRUE(f2.final); 247 EXPECT_FALSE(f2.compress); 248 EXPECT_EQ(std::string("close"), std::string(f2.payload, f2.payloadLength)); 249 250 c.resetDeflateBuffer(); 251 ASSERT_TRUE(c.deflate(f3)); 252 EXPECT_TRUE(f3.final); 253 EXPECT_FALSE(f3.compress); 254 std::copy(&f3.payload[0], &f3.payload[f3.payloadLength], std::inserter(compressed, compressed.end())); 255 256 EXPECT_EQ(7u, compressed.size()); 257 EXPECT_EQ(0, memcmp("\xf2\x48\xcd\xc9\xc9\x07\x00", &compressed[0], compressed.size())); 258} 259 260TEST(WebSocketPerMessageDeflateTest, TestInflate) 261{ 262 WebSocketPerMessageDeflate c; 263 c.enable(8, WebSocketDeflater::TakeOverContext); 264 WebSocketFrame::OpCode opcode = WebSocketFrame::OpCodeText; 265 WebSocketFrame::OpCode continuation = WebSocketFrame::OpCodeContinuation; 266 std::string expected = "HelloHi!Hello"; 267 std::string actual; 268 WebSocketFrame f1(opcode, "\xf2\x48\xcd\xc9\xc9\x07\x00", 7, WebSocketFrame::Final | WebSocketFrame::Compress); 269 WebSocketFrame f2(continuation, "Hi!", 3, WebSocketFrame::Final); 270 WebSocketFrame f3(opcode, "\xf2\x00\x11\x00\x00", 5, WebSocketFrame::Final | WebSocketFrame::Compress); 271 272 ASSERT_TRUE(c.inflate(f1)); 273 EXPECT_EQ(5u, f1.payloadLength); 274 EXPECT_EQ(std::string("Hello"), std::string(f1.payload, f1.payloadLength)); 275 EXPECT_FALSE(f1.compress); 276 EXPECT_TRUE(f1.final); 277 278 c.resetInflateBuffer(); 279 ASSERT_TRUE(c.inflate(f2)); 280 EXPECT_EQ(3u, f2.payloadLength); 281 EXPECT_EQ(std::string("Hi!"), std::string(f2.payload, f2.payloadLength)); 282 EXPECT_FALSE(f2.compress); 283 EXPECT_TRUE(f2.final); 284 285 c.resetInflateBuffer(); 286 ASSERT_TRUE(c.inflate(f3)); 287 EXPECT_EQ(5u, f3.payloadLength); 288 EXPECT_EQ(std::string("Hello"), std::string(f3.payload, f3.payloadLength)); 289 EXPECT_FALSE(f3.compress); 290 EXPECT_TRUE(f3.final); 291} 292 293TEST(WebSocketPerMessageDeflateTest, TestInflateMultipleBlocksOverMultipleFrames) 294{ 295 WebSocketPerMessageDeflate c; 296 c.enable(8, WebSocketDeflater::TakeOverContext); 297 WebSocketFrame::OpCode opcode = WebSocketFrame::OpCodeText; 298 WebSocketFrame::OpCode continuation = WebSocketFrame::OpCodeContinuation; 299 std::string expected = "HelloHello"; 300 std::string actual; 301 WebSocketFrame f1(opcode, "\xf2\x48\xcd\xc9\xc9\x07\x00\x00\x00\xff\xff", 11, WebSocketFrame::Compress); 302 WebSocketFrame f2(continuation, "\xf2\x00\x11\x00\x00", 5, WebSocketFrame::Final); 303 304 ASSERT_TRUE(c.inflate(f1)); 305 EXPECT_FALSE(f1.compress); 306 EXPECT_FALSE(f1.final); 307 actual += std::string(f1.payload, f1.payloadLength); 308 309 c.resetInflateBuffer(); 310 ASSERT_TRUE(c.inflate(f2)); 311 EXPECT_FALSE(f2.compress); 312 EXPECT_TRUE(f2.final); 313 actual += std::string(f2.payload, f2.payloadLength); 314 315 EXPECT_EQ(expected, actual); 316} 317 318TEST(WebSocketPerMessageDeflateTest, TestInflateEmptyFrame) 319{ 320 WebSocketPerMessageDeflate c; 321 c.enable(8, WebSocketDeflater::TakeOverContext); 322 WebSocketFrame::OpCode opcode = WebSocketFrame::OpCodeText; 323 WebSocketFrame::OpCode continuation = WebSocketFrame::OpCodeContinuation; 324 WebSocketFrame f1(opcode, "", 0, WebSocketFrame::Compress); 325 WebSocketFrame f2(continuation, "\xf2\x48\xcd\xc9\xc9\x07\x00", 7, WebSocketFrame::Final); 326 327 ASSERT_TRUE(c.inflate(f1)); 328 EXPECT_EQ(0u, f1.payloadLength); 329 EXPECT_FALSE(f1.compress); 330 EXPECT_FALSE(f1.final); 331 332 c.resetInflateBuffer(); 333 ASSERT_TRUE(c.inflate(f2)); 334 EXPECT_EQ(5u, f2.payloadLength); 335 EXPECT_EQ(std::string("Hello"), std::string(f2.payload, f2.payloadLength)); 336 EXPECT_FALSE(f2.compress); 337 EXPECT_TRUE(f2.final); 338} 339 340TEST(WebSocketPerMessageDeflateTest, TestInflateControlMessageBetweenTextFrames) 341{ 342 WebSocketPerMessageDeflate c; 343 c.enable(8, WebSocketDeflater::TakeOverContext); 344 WebSocketFrame::OpCode close = WebSocketFrame::OpCodeClose; 345 WebSocketFrame::OpCode text = WebSocketFrame::OpCodeText; 346 WebSocketFrame f1(text, "\xf2\x48", 2, WebSocketFrame::Compress); 347 WebSocketFrame f2(close, "close", 5, WebSocketFrame::Final); 348 WebSocketFrame f3(text, "\xcd\xc9\xc9\x07\x00", 5, WebSocketFrame::Final); 349 350 std::vector<char> decompressed; 351 ASSERT_TRUE(c.inflate(f1)); 352 EXPECT_FALSE(f1.final); 353 EXPECT_FALSE(f1.compress); 354 std::copy(&f1.payload[0], &f1.payload[f1.payloadLength], std::inserter(decompressed, decompressed.end())); 355 356 c.resetInflateBuffer(); 357 ASSERT_TRUE(c.inflate(f2)); 358 EXPECT_TRUE(f2.final); 359 EXPECT_FALSE(f2.compress); 360 EXPECT_EQ(std::string("close"), std::string(f2.payload, f2.payloadLength)); 361 362 c.resetInflateBuffer(); 363 ASSERT_TRUE(c.inflate(f3)); 364 std::copy(&f3.payload[0], &f3.payload[f3.payloadLength], std::inserter(decompressed, decompressed.end())); 365 EXPECT_TRUE(f3.final); 366 EXPECT_FALSE(f3.compress); 367 368 EXPECT_EQ(std::string("Hello"), std::string(&decompressed[0], decompressed.size())); 369} 370 371TEST(WebSocketPerMessageDeflateTest, TestNotEnabled) 372{ 373 WebSocketPerMessageDeflate c; 374 WebSocketFrame::OpCode opcode = WebSocketFrame::OpCodeClose; 375 WebSocketFrame f1(opcode, "Hello", 5, WebSocketFrame::Final | WebSocketFrame::Compress); 376 WebSocketFrame f2(opcode, "\xf2\x48\xcd\xc9\xc9\x07\x00", 7, WebSocketFrame::Final | WebSocketFrame::Compress); 377 378 // deflate and inflate return true and do nothing if it is not enabled. 379 ASSERT_TRUE(c.deflate(f1)); 380 ASSERT_TRUE(f1.compress); 381 ASSERT_TRUE(c.inflate(f2)); 382 ASSERT_TRUE(f2.compress); 383} 384 385bool processResponse(const HashMap<String, String>& serverParameters) 386{ 387 return WebSocketPerMessageDeflate().createExtensionProcessor()->processResponse(serverParameters); 388} 389 390TEST(WebSocketPerMessageDeflateTest, TestValidNegotiationResponse) 391{ 392 { 393 HashMap<String, String> params; 394 EXPECT_TRUE(processResponse(params)); 395 } 396 { 397 HashMap<String, String> params; 398 params.add("client_max_window_bits", "15"); 399 EXPECT_TRUE(processResponse(params)); 400 } 401 { 402 HashMap<String, String> params; 403 params.add("client_max_window_bits", "8"); 404 EXPECT_TRUE(processResponse(params)); 405 } 406 { 407 HashMap<String, String> params; 408 params.add("client_max_window_bits", "15"); 409 params.add("client_no_context_takeover", String()); 410 EXPECT_TRUE(processResponse(params)); 411 } 412 { 413 // Unsolicited server_no_context_takeover should be ignored. 414 HashMap<String, String> params; 415 params.add("server_no_context_takeover", String()); 416 EXPECT_TRUE(processResponse(params)); 417 } 418 { 419 // Unsolicited server_max_window_bits should be ignored. 420 HashMap<String, String> params; 421 params.add("server_max_window_bits", "15"); 422 EXPECT_TRUE(processResponse(params)); 423 } 424} 425 426TEST(WebSocketPerMessageDeflateTest, TestInvalidNegotiationResponse) 427{ 428 { 429 HashMap<String, String> params; 430 params.add("method", "deflate"); 431 EXPECT_FALSE(processResponse(params)); 432 } 433 { 434 HashMap<String, String> params; 435 params.add("foo", ""); 436 EXPECT_FALSE(processResponse(params)); 437 } 438 { 439 HashMap<String, String> params; 440 params.add("foo", "bar"); 441 EXPECT_FALSE(processResponse(params)); 442 } 443 { 444 HashMap<String, String> params; 445 params.add("client_max_window_bits", ""); 446 EXPECT_FALSE(processResponse(params)); 447 } 448 { 449 HashMap<String, String> params; 450 params.add("client_max_window_bits", "16"); 451 EXPECT_FALSE(processResponse(params)); 452 } 453 { 454 HashMap<String, String> params; 455 params.add("client_max_window_bits", "7"); 456 EXPECT_FALSE(processResponse(params)); 457 } 458 { 459 HashMap<String, String> params; 460 params.add("client_max_window_bits", "+15"); 461 EXPECT_FALSE(processResponse(params)); 462 } 463 { 464 HashMap<String, String> params; 465 params.add("client_max_window_bits", "0x9"); 466 EXPECT_FALSE(processResponse(params)); 467 } 468 { 469 HashMap<String, String> params; 470 params.add("client_max_window_bits", "08"); 471 EXPECT_FALSE(processResponse(params)); 472 } 473 { 474 // Unsolicited server_no_context_takeover should be verified though it is not used. 475 HashMap<String, String> params; 476 params.add("server_no_context_takeover", "foo"); 477 EXPECT_FALSE(processResponse(params)); 478 } 479 { 480 // Unsolicited server_max_window_bits should be verified though it is not used. 481 HashMap<String, String> params; 482 params.add("server_max_window_bits", "7"); 483 EXPECT_FALSE(processResponse(params)); 484 } 485 { 486 // Unsolicited server_max_window_bits should be verified though it is not used. 487 HashMap<String, String> params; 488 params.add("server_max_window_bits", "bar"); 489 EXPECT_FALSE(processResponse(params)); 490 } 491 { 492 // Unsolicited server_max_window_bits should be verified though it is not used. 493 HashMap<String, String> params; 494 params.add("server_max_window_bits", "16"); 495 EXPECT_FALSE(processResponse(params)); 496 } 497 { 498 // Unsolicited server_max_window_bits should be verified though it is not used. 499 HashMap<String, String> params; 500 params.add("server_max_window_bits", "08"); 501 EXPECT_FALSE(processResponse(params)); 502 } 503} 504 505TEST(WebSocketPerMessageDeflateTest, TestNegotiationRequest) 506{ 507 String actual = WebSocketPerMessageDeflate().createExtensionProcessor()->handshakeString(); 508 EXPECT_EQ(String("permessage-deflate; client_max_window_bits"), actual); 509} 510 511} // namespace 512} // namespace blink 513