1 // Copyright (c) 2012 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.
9 #include "base/bind_helpers.h"
10 #include "chrome/common/automation_messages.h"
11 #include "chrome_frame/test/chrome_frame_test_utils.h"
12 #include "chrome_frame/test/test_server.h"
13 #include "chrome_frame/test/test_with_web_server.h"
14 #include "chrome_frame/urlmon_url_request.h"
15 #include "chrome_frame/urlmon_url_request_private.h"
16 #include "testing/gmock/include/gmock/gmock.h"
17 #include "testing/gmock_mutant.h"
18 #include "testing/gtest/include/gtest/gtest.h"
20 using testing::CreateFunctor;
22 using chrome_frame_test::kChromeFrameLongNavigationTimeout;
24 static void AppendToStream(IStream* s, void* buffer, ULONG cb) {
26 LARGE_INTEGER current_pos;
27 LARGE_INTEGER zero = {0};
28 // Remember current position.
29 ASSERT_HRESULT_SUCCEEDED(s->Seek(zero, STREAM_SEEK_CUR,
30 reinterpret_cast<ULARGE_INTEGER*>(¤t_pos)));
32 ASSERT_HRESULT_SUCCEEDED(s->Seek(zero, STREAM_SEEK_END, NULL));
33 ASSERT_HRESULT_SUCCEEDED(s->Write(buffer, cb, &bytes_written));
34 ASSERT_EQ(cb, bytes_written);
35 // Seek to original position.
36 ASSERT_HRESULT_SUCCEEDED(s->Seek(current_pos, STREAM_SEEK_SET, NULL));
39 class MockUrlDelegate : public PluginUrlRequestDelegate {
41 MOCK_METHOD9(OnResponseStarted, void(int request_id, const char* mime_type,
42 const char* headers, int size, base::Time last_modified,
43 const std::string& redirect_url, int redirect_status,
44 const net::HostPortPair& socket_address, uint64 upload_size));
45 MOCK_METHOD2(OnReadComplete, void(int request_id, const std::string& data));
46 MOCK_METHOD2(OnResponseEnd, void(int request_id,
47 const net::URLRequestStatus& status));
48 MOCK_METHOD4(OnCookiesRetrieved, void(bool success, const GURL& url,
49 const std::string& cookie, int cookie_id));
51 void PostponeReadRequest(chrome_frame_test::TimedMsgLoop* loop,
52 UrlmonUrlRequest* request, int bytes_to_read) {
53 loop->PostTask(FROM_HERE,
54 base::Bind(&MockUrlDelegate::RequestRead,
55 base::Unretained(this), request, bytes_to_read));
59 void RequestRead(UrlmonUrlRequest* request, int bytes_to_read) {
60 request->Read(bytes_to_read);
64 // Simplest UrlmonUrlRequest. Retrieve a file from local web server.
65 TEST(UrlmonUrlRequestTest, Simple1) {
67 chrome_frame_test::TimedMsgLoop loop;
69 testing::StrictMock<MockWebServer> mock_server(1337,
70 ASCIIToWide(chrome_frame_test::GetLocalIPv4Address()),
71 chrome_frame_test::GetTestDataFolder());
72 mock_server.ExpectAndServeAnyRequests(CFInvocation(CFInvocation::NONE));
74 CComObjectStackEx<UrlmonUrlRequest> request;
77 request.Initialize(&mock, 1, // request_id
78 WideToUTF8(mock_server.Resolve(L"chrome_frame_window_open.html")),
83 ResourceType::MAIN_FRAME, // resource type
87 testing::InSequence s;
88 EXPECT_CALL(mock, OnResponseStarted(1, testing::_, testing::_, testing::_,
89 testing::_, testing::_, testing::_,
90 testing::_, testing::_))
92 .WillOnce(testing::IgnoreResult(testing::InvokeWithoutArgs(CreateFunctor(
93 &request, &UrlmonUrlRequest::Read, 512))));
96 EXPECT_CALL(mock, OnReadComplete(1, testing::Property(&std::string::size,
98 .Times(testing::AtLeast(1))
99 .WillRepeatedly(testing::InvokeWithoutArgs(CreateFunctor(&mock,
100 &MockUrlDelegate::PostponeReadRequest, &loop, &request, 64)));
102 EXPECT_CALL(mock, OnResponseEnd(1, testing::_))
104 .WillOnce(QUIT_LOOP_SOON(loop, base::TimeDelta::FromSeconds(2)));
107 loop.RunFor(kChromeFrameLongNavigationTimeout);
111 // Same as Simple1 except we use the HEAD verb to fetch only the headers
113 TEST(UrlmonUrlRequestTest, Head) {
114 MockUrlDelegate mock;
115 chrome_frame_test::TimedMsgLoop loop;
116 // Use SimpleWebServer instead of the python server to support HEAD
118 test_server::SimpleWebServer server(13337);
119 test_server::SimpleResponse head_response("/head", "");
120 server.AddResponse(&head_response);
122 CComObjectStackEx<UrlmonUrlRequest> request;
125 request.Initialize(&mock, 1, // request_id
126 base::StringPrintf("http://%s:13337/head", server.host().c_str()),
131 ResourceType::MAIN_FRAME, // resource type
135 testing::InSequence s;
136 EXPECT_CALL(mock, OnResponseStarted(1, testing::_, testing::_, testing::_,
137 testing::_, testing::_, testing::_,
138 testing::_, testing::_))
140 .WillOnce(testing::IgnoreResult(testing::InvokeWithoutArgs(CreateFunctor(
141 &request, &UrlmonUrlRequest::Read, 512))));
143 // For HEAD requests we don't expect content reads.
144 EXPECT_CALL(mock, OnReadComplete(1, testing::_)).Times(0);
146 EXPECT_CALL(mock, OnResponseEnd(1, testing::_))
148 .WillOnce(QUIT_LOOP_SOON(loop, base::TimeDelta::FromSeconds(2)));
151 loop.RunFor(kChromeFrameLongNavigationTimeout);
155 TEST(UrlmonUrlRequestTest, UnreachableUrl) {
156 MockUrlDelegate mock;
157 chrome_frame_test::TimedMsgLoop loop;
158 CComObjectStackEx<UrlmonUrlRequest> request;
160 testing::StrictMock<MockWebServer> mock_server(1337,
161 ASCIIToWide(chrome_frame_test::GetLocalIPv4Address()),
162 chrome_frame_test::GetTestDataFolder());
163 mock_server.ExpectAndServeAnyRequests(CFInvocation(CFInvocation::NONE));
165 GURL unreachable(WideToUTF8(mock_server.Resolve(
166 L"non_existing.html")));
169 request.Initialize(&mock, 1, // request_id
170 unreachable.spec(), "get",
174 ResourceType::MAIN_FRAME, // resource type
179 EXPECT_CALL(mock, OnResponseStarted(1, testing::_,
180 testing::StartsWith("HTTP/1.1 404"),
181 testing::_, testing::_, testing::_,
182 testing::_, testing::_, testing::_))
184 .WillOnce(QUIT_LOOP_SOON(loop, base::TimeDelta::FromSeconds(2)));
186 EXPECT_CALL(mock, OnResponseEnd(1, testing::Property(
187 &net::URLRequestStatus::error,
188 net::ERR_TUNNEL_CONNECTION_FAILED)))
189 .Times(testing::AtMost(1));
192 loop.RunFor(kChromeFrameLongNavigationTimeout);
196 TEST(UrlmonUrlRequestTest, ZeroLengthResponse) {
197 MockUrlDelegate mock;
198 chrome_frame_test::TimedMsgLoop loop;
200 testing::StrictMock<MockWebServer> mock_server(1337,
201 ASCIIToWide(chrome_frame_test::GetLocalIPv4Address()),
202 chrome_frame_test::GetTestDataFolder());
203 mock_server.ExpectAndServeAnyRequests(CFInvocation(CFInvocation::NONE));
205 CComObjectStackEx<UrlmonUrlRequest> request;
208 request.Initialize(&mock, 1, // request_id
209 WideToUTF8(mock_server.Resolve(L"empty.html")), "get",
213 ResourceType::MAIN_FRAME, // resource type
218 EXPECT_CALL(mock, OnResponseStarted(1, testing::_, testing::_, testing::_,
219 testing::_, testing::_, testing::_,
220 testing::_, testing::_))
222 .WillOnce(QUIT_LOOP(loop));
225 loop.RunFor(kChromeFrameLongNavigationTimeout);
226 EXPECT_FALSE(loop.WasTimedOut());
228 // Should stay quiet, since we do not ask for anything for awhile.
229 EXPECT_CALL(mock, OnResponseEnd(1, testing::_)).Times(0);
230 loop.RunFor(base::TimeDelta::FromSeconds(3));
232 // Invoke read. Only now the response end ("server closed the connection")
233 // is supposed to be delivered.
234 EXPECT_CALL(mock, OnResponseEnd(1, testing::Property(
235 &net::URLRequestStatus::is_success, true))).Times(1);
240 ACTION_P4(ManagerRead, loop, mgr, request_id, bytes_to_read) {
241 loop->PostTask(FROM_HERE,
242 base::Bind(&UrlmonUrlRequestManager::ReadUrlRequest,
243 base::Unretained(mgr), request_id, bytes_to_read));
245 ACTION_P3(ManagerEndRequest, loop, mgr, request_id) {
246 loop->PostTask(FROM_HERE, base::Bind(&UrlmonUrlRequestManager::EndUrlRequest,
247 base::Unretained(mgr), request_id,
248 net::URLRequestStatus()));
251 // Simplest test - retrieve file from local web server.
252 TEST(UrlmonUrlRequestManagerTest, Simple1) {
253 MockUrlDelegate mock;
254 chrome_frame_test::TimedMsgLoop loop;
256 testing::StrictMock<MockWebServer> mock_server(1337,
257 ASCIIToWide(chrome_frame_test::GetLocalIPv4Address()),
258 chrome_frame_test::GetTestDataFolder());
259 mock_server.ExpectAndServeAnyRequests(CFInvocation(CFInvocation::NONE));
261 scoped_ptr<UrlmonUrlRequestManager> mgr(new UrlmonUrlRequestManager());
262 mgr->set_delegate(&mock);
263 AutomationURLRequest r1;
264 r1.url = WideToUTF8(mock_server.Resolve(L"chrome_frame_window_open.html"));
266 r1.resource_type = 0;
269 EXPECT_CALL(mock, OnResponseStarted(1, testing::_, testing::_, testing::_,
270 testing::_, testing::_, testing::_, testing::_,
273 .WillOnce(ManagerRead(&loop, mgr.get(), 1, 512));
275 EXPECT_CALL(mock, OnReadComplete(1, testing::Property(&std::string::size,
277 .Times(testing::AtLeast(1))
278 .WillRepeatedly(ManagerRead(&loop, mgr.get(), 1, 2));
280 EXPECT_CALL(mock, OnResponseEnd(1, testing::_))
282 .WillOnce(QUIT_LOOP_SOON(loop, base::TimeDelta::FromSeconds(2)));
284 mgr->StartUrlRequest(1, r1);
285 loop.RunFor(kChromeFrameLongNavigationTimeout);
289 TEST(UrlmonUrlRequestManagerTest, Abort1) {
290 MockUrlDelegate mock;
291 chrome_frame_test::TimedMsgLoop loop;
293 testing::StrictMock<MockWebServer> mock_server(1337,
294 ASCIIToWide(chrome_frame_test::GetLocalIPv4Address()),
295 chrome_frame_test::GetTestDataFolder());
296 mock_server.ExpectAndServeAnyRequests(CFInvocation(CFInvocation::NONE));
298 scoped_ptr<UrlmonUrlRequestManager> mgr(new UrlmonUrlRequestManager());
299 mgr->set_delegate(&mock);
300 AutomationURLRequest r1;
301 r1.url = WideToUTF8(mock_server.Resolve(L"chrome_frame_window_open.html"));
303 r1.resource_type = 0;
306 EXPECT_CALL(mock, OnResponseStarted(1, testing::_, testing::_, testing::_,
307 testing::_, testing::_, testing::_, testing::_,
310 .WillOnce(testing::DoAll(
311 ManagerEndRequest(&loop, mgr.get(), 1),
312 QUIT_LOOP_SOON(loop, base::TimeDelta::FromSeconds(3))));
314 EXPECT_CALL(mock, OnReadComplete(1, testing::_))
317 EXPECT_CALL(mock, OnResponseEnd(1, testing::_))
320 mgr->StartUrlRequest(1, r1);
321 loop.RunFor(kChromeFrameLongNavigationTimeout);