xref: /aosp_15_r20/external/pigweed/pw_grpc/hpack_test.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1*61c4878aSAndroid Build Coastguard Worker // Copyright 2024 The Pigweed Authors
2*61c4878aSAndroid Build Coastguard Worker //
3*61c4878aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4*61c4878aSAndroid Build Coastguard Worker // use this file except in compliance with the License. You may obtain a copy of
5*61c4878aSAndroid Build Coastguard Worker // the License at
6*61c4878aSAndroid Build Coastguard Worker //
7*61c4878aSAndroid Build Coastguard Worker //     https://www.apache.org/licenses/LICENSE-2.0
8*61c4878aSAndroid Build Coastguard Worker //
9*61c4878aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*61c4878aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11*61c4878aSAndroid Build Coastguard Worker // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12*61c4878aSAndroid Build Coastguard Worker // License for the specific language governing permissions and limitations under
13*61c4878aSAndroid Build Coastguard Worker // the License.
14*61c4878aSAndroid Build Coastguard Worker 
15*61c4878aSAndroid Build Coastguard Worker #include "pw_grpc_private/hpack.h"
16*61c4878aSAndroid Build Coastguard Worker 
17*61c4878aSAndroid Build Coastguard Worker #include "gtest/gtest.h"
18*61c4878aSAndroid Build Coastguard Worker #include "pw_bytes/array.h"
19*61c4878aSAndroid Build Coastguard Worker 
20*61c4878aSAndroid Build Coastguard Worker namespace pw::grpc {
21*61c4878aSAndroid Build Coastguard Worker namespace {
22*61c4878aSAndroid Build Coastguard Worker 
TestIntegerDecode(ConstByteSpan input,int bits,int expected)23*61c4878aSAndroid Build Coastguard Worker void TestIntegerDecode(ConstByteSpan input, int bits, int expected) {
24*61c4878aSAndroid Build Coastguard Worker   auto result = HpackIntegerDecode(input, bits);
25*61c4878aSAndroid Build Coastguard Worker   ASSERT_TRUE(result.ok());
26*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(*result, expected);
27*61c4878aSAndroid Build Coastguard Worker   EXPECT_TRUE(input.empty());  // input has advanced past the integer
28*61c4878aSAndroid Build Coastguard Worker }
29*61c4878aSAndroid Build Coastguard Worker 
TestHuffmanDecode(ConstByteSpan input,std::string_view expected)30*61c4878aSAndroid Build Coastguard Worker void TestHuffmanDecode(ConstByteSpan input, std::string_view expected) {
31*61c4878aSAndroid Build Coastguard Worker   auto result = HpackHuffmanDecode(input);
32*61c4878aSAndroid Build Coastguard Worker   ASSERT_TRUE(result.ok());
33*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(*result, expected);
34*61c4878aSAndroid Build Coastguard Worker }
35*61c4878aSAndroid Build Coastguard Worker 
36*61c4878aSAndroid Build Coastguard Worker // Integer test cases from RFC 7541 Appendix C.1.
TEST(HpackTest,HpackIntegerDecodeC11)37*61c4878aSAndroid Build Coastguard Worker TEST(HpackTest, HpackIntegerDecodeC11) {
38*61c4878aSAndroid Build Coastguard Worker   const auto kInput = bytes::Array<0b11101010>();
39*61c4878aSAndroid Build Coastguard Worker   TestIntegerDecode(kInput, /*bits_in_first_byte=*/5, /*expected=*/10);
40*61c4878aSAndroid Build Coastguard Worker }
TEST(HpackTest,HpackIntegerDecodeC12)41*61c4878aSAndroid Build Coastguard Worker TEST(HpackTest, HpackIntegerDecodeC12) {
42*61c4878aSAndroid Build Coastguard Worker   const auto kInput = bytes::Array<0b11111111, 0b10011010, 0b00001010>();
43*61c4878aSAndroid Build Coastguard Worker   TestIntegerDecode(kInput, /*bits_in_first_byte=*/5, /*expected=*/1337);
44*61c4878aSAndroid Build Coastguard Worker }
TEST(HpackTest,HpackIntegerDecodeC13)45*61c4878aSAndroid Build Coastguard Worker TEST(HpackTest, HpackIntegerDecodeC13) {
46*61c4878aSAndroid Build Coastguard Worker   const auto kInput = bytes::Array<0b00101010>();
47*61c4878aSAndroid Build Coastguard Worker   TestIntegerDecode(kInput, /*bits_in_first_byte=*/8, /*expected=*/42);
48*61c4878aSAndroid Build Coastguard Worker }
49*61c4878aSAndroid Build Coastguard Worker 
50*61c4878aSAndroid Build Coastguard Worker // Huffman test cases from RFC 7541 Appendix C.4.
51*61c4878aSAndroid Build Coastguard Worker // clang-format off
52*61c4878aSAndroid Build Coastguard Worker const auto kHuffmanC41 = bytes::Array<0xf1, 0xe3, 0xc2, 0xe5, 0xf2, 0x3a, 0x6b, 0xa0, 0xab, 0x90, 0xf4, 0xff>();
53*61c4878aSAndroid Build Coastguard Worker const auto kHuffmanC42 = bytes::Array<0xa8, 0xeb, 0x10, 0x64, 0x9c, 0xbf>();
54*61c4878aSAndroid Build Coastguard Worker const auto kHuffmanC43a = bytes::Array<0x25, 0xa8, 0x49, 0xe9, 0x5b, 0xa9, 0x7d, 0x7f>();
55*61c4878aSAndroid Build Coastguard Worker const auto kHuffmanC43b = bytes::Array<0x25, 0xa8, 0x49, 0xe9, 0x5b, 0xb8, 0xe8, 0xb4, 0xbf>();
56*61c4878aSAndroid Build Coastguard Worker // clang-format on
57*61c4878aSAndroid Build Coastguard Worker 
TEST(HpackTest,HpackHuffmanDecodeC41)58*61c4878aSAndroid Build Coastguard Worker TEST(HpackTest, HpackHuffmanDecodeC41) {
59*61c4878aSAndroid Build Coastguard Worker   TestHuffmanDecode(kHuffmanC41, "www.example.com");
60*61c4878aSAndroid Build Coastguard Worker }
TEST(HpackTest,HpackHuffmanDecodeC42)61*61c4878aSAndroid Build Coastguard Worker TEST(HpackTest, HpackHuffmanDecodeC42) {
62*61c4878aSAndroid Build Coastguard Worker   TestHuffmanDecode(kHuffmanC42, "no-cache");
63*61c4878aSAndroid Build Coastguard Worker }
TEST(HpackTest,HpackHuffmanDecodeC43a)64*61c4878aSAndroid Build Coastguard Worker TEST(HpackTest, HpackHuffmanDecodeC43a) {
65*61c4878aSAndroid Build Coastguard Worker   TestHuffmanDecode(kHuffmanC43a, "custom-key");
66*61c4878aSAndroid Build Coastguard Worker }
TEST(HpackTest,HpackHuffmanDecodeC43b)67*61c4878aSAndroid Build Coastguard Worker TEST(HpackTest, HpackHuffmanDecodeC43b) {
68*61c4878aSAndroid Build Coastguard Worker   TestHuffmanDecode(kHuffmanC43b, "custom-value");
69*61c4878aSAndroid Build Coastguard Worker }
70*61c4878aSAndroid Build Coastguard Worker 
71*61c4878aSAndroid Build Coastguard Worker // Header field test cases from RFC 7541 Appendix C.
TEST(HpackTest,HpackParseRequestHeadersFoundIndexedSlash)72*61c4878aSAndroid Build Coastguard Worker TEST(HpackTest, HpackParseRequestHeadersFoundIndexedSlash) {
73*61c4878aSAndroid Build Coastguard Worker   // Appendix C.3.1.
74*61c4878aSAndroid Build Coastguard Worker   const auto kInput = bytes::Array<0x84>();
75*61c4878aSAndroid Build Coastguard Worker   auto result = HpackParseRequestHeaders(kInput);
76*61c4878aSAndroid Build Coastguard Worker   ASSERT_TRUE(result.ok());
77*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(*result, "/");
78*61c4878aSAndroid Build Coastguard Worker }
TEST(HpackTest,HpackParseRequestHeadersFoundIndexedHtml)79*61c4878aSAndroid Build Coastguard Worker TEST(HpackTest, HpackParseRequestHeadersFoundIndexedHtml) {
80*61c4878aSAndroid Build Coastguard Worker   // Appendix C.3.3.
81*61c4878aSAndroid Build Coastguard Worker   const auto kInput = bytes::Array<0x85>();
82*61c4878aSAndroid Build Coastguard Worker   auto result = HpackParseRequestHeaders(kInput);
83*61c4878aSAndroid Build Coastguard Worker   ASSERT_TRUE(result.ok());
84*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(*result, "/index.html");
85*61c4878aSAndroid Build Coastguard Worker }
TEST(HpackTest,HpackParseRequestHeadersFoundNotIndexed)86*61c4878aSAndroid Build Coastguard Worker TEST(HpackTest, HpackParseRequestHeadersFoundNotIndexed) {
87*61c4878aSAndroid Build Coastguard Worker   // clang-format off
88*61c4878aSAndroid Build Coastguard Worker   const auto kInput = bytes::Array<
89*61c4878aSAndroid Build Coastguard Worker       // Appendix C.2.1.
90*61c4878aSAndroid Build Coastguard Worker       0x40, 0x0a, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2d, 0x6b, 0x65, 0x79, 0x0d, 0x63,
91*61c4878aSAndroid Build Coastguard Worker       0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2d, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72,
92*61c4878aSAndroid Build Coastguard Worker       // Appendix C.2.3.
93*61c4878aSAndroid Build Coastguard Worker       0x10, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x06, 0x73, 0x65, 0x63,
94*61c4878aSAndroid Build Coastguard Worker       0x72, 0x65, 0x74,
95*61c4878aSAndroid Build Coastguard Worker       // Appendix C.2.2.
96*61c4878aSAndroid Build Coastguard Worker       0x04, 0x0c, 0x2f, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2f, 0x70, 0x61, 0x74, 0x68
97*61c4878aSAndroid Build Coastguard Worker   >();
98*61c4878aSAndroid Build Coastguard Worker   // clang-format on
99*61c4878aSAndroid Build Coastguard Worker   auto result = HpackParseRequestHeaders(kInput);
100*61c4878aSAndroid Build Coastguard Worker   ASSERT_TRUE(result.ok());
101*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(*result, "/sample/path");
102*61c4878aSAndroid Build Coastguard Worker }
TEST(HpackTest,HpackParseRequestHeadersNotFound)103*61c4878aSAndroid Build Coastguard Worker TEST(HpackTest, HpackParseRequestHeadersNotFound) {
104*61c4878aSAndroid Build Coastguard Worker   // clang-format off
105*61c4878aSAndroid Build Coastguard Worker   const auto kInput = bytes::Array<
106*61c4878aSAndroid Build Coastguard Worker       // Appendix C.2.1.
107*61c4878aSAndroid Build Coastguard Worker       0x40, 0x0a, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2d, 0x6b, 0x65, 0x79, 0x0d, 0x63,
108*61c4878aSAndroid Build Coastguard Worker       0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2d, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72,
109*61c4878aSAndroid Build Coastguard Worker       // Appendix C.2.3.
110*61c4878aSAndroid Build Coastguard Worker       0x10, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x06, 0x73, 0x65, 0x63,
111*61c4878aSAndroid Build Coastguard Worker       0x72, 0x65, 0x74
112*61c4878aSAndroid Build Coastguard Worker   >();
113*61c4878aSAndroid Build Coastguard Worker   // clang-format on
114*61c4878aSAndroid Build Coastguard Worker   auto result = HpackParseRequestHeaders(kInput);
115*61c4878aSAndroid Build Coastguard Worker   ASSERT_FALSE(result.ok());
116*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(result.status().code(), PW_STATUS_NOT_FOUND);
117*61c4878aSAndroid Build Coastguard Worker }
118*61c4878aSAndroid Build Coastguard Worker 
119*61c4878aSAndroid Build Coastguard Worker }  // namespace
120*61c4878aSAndroid Build Coastguard Worker }  // namespace pw::grpc
121