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