/* * Copyright 2007 The WebRTC Project Authors. All rights reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include "rtc_base/httpserver.h" #include "rtc_base/gunit.h" #include "rtc_base/testutils.h" using namespace webrtc::testing; namespace rtc { namespace { const char* const kRequest = "GET /index.html HTTP/1.1\r\n" "Host: localhost\r\n" "\r\n"; struct HttpServerMonitor : public sigslot::has_slots<> { HttpServerTransaction* transaction; bool server_closed, connection_closed; HttpServerMonitor(HttpServer* server) : transaction(nullptr), server_closed(false), connection_closed(false) { server->SignalCloseAllComplete.connect(this, &HttpServerMonitor::OnClosed); server->SignalHttpRequest.connect(this, &HttpServerMonitor::OnRequest); server->SignalHttpRequestComplete.connect(this, &HttpServerMonitor::OnRequestComplete); server->SignalConnectionClosed.connect(this, &HttpServerMonitor::OnConnectionClosed); } void OnRequest(HttpServer*, HttpServerTransaction* t) { ASSERT_FALSE(transaction); transaction = t; transaction->response.set_success(); transaction->response.setHeader(HH_CONNECTION, "Close"); } void OnRequestComplete(HttpServer*, HttpServerTransaction* t, int) { ASSERT_EQ(transaction, t); transaction = nullptr; } void OnClosed(HttpServer*) { server_closed = true; } void OnConnectionClosed(HttpServer*, int, StreamInterface* stream) { connection_closed = true; delete stream; } }; void CreateClientConnection(HttpServer& server, HttpServerMonitor& monitor, bool send_request) { StreamSource* client = new StreamSource; client->SetState(SS_OPEN); server.HandleConnection(client); EXPECT_FALSE(monitor.server_closed); EXPECT_FALSE(monitor.transaction); if (send_request) { // Simulate a request client->QueueString(kRequest); EXPECT_FALSE(monitor.server_closed); } } } // anonymous namespace TEST(HttpServer, DoesNotSignalCloseUnlessCloseAllIsCalled) { HttpServer server; HttpServerMonitor monitor(&server); // Add an active client connection CreateClientConnection(server, monitor, true); // Simulate a response ASSERT_TRUE(nullptr != monitor.transaction); server.Respond(monitor.transaction); EXPECT_FALSE(monitor.transaction); // Connection has closed, but no server close signal EXPECT_FALSE(monitor.server_closed); EXPECT_TRUE(monitor.connection_closed); } TEST(HttpServer, SignalsCloseWhenNoConnectionsAreActive) { HttpServer server; HttpServerMonitor monitor(&server); // Add an idle client connection CreateClientConnection(server, monitor, false); // Perform graceful close server.CloseAll(false); // Connections have all closed EXPECT_TRUE(monitor.server_closed); EXPECT_TRUE(monitor.connection_closed); } TEST(HttpServer, SignalsCloseAfterGracefulCloseAll) { HttpServer server; HttpServerMonitor monitor(&server); // Add an active client connection CreateClientConnection(server, monitor, true); // Initiate a graceful close server.CloseAll(false); EXPECT_FALSE(monitor.server_closed); // Simulate a response ASSERT_TRUE(nullptr != monitor.transaction); server.Respond(monitor.transaction); EXPECT_FALSE(monitor.transaction); // Connections have all closed EXPECT_TRUE(monitor.server_closed); EXPECT_TRUE(monitor.connection_closed); } TEST(HttpServer, SignalsCloseAfterForcedCloseAll) { HttpServer server; HttpServerMonitor monitor(&server); // Add an active client connection CreateClientConnection(server, monitor, true); // Initiate a forceful close server.CloseAll(true); // Connections have all closed EXPECT_TRUE(monitor.server_closed); EXPECT_TRUE(monitor.connection_closed); } } // namespace rtc