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