Add equality operators for public data types in BinaryHttp* PiperOrigin-RevId: 475643555
diff --git a/quiche/binary_http/binary_http_message.h b/quiche/binary_http/binary_http_message.h index d7da4fe..852df93 100644 --- a/quiche/binary_http/binary_http_message.h +++ b/quiche/binary_http/binary_http_message.h
@@ -30,6 +30,10 @@ return name == rhs.name && value == rhs.value; } + bool operator!=(const BinaryHttpMessage::Field& rhs) const { + return !(*this == rhs); + } + std::string DebugString() const; }; virtual ~BinaryHttpMessage() = default; @@ -87,6 +91,12 @@ std::vector<BinaryHttpMessage::Field> fields_; }; + bool operator==(const BinaryHttpMessage& rhs) const { + // `has_host_` is derived from `header_fields_` so it doesn't need to be + // tested directly. + return body_ == rhs.body_ && header_fields_ == rhs.header_fields_; + } + absl::Status EncodeKnownLengthFieldsAndBody( quiche::QuicheDataWriter& writer) const; uint64_t EncodedKnownLengthFieldsAndBodySize() const; @@ -114,6 +124,9 @@ return method == rhs.method && scheme == rhs.scheme && authority == rhs.authority && path == rhs.path; } + bool operator!=(const BinaryHttpRequest::ControlData& rhs) const { + return !(*this == rhs); + } }; explicit BinaryHttpRequest(ControlData control_data) : control_data_(std::move(control_data)) {} @@ -126,6 +139,15 @@ virtual std::string DebugString() const override; + bool operator==(const BinaryHttpRequest& rhs) const { + return control_data_ == rhs.control_data_ && + BinaryHttpMessage::operator==(rhs); + } + + bool operator!=(const BinaryHttpRequest& rhs) const { + return !(*this == rhs); + } + private: absl::Status EncodeControlData(quiche::QuicheDataWriter& writer) const; @@ -164,6 +186,11 @@ return status_code_ == rhs.status_code_ && fields_ == rhs.fields_; } + bool operator!=( + const BinaryHttpResponse::InformationalResponse& rhs) const { + return !(*this == rhs); + } + // Adds a field with the provided name, converted to lower case. // Fields are in the order they are added. void AddField(absl::string_view name, std::string value); @@ -211,6 +238,16 @@ virtual std::string DebugString() const override; + bool operator==(const BinaryHttpResponse& rhs) const { + return informational_response_control_data_ == + rhs.informational_response_control_data_ && + status_code_ == rhs.status_code_ && + BinaryHttpMessage::operator==(rhs); + } + bool operator!=(const BinaryHttpResponse& rhs) const { + return !(*this == rhs); + } + private: // Returns Binary Http known length request formatted response. absl::StatusOr<std::string> EncodeAsKnownLength() const;
diff --git a/quiche/binary_http/binary_http_message_test.cc b/quiche/binary_http/binary_http_message_test.cc index 3ce4b0e..f98a375 100644 --- a/quiche/binary_http/binary_http_message_test.cc +++ b/quiche/binary_http/binary_http_message_test.cc
@@ -262,6 +262,50 @@ "body that I used to post.\r\n}}}")); } +TEST(BinaryHttpRequest, Equality) { + BinaryHttpRequest request({"POST", "https", "www.example.com", "/hello.txt"}); + request.AddHeaderField({"User-Agent", "not/telling"}) + ->set_body({"hello, world!\r\n"}); + + BinaryHttpRequest same({"POST", "https", "www.example.com", "/hello.txt"}); + same.AddHeaderField({"User-Agent", "not/telling"}) + ->set_body({"hello, world!\r\n"}); + EXPECT_EQ(request, same); +} + +TEST(BinaryHttpRequest, Inequality) { + BinaryHttpRequest request({"POST", "https", "www.example.com", "/hello.txt"}); + request.AddHeaderField({"User-Agent", "not/telling"}) + ->set_body({"hello, world!\r\n"}); + + BinaryHttpRequest different_control( + {"PUT", "https", "www.example.com", "/hello.txt"}); + different_control.AddHeaderField({"User-Agent", "not/telling"}) + ->set_body({"hello, world!\r\n"}); + EXPECT_NE(request, different_control); + + BinaryHttpRequest different_header( + {"PUT", "https", "www.example.com", "/hello.txt"}); + different_header.AddHeaderField({"User-Agent", "told/you"}) + ->set_body({"hello, world!\r\n"}); + EXPECT_NE(request, different_header); + + BinaryHttpRequest no_header( + {"PUT", "https", "www.example.com", "/hello.txt"}); + no_header.set_body({"hello, world!\r\n"}); + EXPECT_NE(request, no_header); + + BinaryHttpRequest different_body( + {"POST", "https", "www.example.com", "/hello.txt"}); + different_body.AddHeaderField({"User-Agent", "not/telling"}) + ->set_body({"goodbye, world!\r\n"}); + EXPECT_NE(request, different_body); + + BinaryHttpRequest no_body({"POST", "https", "www.example.com", "/hello.txt"}); + no_body.AddHeaderField({"User-Agent", "not/telling"}); + EXPECT_NE(request, no_body); +} + TEST(BinaryHttpResponse, EncodeNoBody) { /* HTTP/1.1 404 Not Found @@ -572,4 +616,68 @@ EXPECT_EQ(other, "hello, world!"); } +TEST(BinaryHttpResponse, Equality) { + BinaryHttpResponse response(200); + response.AddHeaderField({"Server", "Apache"})->set_body("Hello, world!\r\n"); + ASSERT_OK( + response.AddInformationalResponse(102, {{"Running", "\"sleep 15\""}})); + + BinaryHttpResponse same(200); + same.AddHeaderField({"Server", "Apache"})->set_body("Hello, world!\r\n"); + ASSERT_OK(same.AddInformationalResponse(102, {{"Running", "\"sleep 15\""}})); + ASSERT_EQ(response, same); +} + +TEST(BinaryHttpResponse, Inequality) { + BinaryHttpResponse response(200); + response.AddHeaderField({"Server", "Apache"})->set_body("Hello, world!\r\n"); + ASSERT_OK( + response.AddInformationalResponse(102, {{"Running", "\"sleep 15\""}})); + + BinaryHttpResponse different_status(201); + different_status.AddHeaderField({"Server", "Apache"}) + ->set_body("Hello, world!\r\n"); + EXPECT_OK(different_status.AddInformationalResponse( + 102, {{"Running", "\"sleep 15\""}})); + EXPECT_NE(response, different_status); + + BinaryHttpResponse different_header(200); + different_header.AddHeaderField({"Server", "python3"}) + ->set_body("Hello, world!\r\n"); + EXPECT_OK(different_header.AddInformationalResponse( + 102, {{"Running", "\"sleep 15\""}})); + EXPECT_NE(response, different_header); + + BinaryHttpResponse no_header(200); + no_header.set_body("Hello, world!\r\n"); + EXPECT_OK( + no_header.AddInformationalResponse(102, {{"Running", "\"sleep 15\""}})); + EXPECT_NE(response, no_header); + + BinaryHttpResponse different_body(200); + different_body.AddHeaderField({"Server", "Apache"}) + ->set_body("Goodbye, world!\r\n"); + EXPECT_OK(different_body.AddInformationalResponse( + 102, {{"Running", "\"sleep 15\""}})); + EXPECT_NE(response, different_body); + + BinaryHttpResponse no_body(200); + no_body.AddHeaderField({"Server", "Apache"}); + EXPECT_OK( + no_body.AddInformationalResponse(102, {{"Running", "\"sleep 15\""}})); + EXPECT_NE(response, no_body); + + BinaryHttpResponse different_informational(200); + different_informational.AddHeaderField({"Server", "Apache"}) + ->set_body("Hello, world!\r\n"); + EXPECT_OK(different_informational.AddInformationalResponse( + 198, {{"Running", "\"sleep 15\""}})); + EXPECT_NE(response, different_informational); + + BinaryHttpResponse no_informational(200); + no_informational.AddHeaderField({"Server", "Apache"}) + ->set_body("Hello, world!\r\n"); + EXPECT_NE(response, no_informational); +} + } // namespace quiche