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 <windows.h>
      6 #include <wininet.h>
      7 
      8 #include "base/basictypes.h"
      9 #include "base/bind.h"
     10 #include "base/path_service.h"
     11 #include "base/strings/stringprintf.h"
     12 #include "base/win/scoped_handle.h"
     13 #include "chrome_frame/test/test_server.h"
     14 #include "net/base/request_priority.h"
     15 #include "net/cookies/cookie_monster.h"
     16 #include "net/disk_cache/disk_cache.h"
     17 #include "net/dns/host_resolver_proc.h"
     18 #include "net/http/http_auth_handler_factory.h"
     19 #include "net/http/http_cache.h"
     20 #include "net/http/http_network_session.h"
     21 #include "net/proxy/proxy_service.h"
     22 #include "net/url_request/url_request.h"
     23 #include "net/url_request/url_request_test_util.h"
     24 #include "testing/gtest/include/gtest/gtest.h"
     25 
     26 class TestServerTest: public testing::Test {
     27  protected:
     28   virtual void SetUp() {
     29     PathService::Get(base::DIR_SOURCE_ROOT, &source_path_);
     30     source_path_ = source_path_.Append(FILE_PATH_LITERAL("chrome_frame"));
     31   }
     32   virtual void TearDown() {
     33   }
     34 
     35  public:
     36   const base::FilePath& source_path() const {
     37     return source_path_;
     38   }
     39 
     40  protected:
     41   base::FilePath source_path_;
     42 };
     43 
     44 namespace {
     45 
     46 class ScopedInternet {
     47  public:
     48   explicit ScopedInternet(HINTERNET handle)
     49       : h_(handle) {
     50   }
     51   ~ScopedInternet() {
     52     if (h_) {
     53       InternetCloseHandle(h_);
     54     }
     55   }
     56 
     57   operator HINTERNET() {
     58     return h_;
     59   }
     60 
     61  protected:
     62   HINTERNET h_;
     63 };
     64 
     65 class TestURLRequest : public net::URLRequest {
     66  public:
     67   TestURLRequest(const GURL& url,
     68                  net::RequestPriority priority,
     69                  Delegate* delegate,
     70                  const net::TestURLRequestContext* context)
     71       : net::URLRequest(url, priority, delegate, context) {}
     72 };
     73 
     74 class UrlTaskChain {
     75  public:
     76   UrlTaskChain(const std::string& url, UrlTaskChain* next)
     77       : url_(url), next_(next) {
     78   }
     79 
     80   void Run() {
     81     EXPECT_EQ(0, delegate_.response_started_count());
     82 
     83     base::MessageLoopForIO loop;
     84 
     85     net::TestURLRequestContext context;
     86     TestURLRequest r(GURL(url_), net::DEFAULT_PRIORITY, &delegate_, &context);
     87     r.Start();
     88     EXPECT_TRUE(r.is_pending());
     89 
     90     base::MessageLoop::current()->Run();
     91 
     92     EXPECT_EQ(1, delegate_.response_started_count());
     93     EXPECT_FALSE(delegate_.received_data_before_response());
     94     EXPECT_NE(0, delegate_.bytes_received());
     95   }
     96 
     97   UrlTaskChain* next() const {
     98     return next_;
     99   }
    100 
    101   const std::string& response() const {
    102     return delegate_.data_received();
    103   }
    104 
    105  protected:
    106   std::string url_;
    107   net::TestDelegate delegate_;
    108   UrlTaskChain* next_;
    109 };
    110 
    111 DWORD WINAPI FetchUrl(void* param) {
    112   UrlTaskChain* task = reinterpret_cast<UrlTaskChain*>(param);
    113   while (task != NULL) {
    114     task->Run();
    115     task = task->next();
    116   }
    117 
    118   return 0;
    119 }
    120 
    121 struct QuitMessageHit {
    122   explicit QuitMessageHit(base::MessageLoopForUI* loop)
    123       : loop_(loop), hit_(false) {}
    124 
    125   base::MessageLoopForUI* loop_;
    126   bool hit_;
    127 };
    128 
    129 void QuitMessageLoop(QuitMessageHit* msg) {
    130   msg->hit_ = true;
    131   msg->loop_->PostTask(FROM_HERE, base::MessageLoop::QuitClosure());
    132 }
    133 
    134 }  // end namespace
    135 
    136 TEST_F(TestServerTest, TestServer) {
    137   // The web server needs a loop to exist on this thread during construction
    138   // the loop must be created before we construct the server.
    139   base::MessageLoopForUI loop;
    140 
    141   test_server::SimpleWebServer server(1337);
    142   test_server::SimpleWebServer redirected_server(server.host(), 1338);
    143   test_server::SimpleResponse person("/person", "Guthrie Govan!");
    144   server.AddResponse(&person);
    145   test_server::FileResponse file("/file", source_path().Append(
    146       FILE_PATH_LITERAL("CFInstance.js")));
    147   server.AddResponse(&file);
    148   test_server::RedirectResponse redir(
    149       "/redir",
    150       base::StringPrintf("http://%s:1338/dest",
    151                          redirected_server.host().c_str()));
    152   server.AddResponse(&redir);
    153 
    154   test_server::SimpleResponse dest("/dest", "Destination");
    155   redirected_server.AddResponse(&dest);
    156 
    157   // We should never hit this, but it's our way to break out of the test if
    158   // things start hanging.
    159   QuitMessageHit quit_msg(&loop);
    160   loop.PostDelayedTask(FROM_HERE, base::Bind(QuitMessageLoop, &quit_msg),
    161                        base::TimeDelta::FromSeconds(10));
    162 
    163   UrlTaskChain quit_task(
    164       base::StringPrintf("http://%s:1337/quit", server.host().c_str()), NULL);
    165   UrlTaskChain fnf_task(
    166       base::StringPrintf("http://%s:1337/404", server.host().c_str()),
    167       &quit_task);
    168   UrlTaskChain person_task(
    169       base::StringPrintf("http://%s:1337/person", server.host().c_str()),
    170       &fnf_task);
    171   UrlTaskChain file_task(
    172       base::StringPrintf("http://%s:1337/file", server.host().c_str()),
    173       &person_task);
    174   UrlTaskChain redir_task(
    175       base::StringPrintf("http://%s:1337/redir", server.host().c_str()),
    176       &file_task);
    177 
    178   DWORD tid = 0;
    179   base::win::ScopedHandle worker(::CreateThread(
    180       NULL, 0, FetchUrl, &redir_task, 0, &tid));
    181   loop.base::MessageLoop::Run();
    182 
    183   EXPECT_FALSE(quit_msg.hit_);
    184   if (!quit_msg.hit_) {
    185     EXPECT_EQ(::WaitForSingleObject(worker, 10 * 1000), WAIT_OBJECT_0);
    186 
    187     EXPECT_EQ(person.accessed(), 1);
    188     EXPECT_EQ(file.accessed(), 1);
    189     EXPECT_EQ(redir.accessed(), 1);
    190 
    191     EXPECT_TRUE(person_task.response().find("Guthrie") != std::string::npos);
    192     EXPECT_TRUE(file_task.response().find("function") != std::string::npos);
    193     EXPECT_TRUE(redir_task.response().find("Destination") != std::string::npos);
    194   } else {
    195     ::TerminateThread(worker, ~0);
    196   }
    197 }
    198