devtools_network_controller_unittest.cc revision 46d4c2bc3267f3f028f39e7e311b0f89aba2e4fd
1// Copyright 2014 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/memory/ref_counted.h"
8#include "base/memory/scoped_ptr.h"
9#include "base/message_loop/message_loop.h"
10#include "base/run_loop.h"
11#include "chrome/browser/devtools/devtools_network_conditions.h"
12#include "chrome/browser/devtools/devtools_network_controller.h"
13#include "chrome/browser/devtools/devtools_network_transaction.h"
14#include "net/http/http_transaction_test_util.h"
15#include "testing/gtest/include/gtest/gtest.h"
16#include "url/gurl.h"
17
18namespace test {
19
20const char kClientId[] = "42";
21const char kAnotherClientId[] = "24";
22
23const char kHttpDotCom[] = "http://dot.com";
24const char kHttpDotOrg[] = "http://dot.org";
25const char kCom[] = "com";
26
27class TestCallback {
28 public:
29  TestCallback() : run_count_(0), value_(0) {}
30  void Run(int value) {
31    run_count_++;
32    value_ = value;
33  }
34  int run_count() { return run_count_; }
35  int value() { return value_; }
36
37 private:
38  int run_count_;
39  int value_;
40};
41
42class DevToolsNetworkControllerHelper {
43 public:
44  DevToolsNetworkControllerHelper() :
45      completion_callback_(
46          base::Bind(&TestCallback::Run, base::Unretained(&callback_))),
47      mock_transaction_(kSimpleGET_Transaction),
48      buffer_(new net::IOBuffer(64)) {
49    mock_transaction_.test_mode = TEST_MODE_SYNC_NET_START;
50    mock_transaction_.url = kHttpDotCom;
51    AddMockTransaction(&mock_transaction_);
52
53    scoped_ptr<net::HttpTransaction> network_transaction;
54    network_layer_.CreateTransaction(
55        net::DEFAULT_PRIORITY, &network_transaction);
56    transaction_.reset(new DevToolsNetworkTransaction(
57        &controller_, network_transaction.Pass()));
58  }
59
60  net::HttpRequestInfo* GetRequest() {
61    if (!request_)
62      request_.reset(new MockHttpRequest(mock_transaction_));
63    return request_.get();
64  }
65
66  void SetNetworkState(const std::string& client_id, bool offline) {
67    std::vector<std::string> domains;
68    domains.push_back(kCom);
69    scoped_refptr<DevToolsNetworkConditions> conditions;
70    if (offline)
71      conditions = new DevToolsNetworkConditions(domains);
72    controller_.SetNetworkStateOnIO(client_id, conditions);
73  }
74
75  int Start() {
76    return transaction_->Start(
77        GetRequest(), completion_callback_, net::BoundNetLog());
78  }
79
80  int Read() {
81    return transaction_->Read(buffer_.get(), 64, completion_callback_);
82  }
83
84  ~DevToolsNetworkControllerHelper() {
85    RemoveMockTransaction(&mock_transaction_);
86  }
87
88  TestCallback* callback() { return &callback_; }
89  MockTransaction* mock_transaction() { return &mock_transaction_; }
90  DevToolsNetworkController* controller() { return &controller_; }
91  DevToolsNetworkTransaction* transaction() { return transaction_.get(); }
92
93 private:
94  base::MessageLoop message_loop_;
95  MockNetworkLayer network_layer_;
96  TestCallback callback_;
97  net::CompletionCallback completion_callback_;
98  MockTransaction mock_transaction_;
99  DevToolsNetworkController controller_;
100  scoped_ptr<DevToolsNetworkTransaction> transaction_;
101  scoped_refptr<net::IOBuffer> buffer_;
102  scoped_ptr<MockHttpRequest> request_;
103};
104
105TEST(DevToolsNetworkControllerTest, SingleDisableEnable) {
106  DevToolsNetworkControllerHelper helper;
107  DevToolsNetworkController* controller = helper.controller();
108  net::HttpRequestInfo* request = helper.GetRequest();
109
110  EXPECT_FALSE(controller->ShouldFail(request));
111  helper.SetNetworkState(kClientId, true);
112  EXPECT_TRUE(controller->ShouldFail(request));
113  helper.SetNetworkState(kClientId, false);
114  EXPECT_FALSE(controller->ShouldFail(request));
115}
116
117TEST(DevToolsNetworkControllerTest, DoubleDisableEnable) {
118  DevToolsNetworkControllerHelper helper;
119  DevToolsNetworkController* controller = helper.controller();
120  net::HttpRequestInfo* request = helper.GetRequest();
121
122  EXPECT_FALSE(controller->ShouldFail(request));
123  helper.SetNetworkState(kClientId, true);
124  EXPECT_TRUE(controller->ShouldFail(request));
125  helper.SetNetworkState(kAnotherClientId, true);
126  EXPECT_TRUE(controller->ShouldFail(request));
127  helper.SetNetworkState(kClientId, false);
128  EXPECT_TRUE(controller->ShouldFail(request));
129  helper.SetNetworkState(kAnotherClientId, false);
130  EXPECT_FALSE(controller->ShouldFail(request));
131}
132
133TEST(DevToolsNetworkControllerTest, FailOnStart) {
134  DevToolsNetworkControllerHelper helper;
135  helper.SetNetworkState(kClientId, true);
136
137  int rv = helper.Start();
138  EXPECT_EQ(rv, net::ERR_INTERNET_DISCONNECTED);
139
140  base::RunLoop().RunUntilIdle();
141  EXPECT_EQ(helper.callback()->run_count(), 0);
142}
143
144TEST(DevToolsNetworkControllerTest, FailRunningTransaction) {
145  DevToolsNetworkControllerHelper helper;
146  TestCallback* callback = helper.callback();
147
148  int rv = helper.Start();
149  EXPECT_EQ(rv, net::OK);
150
151  scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(64));
152  rv = helper.Read();
153  EXPECT_EQ(rv, net::ERR_IO_PENDING);
154  EXPECT_EQ(callback->run_count(), 0);
155
156  helper.SetNetworkState(kClientId, true);
157  EXPECT_EQ(callback->run_count(), 1);
158  EXPECT_EQ(callback->value(), net::ERR_INTERNET_DISCONNECTED);
159
160  // Wait until HttpTrancation completes reading and invokes callback.
161  // DevToolsNetworkTransaction should ignore callback, because it has
162  // reported network error already.
163  base::RunLoop().RunUntilIdle();
164  EXPECT_EQ(callback->run_count(), 1);
165
166  // Check that transaction in not failed second time.
167  helper.SetNetworkState(kClientId, false);
168  helper.SetNetworkState(kClientId, true);
169  EXPECT_EQ(callback->run_count(), 1);
170}
171
172TEST(DevToolsNetworkControllerTest, ReadAfterFail) {
173  DevToolsNetworkControllerHelper helper;
174
175  int rv = helper.Start();
176  EXPECT_EQ(rv, net::OK);
177  EXPECT_TRUE(helper.transaction()->request());
178
179  helper.SetNetworkState(kClientId, true);
180  EXPECT_TRUE(helper.transaction()->failed());
181
182  scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(64));
183  rv = helper.Read();
184  EXPECT_EQ(rv, net::ERR_INTERNET_DISCONNECTED);
185
186  // Check that callback is never invoked.
187  base::RunLoop().RunUntilIdle();
188  EXPECT_EQ(helper.callback()->run_count(), 0);
189}
190
191TEST(DevToolsNetworkControllerTest, AllowsDevToolsRequests) {
192  DevToolsNetworkControllerHelper helper;
193  helper.mock_transaction()->request_headers =
194      "X-DevTools-Request-Initiator: frontend\r\n";
195  DevToolsNetworkController* controller = helper.controller();
196  net::HttpRequestInfo* request = helper.GetRequest();
197
198  EXPECT_FALSE(controller->ShouldFail(request));
199  helper.SetNetworkState(kClientId, true);
200  EXPECT_FALSE(controller->ShouldFail(request));
201}
202
203TEST(DevToolsNetworkControllerTest, AllowsNotMatchingRequests) {
204  DevToolsNetworkControllerHelper helper;
205  helper.mock_transaction()->url = kHttpDotOrg;
206  DevToolsNetworkController* controller = helper.controller();
207  net::HttpRequestInfo* request = helper.GetRequest();
208
209  EXPECT_FALSE(controller->ShouldFail(request));
210  helper.SetNetworkState(kClientId, true);
211  EXPECT_FALSE(controller->ShouldFail(request));
212}
213
214}  // namespace test
215