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