• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifdef UNSAFE_BUFFERS_BUILD
6 // TODO(crbug.com/40284755): Remove this and spanify to fix the errors.
7 #pragma allow_unsafe_buffers
8 #endif
9 
10 #include "net/websockets/websocket_deflate_parameters.h"
11 
12 #include <iterator>
13 #include <ostream>
14 #include <string>
15 #include <vector>
16 
17 #include "net/websockets/websocket_extension_parser.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19 
20 namespace net {
21 
22 namespace {
23 
CheckExtension(const WebSocketDeflateParameters & params,const std::string & name,const std::string & value)24 void CheckExtension(const WebSocketDeflateParameters& params,
25                     const std::string& name,
26                     const std::string& value) {
27   WebSocketExtension e = params.AsExtension();
28   EXPECT_EQ("permessage-deflate", e.name());
29   if (e.parameters().size() != 1)
30     FAIL() << "parameters must have one element.";
31   EXPECT_EQ(name, e.parameters()[0].name());
32   EXPECT_EQ(value, e.parameters()[0].value());
33 }
34 
TEST(WebSocketDeflateParametersTest,Empty)35 TEST(WebSocketDeflateParametersTest, Empty) {
36   WebSocketDeflateParameters r;
37 
38   EXPECT_EQ(WebSocketDeflater::TAKE_OVER_CONTEXT,
39             r.server_context_take_over_mode());
40   EXPECT_EQ(WebSocketDeflater::TAKE_OVER_CONTEXT,
41             r.client_context_take_over_mode());
42   EXPECT_FALSE(r.is_server_max_window_bits_specified());
43   EXPECT_FALSE(r.is_client_max_window_bits_specified());
44   EXPECT_TRUE(r.IsValidAsRequest());
45   EXPECT_TRUE(r.IsValidAsResponse());
46   WebSocketExtension e = r.AsExtension();
47   EXPECT_EQ("permessage-deflate", e.name());
48   EXPECT_TRUE(e.parameters().empty());
49 }
50 
TEST(WebSocketDeflateParametersTest,ServerContextTakeover)51 TEST(WebSocketDeflateParametersTest, ServerContextTakeover) {
52   WebSocketDeflateParameters r;
53 
54   r.SetServerNoContextTakeOver();
55   CheckExtension(r, "server_no_context_takeover", "");
56   EXPECT_TRUE(r.IsValidAsRequest());
57   EXPECT_TRUE(r.IsValidAsResponse());
58 }
59 
TEST(WebSocketDeflateParametersTest,ClientContextTakeover)60 TEST(WebSocketDeflateParametersTest, ClientContextTakeover) {
61   WebSocketDeflateParameters r;
62 
63   r.SetClientNoContextTakeOver();
64   CheckExtension(r, "client_no_context_takeover", "");
65   EXPECT_TRUE(r.IsValidAsRequest());
66   EXPECT_TRUE(r.IsValidAsResponse());
67 }
68 
TEST(WebSocketDeflateParametersTest,ServerMaxWindowBits)69 TEST(WebSocketDeflateParametersTest, ServerMaxWindowBits) {
70   WebSocketDeflateParameters r;
71 
72   r.SetServerMaxWindowBits(13);
73   CheckExtension(r, "server_max_window_bits", "13");
74   EXPECT_TRUE(r.IsValidAsRequest());
75   EXPECT_TRUE(r.IsValidAsResponse());
76 }
77 
TEST(WebSocketDeflateParametersTest,ClientMaxWindowBitsWithoutValue)78 TEST(WebSocketDeflateParametersTest, ClientMaxWindowBitsWithoutValue) {
79   WebSocketDeflateParameters r;
80   std::string failure_message;
81 
82   r.SetClientMaxWindowBits();
83   CheckExtension(r, "client_max_window_bits", "");
84   EXPECT_TRUE(r.IsValidAsRequest());
85   EXPECT_FALSE(r.IsValidAsResponse(&failure_message));
86   EXPECT_EQ("client_max_window_bits must have value", failure_message);
87 }
88 
TEST(WebSocketDeflateParametersTest,ClientMaxWindowBitsWithValue)89 TEST(WebSocketDeflateParametersTest, ClientMaxWindowBitsWithValue) {
90   WebSocketDeflateParameters r;
91 
92   r.SetClientMaxWindowBits(12);
93   CheckExtension(r, "client_max_window_bits", "12");
94   EXPECT_TRUE(r.IsValidAsRequest());
95   EXPECT_TRUE(r.IsValidAsResponse());
96 }
97 
98 struct InitializeTestParameter {
99   const std::string query;
100   struct Expectation {
101     bool result;
102     std::string failure_message;
103   } const expected;
104 };
105 
PrintTo(const InitializeTestParameter & p,std::ostream * o)106 void PrintTo(const InitializeTestParameter& p, std::ostream* o) {
107   *o << p.query;
108 }
109 
110 class WebSocketDeflateParametersInitializeTest
111     : public ::testing::TestWithParam<InitializeTestParameter> {};
112 
TEST_P(WebSocketDeflateParametersInitializeTest,Initialize)113 TEST_P(WebSocketDeflateParametersInitializeTest, Initialize) {
114   const std::string query = GetParam().query;
115   const bool expected = GetParam().expected.result;
116   const std::string expected_failure_message =
117       GetParam().expected.failure_message;
118 
119   WebSocketExtensionParser parser;
120   ASSERT_TRUE(parser.Parse("permessage-deflate" + query));
121   ASSERT_EQ(1u, parser.extensions().size());
122   WebSocketExtension extension = parser.extensions()[0];
123 
124   WebSocketDeflateParameters parameters;
125   std::string failure_message;
126   bool actual = parameters.Initialize(extension, &failure_message);
127 
128   if (expected) {
129     EXPECT_TRUE(actual);
130     EXPECT_TRUE(extension.Equivalent(parameters.AsExtension()));
131   } else {
132     EXPECT_FALSE(actual);
133   }
134   EXPECT_EQ(expected_failure_message, failure_message);
135 }
136 
137 struct CompatibilityTestParameter {
138   const char* request_query;
139   const char* response_query;
140   const bool expected;
141 };
142 
PrintTo(const CompatibilityTestParameter & p,std::ostream * o)143 void PrintTo(const CompatibilityTestParameter& p, std::ostream* o) {
144   *o << "req = \"" << p.request_query << "\", res = \"" << p.response_query
145      << "\"";
146 }
147 
148 class WebSocketDeflateParametersCompatibilityTest
149     : public ::testing::TestWithParam<CompatibilityTestParameter> {};
150 
TEST_P(WebSocketDeflateParametersCompatibilityTest,CheckCompatiblity)151 TEST_P(WebSocketDeflateParametersCompatibilityTest, CheckCompatiblity) {
152   const std::string request_query = GetParam().request_query;
153   const std::string response_query = GetParam().response_query;
154   const bool expected = GetParam().expected;
155 
156   std::string message;
157   WebSocketDeflateParameters request, response;
158 
159   WebSocketExtensionParser request_parser;
160   ASSERT_TRUE(request_parser.Parse("permessage-deflate" + request_query));
161   ASSERT_EQ(1u, request_parser.extensions().size());
162   ASSERT_TRUE(request.Initialize(request_parser.extensions()[0], &message));
163   ASSERT_TRUE(request.IsValidAsRequest(&message));
164 
165   WebSocketExtensionParser response_parser;
166   ASSERT_TRUE(response_parser.Parse("permessage-deflate" + response_query));
167   ASSERT_EQ(1u, response_parser.extensions().size());
168   ASSERT_TRUE(response.Initialize(response_parser.extensions()[0], &message));
169   ASSERT_TRUE(response.IsValidAsResponse(&message));
170 
171   EXPECT_EQ(expected, request.IsCompatibleWith(response));
172 }
173 
Duplicate(const std::string & name)174 InitializeTestParameter::Expectation Duplicate(const std::string& name) {
175   return {false,
176           "Received duplicate permessage-deflate extension parameter " + name};
177 }
178 
Invalid(const std::string & name)179 InitializeTestParameter::Expectation Invalid(const std::string& name) {
180   return {false, "Received invalid " + name + " parameter"};
181 }
182 
183 // We need this function in order to avoid global non-pod variables.
InitializeTestParameters()184 std::vector<InitializeTestParameter> InitializeTestParameters() {
185   const InitializeTestParameter::Expectation kInitialized = {true, ""};
186   const InitializeTestParameter::Expectation kUnknownParameter = {
187       false, "Received an unexpected permessage-deflate extension parameter"};
188 
189   const InitializeTestParameter parameters[] = {
190       {"", kInitialized},
191       {"; server_no_context_takeover", kInitialized},
192       {"; server_no_context_takeover=0", Invalid("server_no_context_takeover")},
193       {"; server_no_context_takeover; server_no_context_takeover",
194        Duplicate("server_no_context_takeover")},
195       {"; client_no_context_takeover", kInitialized},
196       {"; client_no_context_takeover=0", Invalid("client_no_context_takeover")},
197       {"; client_no_context_takeover; client_no_context_takeover",
198        Duplicate("client_no_context_takeover")},
199       {"; server_max_window_bits=8", kInitialized},
200       {"; server_max_window_bits=15", kInitialized},
201       {"; server_max_window_bits=15; server_max_window_bits=15",
202        Duplicate("server_max_window_bits")},
203       {"; server_max_window_bits=a", Invalid("server_max_window_bits")},
204       {"; server_max_window_bits=09", Invalid("server_max_window_bits")},
205       {"; server_max_window_bits=+9", Invalid("server_max_window_bits")},
206       {"; server_max_window_bits=9a", Invalid("server_max_window_bits")},
207       {"; server_max_window_bits", Invalid("server_max_window_bits")},
208       {"; server_max_window_bits=7", Invalid("server_max_window_bits")},
209       {"; server_max_window_bits=16", Invalid("server_max_window_bits")},
210       {"; client_max_window_bits=8", kInitialized},
211       {"; client_max_window_bits=15", kInitialized},
212       {"; client_max_window_bits=15; client_max_window_bits=15",
213        Duplicate("client_max_window_bits")},
214       {"; client_max_window_bits=a", Invalid("client_max_window_bits")},
215       {"; client_max_window_bits=09", Invalid("client_max_window_bits")},
216       {"; client_max_window_bits=+9", Invalid("client_max_window_bits")},
217       {"; client_max_window_bits=9a", Invalid("client_max_window_bits")},
218       {"; client_max_window_bits", kInitialized},
219       {"; client_max_window_bits=7", Invalid("client_max_window_bits")},
220       {"; client_max_window_bits=16", Invalid("client_max_window_bits")},
221       {"; server_no_context_takeover; client_no_context_takeover"
222        "; server_max_window_bits=12; client_max_window_bits=13",
223        kInitialized},
224       {"; hogefuga", kUnknownParameter},
225   };
226   return std::vector<InitializeTestParameter>(
227       parameters, parameters + std::size(parameters));
228 }
229 
230 constexpr CompatibilityTestParameter kCompatibilityTestParameters[] = {
231     {"", "", true},
232     // server_no_context_takeover
233     {"", "; server_no_context_takeover", true},
234     {"; server_no_context_takeover", "", false},
235     {"; server_no_context_takeover", "; server_no_context_takeover", true},
236     // client_no_context_takeover
237     {"", "; client_no_context_takeover", true},
238     {"; client_no_context_takeover", "", true},
239     {"; client_no_context_takeover", "; client_no_context_takeover", true},
240     // server_max_window_bits
241     {"", "; server_max_window_bits=14", true},
242     {"; server_max_window_bits=12", "", false},
243     {"; server_max_window_bits=12", "; server_max_window_bits=12", true},
244     {"; server_max_window_bits=12", "; server_max_window_bits=11", true},
245     {"; server_max_window_bits=12", "; server_max_window_bits=13", false},
246     // client_max_window_bits
247     {"", "; client_max_window_bits=14", false},
248     {"; client_max_window_bits", "", true},
249     {"; client_max_window_bits", "; client_max_window_bits=15", true},
250     {"; client_max_window_bits=12", "", true},
251     {"; client_max_window_bits=12", "; client_max_window_bits=12", true},
252     {"; client_max_window_bits=12", "; client_max_window_bits=11", true},
253     {"; client_max_window_bits=12", "; client_max_window_bits=13", true},
254 };
255 
256 INSTANTIATE_TEST_SUITE_P(WebSocketDeflateParametersInitializeTest,
257                          WebSocketDeflateParametersInitializeTest,
258                          ::testing::ValuesIn(InitializeTestParameters()));
259 
260 INSTANTIATE_TEST_SUITE_P(WebSocketDeflateParametersCompatibilityTest,
261                          WebSocketDeflateParametersCompatibilityTest,
262                          ::testing::ValuesIn(kCompatibilityTestParameters));
263 
264 }  // namespace
265 
266 }  // namespace net
267