summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/chrome_tests.gypi2
-rw-r--r--chrome/test/webdriver/http_response.cc67
-rw-r--r--chrome/test/webdriver/http_response.h22
-rw-r--r--chrome/test/webdriver/http_response_unittest.cc28
-rw-r--r--chrome/test/webdriver/webdriver_dispatch.cc75
-rw-r--r--chrome/test/webdriver/webdriver_dispatch_unittest.cc9
-rw-r--r--chrome/test/webdriver/webdriver_server.cc3
-rw-r--r--chrome/test/webdriver/webdriver_switches.cc13
-rw-r--r--chrome/test/webdriver/webdriver_switches.h14
9 files changed, 126 insertions, 107 deletions
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index 9a6d4f3..00523b0 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -806,6 +806,8 @@
'test/webdriver/webdriver_session.h',
'test/webdriver/webdriver_session_manager.cc',
'test/webdriver/webdriver_session_manager.h',
+ 'test/webdriver/webdriver_switches.cc',
+ 'test/webdriver/webdriver_switches.h',
'test/webdriver/webdriver_util.cc',
'test/webdriver/webdriver_util.h',
'test/webdriver/webdriver_util_mac.mm',
diff --git a/chrome/test/webdriver/http_response.cc b/chrome/test/webdriver/http_response.cc
index 6bbe4a9..d07a6b3 100644
--- a/chrome/test/webdriver/http_response.cc
+++ b/chrome/test/webdriver/http_response.cc
@@ -15,14 +15,26 @@ const int HttpResponse::kNoContent = 204;
const int HttpResponse::kSeeOther = 303;
const int HttpResponse::kNotModified = 304;
const int HttpResponse::kBadRequest = 400;
+const int HttpResponse::kForbidden = 403;
const int HttpResponse::kNotFound = 404;
const int HttpResponse::kMethodNotAllowed = 405;
const int HttpResponse::kInternalServerError = 500;
+const int HttpResponse::kNotImplemented = 501;
+
+namespace {
+
+const char* kContentLengthHeader = "content-length";
+
+} // namespace
HttpResponse::HttpResponse()
: status_(kOk) {
}
+HttpResponse::HttpResponse(int status)
+ : status_(status) {
+}
+
HttpResponse::~HttpResponse() {
}
@@ -69,26 +81,10 @@ void HttpResponse::ClearHeaders() {
headers_.clear();
}
-void HttpResponse::UpdateHeader(const std::string& name,
- const std::string& new_value) {
- RemoveHeader(name);
- AddHeader(name, new_value);
-}
-
void HttpResponse::SetMimeType(const std::string& mime_type) {
UpdateHeader("Content-Type", mime_type);
}
-void HttpResponse::SetBody(const std::string& data) {
- SetBody(data.data(), data.length());
-}
-
-void HttpResponse::SetBody(const char* const data, size_t length) {
- data_ = std::string(data, length);
- UpdateHeader("Content-Length",
- base::StringPrintf("%"PRIuS"", data_.length()));
-}
-
std::string HttpResponse::GetReasonPhrase() const {
switch (status_) {
case kOk:
@@ -101,17 +97,42 @@ std::string HttpResponse::GetReasonPhrase() const {
return "Not Modified";
case kBadRequest:
return "Bad Request";
+ case kForbidden:
+ return "Forbidden";
case kNotFound:
return "Not Found";
case kMethodNotAllowed:
return "Method Not Allowed";
case kInternalServerError:
return "Internal Server Error";
+ case kNotImplemented:
+ return "Not Implemented";
default:
return "Unknown";
}
}
+void HttpResponse::GetData(std::string* data) const {
+ *data += base::StringPrintf("HTTP/1.1 %d %s\r\n",
+ status_, GetReasonPhrase().c_str());
+
+ typedef HttpResponse::HeaderMap::const_iterator HeaderIter;
+ for (HeaderIter header = headers_.begin(); header != headers_.end();
+ ++header) {
+ *data += header->first + ":" + header->second + "\r\n";
+ }
+ std::string length;
+ if (!GetHeader(kContentLengthHeader, &length)) {
+ *data += base::StringPrintf(
+ "%s:%"PRIuS"\r\n",
+ kContentLengthHeader, body_.length());
+ }
+ *data += "\r\n";
+
+ if (body_.length())
+ *data += body_;
+}
+
int HttpResponse::status() const {
return status_;
}
@@ -120,16 +141,18 @@ void HttpResponse::set_status(int status) {
status_ = status;
}
-const HttpResponse::HeaderMap* HttpResponse::headers() const {
- return &headers_;
+const std::string& HttpResponse::body() const {
+ return body_;
}
-const char* HttpResponse::data() const {
- return data_.data();
+void HttpResponse::set_body(const std::string& body) {
+ body_ = body;
}
-size_t HttpResponse::length() const {
- return data_.length();
+void HttpResponse::UpdateHeader(const std::string& name,
+ const std::string& new_value) {
+ RemoveHeader(name);
+ AddHeader(name, new_value);
}
} // namespace webdriver
diff --git a/chrome/test/webdriver/http_response.h b/chrome/test/webdriver/http_response.h
index f3c37d8..a3828f2 100644
--- a/chrome/test/webdriver/http_response.h
+++ b/chrome/test/webdriver/http_response.h
@@ -22,11 +22,15 @@ class HttpResponse {
static const int kSeeOther;
static const int kNotModified;
static const int kBadRequest;
+ static const int kForbidden;
static const int kNotFound;
static const int kMethodNotAllowed;
static const int kInternalServerError;
+ static const int kNotImplemented;
+ // Creates an HTTP response with a 200 OK status.
HttpResponse();
+ explicit HttpResponse(int status);
~HttpResponse();
// Sets a header in this response. If a header with the same |name| already
@@ -48,30 +52,26 @@ class HttpResponse {
// Convenience function for setting the Content-Type header for this response.
void SetMimeType(const std::string& mime_type);
- // Sets the message body for this response; will also set the "Content-Length"
- // message header.
- void SetBody(const std::string& data);
- void SetBody(const char* const data, size_t length);
-
// Returns the status phrase recommended by RFC 2616 section 6.1.1 for this
// response's status code. If the status code is not recognized, the default
// "Unknown" status phrase will be used.
std::string GetReasonPhrase() const;
+ // Appends this response to |data|, abiding by HTTP 1.1.
+ // This will add an appropriate "Content-Length" header if not already set.
+ void GetData(std::string* data) const;
+
int status() const;
void set_status(int status);
- const HeaderMap* headers() const;
- const char* data() const;
- size_t length() const;
+ const std::string& body() const;
+ void set_body(const std::string& body);
private:
void UpdateHeader(const std::string& name, const std::string& new_value);
int status_;
HeaderMap headers_;
- std::string data_;
-
- DISALLOW_COPY_AND_ASSIGN(HttpResponse);
+ std::string body_;
};
} // webdriver
diff --git a/chrome/test/webdriver/http_response_unittest.cc b/chrome/test/webdriver/http_response_unittest.cc
index 71be83f..4e204c6 100644
--- a/chrome/test/webdriver/http_response_unittest.cc
+++ b/chrome/test/webdriver/http_response_unittest.cc
@@ -65,25 +65,17 @@ TEST(HttpResponseTest, CanSetMimeType) {
ExpectHeaderValue(response, "content-type", "text/html");
}
-TEST(HttpResponseTest, SetBody) {
+TEST(HttpResponseTest, GetData) {
HttpResponse response;
-
- std::string body("foo bar");
- response.SetBody(body);
- ASSERT_EQ(body.length(), response.length());
- ASSERT_EQ(body, std::string(response.data(), response.length()));
-
- // Grow the response size.
- body.append(" baz");
- response.SetBody(body);
- ASSERT_EQ(body.length(), response.length());
- ASSERT_EQ(body, std::string(response.data(), response.length()));
-
- // Shrink the response size.
- body = "small";
- response.SetBody(body);
- ASSERT_EQ(body.length(), response.length());
- ASSERT_EQ(body, std::string(response.data(), response.length()));
+ response.set_body("my body");
+ std::string data;
+ response.GetData(&data);
+ const char* expected =
+ "HTTP/1.1 200 OK\r\n"
+ "content-length:7\r\n"
+ "\r\n"
+ "my body";
+ ASSERT_STREQ(expected, data.c_str());
}
} // namespace webdriver
diff --git a/chrome/test/webdriver/webdriver_dispatch.cc b/chrome/test/webdriver/webdriver_dispatch.cc
index d5a2784..7034229 100644
--- a/chrome/test/webdriver/webdriver_dispatch.cc
+++ b/chrome/test/webdriver/webdriver_dispatch.cc
@@ -8,6 +8,7 @@
#include <string>
#include <vector>
+#include "base/command_line.h"
#include "base/format_macros.h"
#include "base/json/json_reader.h"
#include "base/logging.h"
@@ -25,6 +26,7 @@
#include "chrome/test/webdriver/http_response.h"
#include "chrome/test/webdriver/webdriver_logging.h"
#include "chrome/test/webdriver/webdriver_session_manager.h"
+#include "chrome/test/webdriver/webdriver_switches.h"
#include "chrome/test/webdriver/webdriver_util.h"
namespace webdriver {
@@ -35,14 +37,6 @@ namespace {
// the message may not be transferred at all.
const size_t kMaxHttpMessageSize = 1024 * 1024 * 16; // 16MB
-bool ForbidsMessageBody(const std::string& request_method,
- const HttpResponse& response) {
- return request_method == "HEAD" ||
- response.status() == HttpResponse::kNoContent ||
- response.status() == HttpResponse::kNotModified ||
- (response.status() >= 100 && response.status() < 200);
-}
-
void ReadRequestBody(const struct mg_request_info* const request_info,
struct mg_connection* const connection,
std::string* request_body) {
@@ -69,6 +63,16 @@ void ReadRequestBody(const struct mg_request_info* const request_info,
}
}
+void WriteHttpResponse(struct mg_connection* connection,
+ const HttpResponse& response) {
+ HttpResponse modified_response(response);
+ if (!CommandLine::ForCurrentProcess()->HasSwitch(kEnableKeepAlive))
+ modified_response.AddHeader("connection", "close");
+ std::string data;
+ modified_response.GetData(&data);
+ mg_write(connection, data.data(), data.length());
+}
+
void DispatchCommand(Command* const command,
const std::string& method,
Response* response) {
@@ -89,12 +93,9 @@ void DispatchCommand(Command* const command,
void SendOkWithBody(struct mg_connection* connection,
const std::string& content) {
- const char* response_fmt = "HTTP/1.1 200 OK\r\n"
- "Content-Length:%d\r\n\r\n"
- "%s";
- std::string response = base::StringPrintf(
- response_fmt, content.length(), content.c_str());
- mg_write(connection, response.data(), response.length());
+ HttpResponse response;
+ response.set_body(content);
+ WriteHttpResponse(connection, response);
}
void Shutdown(struct mg_connection* connection,
@@ -102,7 +103,7 @@ void Shutdown(struct mg_connection* connection,
void* user_data) {
base::WaitableEvent* shutdown_event =
reinterpret_cast<base::WaitableEvent*>(user_data);
- mg_printf(connection, "HTTP/1.1 200 OK\r\n\r\n\r\n");
+ WriteHttpResponse(connection, HttpResponse());
shutdown_event->Signal();
}
@@ -161,16 +162,13 @@ void SimulateHang(struct mg_connection* connection,
void SendNoContentResponse(struct mg_connection* connection,
const struct mg_request_info* request_info,
void* user_data) {
- std::string response = "HTTP/1.1 204 No Content\r\n"
- "Content-Length:0\r\n"
- "\r\n";
- mg_write(connection, response.data(), response.length());
+ WriteHttpResponse(connection, HttpResponse(HttpResponse::kNoContent));
}
void SendForbidden(struct mg_connection* connection,
const struct mg_request_info* request_info,
void* user_data) {
- mg_printf(connection, "HTTP/1.1 403 Forbidden\r\n\r\n");
+ WriteHttpResponse(connection, HttpResponse(HttpResponse::kForbidden));
}
void SendNotImplementedError(struct mg_connection* connection,
@@ -183,14 +181,10 @@ void SendNotImplementedError(struct mg_connection* connection,
"\"Command has not been implemented yet: %s %s\"}}",
kUnknownCommand, request_info->request_method, request_info->uri);
- std::string header = base::StringPrintf(
- "HTTP/1.1 501 Not Implemented\r\n"
- "Content-Type:application/json\r\n"
- "Content-Length:%" PRIuS "\r\n"
- "\r\n", body.length());
-
- mg_write(connection, header.data(), header.length());
- mg_write(connection, body.data(), body.length());
+ HttpResponse response(HttpResponse::kNotImplemented);
+ response.AddHeader("Content-Type", "application/json");
+ response.set_body(body);
+ WriteHttpResponse(connection, response);
}
} // namespace
@@ -214,7 +208,7 @@ void PrepareHttpResponse(const Response& command_response,
if (!value->GetAsString(&location)) {
// This should never happen.
http_response->set_status(HttpResponse::kInternalServerError);
- http_response->SetBody("Unable to set 'Location' header: response "
+ http_response->set_body("Unable to set 'Location' header: response "
"value is not a string: " +
command_response.ToJSON());
return;
@@ -234,7 +228,7 @@ void PrepareHttpResponse(const Response& command_response,
if (!value->IsType(Value::TYPE_LIST)) {
// This should never happen.
http_response->set_status(HttpResponse::kInternalServerError);
- http_response->SetBody(
+ http_response->set_body(
"Unable to set 'Allow' header: response value was "
"not a list of strings: " + command_response.ToJSON());
return;
@@ -250,7 +244,7 @@ void PrepareHttpResponse(const Response& command_response,
} else {
// This should never happen.
http_response->set_status(HttpResponse::kInternalServerError);
- http_response->SetBody(
+ http_response->set_body(
"Unable to set 'Allow' header: response value was "
"not a list of strings: " + command_response.ToJSON());
return;
@@ -270,7 +264,7 @@ void PrepareHttpResponse(const Response& command_response,
}
http_response->SetMimeType("application/json; charset=utf-8");
- http_response->SetBody(command_response.ToJSON());
+ http_response->set_body(command_response.ToJSON());
}
void SendResponse(struct mg_connection* const connection,
@@ -278,22 +272,7 @@ void SendResponse(struct mg_connection* const connection,
const Response& response) {
HttpResponse http_response;
PrepareHttpResponse(response, &http_response);
-
- std::string message_header = base::StringPrintf("HTTP/1.1 %d %s\r\n",
- http_response.status(), http_response.GetReasonPhrase().c_str());
-
- typedef HttpResponse::HeaderMap::const_iterator HeaderIter;
- for (HeaderIter header = http_response.headers()->begin();
- header != http_response.headers()->end();
- ++header) {
- message_header.append(base::StringPrintf("%s:%s\r\n",
- header->first.c_str(), header->second.c_str()));
- }
- message_header.append("\r\n");
-
- mg_write(connection, message_header.data(), message_header.length());
- if (!ForbidsMessageBody(request_method, http_response))
- mg_write(connection, http_response.data(), http_response.length());
+ WriteHttpResponse(connection, http_response);
}
bool ParseRequestInfo(const struct mg_request_info* const request_info,
diff --git a/chrome/test/webdriver/webdriver_dispatch_unittest.cc b/chrome/test/webdriver/webdriver_dispatch_unittest.cc
index edee103..6abf90c 100644
--- a/chrome/test/webdriver/webdriver_dispatch_unittest.cc
+++ b/chrome/test/webdriver/webdriver_dispatch_unittest.cc
@@ -121,23 +121,18 @@ TEST(DispatchTest, ReturnsCommandResponseAsJson) {
EXPECT_EQ(HttpResponse::kOk, http_response.status());
ExpectHeaderValue(http_response, "content-type",
"application/json; charset=utf-8");
- ExpectHeaderValue(http_response, "content-length",
- base::StringPrintf("%"PRIuS, kExpectedData.length()));
// We do not know whether the response status or value will be
// encoded first, so we have to parse the response body to
// verify it is correct.
- std::string actual_data(http_response.data(),
- http_response.length());
-
int error_code;
std::string error_message;
scoped_ptr<Value> parsed_response(base::JSONReader::ReadAndReturnError(
- actual_data, base::JSON_PARSE_RFC, &error_code, &error_message));
+ http_response.body(), base::JSON_PARSE_RFC, &error_code, &error_message));
ASSERT_TRUE(parsed_response.get() != NULL) << error_message;
ASSERT_TRUE(parsed_response->IsType(Value::TYPE_DICTIONARY))
- << "Response should be a dictionary: " << actual_data;
+ << "Response should be a dictionary: " << http_response.body();
DictionaryValue* dict = static_cast<DictionaryValue*>(parsed_response.get());
EXPECT_EQ(2u, dict->size());
diff --git a/chrome/test/webdriver/webdriver_server.cc b/chrome/test/webdriver/webdriver_server.cc
index 899ed28..ccb8c70 100644
--- a/chrome/test/webdriver/webdriver_server.cc
+++ b/chrome/test/webdriver/webdriver_server.cc
@@ -59,6 +59,7 @@
#include "chrome/test/webdriver/webdriver_dispatch.h"
#include "chrome/test/webdriver/webdriver_logging.h"
#include "chrome/test/webdriver/webdriver_session_manager.h"
+#include "chrome/test/webdriver/webdriver_switches.h"
#include "chrome/test/webdriver/webdriver_util.h"
#include "third_party/mongoose/mongoose.h"
@@ -259,7 +260,7 @@ int RunChromeDriver() {
return 1;
}
}
- if (cmd_line->HasSwitch("enable-keep-alive"))
+ if (cmd_line->HasSwitch(kEnableKeepAlive))
enable_keep_alive = true;
bool logging_success = InitWebDriverLogging(log_path, kAllLogLevel);
diff --git a/chrome/test/webdriver/webdriver_switches.cc b/chrome/test/webdriver/webdriver_switches.cc
new file mode 100644
index 0000000..3e44277
--- /dev/null
+++ b/chrome/test/webdriver/webdriver_switches.cc
@@ -0,0 +1,13 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/test/webdriver/webdriver_switches.h"
+
+namespace webdriver {
+
+// Instructs the mongoose webserver to enable HTTP persistent
+// connections.
+const char kEnableKeepAlive[] = "enable-keep-alive";
+
+} // namespace webdriver
diff --git a/chrome/test/webdriver/webdriver_switches.h b/chrome/test/webdriver/webdriver_switches.h
new file mode 100644
index 0000000..639d1b3
--- /dev/null
+++ b/chrome/test/webdriver/webdriver_switches.h
@@ -0,0 +1,14 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_TEST_WEBDRIVER_WEBDRIVER_SWITCHES_H_
+#define CHROME_TEST_WEBDRIVER_WEBDRIVER_SWITCHES_H_
+
+namespace webdriver {
+
+extern const char kEnableKeepAlive[];
+
+} // namespace webdriver
+
+#endif // CHROME_TEST_WEBDRIVER_WEBDRIVER_SWITCHES_H_