- add sources.
[platform/framework/web/crosswalk.git] / src / chrome_frame / test / url_request_test.cc
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.
4
5 #include <atlbase.h>
6 #include <atlcom.h>
7
8 #include "base/bind.h"
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"
19
20 using testing::CreateFunctor;
21
22 using chrome_frame_test::kChromeFrameLongNavigationTimeout;
23
24 static void AppendToStream(IStream* s, void* buffer, ULONG cb) {
25   ULONG bytes_written;
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*>(&current_pos)));
31   // Seek to the end.
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));
37 }
38
39 class MockUrlDelegate : public PluginUrlRequestDelegate {
40  public:
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));
50
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));
56   }
57
58  private:
59   void RequestRead(UrlmonUrlRequest* request, int bytes_to_read) {
60     request->Read(bytes_to_read);
61   }
62 };
63
64 // Simplest UrlmonUrlRequest. Retrieve a file from local web server.
65 TEST(UrlmonUrlRequestTest, Simple1) {
66   MockUrlDelegate mock;
67   chrome_frame_test::TimedMsgLoop loop;
68
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));
73
74   CComObjectStackEx<UrlmonUrlRequest> request;
75
76   request.AddRef();
77   request.Initialize(&mock, 1,  // request_id
78       WideToUTF8(mock_server.Resolve(L"chrome_frame_window_open.html")),
79       "get",
80       "",      // referrer
81       "",      // extra request
82       NULL,    // upload data
83       ResourceType::MAIN_FRAME,  // resource type
84       true,
85       0);   // frame busting
86
87   testing::InSequence s;
88   EXPECT_CALL(mock, OnResponseStarted(1, testing::_, testing::_, testing::_,
89                                       testing::_, testing::_, testing::_,
90                                       testing::_, testing::_))
91     .Times(1)
92     .WillOnce(testing::IgnoreResult(testing::InvokeWithoutArgs(CreateFunctor(
93         &request, &UrlmonUrlRequest::Read, 512))));
94
95
96   EXPECT_CALL(mock, OnReadComplete(1, testing::Property(&std::string::size,
97                                                         testing::Gt(0u))))
98     .Times(testing::AtLeast(1))
99     .WillRepeatedly(testing::InvokeWithoutArgs(CreateFunctor(&mock,
100         &MockUrlDelegate::PostponeReadRequest, &loop, &request, 64)));
101
102   EXPECT_CALL(mock, OnResponseEnd(1, testing::_))
103     .Times(1)
104     .WillOnce(QUIT_LOOP_SOON(loop, base::TimeDelta::FromSeconds(2)));
105
106   request.Start();
107   loop.RunFor(kChromeFrameLongNavigationTimeout);
108   request.Release();
109 }
110
111 // Same as Simple1 except we use the HEAD verb to fetch only the headers
112 // from the server.
113 TEST(UrlmonUrlRequestTest, Head) {
114   MockUrlDelegate mock;
115   chrome_frame_test::TimedMsgLoop loop;
116   // Use SimpleWebServer instead of the python server to support HEAD
117   // requests.
118   test_server::SimpleWebServer server(13337);
119   test_server::SimpleResponse head_response("/head", "");
120   server.AddResponse(&head_response);
121
122   CComObjectStackEx<UrlmonUrlRequest> request;
123
124   request.AddRef();
125   request.Initialize(&mock, 1,  // request_id
126       base::StringPrintf("http://%s:13337/head", server.host().c_str()),
127       "head",
128       "",      // referrer
129       "",      // extra request
130       NULL,    // upload data
131       ResourceType::MAIN_FRAME,  // resource type
132       true,
133       0);   // frame busting
134
135   testing::InSequence s;
136   EXPECT_CALL(mock, OnResponseStarted(1, testing::_, testing::_, testing::_,
137                                       testing::_, testing::_, testing::_,
138                                       testing::_, testing::_))
139     .Times(1)
140     .WillOnce(testing::IgnoreResult(testing::InvokeWithoutArgs(CreateFunctor(
141         &request, &UrlmonUrlRequest::Read, 512))));
142
143   // For HEAD requests we don't expect content reads.
144   EXPECT_CALL(mock, OnReadComplete(1, testing::_)).Times(0);
145
146   EXPECT_CALL(mock, OnResponseEnd(1, testing::_))
147     .Times(1)
148     .WillOnce(QUIT_LOOP_SOON(loop, base::TimeDelta::FromSeconds(2)));
149
150   request.Start();
151   loop.RunFor(kChromeFrameLongNavigationTimeout);
152   request.Release();
153 }
154
155 TEST(UrlmonUrlRequestTest, UnreachableUrl) {
156   MockUrlDelegate mock;
157   chrome_frame_test::TimedMsgLoop loop;
158   CComObjectStackEx<UrlmonUrlRequest> request;
159
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));
164
165   GURL unreachable(WideToUTF8(mock_server.Resolve(
166       L"non_existing.html")));
167
168   request.AddRef();
169   request.Initialize(&mock, 1,  // request_id
170       unreachable.spec(), "get",
171       "",      // referrer
172       "",      // extra request
173       NULL,    // upload data
174       ResourceType::MAIN_FRAME,  // resource type
175       true,
176       0);   // frame busting
177
178   // Expect headers
179   EXPECT_CALL(mock, OnResponseStarted(1, testing::_,
180                                       testing::StartsWith("HTTP/1.1 404"),
181                                       testing::_, testing::_, testing::_,
182                                       testing::_, testing::_, testing::_))
183     .Times(1)
184     .WillOnce(QUIT_LOOP_SOON(loop, base::TimeDelta::FromSeconds(2)));
185
186   EXPECT_CALL(mock, OnResponseEnd(1, testing::Property(
187               &net::URLRequestStatus::error,
188               net::ERR_TUNNEL_CONNECTION_FAILED)))
189     .Times(testing::AtMost(1));
190
191   request.Start();
192   loop.RunFor(kChromeFrameLongNavigationTimeout);
193   request.Release();
194 }
195
196 TEST(UrlmonUrlRequestTest, ZeroLengthResponse) {
197   MockUrlDelegate mock;
198   chrome_frame_test::TimedMsgLoop loop;
199
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));
204
205   CComObjectStackEx<UrlmonUrlRequest> request;
206
207   request.AddRef();
208   request.Initialize(&mock, 1,  // request_id
209       WideToUTF8(mock_server.Resolve(L"empty.html")), "get",
210       "",      // referrer
211       "",      // extra request
212       NULL,    // upload data
213       ResourceType::MAIN_FRAME,  // resource type
214       true,
215       0);   // frame busting
216
217   // Expect headers
218   EXPECT_CALL(mock, OnResponseStarted(1, testing::_, testing::_, testing::_,
219                                       testing::_, testing::_, testing::_,
220                                       testing::_, testing::_))
221     .Times(1)
222     .WillOnce(QUIT_LOOP(loop));
223
224   request.Start();
225   loop.RunFor(kChromeFrameLongNavigationTimeout);
226   EXPECT_FALSE(loop.WasTimedOut());
227
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));
231
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);
236   request.Read(512);
237   request.Release();
238 }
239
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));
244 }
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()));
249 }
250
251 // Simplest test - retrieve file from local web server.
252 TEST(UrlmonUrlRequestManagerTest, Simple1) {
253   MockUrlDelegate mock;
254   chrome_frame_test::TimedMsgLoop loop;
255
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));
260
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"));
265   r1.method = "get";
266   r1.resource_type = 0;
267   r1.load_flags = 0;
268
269   EXPECT_CALL(mock, OnResponseStarted(1, testing::_, testing::_, testing::_,
270                              testing::_, testing::_, testing::_, testing::_,
271                              testing::_))
272       .Times(1)
273       .WillOnce(ManagerRead(&loop, mgr.get(), 1, 512));
274
275   EXPECT_CALL(mock, OnReadComplete(1, testing::Property(&std::string::size,
276                                                         testing::Gt(0u))))
277     .Times(testing::AtLeast(1))
278     .WillRepeatedly(ManagerRead(&loop, mgr.get(), 1, 2));
279
280   EXPECT_CALL(mock, OnResponseEnd(1, testing::_))
281     .Times(1)
282     .WillOnce(QUIT_LOOP_SOON(loop, base::TimeDelta::FromSeconds(2)));
283
284   mgr->StartUrlRequest(1, r1);
285   loop.RunFor(kChromeFrameLongNavigationTimeout);
286   mgr.reset();
287 }
288
289 TEST(UrlmonUrlRequestManagerTest, Abort1) {
290   MockUrlDelegate mock;
291   chrome_frame_test::TimedMsgLoop loop;
292
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));
297
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"));
302   r1.method = "get";
303   r1.resource_type = 0;
304   r1.load_flags = 0;
305
306   EXPECT_CALL(mock, OnResponseStarted(1, testing::_, testing::_, testing::_,
307                                testing::_, testing::_, testing::_, testing::_,
308                                testing::_))
309     .Times(1)
310     .WillOnce(testing::DoAll(
311         ManagerEndRequest(&loop, mgr.get(), 1),
312         QUIT_LOOP_SOON(loop, base::TimeDelta::FromSeconds(3))));
313
314   EXPECT_CALL(mock, OnReadComplete(1, testing::_))
315     .Times(0);
316
317   EXPECT_CALL(mock, OnResponseEnd(1, testing::_))
318     .Times(0);
319
320   mgr->StartUrlRequest(1, r1);
321   loop.RunFor(kChromeFrameLongNavigationTimeout);
322   mgr.reset();
323 }