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

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: Remove cronet_test_bundle_data target and use data bundled with net_test_support. 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 <Cronet/Cronet.h>
5 #import <Foundation/Foundation.h> 6 #import <Foundation/Foundation.h>
7
6 #include <stdint.h> 8 #include <stdint.h>
7 9
8 #import <CrNet/CrNet.h>
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" 14 #include "components/cronet/ios/test/test_server.h"
15 #include "net/base/mac/url_conversions.h" 15 #include "net/base/mac/url_conversions.h"
16 #include "net/base/net_errors.h"
17 #include "net/cert/mock_cert_verifier.h"
16 #include "testing/gtest/include/gtest/gtest.h" 18 #include "testing/gtest/include/gtest/gtest.h"
17 #include "testing/gtest_mac.h" 19 #include "testing/gtest_mac.h"
20
18 #include "url/gurl.h" 21 #include "url/gurl.h"
19 22
20 @interface TestDelegate : NSObject<NSURLSessionDataDelegate, 23 @interface TestDelegate : NSObject<NSURLSessionDataDelegate,
21 NSURLSessionDelegate, 24 NSURLSessionDelegate,
22 NSURLSessionTaskDelegate> 25 NSURLSessionTaskDelegate>
23 26
24 // Completion semaphore for this TestDelegate. When the request this delegate is 27 // Completion semaphore for this TestDelegate. When the request this delegate is
25 // attached to finishes (either successfully or with an error), this delegate 28 // attached to finishes (either successfully or with an error), this delegate
26 // signals this semaphore. 29 // signals this semaphore.
27 @property(assign, nonatomic) dispatch_semaphore_t semaphore; 30 @property(assign, nonatomic) dispatch_semaphore_t semaphore;
28 31
29 // Total count of bytes received by the request this delegate is attached to. 32 // Body of response received by the request this delegate is attached to.
30 @property(nonatomic) unsigned long receivedBytes; 33 @property(retain, nonatomic) NSString* responseBody;
31 34
32 // Error the request this delegate is attached to failed with, if any. 35 // Error the request this delegate is attached to failed with, if any.
33 @property(retain, nonatomic) NSError* error; 36 @property(retain, nonatomic) NSError* error;
34 37
35 @end 38 @end
36 39
37 @implementation TestDelegate 40 @implementation TestDelegate
38 @synthesize semaphore = _semaphore; 41 @synthesize semaphore = _semaphore;
39 @synthesize receivedBytes = _receivedBytes; 42 @synthesize responseBody = _responseBody;
40 @synthesize error = _error; 43 @synthesize error = _error;
41 44
42 - (id)init { 45 - (id)init {
43 if (self = [super init]) { 46 if (self = [super init]) {
44 _semaphore = dispatch_semaphore_create(0); 47 _semaphore = dispatch_semaphore_create(0);
45 } 48 }
46 return self; 49 return self;
47 } 50 }
48 51
49 - (void)dealloc { 52 - (void)dealloc {
(...skipping 27 matching lines...) Expand all
77 dataTask:(NSURLSessionDataTask*)dataTask 80 dataTask:(NSURLSessionDataTask*)dataTask
78 didReceiveResponse:(NSURLResponse*)response 81 didReceiveResponse:(NSURLResponse*)response
79 completionHandler:(void (^)(NSURLSessionResponseDisposition disposition)) 82 completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))
80 completionHandler { 83 completionHandler {
81 completionHandler(NSURLSessionResponseAllow); 84 completionHandler(NSURLSessionResponseAllow);
82 } 85 }
83 86
84 - (void)URLSession:(NSURLSession*)session 87 - (void)URLSession:(NSURLSession*)session
85 dataTask:(NSURLSessionDataTask*)dataTask 88 dataTask:(NSURLSessionDataTask*)dataTask
86 didReceiveData:(NSData*)data { 89 didReceiveData:(NSData*)data {
87 _receivedBytes += (unsigned long)data.length; 90 NSString* stringData =
91 [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
92 if (_responseBody == nil) {
93 _responseBody = stringData;
94 } else {
95 _responseBody = [_responseBody stringByAppendingString:stringData];
96 }
88 } 97 }
89 98
90 - (void)URLSession:(NSURLSession*)session 99 - (void)URLSession:(NSURLSession*)session
91 dataTask:(NSURLSessionDataTask*)dataTask 100 dataTask:(NSURLSessionDataTask*)dataTask
92 willCacheResponse:(NSCachedURLResponse*)proposedResponse 101 willCacheResponse:(NSCachedURLResponse*)proposedResponse
93 completionHandler: 102 completionHandler:
94 (void (^)(NSCachedURLResponse* cachedResponse))completionHandler { 103 (void (^)(NSCachedURLResponse* cachedResponse))completionHandler {
95 completionHandler(proposedResponse); 104 completionHandler(proposedResponse);
96 } 105 }
97 106
98 @end 107 @end
99 108
109 namespace cronet {
100 // base::TimeDelta would normally be ideal for this but it does not support 110 // base::TimeDelta would normally be ideal for this but it does not support
101 // nanosecond resolution. 111 // nanosecond resolution.
102 static const int64_t ns_in_second = 1000000000LL; 112 static const int64_t ns_in_second = 1000000000LL;
103 const char kUserAgent[] = "CrNetTest/1.0.0.0"; 113 const char kUserAgent[] = "CronetTest/1.0.0.0";
114
115 // TODO(mef): Create common header file to declare this.
116 void StartCronetIfNecessary();
104 117
105 class HttpTest : public ::testing::Test { 118 class HttpTest : public ::testing::Test {
106 protected: 119 protected:
107 HttpTest() {} 120 HttpTest() {}
108 ~HttpTest() override {} 121 ~HttpTest() override {}
109 122
110 void SetUp() override { 123 void SetUp() override {
111 [CrNet setUserAgent:base::SysUTF8ToNSString(kUserAgent) partial:NO]; 124 StartCronetIfNecessary();
112 [CrNet install];
113 NSURLSessionConfiguration* config = 125 NSURLSessionConfiguration* config =
114 [NSURLSessionConfiguration ephemeralSessionConfiguration]; 126 [NSURLSessionConfiguration ephemeralSessionConfiguration];
115 [CrNet installIntoSessionConfiguration:config]; 127 [Cronet installIntoSessionConfiguration:config];
116 delegate_.reset([[TestDelegate alloc] init]); 128 delegate_.reset([[TestDelegate alloc] init]);
117 NSURLSession* session = [NSURLSession sessionWithConfiguration:config 129 NSURLSession* session = [NSURLSession sessionWithConfiguration:config
118 delegate:delegate_ 130 delegate:delegate_
119 delegateQueue:nil]; 131 delegateQueue:nil];
120 // Take a reference to the session and store it so it doesn't get 132 // Take a reference to the session and store it so it doesn't get
121 // deallocated until this object does. 133 // deallocated until this object does.
122 session_.reset([session retain]); 134 session_.reset([session retain]);
123 web_server_.reset([[GCDWebServer alloc] init]); 135 StartQuicTestServer();
136 TestServer::Start();
124 } 137 }
125 138
126 void TearDown() override { 139 void TearDown() override {
127 [CrNet uninstall]; 140 ShutdownQuicTestServer();
128 [web_server_ stop]; 141 TestServer::Shutdown();
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 } 142 }
158 143
159 // Launches the supplied |task| and blocks until it completes, with a timeout 144 // Launches the supplied |task| and blocks until it completes, with a timeout
160 // of 1 second. 145 // of 1 second.
161 void StartDataTaskAndWaitForCompletion(NSURLSessionDataTask* task) { 146 void StartDataTaskAndWaitForCompletion(NSURLSessionDataTask* task) {
162 [task resume]; 147 [task resume];
163 int64_t deadline_ns = 1 * ns_in_second; 148 int64_t deadline_ns = 1 * ns_in_second;
164 dispatch_semaphore_wait([delegate_ semaphore], 149 dispatch_semaphore_wait([delegate_ semaphore],
165 dispatch_time(DISPATCH_TIME_NOW, deadline_ns)); 150 dispatch_time(DISPATCH_TIME_NOW, deadline_ns));
166 } 151 }
167 152
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_; 153 base::scoped_nsobject<NSURLSession> session_;
192 base::scoped_nsobject<TestDelegate> delegate_; 154 base::scoped_nsobject<TestDelegate> delegate_;
193
194 private:
195 base::scoped_nsobject<GCDWebServer> web_server_;
196 GURL server_root_;
197 }; 155 };
198 156
199 TEST_F(HttpTest, NSURLSessionReceivesData) { 157 TEST_F(HttpTest, NSURLSessionReceivesData) {
200 const char kPath[] = "/foo"; 158 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]; 159 NSURLSessionDataTask* task = [session_ dataTaskWithURL:url];
207 StartDataTaskAndWaitForCompletion(task); 160 StartDataTaskAndWaitForCompletion(task);
208 EXPECT_EQ(nil, [delegate_ error]); 161 EXPECT_EQ(nil, [delegate_ error]);
209 EXPECT_EQ(strlen(kData), [delegate_ receivedBytes]); 162 EXPECT_STREQ(kHelloBodyValue, [[delegate_ responseBody] UTF8String]);
163 }
164
165 TEST_F(HttpTest, GetGlobalMetricsDeltas) {
166 NSData* delta1 = [Cronet getGlobalMetricsDeltas];
167
168 NSURL* url = net::NSURLWithGURL(GURL(kTestServerUrl));
169 NSURLSessionDataTask* task = [session_ dataTaskWithURL:url];
170 StartDataTaskAndWaitForCompletion(task);
171 EXPECT_EQ(nil, [delegate_ error]);
172 EXPECT_STREQ(kHelloBodyValue, [[delegate_ responseBody] UTF8String]);
173
174 NSData* delta2 = [Cronet getGlobalMetricsDeltas];
175 EXPECT_FALSE([delta2 isEqualToData:delta1]);
210 } 176 }
211 177
212 TEST_F(HttpTest, SdchDisabledByDefault) { 178 TEST_F(HttpTest, SdchDisabledByDefault) {
213 const char kPath[] = "/sdchtest"; 179 NSURL* url =
214 RegisterPathHandler(kPath, 180 net::NSURLWithGURL(GURL(TestServer::GetEchoHeaderURL("Accept-Encoding")));
215 ^GCDWebServerResponse* (GCDWebServerRequest* req) {
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]; 181 NSURLSessionDataTask* task = [session_ dataTaskWithURL:url];
222 StartDataTaskAndWaitForCompletion(task); 182 StartDataTaskAndWaitForCompletion(task);
223 EXPECT_EQ(nil, [delegate_ error]); 183 EXPECT_EQ(nil, [delegate_ error]);
224 EXPECT_TRUE([delegate_ receivedBytes]); 184 EXPECT_FALSE([[delegate_ responseBody] containsString:@"sdch"]);
185 }
186
187 TEST_F(HttpTest, NSURLSessionAcceptLanguage) {
188 NSURL* url =
189 net::NSURLWithGURL(GURL(TestServer::GetEchoHeaderURL("Accept-Language")));
190 NSURLSessionDataTask* task = [session_ dataTaskWithURL:url];
191 StartDataTaskAndWaitForCompletion(task);
192 EXPECT_EQ(nil, [delegate_ error]);
193 ASSERT_STREQ("en-US,en", [[delegate_ responseBody] UTF8String]);
225 } 194 }
226 195
227 TEST_F(HttpTest, SetUserAgentIsExact) { 196 TEST_F(HttpTest, SetUserAgentIsExact) {
228 const char kPath[] = "/uatest"; 197 NSURL* url =
229 RegisterPathHandler(kPath, ^GCDWebServerResponse*(GCDWebServerRequest* req) { 198 net::NSURLWithGURL(GURL(TestServer::GetEchoHeaderURL("User-Agent")));
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]; 199 NSURLSessionDataTask* task = [session_ dataTaskWithURL:url];
237 StartDataTaskAndWaitForCompletion(task); 200 StartDataTaskAndWaitForCompletion(task);
238 EXPECT_EQ(nil, [delegate_ error]); 201 EXPECT_EQ(nil, [delegate_ error]);
239 EXPECT_TRUE([delegate_ receivedBytes]); 202 EXPECT_STREQ(kUserAgent, [[delegate_ responseBody] UTF8String]);
240 } 203 }
241 204
242 // TODO(ellyjones): There needs to be a test that enabling SDCH works, but 205 } // 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.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698