| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #import <Foundation/Foundation.h> | 5 #import <Foundation/Foundation.h> |
| 6 | 6 |
| 7 #import "CrNet.h" | 7 #import "CrNet.h" |
| 8 | 8 |
| 9 #include "base/logging.h" |
| 9 #include "base/mac/scoped_nsobject.h" | 10 #include "base/mac/scoped_nsobject.h" |
| 11 #include "base/strings/sys_string_conversions.h" |
| 10 #import "ios/third_party/gcdwebserver/src/GCDWebServer/Core/GCDWebServer.h" | 12 #import "ios/third_party/gcdwebserver/src/GCDWebServer/Core/GCDWebServer.h" |
| 11 #include "net/base/mac/url_conversions.h" | 13 #include "net/base/mac/url_conversions.h" |
| 12 #include "testing/gtest/include/gtest/gtest.h" | 14 #include "testing/gtest/include/gtest/gtest.h" |
| 13 #include "testing/gtest_mac.h" | 15 #include "testing/gtest_mac.h" |
| 14 #include "url/gurl.h" | 16 #include "url/gurl.h" |
| 15 | 17 |
| 16 @interface TestDelegate : NSObject<NSURLSessionDataDelegate, | 18 @interface TestDelegate : NSObject<NSURLSessionDataDelegate, |
| 17 NSURLSessionDelegate, | 19 NSURLSessionDelegate, |
| 18 NSURLSessionTaskDelegate> | 20 NSURLSessionTaskDelegate> |
| 19 | 21 |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 127 // root URL for later; tests can use GetURL() to produce a URL referring to a | 129 // root URL for later; tests can use GetURL() to produce a URL referring to a |
| 128 // specific resource under the root URL. | 130 // specific resource under the root URL. |
| 129 void StartWebServer() { | 131 void StartWebServer() { |
| 130 [web_server_ startWithPort:8080 bonjourName:nil]; | 132 [web_server_ startWithPort:8080 bonjourName:nil]; |
| 131 server_root_ = net::GURLWithNSURL([web_server_ serverURL]); | 133 server_root_ = net::GURLWithNSURL([web_server_ serverURL]); |
| 132 } | 134 } |
| 133 | 135 |
| 134 // Registers a fixed response |text| to be returned to requests for |path|, | 136 // Registers a fixed response |text| to be returned to requests for |path|, |
| 135 // which is relative to |server_root_|. | 137 // which is relative to |server_root_|. |
| 136 void RegisterPathText(const std::string& path, const std::string& text) { | 138 void RegisterPathText(const std::string& path, const std::string& text) { |
| 137 NSString* nspath = | 139 NSString* nspath = base::SysUTF8ToNSString(path); |
| 138 [NSString stringWithCString:path.c_str() encoding:NSUTF8StringEncoding]; | |
| 139 NSData* data = [NSData dataWithBytes:text.c_str() length:text.length()]; | 140 NSData* data = [NSData dataWithBytes:text.c_str() length:text.length()]; |
| 140 [web_server_ addGETHandlerForPath:nspath | 141 [web_server_ addGETHandlerForPath:nspath |
| 141 staticData:data | 142 staticData:data |
| 142 contentType:@"text/plain" | 143 contentType:@"text/plain" |
| 143 cacheAge:30]; | 144 cacheAge:30]; |
| 144 } | 145 } |
| 145 | 146 |
| 147 void RegisterPathHandler(const std::string& path, |
| 148 GCDWebServerProcessBlock handler) { |
| 149 NSString* nspath = base::SysUTF8ToNSString(path); |
| 150 [web_server_ addHandlerForMethod:@"GET" |
| 151 path:nspath |
| 152 requestClass:NSClassFromString(@"GCDWebServerRequest") |
| 153 processBlock:handler]; |
| 154 } |
| 155 |
| 146 // Launches the supplied |task| and blocks until it completes, with a timeout | 156 // Launches the supplied |task| and blocks until it completes, with a timeout |
| 147 // of 1 second. | 157 // of 1 second. |
| 148 void StartDataTaskAndWaitForCompletion(NSURLSessionDataTask* task) { | 158 void StartDataTaskAndWaitForCompletion(NSURLSessionDataTask* task) { |
| 149 [task resume]; | 159 [task resume]; |
| 150 int64_t deadline_ns = 1 * ns_in_second; | 160 int64_t deadline_ns = 1 * ns_in_second; |
| 151 dispatch_semaphore_wait([delegate_ semaphore], | 161 dispatch_semaphore_wait([delegate_ semaphore], |
| 152 dispatch_time(DISPATCH_TIME_NOW, deadline_ns)); | 162 dispatch_time(DISPATCH_TIME_NOW, deadline_ns)); |
| 153 } | 163 } |
| 154 | 164 |
| 155 // Returns a URL to refer to the resource named |path| served by the test | 165 // Returns a URL to refer to the resource named |path| served by the test |
| 156 // server. If |path| starts with a /, the leading / will be stripped. | 166 // server. If |path| starts with a /, the leading / will be stripped. |
| 157 GURL GetURL(const std::string& path) { | 167 GURL GetURL(const std::string& path) { |
| 158 std::string real_path = path[0] == '/' ? path.substr(1) : path; | 168 std::string real_path = path[0] == '/' ? path.substr(1) : path; |
| 159 return server_root_.Resolve(real_path); | 169 return server_root_.Resolve(real_path); |
| 160 } | 170 } |
| 161 | 171 |
| 172 // Some convenience functions for working with GCDWebServerRequest and |
| 173 // GCDWebServerResponse. |
| 174 |
| 175 // Returns true if the value for the request header |header| is not nil and |
| 176 // contains the string |target|. |
| 177 bool HeaderValueContains(GCDWebServerRequest* request, |
| 178 const std::string& header, |
| 179 const std::string& target) { |
| 180 NSString* key = base::SysUTF8ToNSString(header); |
| 181 NSString* needle = base::SysUTF8ToNSString(target); |
| 182 NSString* haystack = request.headers[key]; |
| 183 if (!haystack) |
| 184 return false; |
| 185 return [haystack rangeOfString:needle].location != NSNotFound; |
| 186 } |
| 187 |
| 162 base::scoped_nsobject<NSURLSession> session_; | 188 base::scoped_nsobject<NSURLSession> session_; |
| 163 base::scoped_nsobject<TestDelegate> delegate_; | 189 base::scoped_nsobject<TestDelegate> delegate_; |
| 164 | 190 |
| 165 private: | 191 private: |
| 166 base::scoped_nsobject<GCDWebServer> web_server_; | 192 base::scoped_nsobject<GCDWebServer> web_server_; |
| 167 GURL server_root_; | 193 GURL server_root_; |
| 168 }; | 194 }; |
| 169 | 195 |
| 170 TEST_F(HttpTest, NSURLConnectionReceivesData) { | 196 TEST_F(HttpTest, NSURLConnectionReceivesData) { |
| 171 const char kData[] = "foobar"; | 197 const char kData[] = "foobar"; |
| 172 const char kPath[] = "/foo"; | 198 const char kPath[] = "/foo"; |
| 173 RegisterPathText(kPath, kData); | 199 RegisterPathText(kPath, kData); |
| 174 StartWebServer(); | 200 StartWebServer(); |
| 175 | 201 |
| 176 NSURL* url = net::NSURLWithGURL(GetURL(kPath)); | 202 NSURL* url = net::NSURLWithGURL(GetURL(kPath)); |
| 177 NSURLRequest* req = [NSURLRequest requestWithURL:url]; | 203 NSURLRequest* req = [NSURLRequest requestWithURL:url]; |
| 178 NSURLResponse* resp = nil; | 204 NSURLResponse* resp = nil; |
| 205 NSData* received = [NSURLConnection sendSynchronousRequest:req |
| 206 returningResponse:&resp |
| 207 error:nullptr]; |
| 208 EXPECT_EQ(0, memcmp([received bytes], kData, sizeof(kData))); |
| 209 } |
| 210 |
| 211 TEST_F(HttpTest, NSURLSessionReceivesData) { |
| 212 const char kPath[] = "/foo"; |
| 213 const char kData[] = "foobar"; |
| 214 RegisterPathText(kPath, kData); |
| 215 StartWebServer(); |
| 216 |
| 217 NSURL* url = net::NSURLWithGURL(GetURL(kPath)); |
| 218 NSURLSessionDataTask* task = [session_ dataTaskWithURL:url]; |
| 219 StartDataTaskAndWaitForCompletion(task); |
| 220 EXPECT_EQ(nil, [delegate_ error]); |
| 221 EXPECT_EQ(strlen(kData), [delegate_ receivedBytes]); |
| 222 } |
| 223 |
| 224 TEST_F(HttpTest, SdchDisabledByDefault) { |
| 225 const char kPath[] = "/foo"; |
| 226 RegisterPathHandler(kPath, |
| 227 ^GCDWebServerResponse* (GCDWebServerRequest* req) { |
| 228 EXPECT_FALSE(HeaderValueContains(req, "Accept-Encoding", "sdch")); |
| 229 return nil; |
| 230 }); |
| 231 StartWebServer(); |
| 232 NSURL* url = net::NSURLWithGURL(GetURL(kPath)); |
| 233 NSURLRequest* req = [NSURLRequest requestWithURL:url]; |
| 234 NSURLResponse* resp = nil; |
| 179 NSError* error = nil; | 235 NSError* error = nil; |
| 180 NSData* received = [NSURLConnection sendSynchronousRequest:req | 236 NSData* received = [NSURLConnection sendSynchronousRequest:req |
| 181 returningResponse:&resp | 237 returningResponse:&resp |
| 182 error:&error]; | 238 error:&error]; |
| 183 EXPECT_EQ(0, memcmp([received bytes], kData, sizeof(kData))); | 239 DCHECK(received); |
| 184 } | 240 } |
| 185 | 241 |
| 186 TEST_F(HttpTest, NSURLSessionReceivesData) { | 242 // TODO(ellyjones): There needs to be a test that enabling SDCH works, but |
| 187 const char data[] = "foobar"; | 243 // because CrNet is static and 'uninstall' only disables it, there is no way to |
| 188 RegisterPathText("/foo", data); | 244 // have an individual test enable or disable SDCH. |
| 189 StartWebServer(); | 245 // Probably there is a way to get gtest tests to run in a separate process, but |
| 190 | 246 // I'm not sure what it is. |
| 191 NSURL* url = net::NSURLWithGURL(GetURL("foo")); | |
| 192 NSURLSessionDataTask* task = [session_ dataTaskWithURL:url]; | |
| 193 StartDataTaskAndWaitForCompletion(task); | |
| 194 EXPECT_EQ(nil, [delegate_ error]); | |
| 195 EXPECT_EQ(strlen(data), [delegate_ receivedBytes]); | |
| 196 } | |
| OLD | NEW |