summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorstuartmorgan <stuartmorgan@chromium.org>2015-03-20 09:55:53 -0700
committerCommit bot <commit-bot@chromium.org>2015-03-20 16:56:24 +0000
commit9c337fc9eb6f0f5bdd012e742de5f247b3c8d489 (patch)
tree59a6a8ddbb22c765a10b14f16d0c18a80716293a
parentae17b0b0da06b898e7716a56235b43287fd3a23e (diff)
downloadchromium_src-9c337fc9eb6f0f5bdd012e742de5f247b3c8d489.zip
chromium_src-9c337fc9eb6f0f5bdd012e742de5f247b3c8d489.tar.gz
chromium_src-9c337fc9eb6f0f5bdd012e742de5f247b3c8d489.tar.bz2
Upstream ios/testing
Upstreams the ios/testing directory, which contains a helper utility for validating non-ObjC parameters in tests using OCMock. BUG=None Review URL: https://codereview.chromium.org/1024443002 Cr-Commit-Position: refs/heads/master@{#321583}
-rw-r--r--ios/ios.gyp5
-rw-r--r--ios/testing/DEPS4
-rw-r--r--ios/testing/ios_testing.gyp49
-rw-r--r--ios/testing/ocmock_complex_type_helper.h26
-rw-r--r--ios/testing/ocmock_complex_type_helper.mm78
-rw-r--r--ios/testing/ocmock_complex_type_helper_unittest.mm101
6 files changed, 261 insertions, 2 deletions
diff --git a/ios/ios.gyp b/ios/ios.gyp
index ee9eb71..80b221bd 100644
--- a/ios/ios.gyp
+++ b/ios/ios.gyp
@@ -11,10 +11,11 @@
'type': 'none',
'dependencies': [
'chrome/ios_chrome_tests.gyp:*',
- 'provider/ios_provider_chrome.gyp:*',
- 'provider/ios_provider_web.gyp:*',
'net/ios_net.gyp:*',
'net/ios_net_unittests.gyp:*',
+ 'provider/ios_provider_chrome.gyp:*',
+ 'provider/ios_provider_web.gyp:*',
+ 'testing/ios_testing.gyp:*',
'web/ios_web.gyp:*',
'web/ios_web_unittests.gyp:*',
],
diff --git a/ios/testing/DEPS b/ios/testing/DEPS
new file mode 100644
index 0000000..b94b26c
--- /dev/null
+++ b/ios/testing/DEPS
@@ -0,0 +1,4 @@
+include_rules = [
+ "+third_party/google_toolbox_for_mac",
+ "+third_party/ocmock",
+]
diff --git a/ios/testing/ios_testing.gyp b/ios/testing/ios_testing.gyp
new file mode 100644
index 0000000..d4525ce
--- /dev/null
+++ b/ios/testing/ios_testing.gyp
@@ -0,0 +1,49 @@
+# Copyright 2014 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': [
+ {
+ 'target_name': 'ocmock_support',
+ 'type': 'static_library',
+ 'dependencies': [
+ '../../base/base.gyp:base',
+ '../../third_party/ocmock/ocmock.gyp:ocmock',
+ '../../third_party/google_toolbox_for_mac/google_toolbox_for_mac.gyp:google_toolbox_for_mac',
+ ],
+ 'sources': [
+ 'ocmock_complex_type_helper.h',
+ 'ocmock_complex_type_helper.mm',
+ ],
+ 'include_dirs': [
+ '../..',
+ ],
+ },
+ {
+ 'target_name': 'ocmock_support_unittest',
+ 'type': 'executable',
+ 'variables': {
+ 'ios_product_name': '<(_target_name)',
+ },
+ 'sources': [
+ 'ocmock_complex_type_helper_unittest.mm',
+ ],
+ 'dependencies': [
+ 'ocmock_support',
+ '../../base/base.gyp:run_all_unittests',
+ '../../base/base.gyp:test_support_base',
+ '../../testing/gmock.gyp:gmock',
+ '../../testing/gtest.gyp:gtest',
+ '../../testing/iossim/iossim.gyp:iossim#host',
+ '../../third_party/ocmock/ocmock.gyp:ocmock',
+ ],
+ 'include_dirs': [
+ '../..',
+ ],
+ 'xcode_settings': {'OTHER_LDFLAGS': ['-ObjC']},
+ },
+ ],
+}
diff --git a/ios/testing/ocmock_complex_type_helper.h b/ios/testing/ocmock_complex_type_helper.h
new file mode 100644
index 0000000..ad8d83d
--- /dev/null
+++ b/ios/testing/ocmock_complex_type_helper.h
@@ -0,0 +1,26 @@
+// Copyright 2012 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.
+
+#ifndef IOS_TESTING_OCMOCK_COMPLEX_TYPE_HELPER_H_
+#define IOS_TESTING_OCMOCK_COMPLEX_TYPE_HELPER_H_
+
+#import "third_party/google_toolbox_for_mac/src/Foundation/GTMLightweightProxy.h"
+#import "third_party/ocmock/OCMock/OCMock.h"
+
+// OCMock cannot check scalar arguments to method as it requires NSObjects to
+// work its magic. This class tries to alleviate this restriction in a crude
+// way. For an example of use, see the associated unittest class.
+@interface OCMockComplexTypeHelper : GTMLightweightProxy
+// As opposed to its parent class the OCMockComplexTypeHelper retains its
+// represented object.
+- (instancetype)initWithRepresentedObject:(id)object;
+// Registers a block to be called when a selector is called.
+- (void)onSelector:(SEL)selector callBlockExpectation:(id)block;
+// Unregisters the block associated to the selector.
+- (void)removeBlockExpectationOnSelector:(SEL)selector;
+// Returns the block for the given selector. Intended for use by subclasses.
+- (id)blockForSelector:(SEL)selector;
+@end
+
+#endif // IOS_TESTING_OCMOCK_COMPLEX_TYPE_HELPER_H_
diff --git a/ios/testing/ocmock_complex_type_helper.mm b/ios/testing/ocmock_complex_type_helper.mm
new file mode 100644
index 0000000..bc89a88
--- /dev/null
+++ b/ios/testing/ocmock_complex_type_helper.mm
@@ -0,0 +1,78 @@
+// Copyright 2012 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 "ios/testing/ocmock_complex_type_helper.h"
+
+#include "base/logging.h"
+#include "base/mac/scoped_nsobject.h"
+
+@implementation OCMockComplexTypeHelper {
+ // Same as the superclass -representedObject, but retained.
+ base::scoped_nsobject<OCMockObject> _object;
+ // All the blocks registered by selector.
+ base::scoped_nsobject<NSMutableDictionary> _blocks;
+}
+
+#pragma mark - public methods.
+
+- (instancetype)initWithRepresentedObject:(id)object {
+ if ((self = [super initWithRepresentedObject:object]))
+ _object.reset([object retain]);
+ return self;
+}
+
+- (void)onSelector:(SEL)selector callBlockExpectation:(id)block {
+ if (!_blocks)
+ _blocks.reset([[NSMutableDictionary alloc] init]);
+
+ NSString* key = NSStringFromSelector(selector);
+ DCHECK(![_blocks objectForKey:key]) << "Only one expectation per signature";
+ base::scoped_nsobject<id> value([block copy]);
+ [_blocks setObject:value forKey:key];
+}
+
+- (void)removeBlockExpectationOnSelector:(SEL)selector {
+ NSString* key = NSStringFromSelector(selector);
+ DCHECK([_blocks objectForKey:key]) << "No expectation for selector "
+ << [key UTF8String];
+ [_blocks removeObjectForKey:key];
+}
+
+- (id)blockForSelector:(SEL)selector {
+ NSString* key = NSStringFromSelector(selector);
+ id block = [_blocks objectForKey:key];
+ DCHECK(block) << "Missing block expectation for selector "
+ << [key UTF8String];
+ return block;
+}
+
+#pragma mark - OCMockObject forwarding.
+
+// OCMockObject -respondsToSelector responds NO for the OCMock object specific
+// methods. This confuses the GTMLightweightProxy class. In order to forward
+// those properly the simplest approach is to forward them explicitely.
+- (id)stub {
+ return [_object stub];
+}
+- (id)expect {
+ return [_object expect];
+}
+- (id)reject {
+ return [_object reject];
+}
+- (void)verify {
+ [_object verify];
+}
+- (void)setExpectationOrderMatters:(BOOL)flag {
+ [_object setExpectationOrderMatters:flag];
+}
+
+#pragma mark - Internal methods.
+
+- (BOOL)respondsToSelector:(SEL)selector {
+ DCHECK(![_blocks objectForKey:NSStringFromSelector(selector)]);
+ return [super respondsToSelector:selector];
+}
+
+@end
diff --git a/ios/testing/ocmock_complex_type_helper_unittest.mm b/ios/testing/ocmock_complex_type_helper_unittest.mm
new file mode 100644
index 0000000..df2fba2
--- /dev/null
+++ b/ios/testing/ocmock_complex_type_helper_unittest.mm
@@ -0,0 +1,101 @@
+// Copyright 2012 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 "ios/testing/ocmock_complex_type_helper.h"
+
+#include "base/logging.h"
+#include "base/mac/scoped_nsobject.h"
+#include "testing/platform_test.h"
+#import "third_party/ocmock/OCMock/OCMock.h"
+#include "third_party/ocmock/gtest_support.h"
+
+// A complex type to test with..
+struct SampleComplexType {
+ int number;
+ float blob;
+};
+
+typedef int ScalarType;
+
+@protocol TestedProtocol
+- (void)passObject:(id)foo;
+- (void)passComplexType:(const SampleComplexType&)foo;
+- (void)passScalar:(ScalarType)foo;
+@end
+
+@interface MockClass : OCMockComplexTypeHelper
+@end
+
+@implementation MockClass
+
+typedef void (^complexTypeBlock)(const SampleComplexType&);
+
+- (void)passComplexType:(const SampleComplexType&)foo {
+ return static_cast<complexTypeBlock>([self blockForSelector:_cmd])(foo);
+}
+
+typedef void (^ScalarBlock)(const ScalarType&);
+
+- (void)passScalar:(ScalarType)foo {
+ return static_cast<ScalarBlock>([self blockForSelector:_cmd])(foo);
+}
+
+@end
+
+namespace {
+
+class OCMockComplexTypeHelperTest : public PlatformTest {
+ protected:
+ void SetUp() override {
+ PlatformTest::SetUp();
+ helped_mock_.reset([[MockClass alloc]
+ initWithRepresentedObject:
+ [OCMockObject mockForProtocol:@protocol(TestedProtocol)]]);
+ }
+
+ void TearDown() override {
+ EXPECT_OCMOCK_VERIFY(helped_mock_);
+ PlatformTest::TearDown();
+ }
+
+ base::scoped_nsobject<id> helped_mock_;
+};
+
+TEST_F(OCMockComplexTypeHelperTest, nilObjectStillWorks) {
+ [[helped_mock_ expect] passObject:nil];
+ [helped_mock_ passObject:nil];
+}
+
+TEST_F(OCMockComplexTypeHelperTest, anyObjectStillWorks) {
+ base::scoped_nsobject<id> someObject([[NSObject alloc] init]);
+ [[helped_mock_ expect] passObject:OCMOCK_ANY];
+ [helped_mock_ passObject:someObject];
+}
+
+TEST_F(OCMockComplexTypeHelperTest, complexType) {
+ const SampleComplexType expected_value = {1, 1.0};
+
+ complexTypeBlock block = ^(const SampleComplexType& value) {
+ EXPECT_EQ(expected_value.number, value.number);
+ EXPECT_EQ(expected_value.blob, value.blob);
+ };
+ [helped_mock_ onSelector:@selector(passComplexType:)
+ callBlockExpectation:(id)block];
+
+ [helped_mock_ passComplexType:expected_value];
+}
+
+TEST_F(OCMockComplexTypeHelperTest, scalarType) {
+ const ScalarType expected_value = 42;
+
+ ScalarBlock block = ^(const ScalarType& value) {
+ EXPECT_EQ(expected_value, value);
+ };
+ [helped_mock_ onSelector:@selector(passScalar:)
+ callBlockExpectation:(id)block];
+
+ [helped_mock_ passScalar:expected_value];
+}
+
+} // namespace