Home | History | Annotate | Download | only in test
      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 }
    324