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 
     49   void PostponeReadRequest(chrome_frame_test::TimedMsgLoop* loop,
     50                    UrlmonUrlRequest* request, int bytes_to_read) {
     51     loop->PostTask(FROM_HERE,
     52                    base::Bind(&MockUrlDelegate::RequestRead,
     53                               base::Unretained(this), request, bytes_to_read));
     54   }
     55 
     56  private:
     57   void RequestRead(UrlmonUrlRequest* request, int bytes_to_read) {
     58     request->Read(bytes_to_read);
     59   }
     60 };
     61 
     62 // Simplest UrlmonUrlRequest. Retrieve a file from local web server.
     63 TEST(UrlmonUrlRequestTest, Simple1) {
     64   MockUrlDelegate mock;
     65   chrome_frame_test::TimedMsgLoop loop;
     66 
     67   testing::StrictMock<MockWebServer> mock_server(1337,
     68       ASCIIToWide(chrome_frame_test::GetLocalIPv4Address()),
     69       chrome_frame_test::GetTestDataFolder());
     70   mock_server.ExpectAndServeAnyRequests(CFInvocation(CFInvocation::NONE));
     71 
     72   CComObjectStackEx<UrlmonUrlRequest> request;
     73 
     74   request.AddRef();
     75   request.Initialize(&mock, 1,  // request_id
     76       WideToUTF8(mock_server.Resolve(L"chrome_frame_window_open.html")),
     77       "get",
     78       "",      // referrer
     79       "",      // extra request
     80       NULL,    // upload data
     81       ResourceType::MAIN_FRAME,  // resource type
     82       true,
     83       0);   // frame busting
     84 
     85   testing::InSequence s;
     86   EXPECT_CALL(mock, OnResponseStarted(1, testing::_, testing::_, testing::_,
     87                                       testing::_, testing::_, testing::_,
     88                                       testing::_, testing::_))
     89     .Times(1)
     90     .WillOnce(testing::IgnoreResult(testing::InvokeWithoutArgs(CreateFunctor(
     91         &request, &UrlmonUrlRequest::Read, 512))));
     92 
     93 
     94   EXPECT_CALL(mock, OnReadComplete(1, testing::Property(&std::string::size,
     95                                                         testing::Gt(0u))))
     96     .Times(testing::AtLeast(1))
     97     .WillRepeatedly(testing::InvokeWithoutArgs(CreateFunctor(&mock,
     98         &MockUrlDelegate::PostponeReadRequest, &loop, &request, 64)));
     99 
    100   EXPECT_CALL(mock, OnResponseEnd(1, testing::_))
    101     .Times(1)
    102     .WillOnce(QUIT_LOOP_SOON(loop, base::TimeDelta::FromSeconds(2)));
    103 
    104   request.Start();
    105   loop.RunFor(kChromeFrameLongNavigationTimeout);
    106   request.Release();
    107 }
    108 
    109 // Same as Simple1 except we use the HEAD verb to fetch only the headers
    110 // from the server.
    111 TEST(UrlmonUrlRequestTest, Head) {
    112   MockUrlDelegate mock;
    113   chrome_frame_test::TimedMsgLoop loop;
    114   // Use SimpleWebServer instead of the python server to support HEAD
    115   // requests.
    116   test_server::SimpleWebServer server(13337);
    117   test_server::SimpleResponse head_response("/head", "");
    118   server.AddResponse(&head_response);
    119 
    120   CComObjectStackEx<UrlmonUrlRequest> request;
    121 
    122   request.AddRef();
    123   request.Initialize(&mock, 1,  // request_id
    124       base::StringPrintf("http://%s:13337/head", server.host().c_str()),
    125       "head",
    126       "",      // referrer
    127       "",      // extra request
    128       NULL,    // upload data
    129       ResourceType::MAIN_FRAME,  // resource type
    130       true,
    131       0);   // frame busting
    132 
    133   testing::InSequence s;
    134   EXPECT_CALL(mock, OnResponseStarted(1, testing::_, testing::_, testing::_,
    135                                       testing::_, testing::_, testing::_,
    136                                       testing::_, testing::_))
    137     .Times(1)
    138     .WillOnce(testing::IgnoreResult(testing::InvokeWithoutArgs(CreateFunctor(
    139         &request, &UrlmonUrlRequest::Read, 512))));
    140 
    141   // For HEAD requests we don't expect content reads.
    142   EXPECT_CALL(mock, OnReadComplete(1, testing::_)).Times(0);
    143 
    144   EXPECT_CALL(mock, OnResponseEnd(1, testing::_))
    145     .Times(1)
    146     .WillOnce(QUIT_LOOP_SOON(loop, base::TimeDelta::FromSeconds(2)));
    147 
    148   request.Start();
    149   loop.RunFor(kChromeFrameLongNavigationTimeout);
    150   request.Release();
    151 }
    152 
    153 TEST(UrlmonUrlRequestTest, UnreachableUrl) {
    154   MockUrlDelegate mock;
    155   chrome_frame_test::TimedMsgLoop loop;
    156   CComObjectStackEx<UrlmonUrlRequest> request;
    157 
    158   testing::StrictMock<MockWebServer> mock_server(1337,
    159       ASCIIToWide(chrome_frame_test::GetLocalIPv4Address()),
    160       chrome_frame_test::GetTestDataFolder());
    161   mock_server.ExpectAndServeAnyRequests(CFInvocation(CFInvocation::NONE));
    162 
    163   GURL unreachable(WideToUTF8(mock_server.Resolve(
    164       L"non_existing.html")));
    165 
    166   request.AddRef();
    167   request.Initialize(&mock, 1,  // request_id
    168       unreachable.spec(), "get",
    169       "",      // referrer
    170       "",      // extra request
    171       NULL,    // upload data
    172       ResourceType::MAIN_FRAME,  // resource type
    173       true,
    174       0);   // frame busting
    175 
    176   // Expect headers
    177   EXPECT_CALL(mock, OnResponseStarted(1, testing::_,
    178                                       testing::StartsWith("HTTP/1.1 404"),
    179                                       testing::_, testing::_, testing::_,
    180                                       testing::_, testing::_, testing::_))
    181     .Times(1)
    182     .WillOnce(QUIT_LOOP_SOON(loop, base::TimeDelta::FromSeconds(2)));
    183 
    184   EXPECT_CALL(mock, OnResponseEnd(1, testing::Property(
    185               &net::URLRequestStatus::error,
    186               net::ERR_TUNNEL_CONNECTION_FAILED)))
    187     .Times(testing::AtMost(1));
    188 
    189   request.Start();
    190   loop.RunFor(kChromeFrameLongNavigationTimeout);
    191   request.Release();
    192 }
    193 
    194 TEST(UrlmonUrlRequestTest, ZeroLengthResponse) {
    195   MockUrlDelegate mock;
    196   chrome_frame_test::TimedMsgLoop loop;
    197 
    198   testing::StrictMock<MockWebServer> mock_server(1337,
    199       ASCIIToWide(chrome_frame_test::GetLocalIPv4Address()),
    200       chrome_frame_test::GetTestDataFolder());
    201   mock_server.ExpectAndServeAnyRequests(CFInvocation(CFInvocation::NONE));
    202 
    203   CComObjectStackEx<UrlmonUrlRequest> request;
    204 
    205   request.AddRef();
    206   request.Initialize(&mock, 1,  // request_id
    207       WideToUTF8(mock_server.Resolve(L"empty.html")), "get",
    208       "",      // referrer
    209       "",      // extra request
    210       NULL,    // upload data
    211       ResourceType::MAIN_FRAME,  // resource type
    212       true,
    213       0);   // frame busting
    214 
    215   // Expect headers
    216   EXPECT_CALL(mock, OnResponseStarted(1, testing::_, testing::_, testing::_,
    217                                       testing::_, testing::_, testing::_,
    218                                       testing::_, testing::_))
    219     .Times(1)
    220     .WillOnce(QUIT_LOOP(loop));
    221 
    222   request.Start();
    223   loop.RunFor(kChromeFrameLongNavigationTimeout);
    224   EXPECT_FALSE(loop.WasTimedOut());
    225 
    226   // Should stay quiet, since we do not ask for anything for awhile.
    227   EXPECT_CALL(mock, OnResponseEnd(1, testing::_)).Times(0);
    228   loop.RunFor(base::TimeDelta::FromSeconds(3));
    229 
    230   // Invoke read. Only now the response end ("server closed the connection")
    231   // is supposed to be delivered.
    232   EXPECT_CALL(mock, OnResponseEnd(1, testing::Property(
    233       &net::URLRequestStatus::is_success, true))).Times(1);
    234   request.Read(512);
    235   request.Release();
    236 }
    237 
    238 ACTION_P4(ManagerRead, loop, mgr, request_id, bytes_to_read) {
    239   loop->PostTask(FROM_HERE,
    240                  base::Bind(&UrlmonUrlRequestManager::ReadUrlRequest,
    241                             base::Unretained(mgr), request_id, bytes_to_read));
    242 }
    243 ACTION_P3(ManagerEndRequest, loop, mgr, request_id) {
    244   loop->PostTask(FROM_HERE, base::Bind(&UrlmonUrlRequestManager::EndUrlRequest,
    245                                        base::Unretained(mgr), request_id,
    246                                        net::URLRequestStatus()));
    247 }
    248 
    249 // Simplest test - retrieve file from local web server.
    250 TEST(UrlmonUrlRequestManagerTest, Simple1) {
    251   MockUrlDelegate mock;
    252   chrome_frame_test::TimedMsgLoop loop;
    253 
    254   testing::StrictMock<MockWebServer> mock_server(1337,
    255       ASCIIToWide(chrome_frame_test::GetLocalIPv4Address()),
    256       chrome_frame_test::GetTestDataFolder());
    257   mock_server.ExpectAndServeAnyRequests(CFInvocation(CFInvocation::NONE));
    258 
    259   scoped_ptr<UrlmonUrlRequestManager> mgr(new UrlmonUrlRequestManager());
    260   mgr->set_delegate(&mock);
    261   AutomationURLRequest r1;
    262   r1.url =  WideToUTF8(mock_server.Resolve(L"chrome_frame_window_open.html"));
    263   r1.method = "get";
    264   r1.resource_type = 0;
    265   r1.load_flags = 0;
    266 
    267   EXPECT_CALL(mock, OnResponseStarted(1, testing::_, testing::_, testing::_,
    268                              testing::_, testing::_, testing::_, testing::_,
    269                              testing::_))
    270       .Times(1)
    271       .WillOnce(ManagerRead(&loop, mgr.get(), 1, 512));
    272 
    273   EXPECT_CALL(mock, OnReadComplete(1, testing::Property(&std::string::size,
    274                                                         testing::Gt(0u))))
    275     .Times(testing::AtLeast(1))
    276     .WillRepeatedly(ManagerRead(&loop, mgr.get(), 1, 2));
    277 
    278   EXPECT_CALL(mock, OnResponseEnd(1, testing::_))
    279     .Times(1)
    280     .WillOnce(QUIT_LOOP_SOON(loop, base::TimeDelta::FromSeconds(2)));
    281 
    282   mgr->StartUrlRequest(1, r1);
    283   loop.RunFor(kChromeFrameLongNavigationTimeout);
    284   mgr.reset();
    285 }
    286 
    287 TEST(UrlmonUrlRequestManagerTest, Abort1) {
    288   MockUrlDelegate mock;
    289   chrome_frame_test::TimedMsgLoop loop;
    290 
    291   testing::StrictMock<MockWebServer> mock_server(1337,
    292       ASCIIToWide(chrome_frame_test::GetLocalIPv4Address()),
    293       chrome_frame_test::GetTestDataFolder());
    294   mock_server.ExpectAndServeAnyRequests(CFInvocation(CFInvocation::NONE));
    295 
    296   scoped_ptr<UrlmonUrlRequestManager> mgr(new UrlmonUrlRequestManager());
    297   mgr->set_delegate(&mock);
    298   AutomationURLRequest r1;
    299   r1.url = WideToUTF8(mock_server.Resolve(L"chrome_frame_window_open.html"));
    300   r1.method = "get";
    301   r1.resource_type = 0;
    302   r1.load_flags = 0;
    303 
    304   EXPECT_CALL(mock, OnResponseStarted(1, testing::_, testing::_, testing::_,
    305                                testing::_, testing::_, testing::_, testing::_,
    306                                testing::_))
    307     .Times(1)
    308     .WillOnce(testing::DoAll(
    309         ManagerEndRequest(&loop, mgr.get(), 1),
    310         QUIT_LOOP_SOON(loop, base::TimeDelta::FromSeconds(3))));
    311 
    312   EXPECT_CALL(mock, OnReadComplete(1, testing::_))
    313     .Times(0);
    314 
    315   EXPECT_CALL(mock, OnResponseEnd(1, testing::_))
    316     .Times(0);
    317 
    318   mgr->StartUrlRequest(1, r1);
    319   loop.RunFor(kChromeFrameLongNavigationTimeout);
    320   mgr.reset();
    321 }
    322