Commit 9c337fc9 authored by stuartmorgan's avatar stuartmorgan Committed by Commit bot

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}
parent ae17b0b0
......@@ -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:*',
],
......
include_rules = [
"+third_party/google_toolbox_for_mac",
"+third_party/ocmock",
]
# 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']},
},
],
}
// 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_
// 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
// 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
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment