diff options
author | stuartmorgan <stuartmorgan@chromium.org> | 2015-03-20 09:55:53 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-03-20 16:56:24 +0000 |
commit | 9c337fc9eb6f0f5bdd012e742de5f247b3c8d489 (patch) | |
tree | 59a6a8ddbb22c765a10b14f16d0c18a80716293a | |
parent | ae17b0b0da06b898e7716a56235b43287fd3a23e (diff) | |
download | chromium_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.gyp | 5 | ||||
-rw-r--r-- | ios/testing/DEPS | 4 | ||||
-rw-r--r-- | ios/testing/ios_testing.gyp | 49 | ||||
-rw-r--r-- | ios/testing/ocmock_complex_type_helper.h | 26 | ||||
-rw-r--r-- | ios/testing/ocmock_complex_type_helper.mm | 78 | ||||
-rw-r--r-- | ios/testing/ocmock_complex_type_helper_unittest.mm | 101 |
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 |