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 <Cronet/Cronet.h> | 5 #import <Cronet/Cronet.h> |
6 #import <Foundation/Foundation.h> | 6 #import <Foundation/Foundation.h> |
7 | 7 |
8 #include <stdint.h> | 8 #include <stdint.h> |
9 | 9 |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 10 matching lines...) Expand all Loading... | |
21 | 21 |
22 #include "url/gurl.h" | 22 #include "url/gurl.h" |
23 | 23 |
24 @interface TestDelegate : NSObject<NSURLSessionDataDelegate, | 24 @interface TestDelegate : NSObject<NSURLSessionDataDelegate, |
25 NSURLSessionDelegate, | 25 NSURLSessionDelegate, |
26 NSURLSessionTaskDelegate> | 26 NSURLSessionTaskDelegate> |
27 | 27 |
28 // Completion semaphore for this TestDelegate. When the request this delegate is | 28 // Completion semaphore for this TestDelegate. When the request this delegate is |
29 // attached to finishes (either successfully or with an error), this delegate | 29 // attached to finishes (either successfully or with an error), this delegate |
30 // signals this semaphore. | 30 // signals this semaphore. |
31 @property(assign, nonatomic) dispatch_semaphore_t semaphore; | 31 @property(assign, atomic) dispatch_semaphore_t semaphore; |
32 | |
33 // Body of response received by the request this delegate is attached to. | |
34 @property(retain, nonatomic) NSString* responseBody; | |
35 | 32 |
36 // Error the request this delegate is attached to failed with, if any. | 33 // Error the request this delegate is attached to failed with, if any. |
37 @property(retain, nonatomic) NSError* error; | 34 @property(retain, atomic) NSError* error; |
38 | 35 |
39 @end | 36 @end |
40 | 37 |
41 @implementation TestDelegate | 38 @implementation TestDelegate |
42 @synthesize semaphore = _semaphore; | 39 @synthesize semaphore = _semaphore; |
43 @synthesize responseBody = _responseBody; | |
44 @synthesize error = _error; | 40 @synthesize error = _error; |
45 | 41 |
42 NSMutableArray<NSData*>* _responseData; | |
43 | |
46 - (id)init { | 44 - (id)init { |
47 if (self = [super init]) { | 45 if (self = [super init]) { |
48 _semaphore = dispatch_semaphore_create(0); | 46 _semaphore = dispatch_semaphore_create(0); |
49 } | 47 } |
50 return self; | 48 return self; |
51 } | 49 } |
52 | 50 |
53 - (void)dealloc { | 51 - (void)dealloc { |
54 dispatch_release(_semaphore); | 52 dispatch_release(_semaphore); |
55 [_error release]; | 53 [_error release]; |
56 _error = nil; | 54 _error = nil; |
57 [super dealloc]; | 55 [super dealloc]; |
58 } | 56 } |
59 | 57 |
60 - (void)reset { | 58 - (void)reset { |
61 _responseBody = nil; | 59 [_responseData dealloc]; |
kapishnikov
2017/04/19 16:14:16
Are the test compiled under ARC? If yes, it should
mef
2017/04/19 17:39:09
Currently they are NOT. IIUIC Chrome does not use
kapishnikov
2017/04/19 18:19:01
I think ARC is the way to go. Let's keep the enab
mef
2017/04/19 19:04:48
ack, sgtm
| |
60 _responseData = nil; | |
62 _error = nil; | 61 _error = nil; |
63 } | 62 } |
64 | 63 |
64 - (NSString*)responseBody { | |
65 if (_responseData == nil) { | |
66 return nil; | |
67 } | |
68 NSMutableString* body = [NSMutableString string]; | |
69 for (NSData* data in _responseData) { | |
70 [body appendString:[[NSString alloc] initWithData:data | |
71 encoding:NSUTF8StringEncoding]]; | |
72 } | |
73 VLOG(3) << "responseBody size:" << [body length] | |
74 << " chunks:" << [_responseData count]; | |
75 return body; | |
76 } | |
77 | |
65 - (void)URLSession:(NSURLSession*)session | 78 - (void)URLSession:(NSURLSession*)session |
66 didBecomeInvalidWithError:(NSError*)error { | 79 didBecomeInvalidWithError:(NSError*)error { |
67 } | 80 } |
68 | 81 |
69 - (void)URLSession:(NSURLSession*)session | 82 - (void)URLSession:(NSURLSession*)session |
70 task:(NSURLSessionTask*)task | 83 task:(NSURLSessionTask*)task |
71 didCompleteWithError:(NSError*)error { | 84 didCompleteWithError:(NSError*)error { |
72 [self setError:error]; | 85 [self setError:error]; |
73 dispatch_semaphore_signal(_semaphore); | 86 dispatch_semaphore_signal(_semaphore); |
74 } | 87 } |
(...skipping 11 matching lines...) Expand all Loading... | |
86 dataTask:(NSURLSessionDataTask*)dataTask | 99 dataTask:(NSURLSessionDataTask*)dataTask |
87 didReceiveResponse:(NSURLResponse*)response | 100 didReceiveResponse:(NSURLResponse*)response |
88 completionHandler:(void (^)(NSURLSessionResponseDisposition disposition)) | 101 completionHandler:(void (^)(NSURLSessionResponseDisposition disposition)) |
89 completionHandler { | 102 completionHandler { |
90 completionHandler(NSURLSessionResponseAllow); | 103 completionHandler(NSURLSessionResponseAllow); |
91 } | 104 } |
92 | 105 |
93 - (void)URLSession:(NSURLSession*)session | 106 - (void)URLSession:(NSURLSession*)session |
94 dataTask:(NSURLSessionDataTask*)dataTask | 107 dataTask:(NSURLSessionDataTask*)dataTask |
95 didReceiveData:(NSData*)data { | 108 didReceiveData:(NSData*)data { |
96 NSString* stringData = | 109 if (_responseData == nil) { |
97 [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; | 110 _responseData = [[NSMutableArray alloc] init]; |
98 if (_responseBody == nil) { | |
99 _responseBody = stringData; | |
100 } else { | |
101 _responseBody = [_responseBody stringByAppendingString:stringData]; | |
102 } | 111 } |
112 [_responseData addObject:data]; | |
103 } | 113 } |
104 | 114 |
105 - (void)URLSession:(NSURLSession*)session | 115 - (void)URLSession:(NSURLSession*)session |
106 dataTask:(NSURLSessionDataTask*)dataTask | 116 dataTask:(NSURLSessionDataTask*)dataTask |
107 willCacheResponse:(NSCachedURLResponse*)proposedResponse | 117 willCacheResponse:(NSCachedURLResponse*)proposedResponse |
108 completionHandler: | 118 completionHandler: |
109 (void (^)(NSCachedURLResponse* cachedResponse))completionHandler { | 119 (void (^)(NSCachedURLResponse* cachedResponse))completionHandler { |
110 completionHandler(proposedResponse); | 120 completionHandler(proposedResponse); |
111 } | 121 } |
112 | 122 |
113 @end | 123 @end |
114 | 124 |
115 namespace cronet { | 125 namespace cronet { |
116 // base::TimeDelta would normally be ideal for this but it does not support | |
117 // nanosecond resolution. | |
118 static const int64_t ns_in_second = 1000000000LL; | |
119 const char kUserAgent[] = "CronetTest/1.0.0.0"; | 126 const char kUserAgent[] = "CronetTest/1.0.0.0"; |
120 | 127 |
121 class HttpTest : public ::testing::Test { | 128 class HttpTest : public ::testing::Test { |
122 protected: | 129 protected: |
123 HttpTest() {} | 130 HttpTest() {} |
124 ~HttpTest() override {} | 131 ~HttpTest() override {} |
125 | 132 |
126 void SetUp() override { | 133 void SetUp() override { |
127 grpc_support::StartQuicTestServer(); | 134 grpc_support::StartQuicTestServer(); |
128 TestServer::Start(); | 135 TestServer::Start(); |
(...skipping 18 matching lines...) Expand all Loading... | |
147 void TearDown() override { | 154 void TearDown() override { |
148 grpc_support::ShutdownQuicTestServer(); | 155 grpc_support::ShutdownQuicTestServer(); |
149 TestServer::Shutdown(); | 156 TestServer::Shutdown(); |
150 } | 157 } |
151 | 158 |
152 // Launches the supplied |task| and blocks until it completes, with a timeout | 159 // Launches the supplied |task| and blocks until it completes, with a timeout |
153 // of 1 second. | 160 // of 1 second. |
154 void StartDataTaskAndWaitForCompletion(NSURLSessionDataTask* task) { | 161 void StartDataTaskAndWaitForCompletion(NSURLSessionDataTask* task) { |
155 [delegate_ reset]; | 162 [delegate_ reset]; |
156 [task resume]; | 163 [task resume]; |
157 int64_t deadline_ns = 1 * ns_in_second; | 164 dispatch_semaphore_wait([delegate_ semaphore], DISPATCH_TIME_FOREVER); |
kapishnikov
2017/04/19 16:14:16
Why are we changing the timeout to DISPATCH_TIME_F
mef
2017/04/19 17:39:09
Done. One second was too short for perf tests. I'v
| |
158 dispatch_semaphore_wait([delegate_ semaphore], | |
159 dispatch_time(DISPATCH_TIME_NOW, deadline_ns)); | |
160 } | 165 } |
161 | 166 |
162 base::scoped_nsobject<NSURLSession> session_; | 167 base::scoped_nsobject<NSURLSession> session_; |
163 base::scoped_nsobject<TestDelegate> delegate_; | 168 base::scoped_nsobject<TestDelegate> delegate_; |
164 }; | 169 }; |
165 | 170 |
166 TEST_F(HttpTest, NSURLSessionReceivesData) { | 171 TEST_F(HttpTest, NSURLSessionReceivesData) { |
167 NSURL* url = net::NSURLWithGURL(GURL(grpc_support::kTestServerUrl)); | 172 NSURL* url = net::NSURLWithGURL(GURL(grpc_support::kTestServerSimpleUrl)); |
168 __block BOOL block_used = NO; | 173 __block BOOL block_used = NO; |
169 NSURLSessionDataTask* task = [session_ dataTaskWithURL:url]; | 174 NSURLSessionDataTask* task = [session_ dataTaskWithURL:url]; |
170 [Cronet setRequestFilterBlock:^(NSURLRequest* request) { | 175 [Cronet setRequestFilterBlock:^(NSURLRequest* request) { |
171 block_used = YES; | 176 block_used = YES; |
172 EXPECT_EQ([request URL], url); | 177 EXPECT_EQ([request URL], url); |
173 return YES; | 178 return YES; |
174 }]; | 179 }]; |
175 StartDataTaskAndWaitForCompletion(task); | 180 StartDataTaskAndWaitForCompletion(task); |
176 EXPECT_TRUE(block_used); | 181 EXPECT_TRUE(block_used); |
177 EXPECT_EQ(nil, [delegate_ error]); | 182 EXPECT_EQ(nil, [delegate_ error]); |
178 EXPECT_STREQ(grpc_support::kHelloBodyValue, | 183 EXPECT_STREQ(grpc_support::kSimpleBodyValue, |
179 base::SysNSStringToUTF8([delegate_ responseBody]).c_str()); | 184 base::SysNSStringToUTF8([delegate_ responseBody]).c_str()); |
180 } | 185 } |
181 | 186 |
187 TEST_F(HttpTest, NSURLSessionReceivesBigHttpDataLoop) { | |
188 int iterations = 50; | |
189 long size = 10 * 1024 * 1024; | |
190 LOG(INFO) << "Downloading " << size << " bytes " << iterations << " times."; | |
191 NSTimeInterval elapsed_avg = 0; | |
192 NSTimeInterval elapsed_max = 0; | |
193 NSURL* url = net::NSURLWithGURL(GURL(TestServer::GetBigDataURL(size))); | |
194 for (int i = 0; i < iterations; ++i) { | |
195 [delegate_ reset]; | |
196 __block BOOL block_used = NO; | |
197 NSURLSessionDataTask* task = [session_ dataTaskWithURL:url]; | |
198 [Cronet setRequestFilterBlock:^(NSURLRequest* request) { | |
199 block_used = YES; | |
200 EXPECT_EQ([request URL], url); | |
201 return YES; | |
202 }]; | |
203 NSDate* date = [NSDate date]; | |
204 StartDataTaskAndWaitForCompletion(task); | |
205 NSTimeInterval elapsed = [date timeIntervalSinceNow] * -1000.0; | |
kapishnikov
2017/04/19 18:19:01
NSTimeInterval should always contain the time inte
mef
2017/04/19 19:04:48
Good point. Done.
| |
206 elapsed_avg += elapsed; | |
207 if (elapsed > elapsed_max) | |
208 elapsed_max = elapsed; | |
209 EXPECT_TRUE(block_used); | |
210 EXPECT_EQ(nil, [delegate_ error]); | |
211 } | |
212 LOG(INFO) << "Elapsed Average:" << elapsed_avg / iterations | |
213 << "ms Max:" << elapsed_max << "ms"; | |
214 } | |
215 | |
182 TEST_F(HttpTest, GetGlobalMetricsDeltas) { | 216 TEST_F(HttpTest, GetGlobalMetricsDeltas) { |
183 NSData* delta1 = [Cronet getGlobalMetricsDeltas]; | 217 NSData* delta1 = [Cronet getGlobalMetricsDeltas]; |
184 | 218 |
185 NSURL* url = net::NSURLWithGURL(GURL(grpc_support::kTestServerUrl)); | 219 NSURL* url = net::NSURLWithGURL(GURL(grpc_support::kTestServerSimpleUrl)); |
186 NSURLSessionDataTask* task = [session_ dataTaskWithURL:url]; | 220 NSURLSessionDataTask* task = [session_ dataTaskWithURL:url]; |
187 StartDataTaskAndWaitForCompletion(task); | 221 StartDataTaskAndWaitForCompletion(task); |
188 EXPECT_EQ(nil, [delegate_ error]); | 222 EXPECT_EQ(nil, [delegate_ error]); |
189 EXPECT_STREQ(grpc_support::kHelloBodyValue, | 223 EXPECT_STREQ(grpc_support::kSimpleBodyValue, |
190 base::SysNSStringToUTF8([delegate_ responseBody]).c_str()); | 224 base::SysNSStringToUTF8([delegate_ responseBody]).c_str()); |
191 | 225 |
192 NSData* delta2 = [Cronet getGlobalMetricsDeltas]; | 226 NSData* delta2 = [Cronet getGlobalMetricsDeltas]; |
193 EXPECT_FALSE([delta2 isEqualToData:delta1]); | 227 EXPECT_FALSE([delta2 isEqualToData:delta1]); |
194 } | 228 } |
195 | 229 |
196 TEST_F(HttpTest, SdchDisabledByDefault) { | 230 TEST_F(HttpTest, SdchDisabledByDefault) { |
197 NSURL* url = | 231 NSURL* url = |
198 net::NSURLWithGURL(GURL(TestServer::GetEchoHeaderURL("Accept-Encoding"))); | 232 net::NSURLWithGURL(GURL(TestServer::GetEchoHeaderURL("Accept-Encoding"))); |
199 NSURLSessionDataTask* task = [session_ dataTaskWithURL:url]; | 233 NSURLSessionDataTask* task = [session_ dataTaskWithURL:url]; |
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
409 [Cronet setRequestFilterBlock:^(NSURLRequest* request) { | 443 [Cronet setRequestFilterBlock:^(NSURLRequest* request) { |
410 EXPECT_TRUE(false) << "Block should not be called for unsupported requests"; | 444 EXPECT_TRUE(false) << "Block should not be called for unsupported requests"; |
411 return YES; | 445 return YES; |
412 }]; | 446 }]; |
413 StartDataTaskAndWaitForCompletion(task); | 447 StartDataTaskAndWaitForCompletion(task); |
414 EXPECT_EQ(nil, [delegate_ error]); | 448 EXPECT_EQ(nil, [delegate_ error]); |
415 EXPECT_TRUE([[delegate_ responseBody] containsString:testString]); | 449 EXPECT_TRUE([[delegate_ responseBody] containsString:testString]); |
416 } | 450 } |
417 | 451 |
418 } // namespace cronet | 452 } // namespace cronet |
OLD | NEW |