1// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <string>
6
7#include "base/bind.h"
8#include "base/json/json_writer.h"
9#include "base/memory/scoped_ptr.h"
10#include "base/values.h"
11#include "chrome/test/chromedriver/chrome/log.h"
12#include "chrome/test/chromedriver/chrome/status.h"
13#include "chrome/test/chromedriver/command.h"
14#include "chrome/test/chromedriver/server/http_handler.h"
15#include "net/http/http_status_code.h"
16#include "net/server/http_server_request_info.h"
17#include "net/server/http_server_response_info.h"
18#include "testing/gtest/include/gtest/gtest.h"
19
20namespace {
21
22void DummyCommand(
23    const Status& status,
24    const base::DictionaryValue& params,
25    const std::string& session_id,
26    const CommandCallback& callback) {
27  callback.Run(status,
28               scoped_ptr<base::Value>(new base::FundamentalValue(1)),
29               "session_id");
30}
31
32void OnResponse(net::HttpServerResponseInfo* response_to_set,
33                scoped_ptr<net::HttpServerResponseInfo> response) {
34  *response_to_set = *response;
35}
36
37}  // namespace
38
39TEST(HttpHandlerTest, HandleOutsideOfBaseUrl) {
40  HttpHandler handler("base/url/");
41  net::HttpServerRequestInfo request;
42  request.method = "get";
43  request.path = "base/path";
44  request.data = "body";
45  net::HttpServerResponseInfo response;
46  handler.Handle(request, base::Bind(&OnResponse, &response));
47  ASSERT_EQ(net::HTTP_BAD_REQUEST, response.status_code());
48}
49
50TEST(HttpHandlerTest, HandleUnknownCommand) {
51  HttpHandler handler("/");
52  net::HttpServerRequestInfo request;
53  request.method = "get";
54  request.path = "/path";
55  net::HttpServerResponseInfo response;
56  handler.Handle(request, base::Bind(&OnResponse, &response));
57  ASSERT_EQ(net::HTTP_NOT_FOUND, response.status_code());
58}
59
60TEST(HttpHandlerTest, HandleNewSession) {
61  HttpHandler handler("/base/");
62  handler.command_map_.reset(new HttpHandler::CommandMap());
63  handler.command_map_->push_back(
64      CommandMapping(kPost, internal::kNewSessionPathPattern,
65                     base::Bind(&DummyCommand, Status(kOk))));
66  net::HttpServerRequestInfo request;
67  request.method = "post";
68  request.path = "/base/session";
69  net::HttpServerResponseInfo response;
70  handler.Handle(request, base::Bind(&OnResponse, &response));
71  ASSERT_EQ(net::HTTP_OK, response.status_code());
72  base::DictionaryValue body;
73  body.SetInteger("status", kOk);
74  body.SetInteger("value", 1);
75  body.SetString("sessionId", "session_id");
76  std::string json;
77  base::JSONWriter::Write(&body, &json);
78  ASSERT_EQ(json, response.body());
79}
80
81TEST(HttpHandlerTest, HandleInvalidPost) {
82  HttpHandler handler("/");
83  handler.command_map_->push_back(
84      CommandMapping(kPost, "path", base::Bind(&DummyCommand, Status(kOk))));
85  net::HttpServerRequestInfo request;
86  request.method = "post";
87  request.path = "/path";
88  request.data = "should be a dictionary";
89  net::HttpServerResponseInfo response;
90  handler.Handle(request, base::Bind(&OnResponse, &response));
91  ASSERT_EQ(net::HTTP_BAD_REQUEST, response.status_code());
92}
93
94TEST(HttpHandlerTest, HandleUnimplementedCommand) {
95  HttpHandler handler("/");
96  handler.command_map_->push_back(
97      CommandMapping(kPost, "path",
98                     base::Bind(&DummyCommand, Status(kUnknownCommand))));
99  net::HttpServerRequestInfo request;
100  request.method = "post";
101  request.path = "/path";
102  net::HttpServerResponseInfo response;
103  handler.Handle(request, base::Bind(&OnResponse, &response));
104  ASSERT_EQ(net::HTTP_NOT_IMPLEMENTED, response.status_code());
105}
106
107TEST(HttpHandlerTest, HandleCommand) {
108  HttpHandler handler("/");
109  handler.command_map_->push_back(
110      CommandMapping(kPost, "path", base::Bind(&DummyCommand, Status(kOk))));
111  net::HttpServerRequestInfo request;
112  request.method = "post";
113  request.path = "/path";
114  net::HttpServerResponseInfo response;
115  handler.Handle(request, base::Bind(&OnResponse, &response));
116  ASSERT_EQ(net::HTTP_OK, response.status_code());
117  base::DictionaryValue body;
118  body.SetInteger("status", kOk);
119  body.SetInteger("value", 1);
120  body.SetString("sessionId", "session_id");
121  std::string json;
122  base::JSONWriter::Write(&body, &json);
123  ASSERT_EQ(json, response.body());
124}
125
126TEST(MatchesCommandTest, DiffMethod) {
127  CommandMapping command(kPost, "path", base::Bind(&DummyCommand, Status(kOk)));
128  std::string session_id;
129  base::DictionaryValue params;
130  ASSERT_FALSE(internal::MatchesCommand(
131      "get", "path", command, &session_id, &params));
132  ASSERT_TRUE(session_id.empty());
133  ASSERT_EQ(0u, params.size());
134}
135
136TEST(MatchesCommandTest, DiffPathLength) {
137  CommandMapping command(kPost, "path/path",
138                         base::Bind(&DummyCommand, Status(kOk)));
139  std::string session_id;
140  base::DictionaryValue params;
141  ASSERT_FALSE(internal::MatchesCommand(
142      "post", "path", command, &session_id, &params));
143  ASSERT_FALSE(internal::MatchesCommand(
144      "post", std::string(), command, &session_id, &params));
145  ASSERT_FALSE(
146      internal::MatchesCommand("post", "/", command, &session_id, &params));
147  ASSERT_FALSE(internal::MatchesCommand(
148      "post", "path/path/path", command, &session_id, &params));
149}
150
151TEST(MatchesCommandTest, DiffPaths) {
152  CommandMapping command(kPost, "path/apath",
153                         base::Bind(&DummyCommand, Status(kOk)));
154  std::string session_id;
155  base::DictionaryValue params;
156  ASSERT_FALSE(internal::MatchesCommand(
157      "post", "path/bpath", command, &session_id, &params));
158}
159
160TEST(MatchesCommandTest, Substitution) {
161  CommandMapping command(kPost, "path/:sessionId/space/:a/:b",
162                         base::Bind(&DummyCommand, Status(kOk)));
163  std::string session_id;
164  base::DictionaryValue params;
165  ASSERT_TRUE(internal::MatchesCommand(
166      "post", "path/1/space/2/3", command, &session_id, &params));
167  ASSERT_EQ("1", session_id);
168  ASSERT_EQ(2u, params.size());
169  std::string param;
170  ASSERT_TRUE(params.GetString("a", &param));
171  ASSERT_EQ("2", param);
172  ASSERT_TRUE(params.GetString("b", &param));
173  ASSERT_EQ("3", param);
174}
175