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 #include <stdint.h> | 6 #include <stdint.h> |
7 | 7 |
8 #import "CrNet.h" | 8 #import "components/cronet/ios/Cronet.h" |
9 | 9 |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
11 #include "base/mac/scoped_nsobject.h" | 11 #include "base/mac/scoped_nsobject.h" |
12 #include "base/strings/sys_string_conversions.h" | 12 #include "base/strings/sys_string_conversions.h" |
13 #import "ios/third_party/gcdwebserver/src/GCDWebServer/Core/GCDWebServer.h" | 13 #include "components/cronet/ios/test/quic_test_server.h" |
14 #include "net/base/mac/url_conversions.h" | 14 #include "net/base/mac/url_conversions.h" |
| 15 #include "net/base/net_errors.h" |
| 16 #include "net/cert/mock_cert_verifier.h" |
15 #include "testing/gtest/include/gtest/gtest.h" | 17 #include "testing/gtest/include/gtest/gtest.h" |
16 #include "testing/gtest_mac.h" | 18 #include "testing/gtest_mac.h" |
17 #include "url/gurl.h" | 19 #include "url/gurl.h" |
18 | 20 |
19 @interface TestDelegate : NSObject<NSURLSessionDataDelegate, | 21 @interface TestDelegate : NSObject<NSURLSessionDataDelegate, |
20 NSURLSessionDelegate, | 22 NSURLSessionDelegate, |
21 NSURLSessionTaskDelegate> | 23 NSURLSessionTaskDelegate> |
22 | 24 |
23 // Completion semaphore for this TestDelegate. When the request this delegate is | 25 // Completion semaphore for this TestDelegate. When the request this delegate is |
24 // attached to finishes (either successfully or with an error), this delegate | 26 // attached to finishes (either successfully or with an error), this delegate |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
89 - (void)URLSession:(NSURLSession*)session | 91 - (void)URLSession:(NSURLSession*)session |
90 dataTask:(NSURLSessionDataTask*)dataTask | 92 dataTask:(NSURLSessionDataTask*)dataTask |
91 willCacheResponse:(NSCachedURLResponse*)proposedResponse | 93 willCacheResponse:(NSCachedURLResponse*)proposedResponse |
92 completionHandler: | 94 completionHandler: |
93 (void (^)(NSCachedURLResponse* cachedResponse))completionHandler { | 95 (void (^)(NSCachedURLResponse* cachedResponse))completionHandler { |
94 completionHandler(proposedResponse); | 96 completionHandler(proposedResponse); |
95 } | 97 } |
96 | 98 |
97 @end | 99 @end |
98 | 100 |
| 101 namespace cronet { |
99 // base::TimeDelta would normally be ideal for this but it does not support | 102 // base::TimeDelta would normally be ideal for this but it does not support |
100 // nanosecond resolution. | 103 // nanosecond resolution. |
101 static const int64_t ns_in_second = 1000000000LL; | 104 static const int64_t ns_in_second = 1000000000LL; |
102 | 105 |
| 106 // TODO(mef): Create common header file to declare this. |
| 107 void StartCronetIfNecessary(); |
| 108 |
103 class HttpTest : public ::testing::Test { | 109 class HttpTest : public ::testing::Test { |
104 protected: | 110 protected: |
105 HttpTest() {} | 111 HttpTest() {} |
106 ~HttpTest() override {} | 112 ~HttpTest() override {} |
107 | 113 |
108 void SetUp() override { | 114 void SetUp() override { |
109 [CrNet setPartialUserAgent:@"CrNetTest/1.0.0.0"]; | 115 StartCronetIfNecessary(); |
110 [CrNet install]; | |
111 NSURLSessionConfiguration* config = | 116 NSURLSessionConfiguration* config = |
112 [NSURLSessionConfiguration ephemeralSessionConfiguration]; | 117 [NSURLSessionConfiguration ephemeralSessionConfiguration]; |
113 [CrNet installIntoSessionConfiguration:config]; | 118 [Cronet installIntoSessionConfiguration:config]; |
114 delegate_.reset([[TestDelegate alloc] init]); | 119 delegate_.reset([[TestDelegate alloc] init]); |
115 NSURLSession* session = [NSURLSession sessionWithConfiguration:config | 120 NSURLSession* session = [NSURLSession sessionWithConfiguration:config |
116 delegate:delegate_ | 121 delegate:delegate_ |
117 delegateQueue:nil]; | 122 delegateQueue:nil]; |
118 // Take a reference to the session and store it so it doesn't get | 123 // Take a reference to the session and store it so it doesn't get |
119 // deallocated until this object does. | 124 // deallocated until this object does. |
120 session_.reset([session retain]); | 125 session_.reset([session retain]); |
121 web_server_.reset([[GCDWebServer alloc] init]); | 126 StartQuicTestServer(); |
122 } | 127 } |
123 | 128 |
124 void TearDown() override { | 129 void TearDown() override { ShutdownQuicTestServer(); } |
125 [CrNet uninstall]; | |
126 [web_server_ stop]; | |
127 } | |
128 | |
129 // Starts a GCDWebServer instance on localhost port 8080, and remembers the | |
130 // root URL for later; tests can use GetURL() to produce a URL referring to a | |
131 // specific resource under the root URL. | |
132 void StartWebServer() { | |
133 [web_server_ startWithPort:8080 bonjourName:nil]; | |
134 server_root_ = net::GURLWithNSURL([web_server_ serverURL]); | |
135 } | |
136 | |
137 // Registers a fixed response |text| to be returned to requests for |path|, | |
138 // which is relative to |server_root_|. | |
139 void RegisterPathText(const std::string& path, const std::string& text) { | |
140 NSString* nspath = base::SysUTF8ToNSString(path); | |
141 NSData* data = [NSData dataWithBytes:text.c_str() length:text.length()]; | |
142 [web_server_ addGETHandlerForPath:nspath | |
143 staticData:data | |
144 contentType:@"text/plain" | |
145 cacheAge:30]; | |
146 } | |
147 | |
148 void RegisterPathHandler(const std::string& path, | |
149 GCDWebServerProcessBlock handler) { | |
150 NSString* nspath = base::SysUTF8ToNSString(path); | |
151 [web_server_ addHandlerForMethod:@"GET" | |
152 path:nspath | |
153 requestClass:NSClassFromString(@"GCDWebServerRequest") | |
154 processBlock:handler]; | |
155 } | |
156 | 130 |
157 // Launches the supplied |task| and blocks until it completes, with a timeout | 131 // Launches the supplied |task| and blocks until it completes, with a timeout |
158 // of 1 second. | 132 // of 1 second. |
159 void StartDataTaskAndWaitForCompletion(NSURLSessionDataTask* task) { | 133 void StartDataTaskAndWaitForCompletion(NSURLSessionDataTask* task) { |
160 [task resume]; | 134 [task resume]; |
161 int64_t deadline_ns = 1 * ns_in_second; | 135 int64_t deadline_ns = 1 * ns_in_second; |
162 dispatch_semaphore_wait([delegate_ semaphore], | 136 dispatch_semaphore_wait([delegate_ semaphore], |
163 dispatch_time(DISPATCH_TIME_NOW, deadline_ns)); | 137 dispatch_time(DISPATCH_TIME_NOW, deadline_ns)); |
164 } | 138 } |
165 | 139 |
166 // Returns a URL to refer to the resource named |path| served by the test | |
167 // server. If |path| starts with a /, the leading / will be stripped. | |
168 GURL GetURL(const std::string& path) { | |
169 std::string real_path = path[0] == '/' ? path.substr(1) : path; | |
170 return server_root_.Resolve(real_path); | |
171 } | |
172 | |
173 // Some convenience functions for working with GCDWebServerRequest and | |
174 // GCDWebServerResponse. | |
175 | |
176 // Returns true if the value for the request header |header| is not nil and | |
177 // contains the string |target|. | |
178 bool HeaderValueContains(GCDWebServerRequest* request, | |
179 const std::string& header, | |
180 const std::string& target) { | |
181 NSString* key = base::SysUTF8ToNSString(header); | |
182 NSString* needle = base::SysUTF8ToNSString(target); | |
183 NSString* haystack = request.headers[key]; | |
184 if (!haystack) | |
185 return false; | |
186 return [haystack rangeOfString:needle].location != NSNotFound; | |
187 } | |
188 | |
189 base::scoped_nsobject<NSURLSession> session_; | 140 base::scoped_nsobject<NSURLSession> session_; |
190 base::scoped_nsobject<TestDelegate> delegate_; | 141 base::scoped_nsobject<TestDelegate> delegate_; |
191 | |
192 private: | |
193 base::scoped_nsobject<GCDWebServer> web_server_; | |
194 GURL server_root_; | |
195 }; | 142 }; |
196 | 143 |
197 TEST_F(HttpTest, NSURLSessionReceivesData) { | 144 TEST_F(HttpTest, NSURLSessionReceivesData) { |
198 const char kPath[] = "/foo"; | 145 NSURL* url = net::NSURLWithGURL(GURL(kTestServerUrl)); |
199 const char kData[] = "foobar"; | |
200 RegisterPathText(kPath, kData); | |
201 StartWebServer(); | |
202 | |
203 NSURL* url = net::NSURLWithGURL(GetURL(kPath)); | |
204 NSURLSessionDataTask* task = [session_ dataTaskWithURL:url]; | 146 NSURLSessionDataTask* task = [session_ dataTaskWithURL:url]; |
205 StartDataTaskAndWaitForCompletion(task); | 147 StartDataTaskAndWaitForCompletion(task); |
206 EXPECT_EQ(nil, [delegate_ error]); | 148 EXPECT_EQ(nil, [delegate_ error]); |
207 EXPECT_EQ(strlen(kData), [delegate_ receivedBytes]); | 149 EXPECT_EQ(strlen(kHelloBodyValue), [delegate_ receivedBytes]); |
208 } | 150 } |
209 | 151 |
210 TEST_F(HttpTest, SdchDisabledByDefault) { | 152 TEST_F(HttpTest, GetGlobalMetricsDeltas) { |
211 const char kPath[] = "/foo"; | 153 NSData* delta1 = [Cronet getGlobalMetricsDeltas]; |
212 RegisterPathHandler(kPath, | 154 |
213 ^GCDWebServerResponse* (GCDWebServerRequest* req) { | 155 NSURL* url = net::NSURLWithGURL(GURL(kTestServerUrl)); |
214 EXPECT_FALSE(HeaderValueContains(req, "Accept-Encoding", "sdch")); | |
215 return nil; | |
216 }); | |
217 StartWebServer(); | |
218 NSURL* url = net::NSURLWithGURL(GetURL(kPath)); | |
219 NSURLSessionDataTask* task = [session_ dataTaskWithURL:url]; | 156 NSURLSessionDataTask* task = [session_ dataTaskWithURL:url]; |
220 StartDataTaskAndWaitForCompletion(task); | 157 StartDataTaskAndWaitForCompletion(task); |
221 EXPECT_EQ(nil, [delegate_ error]); | 158 EXPECT_EQ(nil, [delegate_ error]); |
222 EXPECT_TRUE([delegate_ receivedBytes]); | 159 EXPECT_EQ(strlen(kHelloBodyValue), [delegate_ receivedBytes]); |
| 160 |
| 161 NSData* delta2 = [Cronet getGlobalMetricsDeltas]; |
| 162 EXPECT_FALSE([delta2 isEqualToData:delta1]); |
223 } | 163 } |
224 | 164 |
225 // TODO(ellyjones): There needs to be a test that enabling SDCH works, but | 165 } // namespace cronet |
226 // because CrNet is static and 'uninstall' only disables it, there is no way to | |
227 // have an individual test enable or disable SDCH. | |
228 // Probably there is a way to get gtest tests to run in a separate process, but | |
229 // I'm not sure what it is. | |
OLD | NEW |