1 // Copyright 2023 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 "quiche/web_transport/web_transport_headers.h"
6
7 #include "absl/status/status.h"
8 #include "quiche/common/platform/api/quiche_test.h"
9 #include "quiche/common/test_tools/quiche_test_utils.h"
10
11 namespace webtransport {
12 namespace {
13
14 using ::quiche::test::IsOkAndHolds;
15 using ::quiche::test::StatusIs;
16 using ::testing::ElementsAre;
17 using ::testing::HasSubstr;
18
TEST(WebTransportHeaders,ParseSubprotocolRequestHeader)19 TEST(WebTransportHeaders, ParseSubprotocolRequestHeader) {
20 EXPECT_THAT(ParseSubprotocolRequestHeader("test"),
21 IsOkAndHolds(ElementsAre("test")));
22 EXPECT_THAT(ParseSubprotocolRequestHeader("moqt-draft01, moqt-draft02"),
23 IsOkAndHolds(ElementsAre("moqt-draft01", "moqt-draft02")));
24 EXPECT_THAT(ParseSubprotocolRequestHeader("moqt-draft01; a=b, moqt-draft02"),
25 IsOkAndHolds(ElementsAre("moqt-draft01", "moqt-draft02")));
26 EXPECT_THAT(ParseSubprotocolRequestHeader("moqt-draft01, moqt-draft02; a=b"),
27 IsOkAndHolds(ElementsAre("moqt-draft01", "moqt-draft02")));
28 EXPECT_THAT(ParseSubprotocolRequestHeader("\"test\""),
29 StatusIs(absl::StatusCode::kInvalidArgument,
30 HasSubstr("found string instead")));
31 EXPECT_THAT(ParseSubprotocolRequestHeader("42"),
32 StatusIs(absl::StatusCode::kInvalidArgument,
33 HasSubstr("found integer instead")));
34 EXPECT_THAT(ParseSubprotocolRequestHeader("a, (b)"),
35 StatusIs(absl::StatusCode::kInvalidArgument,
36 HasSubstr("found a nested list instead")));
37 EXPECT_THAT(ParseSubprotocolRequestHeader("a, (b c)"),
38 StatusIs(absl::StatusCode::kInvalidArgument,
39 HasSubstr("found a nested list instead")));
40 EXPECT_THAT(ParseSubprotocolRequestHeader("foo, ?1, bar"),
41 StatusIs(absl::StatusCode::kInvalidArgument,
42 HasSubstr("found boolean instead")));
43 EXPECT_THAT(ParseSubprotocolRequestHeader("(a"),
44 StatusIs(absl::StatusCode::kInvalidArgument,
45 HasSubstr("parse the header as an sf-list")));
46 }
47
TEST(WebTransportHeaders,SerializeSubprotocolRequestHeader)48 TEST(WebTransportHeaders, SerializeSubprotocolRequestHeader) {
49 EXPECT_THAT(SerializeSubprotocolRequestHeader({"test"}),
50 IsOkAndHolds("test"));
51 EXPECT_THAT(SerializeSubprotocolRequestHeader({"foo", "bar"}),
52 IsOkAndHolds("foo, bar"));
53 EXPECT_THAT(SerializeSubprotocolRequestHeader({"moqt-draft01", "a/b/c"}),
54 IsOkAndHolds("moqt-draft01, a/b/c"));
55 EXPECT_THAT(
56 SerializeSubprotocolRequestHeader({"abcd", "0123", "efgh"}),
57 StatusIs(absl::StatusCode::kInvalidArgument, "Invalid token: 0123"));
58 }
59
TEST(WebTransportHeader,ParseSubprotocolResponseHeader)60 TEST(WebTransportHeader, ParseSubprotocolResponseHeader) {
61 EXPECT_THAT(ParseSubprotocolResponseHeader("foo"), IsOkAndHolds("foo"));
62 EXPECT_THAT(ParseSubprotocolResponseHeader("foo; a=b"), IsOkAndHolds("foo"));
63 EXPECT_THAT(
64 ParseSubprotocolResponseHeader("1234"),
65 StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("found integer")));
66 EXPECT_THAT(
67 ParseSubprotocolResponseHeader("(a"),
68 StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("parse sf-item")));
69 }
70
TEST(WebTransportHeader,SerializeSubprotocolResponseHeader)71 TEST(WebTransportHeader, SerializeSubprotocolResponseHeader) {
72 EXPECT_THAT(SerializeSubprotocolResponseHeader("foo"), IsOkAndHolds("foo"));
73 EXPECT_THAT(SerializeSubprotocolResponseHeader("moqt-draft01"),
74 IsOkAndHolds("moqt-draft01"));
75 EXPECT_THAT(SerializeSubprotocolResponseHeader("123abc"),
76 StatusIs(absl::StatusCode::kInvalidArgument));
77 }
78
TEST(WebTransportHeader,ParseInitHeader)79 TEST(WebTransportHeader, ParseInitHeader) {
80 WebTransportInitHeader expected_header;
81 expected_header.initial_unidi_limit = 100;
82 expected_header.initial_incoming_bidi_limit = 200;
83 expected_header.initial_outgoing_bidi_limit = 400;
84 EXPECT_THAT(ParseInitHeader("br=400, bl=200, u=100"),
85 IsOkAndHolds(expected_header));
86 EXPECT_THAT(ParseInitHeader("br=300, bl=200, u=100, br=400"),
87 IsOkAndHolds(expected_header));
88 EXPECT_THAT(ParseInitHeader("br=400, bl=200; foo=bar, u=100"),
89 IsOkAndHolds(expected_header));
90 EXPECT_THAT(ParseInitHeader("br=400, bl=200, u=100.0"),
91 StatusIs(absl::StatusCode::kInvalidArgument,
92 HasSubstr("found decimal instead")));
93 EXPECT_THAT(ParseInitHeader("br=400, bl=200, u=?1"),
94 StatusIs(absl::StatusCode::kInvalidArgument,
95 HasSubstr("found boolean instead")));
96 EXPECT_THAT(ParseInitHeader("br=400, bl=200, u=(a b)"),
97 StatusIs(absl::StatusCode::kInvalidArgument,
98 HasSubstr("found a nested list instead")));
99 EXPECT_THAT(ParseInitHeader("br=400, bl=200, u=:abcd:"),
100 StatusIs(absl::StatusCode::kInvalidArgument,
101 HasSubstr("found byte sequence instead")));
102 EXPECT_THAT(ParseInitHeader("br=400, bl=200, u=-1"),
103 StatusIs(absl::StatusCode::kInvalidArgument,
104 HasSubstr("negative value")));
105 EXPECT_THAT(ParseInitHeader("br=400, bl=200, u=18446744073709551615"),
106 StatusIs(absl::StatusCode::kInvalidArgument,
107 HasSubstr("Failed to parse")));
108 }
109
TEST(WebTransportHeaders,SerializeInitHeader)110 TEST(WebTransportHeaders, SerializeInitHeader) {
111 EXPECT_THAT(SerializeInitHeader(WebTransportInitHeader{}),
112 IsOkAndHolds("u=0, bl=0, br=0"));
113
114 WebTransportInitHeader test_header;
115 test_header.initial_unidi_limit = 100;
116 test_header.initial_incoming_bidi_limit = 200;
117 test_header.initial_outgoing_bidi_limit = 400;
118 EXPECT_THAT(SerializeInitHeader(test_header),
119 IsOkAndHolds("u=100, bl=200, br=400"));
120 }
121
122 } // namespace
123 } // namespace webtransport
124