Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(158)

Side by Side Diff: components/cronet/ios/test/cronet_http_test.mm

Issue 2146643002: [Cronet] Integrate CrNet functionality into Cronet on iOS. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Sync Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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/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 #import "ios/third_party/gcdwebserver/src/GCDWebServer/Responses/GCDWebServerDat aResponse.h"
15 #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"
16 #include "testing/gtest/include/gtest/gtest.h" 17 #include "testing/gtest/include/gtest/gtest.h"
17 #include "testing/gtest_mac.h" 18 #include "testing/gtest_mac.h"
19
18 #include "url/gurl.h" 20 #include "url/gurl.h"
19 21
20 @interface TestDelegate : NSObject<NSURLSessionDataDelegate, 22 @interface TestDelegate : NSObject<NSURLSessionDataDelegate,
21 NSURLSessionDelegate, 23 NSURLSessionDelegate,
22 NSURLSessionTaskDelegate> 24 NSURLSessionTaskDelegate>
23 25
24 // Completion semaphore for this TestDelegate. When the request this delegate is 26 // Completion semaphore for this TestDelegate. When the request this delegate is
25 // attached to finishes (either successfully or with an error), this delegate 27 // attached to finishes (either successfully or with an error), this delegate
26 // signals this semaphore. 28 // signals this semaphore.
27 @property(assign, nonatomic) dispatch_semaphore_t semaphore; 29 @property(assign, nonatomic) dispatch_semaphore_t semaphore;
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
90 - (void)URLSession:(NSURLSession*)session 92 - (void)URLSession:(NSURLSession*)session
91 dataTask:(NSURLSessionDataTask*)dataTask 93 dataTask:(NSURLSessionDataTask*)dataTask
92 willCacheResponse:(NSCachedURLResponse*)proposedResponse 94 willCacheResponse:(NSCachedURLResponse*)proposedResponse
93 completionHandler: 95 completionHandler:
94 (void (^)(NSCachedURLResponse* cachedResponse))completionHandler { 96 (void (^)(NSCachedURLResponse* cachedResponse))completionHandler {
95 completionHandler(proposedResponse); 97 completionHandler(proposedResponse);
96 } 98 }
97 99
98 @end 100 @end
99 101
102 namespace cronet {
100 // base::TimeDelta would normally be ideal for this but it does not support 103 // base::TimeDelta would normally be ideal for this but it does not support
101 // nanosecond resolution. 104 // nanosecond resolution.
102 static const int64_t ns_in_second = 1000000000LL; 105 static const int64_t ns_in_second = 1000000000LL;
103 const char kUserAgent[] = "CrNetTest/1.0.0.0"; 106 const char kUserAgent[] = "CronetTest/1.0.0.0";
107
108 // TODO(mef): Create common header file to declare this.
109 void StartCronetIfNecessary();
104 110
105 class HttpTest : public ::testing::Test { 111 class HttpTest : public ::testing::Test {
106 protected: 112 protected:
107 HttpTest() {} 113 HttpTest() {}
108 ~HttpTest() override {} 114 ~HttpTest() override {}
109 115
110 void SetUp() override { 116 void SetUp() override {
111 [CrNet setUserAgent:base::SysUTF8ToNSString(kUserAgent) partial:NO]; 117 StartCronetIfNecessary();
112 [CrNet install];
113 NSURLSessionConfiguration* config = 118 NSURLSessionConfiguration* config =
114 [NSURLSessionConfiguration ephemeralSessionConfiguration]; 119 [NSURLSessionConfiguration ephemeralSessionConfiguration];
115 [CrNet installIntoSessionConfiguration:config]; 120 [Cronet installIntoSessionConfiguration:config];
116 delegate_.reset([[TestDelegate alloc] init]); 121 delegate_.reset([[TestDelegate alloc] init]);
117 NSURLSession* session = [NSURLSession sessionWithConfiguration:config 122 NSURLSession* session = [NSURLSession sessionWithConfiguration:config
118 delegate:delegate_ 123 delegate:delegate_
119 delegateQueue:nil]; 124 delegateQueue:nil];
120 // Take a reference to the session and store it so it doesn't get 125 // Take a reference to the session and store it so it doesn't get
121 // deallocated until this object does. 126 // deallocated until this object does.
122 session_.reset([session retain]); 127 session_.reset([session retain]);
123 web_server_.reset([[GCDWebServer alloc] init]); 128 StartQuicTestServer();
124 } 129 }
125 130
126 void TearDown() override { 131 void TearDown() override { ShutdownQuicTestServer(); }
127 [CrNet uninstall];
128 [web_server_ stop];
129 }
130
131 // Starts a GCDWebServer instance on localhost port 8080, and remembers the
132 // root URL for later; tests can use GetURL() to produce a URL referring to a
133 // specific resource under the root URL.
134 void StartWebServer() {
135 [web_server_ startWithPort:8080 bonjourName:nil];
136 server_root_ = net::GURLWithNSURL([web_server_ serverURL]);
137 }
138
139 // Registers a fixed response |text| to be returned to requests for |path|,
140 // which is relative to |server_root_|.
141 void RegisterPathText(const std::string& path, const std::string& text) {
142 NSString* nspath = base::SysUTF8ToNSString(path);
143 NSData* data = [NSData dataWithBytes:text.c_str() length:text.length()];
144 [web_server_ addGETHandlerForPath:nspath
145 staticData:data
146 contentType:@"text/plain"
147 cacheAge:30];
148 }
149
150 void RegisterPathHandler(const std::string& path,
151 GCDWebServerProcessBlock handler) {
152 NSString* nspath = base::SysUTF8ToNSString(path);
153 [web_server_ addHandlerForMethod:@"GET"
154 path:nspath
155 requestClass:NSClassFromString(@"GCDWebServerRequest")
156 processBlock:handler];
157 }
158 132
159 // Launches the supplied |task| and blocks until it completes, with a timeout 133 // Launches the supplied |task| and blocks until it completes, with a timeout
160 // of 1 second. 134 // of 1 second.
161 void StartDataTaskAndWaitForCompletion(NSURLSessionDataTask* task) { 135 void StartDataTaskAndWaitForCompletion(NSURLSessionDataTask* task) {
162 [task resume]; 136 [task resume];
163 int64_t deadline_ns = 1 * ns_in_second; 137 int64_t deadline_ns = 1 * ns_in_second;
164 dispatch_semaphore_wait([delegate_ semaphore], 138 dispatch_semaphore_wait([delegate_ semaphore],
165 dispatch_time(DISPATCH_TIME_NOW, deadline_ns)); 139 dispatch_time(DISPATCH_TIME_NOW, deadline_ns));
166 } 140 }
167 141
168 // Returns a URL to refer to the resource named |path| served by the test
169 // server. If |path| starts with a /, the leading / will be stripped.
170 GURL GetURL(const std::string& path) {
171 std::string real_path = path[0] == '/' ? path.substr(1) : path;
172 return server_root_.Resolve(real_path);
173 }
174
175 // Some convenience functions for working with GCDWebServerRequest and
176 // GCDWebServerResponse.
177
178 // Returns true if the value for the request header |header| is not nil and
179 // contains the string |target|.
180 bool HeaderValueContains(GCDWebServerRequest* request,
181 const std::string& header,
182 const std::string& target) {
183 NSString* key = base::SysUTF8ToNSString(header);
184 NSString* needle = base::SysUTF8ToNSString(target);
185 NSString* haystack = request.headers[key];
186 if (!haystack)
187 return false;
188 return [haystack rangeOfString:needle].location != NSNotFound;
189 }
190
191 base::scoped_nsobject<NSURLSession> session_; 142 base::scoped_nsobject<NSURLSession> session_;
192 base::scoped_nsobject<TestDelegate> delegate_; 143 base::scoped_nsobject<TestDelegate> delegate_;
193
194 private:
195 base::scoped_nsobject<GCDWebServer> web_server_;
196 GURL server_root_;
197 }; 144 };
198 145
199 TEST_F(HttpTest, NSURLSessionReceivesData) { 146 TEST_F(HttpTest, NSURLSessionReceivesData) {
200 const char kPath[] = "/foo"; 147 NSURL* url = net::NSURLWithGURL(GURL(kTestServerUrl));
201 const char kData[] = "foobar";
202 RegisterPathText(kPath, kData);
203 StartWebServer();
204
205 NSURL* url = net::NSURLWithGURL(GetURL(kPath));
206 NSURLSessionDataTask* task = [session_ dataTaskWithURL:url]; 148 NSURLSessionDataTask* task = [session_ dataTaskWithURL:url];
207 StartDataTaskAndWaitForCompletion(task); 149 StartDataTaskAndWaitForCompletion(task);
208 EXPECT_EQ(nil, [delegate_ error]); 150 EXPECT_EQ(nil, [delegate_ error]);
209 EXPECT_EQ(strlen(kData), [delegate_ receivedBytes]); 151 EXPECT_EQ(strlen(kHelloBodyValue), [delegate_ receivedBytes]);
210 } 152 }
211 153
212 TEST_F(HttpTest, SdchDisabledByDefault) { 154 TEST_F(HttpTest, GetGlobalMetricsDeltas) {
213 const char kPath[] = "/sdchtest"; 155 NSData* delta1 = [Cronet getGlobalMetricsDeltas];
214 RegisterPathHandler(kPath, 156
215 ^GCDWebServerResponse* (GCDWebServerRequest* req) { 157 NSURL* url = net::NSURLWithGURL(GURL(kTestServerUrl));
216 EXPECT_FALSE(HeaderValueContains(req, "Accept-Encoding", "sdch"));
217 return [GCDWebServerDataResponse responseWithText:@"woot!"];
218 });
219 StartWebServer();
220 NSURL* url = net::NSURLWithGURL(GetURL(kPath));
221 NSURLSessionDataTask* task = [session_ dataTaskWithURL:url]; 158 NSURLSessionDataTask* task = [session_ dataTaskWithURL:url];
222 StartDataTaskAndWaitForCompletion(task); 159 StartDataTaskAndWaitForCompletion(task);
223 EXPECT_EQ(nil, [delegate_ error]); 160 EXPECT_EQ(nil, [delegate_ error]);
224 EXPECT_TRUE([delegate_ receivedBytes]); 161 EXPECT_EQ(strlen(kHelloBodyValue), [delegate_ receivedBytes]);
162
163 NSData* delta2 = [Cronet getGlobalMetricsDeltas];
164 EXPECT_FALSE([delta2 isEqualToData:delta1]);
225 } 165 }
226 166
227 TEST_F(HttpTest, SetUserAgentIsExact) { 167 TEST_F(HttpTest, NSURLSessionReceivesData2) {
228 const char kPath[] = "/uatest"; 168 NSURL* url = net::NSURLWithGURL(GURL(GetTestServerURL("/")));
229 RegisterPathHandler(kPath, ^GCDWebServerResponse*(GCDWebServerRequest* req) {
230 EXPECT_STREQ(kUserAgent,
231 [[req.headers valueForKey:@"User-Agent"] UTF8String]);
232 return [GCDWebServerDataResponse responseWithText:@"yay!"];
233 });
234 StartWebServer();
235 NSURL* url = net::NSURLWithGURL(GetURL(kPath));
236 NSURLSessionDataTask* task = [session_ dataTaskWithURL:url]; 169 NSURLSessionDataTask* task = [session_ dataTaskWithURL:url];
237 StartDataTaskAndWaitForCompletion(task); 170 StartDataTaskAndWaitForCompletion(task);
238 EXPECT_EQ(nil, [delegate_ error]); 171 EXPECT_EQ(nil, [delegate_ error]);
239 EXPECT_TRUE([delegate_ receivedBytes]); 172 EXPECT_EQ(strlen(kUserAgent), [delegate_ receivedBytes]);
240 } 173 }
241 174
242 // TODO(ellyjones): There needs to be a test that enabling SDCH works, but 175 } // namespace cronet
243 // because CrNet is static and 'uninstall' only disables it, there is no way to
244 // have an individual test enable or disable SDCH.
245 // Probably there is a way to get gtest tests to run in a separate process, but
246 // I'm not sure what it is.
OLDNEW
« no previous file with comments | « components/cronet/ios/test/cronet_bidirectional_stream_test.mm ('k') | components/cronet/ios/test/quic_test_server.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698