summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorellyjones <ellyjones@chromium.org>2015-08-12 09:19:00 -0700
committerCommit bot <commit-bot@chromium.org>2015-08-12 16:19:46 +0000
commit829ab733f47fd0fa4395f6347411a5a5ab41451b (patch)
treebf4f0bc816b6598091c231a1315c79f364c398c6
parentc0d31ab28e21c048f40584ace3b0a8aca5723c17 (diff)
downloadchromium_src-829ab733f47fd0fa4395f6347411a5a5ab41451b.zip
chromium_src-829ab733f47fd0fa4395f6347411a5a5ab41451b.tar.gz
chromium_src-829ab733f47fd0fa4395f6347411a5a5ab41451b.tar.bz2
Add CrNet integration test framework.
this adds a new target, crnet_test, which builds a standalone binary that runs CrNet integration tests. Currently there are only two tests, which cover basic HTTP fetch functionality. Further tests will be added in later CLs. BUG=422451 Review URL: https://codereview.chromium.org/1235203002 Cr-Commit-Position: refs/heads/master@{#343027}
-rw-r--r--ios/crnet/DEPS1
-rw-r--r--ios/crnet/test/Default.pngbin0 -> 6540 bytes
-rw-r--r--ios/crnet/test/crnet_http_tests.mm196
-rw-r--r--ios/crnet/test/crnet_test.gyp40
-rw-r--r--ios/crnet/test/crnet_test_runner.mm11
-rw-r--r--ios/ios.gyp1
6 files changed, 249 insertions, 0 deletions
diff --git a/ios/crnet/DEPS b/ios/crnet/DEPS
index df845d4..928073c 100644
--- a/ios/crnet/DEPS
+++ b/ios/crnet/DEPS
@@ -3,6 +3,7 @@ include_rules = [
"+crypto/nss_util.h",
"+ios/crnet",
"+ios/net",
+ "+ios/third_party/gcdwebserver",
"+ios/web/public/user_agent.h",
"+net"
]
diff --git a/ios/crnet/test/Default.png b/ios/crnet/test/Default.png
new file mode 100644
index 0000000..4c8ca6f69
--- /dev/null
+++ b/ios/crnet/test/Default.png
Binary files differ
diff --git a/ios/crnet/test/crnet_http_tests.mm b/ios/crnet/test/crnet_http_tests.mm
new file mode 100644
index 0000000..4436e09
--- /dev/null
+++ b/ios/crnet/test/crnet_http_tests.mm
@@ -0,0 +1,196 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import <Foundation/Foundation.h>
+
+#import "CrNet.h"
+
+#include "base/mac/scoped_nsobject.h"
+#import "ios/third_party/gcdwebserver/src/GCDWebServer/Core/GCDWebServer.h"
+#include "net/base/mac/url_conversions.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/gtest_mac.h"
+#include "url/gurl.h"
+
+@interface TestDelegate : NSObject<NSURLSessionDataDelegate,
+ NSURLSessionDelegate,
+ NSURLSessionTaskDelegate>
+
+// Completion semaphore for this TestDelegate. When the request this delegate is
+// attached to finishes (either successfully or with an error), this delegate
+// signals this semaphore.
+@property(assign, nonatomic) dispatch_semaphore_t semaphore;
+
+// Total count of bytes received by the request this delegate is attached to.
+@property(nonatomic) unsigned long receivedBytes;
+
+// Error the request this delegate is attached to failed with, if any.
+@property(retain, nonatomic) NSError* error;
+
+@end
+
+@implementation TestDelegate
+@synthesize semaphore = _semaphore;
+@synthesize receivedBytes = _receivedBytes;
+@synthesize error = _error;
+
+- (id)init {
+ if (self = [super init]) {
+ _semaphore = dispatch_semaphore_create(0);
+ }
+ return self;
+}
+
+- (void)dealloc {
+ dispatch_release(_semaphore);
+ [_error release];
+ _error = nil;
+ [super dealloc];
+}
+
+- (void)URLSession:(NSURLSession*)session
+ didBecomeInvalidWithError:(NSError*)error {
+}
+
+- (void)URLSession:(NSURLSession*)session
+ task:(NSURLSessionTask*)task
+ didCompleteWithError:(NSError*)error {
+ [self setError:error];
+ dispatch_semaphore_signal(_semaphore);
+}
+
+- (void)URLSession:(NSURLSession*)session
+ task:(NSURLSessionTask*)task
+ didReceiveChallenge:(NSURLAuthenticationChallenge*)challenge
+ completionHandler:
+ (void (^)(NSURLSessionAuthChallengeDisposition disp,
+ NSURLCredential* credential))completionHandler {
+ completionHandler(NSURLSessionAuthChallengeUseCredential, nil);
+}
+
+- (void)URLSession:(NSURLSession*)session
+ dataTask:(NSURLSessionDataTask*)dataTask
+ didReceiveResponse:(NSURLResponse*)response
+ completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))
+ completionHandler {
+ completionHandler(NSURLSessionResponseAllow);
+}
+
+- (void)URLSession:(NSURLSession*)session
+ dataTask:(NSURLSessionDataTask*)dataTask
+ didReceiveData:(NSData*)data {
+ _receivedBytes += (unsigned long)data.length;
+}
+
+- (void)URLSession:(NSURLSession*)session
+ dataTask:(NSURLSessionDataTask*)dataTask
+ willCacheResponse:(NSCachedURLResponse*)proposedResponse
+ completionHandler:
+ (void (^)(NSCachedURLResponse* cachedResponse))completionHandler {
+ completionHandler(proposedResponse);
+}
+
+@end
+
+// base::TimeDelta would normally be ideal for this but it does not support
+// nanosecond resolution.
+static const int64_t ns_in_second = 1000000000LL;
+
+class HttpTest : public ::testing::Test {
+ protected:
+ HttpTest() {}
+ ~HttpTest() override {}
+
+ void SetUp() override {
+ [CrNet setPartialUserAgent:@"CrNetTest/1.0.0.0"];
+ [CrNet install];
+ NSURLSessionConfiguration* config =
+ [NSURLSessionConfiguration ephemeralSessionConfiguration];
+ [CrNet installIntoSessionConfiguration:config];
+ delegate_.reset([[TestDelegate alloc] init]);
+ NSURLSession* session = [NSURLSession sessionWithConfiguration:config
+ delegate:delegate_
+ delegateQueue:nil];
+ // Take a reference to the session and store it so it doesn't get
+ // deallocated until this object does.
+ session_.reset([session retain]);
+ web_server_.reset([[GCDWebServer alloc] init]);
+ }
+
+ void TearDown() override {
+ [CrNet uninstall];
+ [web_server_ stop];
+ }
+
+ // Starts a GCDWebServer instance on localhost port 8080, and remembers the
+ // root URL for later; tests can use GetURL() to produce a URL referring to a
+ // specific resource under the root URL.
+ void StartWebServer() {
+ [web_server_ startWithPort:8080 bonjourName:nil];
+ server_root_ = net::GURLWithNSURL([web_server_ serverURL]);
+ }
+
+ // Registers a fixed response |text| to be returned to requests for |path|,
+ // which is relative to |server_root_|.
+ void RegisterPathText(const std::string& path, const std::string& text) {
+ NSString* nspath =
+ [NSString stringWithCString:path.c_str() encoding:NSUTF8StringEncoding];
+ NSData* data = [NSData dataWithBytes:text.c_str() length:text.length()];
+ [web_server_ addGETHandlerForPath:nspath
+ staticData:data
+ contentType:@"text/plain"
+ cacheAge:30];
+ }
+
+ // Launches the supplied |task| and blocks until it completes, with a timeout
+ // of 1 second.
+ void StartDataTaskAndWaitForCompletion(NSURLSessionDataTask* task) {
+ [task resume];
+ int64_t deadline_ns = 1 * ns_in_second;
+ dispatch_semaphore_wait([delegate_ semaphore],
+ dispatch_time(DISPATCH_TIME_NOW, deadline_ns));
+ }
+
+ // Returns a URL to refer to the resource named |path| served by the test
+ // server. If |path| starts with a /, the leading / will be stripped.
+ GURL GetURL(const std::string& path) {
+ std::string real_path = path[0] == '/' ? path.substr(1) : path;
+ return server_root_.Resolve(real_path);
+ }
+
+ base::scoped_nsobject<NSURLSession> session_;
+ base::scoped_nsobject<TestDelegate> delegate_;
+
+ private:
+ base::scoped_nsobject<GCDWebServer> web_server_;
+ GURL server_root_;
+};
+
+TEST_F(HttpTest, NSURLConnectionReceivesData) {
+ const char kData[] = "foobar";
+ const char kPath[] = "/foo";
+ RegisterPathText(kPath, kData);
+ StartWebServer();
+
+ NSURL* url = net::NSURLWithGURL(GetURL(kPath));
+ NSURLRequest* req = [NSURLRequest requestWithURL:url];
+ NSURLResponse* resp = nil;
+ NSError* error = nil;
+ NSData* received = [NSURLConnection sendSynchronousRequest:req
+ returningResponse:&resp
+ error:&error];
+ EXPECT_EQ(0, memcmp([received bytes], kData, sizeof(kData)));
+}
+
+TEST_F(HttpTest, NSURLSessionReceivesData) {
+ const char data[] = "foobar";
+ RegisterPathText("/foo", data);
+ StartWebServer();
+
+ NSURL* url = net::NSURLWithGURL(GetURL("foo"));
+ NSURLSessionDataTask* task = [session_ dataTaskWithURL:url];
+ StartDataTaskAndWaitForCompletion(task);
+ EXPECT_EQ(nil, [delegate_ error]);
+ EXPECT_EQ(strlen(data), [delegate_ receivedBytes]);
+}
diff --git a/ios/crnet/test/crnet_test.gyp b/ios/crnet/test/crnet_test.gyp
new file mode 100644
index 0000000..ea785b2
--- /dev/null
+++ b/ios/crnet/test/crnet_test.gyp
@@ -0,0 +1,40 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'variables': {
+ 'chromium_code': 1,
+ },
+ 'targets': [],
+ 'conditions': [
+ # The CrNet build is ninja-only because of the hack in
+ # ios/build/packaging/link_dependencies.py.
+ ['OS=="ios" and "<(GENERATOR)"=="ninja"', {
+ 'targets': [
+ {
+ 'target_name': 'crnet_test',
+ 'type': 'executable',
+ 'dependencies': [
+ '../../../ios/crnet/crnet.gyp:crnet',
+ '../../../ios/third_party/gcdwebserver/gcdwebserver.gyp:gcdwebserver',
+ '../../../testing/gtest.gyp:gtest',
+ ],
+ 'sources': [
+ 'crnet_http_tests.mm',
+ 'crnet_test_runner.mm',
+ ],
+ 'mac_bundle_resources': [
+ 'Default.png',
+ ],
+ 'include_dirs': [
+ '../../..',
+ '..',
+ ],
+ 'link_settings': {
+ },
+ },
+ ],
+ }],
+ ],
+}
diff --git a/ios/crnet/test/crnet_test_runner.mm b/ios/crnet/test/crnet_test_runner.mm
new file mode 100644
index 0000000..869f738
--- /dev/null
+++ b/ios/crnet/test/crnet_test_runner.mm
@@ -0,0 +1,11 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/gtest_mac.h"
+
+int main(int argc, char* argv[]) {
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
diff --git a/ios/ios.gyp b/ios/ios.gyp
index 4caf955..17af2d1 100644
--- a/ios/ios.gyp
+++ b/ios/ios.gyp
@@ -14,6 +14,7 @@
'crnet/crnet.gyp:*',
'crnet/crnet_pack.gyp:*',
'crnet/crnet_consumer/crnet_consumer.gyp:*',
+ 'crnet/test/crnet_test.gyp:*',
'net/ios_net.gyp:*',
'net/ios_net_unittests.gyp:*',
'provider/ios_provider_chrome.gyp:*',