1 // Copyright 2007 Google Inc. 2 // All Rights Reserved. 3 4 5 #include "talk/base/gunit.h" 6 #include "talk/base/httpserver.h" 7 #include "talk/base/testutils.h" 8 9 using namespace testing; 10 11 namespace talk_base { 12 13 namespace { 14 const char* const kRequest = 15 "GET /index.html HTTP/1.1\r\n" 16 "Host: localhost\r\n" 17 "\r\n"; 18 19 const char* const kResponse = 20 "HTTP/1.1 200\r\n" 21 "Connection: Close\r\n" 22 "Content-Length: 0\r\n" 23 "\r\n"; 24 25 struct HttpServerMonitor : public sigslot::has_slots<> { 26 HttpServerTransaction* transaction; 27 bool server_closed, connection_closed; 28 29 HttpServerMonitor(HttpServer* server) 30 : transaction(NULL), server_closed(false), connection_closed(false) { 31 server->SignalCloseAllComplete.connect(this, 32 &HttpServerMonitor::OnClosed); 33 server->SignalHttpRequest.connect(this, &HttpServerMonitor::OnRequest); 34 server->SignalHttpRequestComplete.connect(this, 35 &HttpServerMonitor::OnRequestComplete); 36 server->SignalConnectionClosed.connect(this, 37 &HttpServerMonitor::OnConnectionClosed); 38 } 39 void OnRequest(HttpServer*, HttpServerTransaction* t) { 40 ASSERT_FALSE(transaction); 41 transaction = t; 42 transaction->response.set_success(); 43 transaction->response.setHeader(HH_CONNECTION, "Close"); 44 } 45 void OnRequestComplete(HttpServer*, HttpServerTransaction* t, int) { 46 ASSERT_EQ(transaction, t); 47 transaction = NULL; 48 } 49 void OnClosed(HttpServer*) { 50 server_closed = true; 51 } 52 void OnConnectionClosed(HttpServer*, int, StreamInterface* stream) { 53 connection_closed = true; 54 delete stream; 55 } 56 }; 57 58 void CreateClientConnection(HttpServer& server, 59 HttpServerMonitor& monitor, 60 bool send_request) { 61 StreamSource* client = new StreamSource; 62 client->SetState(SS_OPEN); 63 server.HandleConnection(client); 64 EXPECT_FALSE(monitor.server_closed); 65 EXPECT_FALSE(monitor.transaction); 66 67 if (send_request) { 68 // Simulate a request 69 client->QueueString(kRequest); 70 EXPECT_FALSE(monitor.server_closed); 71 } 72 } 73 } // anonymous namespace 74 75 TEST(HttpServer, DoesNotSignalCloseUnlessCloseAllIsCalled) { 76 HttpServer server; 77 HttpServerMonitor monitor(&server); 78 // Add an active client connection 79 CreateClientConnection(server, monitor, true); 80 // Simulate a response 81 ASSERT_TRUE(NULL != monitor.transaction); 82 server.Respond(monitor.transaction); 83 EXPECT_FALSE(monitor.transaction); 84 // Connection has closed, but no server close signal 85 EXPECT_FALSE(monitor.server_closed); 86 EXPECT_TRUE(monitor.connection_closed); 87 } 88 89 TEST(HttpServer, SignalsCloseWhenNoConnectionsAreActive) { 90 HttpServer server; 91 HttpServerMonitor monitor(&server); 92 // Add an idle client connection 93 CreateClientConnection(server, monitor, false); 94 // Perform graceful close 95 server.CloseAll(false); 96 // Connections have all closed 97 EXPECT_TRUE(monitor.server_closed); 98 EXPECT_TRUE(monitor.connection_closed); 99 } 100 101 TEST(HttpServer, SignalsCloseAfterGracefulCloseAll) { 102 HttpServer server; 103 HttpServerMonitor monitor(&server); 104 // Add an active client connection 105 CreateClientConnection(server, monitor, true); 106 // Initiate a graceful close 107 server.CloseAll(false); 108 EXPECT_FALSE(monitor.server_closed); 109 // Simulate a response 110 ASSERT_TRUE(NULL != monitor.transaction); 111 server.Respond(monitor.transaction); 112 EXPECT_FALSE(monitor.transaction); 113 // Connections have all closed 114 EXPECT_TRUE(monitor.server_closed); 115 EXPECT_TRUE(monitor.connection_closed); 116 } 117 118 TEST(HttpServer, SignalsCloseAfterForcedCloseAll) { 119 HttpServer server; 120 HttpServerMonitor monitor(&server); 121 // Add an active client connection 122 CreateClientConnection(server, monitor, true); 123 // Initiate a forceful close 124 server.CloseAll(true); 125 // Connections have all closed 126 EXPECT_TRUE(monitor.server_closed); 127 EXPECT_TRUE(monitor.connection_closed); 128 } 129 130 } // namespace talk_base 131