Skip to content

Commit b466d2e

Browse files
committed
Merge branch 'realNil' of git://github.com/dmaclach/ocmock into dmaclach-realNil
2 parents 461c694 + 4fd7245 commit b466d2e

File tree

6 files changed

+198
-22
lines changed

6 files changed

+198
-22
lines changed

Source/OCMock.xcodeproj/project.pbxproj

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,10 @@
281281
817EB1661BD7674D0047E85A /* OCMFunctionsPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 03F370CA1BAA1DE800CAD3E8 /* OCMFunctionsPrivate.h */; };
282282
8BF73E53246CA75E00B9A52C /* OCMNoEscapeBlockTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BF73E52246CA75E00B9A52C /* OCMNoEscapeBlockTests.m */; settings = {COMPILER_FLAGS = "-Xclang -fexperimental-optimized-noescape"; }; };
283283
8BF73E54246CA75E00B9A52C /* OCMNoEscapeBlockTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BF73E52246CA75E00B9A52C /* OCMNoEscapeBlockTests.m */; settings = {COMPILER_FLAGS = "-Xclang -fexperimental-optimized-noescape"; }; };
284+
8B11D4B72448E2E900247BE2 /* OCMCPlusPlus98Tests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8B11D4B62448E2E900247BE2 /* OCMCPlusPlus98Tests.mm */; settings = {COMPILER_FLAGS = "-std=gnu++98"; }; };
285+
8B11D4B82448E2F400247BE2 /* OCMCPlusPlus98Tests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8B11D4B62448E2E900247BE2 /* OCMCPlusPlus98Tests.mm */; settings = {COMPILER_FLAGS = "-std=gnu++98"; }; };
286+
8B11D4BA2448E53600247BE2 /* OCMCPlusPlus11Tests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8B11D4B92448E53600247BE2 /* OCMCPlusPlus11Tests.mm */; settings = {COMPILER_FLAGS = "-std=gnu++11"; }; };
287+
8B11D4BB2448E53600247BE2 /* OCMCPlusPlus11Tests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8B11D4B92448E53600247BE2 /* OCMCPlusPlus11Tests.mm */; settings = {COMPILER_FLAGS = "-std=gnu++11"; }; };
284288
8DE97C5522B43EE60098C63F /* OCMockObject.m in Sources */ = {isa = PBXBuildFile; fileRef = 03B3159E146333BF0052CD09 /* OCMockObject.m */; };
285289
8DE97C5622B43EE60098C63F /* OCClassMockObject.m in Sources */ = {isa = PBXBuildFile; fileRef = 03B3158C146333BF0052CD09 /* OCClassMockObject.m */; };
286290
8DE97C5722B43EE60098C63F /* OCPartialMockObject.m in Sources */ = {isa = PBXBuildFile; fileRef = 03B315AA146333BF0052CD09 /* OCPartialMockObject.m */; };
@@ -547,7 +551,7 @@
547551
2FA28006D043CBDBBAEF6E3F /* OCMMacroState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OCMMacroState.h; sourceTree = "<group>"; };
548552
2FA280987F4EA8A4D79000D0 /* OCMMacroState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OCMMacroState.m; sourceTree = "<group>"; };
549553
2FA280EB5E8CDEEAE76861F7 /* OCMNonRetainingObjectReturnValueProvider.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OCMNonRetainingObjectReturnValueProvider.m; sourceTree = "<group>"; };
550-
2FA2813F93050582D83E1499 /* OCMockObjectRuntimeTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OCMockObjectRuntimeTests.m; sourceTree = "<group>"; };
554+
2FA2813F93050582D83E1499 /* OCMockObjectRuntimeTests.m */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.objcpp; fileEncoding = 4; path = OCMockObjectRuntimeTests.m; sourceTree = "<group>"; };
551555
2FA2822E19948FC997965267 /* OCMockObjectTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OCMockObjectTests.m; sourceTree = "<group>"; };
552556
2FA2833B48908EAD36444671 /* OCMArgAction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OCMArgAction.h; sourceTree = "<group>"; };
553557
2FA283D58AA7569D8A5B0C57 /* OCMBlockArgCaller.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OCMBlockArgCaller.m; sourceTree = "<group>"; };
@@ -572,6 +576,8 @@
572576
3CFBDD761BB3DB200050D9C5 /* TestClassWithCustomReferenceCounting.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TestClassWithCustomReferenceCounting.m; sourceTree = "<group>"; };
573577
817EB1621BD765130047E85A /* OCMock.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = OCMock.framework; sourceTree = BUILT_PRODUCTS_DIR; };
574578
8BF73E52246CA75E00B9A52C /* OCMNoEscapeBlockTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OCMNoEscapeBlockTests.m; sourceTree = "<group>"; };
579+
8B11D4B62448E2E900247BE2 /* OCMCPlusPlus98Tests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = OCMCPlusPlus98Tests.mm; sourceTree = "<group>"; };
580+
8B11D4B92448E53600247BE2 /* OCMCPlusPlus11Tests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = OCMCPlusPlus11Tests.mm; sourceTree = "<group>"; };
575581
8DE97CA022B43EE60098C63F /* OCMock.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = OCMock.framework; sourceTree = BUILT_PRODUCTS_DIR; };
576582
A02926811CA0725A00594AAF /* TestObjects.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = TestObjects.xcdatamodel; sourceTree = "<group>"; };
577583
D31108AD1828DB8700737925 /* OCMockLibTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = OCMockLibTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -751,6 +757,8 @@
751757
037ECD5318FAD84100AF0E4C /* OCMInvocationMatcherTests.m */,
752758
031E50571BB4A56300E257C3 /* OCMBoxedReturnValueProviderTests.m */,
753759
03B316211463350E0052CD09 /* OCMConstraintTests.m */,
760+
8B11D4B62448E2E900247BE2 /* OCMCPlusPlus98Tests.mm */,
761+
8B11D4B92448E53600247BE2 /* OCMCPlusPlus11Tests.mm */,
754762
2FA28EDBF243639C57F88A1B /* OCMArgTests.m */,
755763
036865631D3571A8005E6BEE /* OCMQuantifierTests.m */,
756764
03B316291463350E0052CD09 /* OCObserverMockObjectTests.m */,
@@ -1501,9 +1509,11 @@
15011509
03565A4818F05721003AE91E /* OCMStubRecorderTests.m in Sources */,
15021510
03565A4518F05721003AE91E /* OCMockObjectForwardingTargetTests.m in Sources */,
15031511
2FA28FA53C57236B6DD64E82 /* OCMockObjectRuntimeTests.m in Sources */,
1512+
8B11D4BA2448E53600247BE2 /* OCMCPlusPlus11Tests.mm in Sources */,
15041513
2FA2839F33289795284C32FB /* OCMockObjectTests.m in Sources */,
15051514
038599F723807B06002B3ABE /* OCMockObjectInternalTests.m in Sources */,
15061515
8BF73E53246CA75E00B9A52C /* OCMNoEscapeBlockTests.m in Sources */,
1516+
8B11D4B72448E2E900247BE2 /* OCMCPlusPlus98Tests.mm in Sources */,
15071517
2FA28AB33F01A7D980F2C705 /* OCMockObjectDynamicPropertyMockingTests.m in Sources */,
15081518
031E50581BB4A56300E257C3 /* OCMBoxedReturnValueProviderTests.m in Sources */,
15091519
);
@@ -1614,9 +1624,11 @@
16141624
03C9CA1D18F05A75006DF94D /* OCMockObjectProtocolMocksTests.m in Sources */,
16151625
03E98D5118F310EE00522D42 /* OCMockObjectMacroTests.m in Sources */,
16161626
A06930951CA1BFC900513023 /* TestObjects.xcdatamodeld in Sources */,
1627+
8B11D4BB2448E53600247BE2 /* OCMCPlusPlus11Tests.mm in Sources */,
16171628
2FA28295E1F58F40A77D7448 /* OCMockObjectRuntimeTests.m in Sources */,
16181629
038599F823807B06002B3ABE /* OCMockObjectInternalTests.m in Sources */,
16191630
8BF73E54246CA75E00B9A52C /* OCMNoEscapeBlockTests.m in Sources */,
1631+
8B11D4B82448E2F400247BE2 /* OCMCPlusPlus98Tests.mm in Sources */,
16201632
2FA28246CD449A01717B1CEC /* OCMockObjectTests.m in Sources */,
16211633
2FA28F12AAD384A8CB16094B /* OCMockObjectDynamicPropertyMockingTests.m in Sources */,
16221634
);

Source/OCMock/OCMBoxedReturnValueProvider.m

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,18 @@
1818
#import "OCMFunctionsPrivate.h"
1919
#import "NSValue+OCMAdditions.h"
2020

21+
static BOOL IsZeroBuffer(const char* buffer, size_t length)
22+
{
23+
for(size_t i = 0; i < length; ++i)
24+
{
25+
if(buffer[i] != 0)
26+
{
27+
return NO;
28+
}
29+
}
30+
return YES;
31+
}
32+
2133
@implementation OCMBoxedReturnValueProvider
2234

2335
- (void)handleInvocation:(NSInvocation *)anInvocation
@@ -26,10 +38,13 @@ - (void)handleInvocation:(NSInvocation *)anInvocation
2638
NSUInteger returnTypeSize = [[anInvocation methodSignature] methodReturnLength];
2739
char valueBuffer[returnTypeSize];
2840
NSValue *returnValueAsNSValue = (NSValue *)returnValue;
41+
[returnValueAsNSValue getValue:valueBuffer];
2942

30-
if([self isMethodReturnType:returnType compatibleWithValueType:[returnValueAsNSValue objCType]])
43+
if([self isMethodReturnType:returnType
44+
compatibleWithValueType:[returnValueAsNSValue objCType]
45+
value:valueBuffer
46+
valueSize:returnTypeSize])
3147
{
32-
[returnValueAsNSValue getValue:valueBuffer];
3348
[anInvocation setReturnValue:valueBuffer];
3449
}
3550
else if([returnValueAsNSValue getBytes:valueBuffer objCType:returnType])
@@ -43,16 +58,37 @@ - (void)handleInvocation:(NSInvocation *)anInvocation
4358
}
4459
}
4560

46-
47-
- (BOOL)isMethodReturnType:(const char *)returnType compatibleWithValueType:(const char *)valueType
61+
- (BOOL)isMethodReturnType:(const char *)returnType compatibleWithValueType:(const char *)valueType value:(const char*)value valueSize:(size_t)valueSize
4862
{
4963
/* Same types are obviously compatible */
5064
if(strcmp(returnType, valueType) == 0)
5165
return YES;
5266

53-
/* Allow void* for methods that return id, mainly to be able to handle nil */
54-
if(strcmp(returnType, @encode(id)) == 0 && strcmp(valueType, @encode(void *)) == 0)
55-
return YES;
67+
// Special casing for nil and Nil
68+
if(strcmp(returnType, @encode(id)) == 0 || strcmp(returnType, @encode(Class)) == 0)
69+
{
70+
// Check to verify that the value is actually zero.
71+
if(IsZeroBuffer(value, valueSize))
72+
{
73+
// nil and Nil get potentially different encodings depending on the compilation
74+
// settings of the file where the return value gets recorded. We check to verify
75+
// against all the values we know of.
76+
const char *validNilEncodings[] =
77+
{
78+
@encode(void *), // Standard Obj C
79+
@encode(int), // 32 bit C++ (before nullptr)
80+
@encode(long long), // 64 bit C++ (before nullptr)
81+
@encode(char *), // C++ with nullptr
82+
};
83+
for(size_t i = 0; i < sizeof(validNilEncodings) / sizeof(validNilEncodings[0]); ++i)
84+
{
85+
if(strcmp(valueType, validNilEncodings[i]) == 0)
86+
{
87+
return YES;
88+
}
89+
}
90+
}
91+
}
5692

5793
return OCMEqualTypesAllowingOpaqueStructs(returnType, valueType);
5894
}

Source/OCMockTests/OCMBoxedReturnValueProviderTests.m

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,24 @@
1818
#import "OCMBoxedReturnValueProvider.h"
1919

2020
@interface OCMBoxedReturnValueProvider(Private)
21-
- (BOOL)isMethodReturnType:(const char *)returnType compatibleWithValueType:(const char *)valueType;
21+
- (BOOL)isMethodReturnType:(const char *)returnType compatibleWithValueType:(const char *)valueType value:(const char*)value valueSize:(size_t)valueSize;
2222
@end
2323

2424
@interface OCMBoxedReturnValueProviderTests : XCTestCase
25-
25+
{
26+
char value;
27+
size_t valueSize;
28+
}
2629
@end
2730

2831
@implementation OCMBoxedReturnValueProviderTests
2932

33+
- (void)setUp {
34+
[super setUp];
35+
value = 'A';
36+
valueSize = 1;
37+
}
38+
3039
- (void)testCorrectEqualityForCppProperty
3140
{
3241
// see https://github.com/erikdoe/ocmock/issues/96
@@ -53,12 +62,12 @@ - (void)testCorrectEqualityForCppProperty
5362
"r^{GURL}";
5463

5564
OCMBoxedReturnValueProvider *boxed = [OCMBoxedReturnValueProvider new];
56-
XCTAssertTrue([boxed isMethodReturnType:type1 compatibleWithValueType:type2]);
57-
XCTAssertTrue([boxed isMethodReturnType:type1 compatibleWithValueType:type3]);
58-
XCTAssertTrue([boxed isMethodReturnType:type2 compatibleWithValueType:type1]);
59-
XCTAssertTrue([boxed isMethodReturnType:type2 compatibleWithValueType:type3]);
60-
XCTAssertTrue([boxed isMethodReturnType:type3 compatibleWithValueType:type1]);
61-
XCTAssertTrue([boxed isMethodReturnType:type3 compatibleWithValueType:type2]);
65+
XCTAssertTrue([boxed isMethodReturnType:type1 compatibleWithValueType:type2 value:&value valueSize:valueSize]);
66+
XCTAssertTrue([boxed isMethodReturnType:type1 compatibleWithValueType:type3 value:&value valueSize:valueSize]);
67+
XCTAssertTrue([boxed isMethodReturnType:type2 compatibleWithValueType:type1 value:&value valueSize:valueSize]);
68+
XCTAssertTrue([boxed isMethodReturnType:type2 compatibleWithValueType:type3 value:&value valueSize:valueSize]);
69+
XCTAssertTrue([boxed isMethodReturnType:type3 compatibleWithValueType:type1 value:&value valueSize:valueSize]);
70+
XCTAssertTrue([boxed isMethodReturnType:type3 compatibleWithValueType:type2 value:&value valueSize:valueSize]);
6271
}
6372

6473

@@ -78,7 +87,7 @@ - (void)testCorrectEqualityForCppReturnTypesWithVtables
7887
"ar> >={__rep=(?={__long=QQ*}{__short=(?=Cc)[23c]}{__raw=[3Q]})}}}}";
7988

8089
OCMBoxedReturnValueProvider *boxed = [OCMBoxedReturnValueProvider new];
81-
XCTAssertTrue([boxed isMethodReturnType:type1 compatibleWithValueType:type2]);
90+
XCTAssertTrue([boxed isMethodReturnType:type1 compatibleWithValueType:type2 value:&value valueSize:valueSize]);
8291
}
8392

8493

@@ -89,7 +98,7 @@ - (void)testCorrectEqualityForStructureWithUnknownName
8998
const char *type2 = "{CLLocationCoordinate2D=dd}";
9099

91100
OCMBoxedReturnValueProvider *boxed = [OCMBoxedReturnValueProvider new];
92-
XCTAssertTrue([boxed isMethodReturnType:type1 compatibleWithValueType:type2]);
101+
XCTAssertTrue([boxed isMethodReturnType:type1 compatibleWithValueType:type2 value:&value valueSize:valueSize]);
93102

94103
}
95104

@@ -115,7 +124,7 @@ - (void)testCorrectEqualityForStructureWithoutName
115124
"pressed_pair<GURL *, std::__1::default_delete<GURL> >=^{GURL}}}}";
116125

117126
OCMBoxedReturnValueProvider *boxed = [OCMBoxedReturnValueProvider new];
118-
XCTAssertTrue([boxed isMethodReturnType:type1 compatibleWithValueType:type2]);
127+
XCTAssertTrue([boxed isMethodReturnType:type1 compatibleWithValueType:type2 value:&value valueSize:valueSize]);
119128

120129
}
121130

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* Copyright (c) 2020 Erik Doernenburg and contributors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may
5+
* not use these files except in compliance with the License. You may obtain
6+
* a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
* License for the specific language governing permissions and limitations
14+
* under the License.
15+
*/
16+
17+
#import <XCTest/XCTest.h>
18+
#import <OCMock/OCMock.h>
19+
20+
#if !defined(__cplusplus)
21+
#error This file must be compiled with C++
22+
#endif
23+
24+
#if !__has_feature(cxx_nullptr)
25+
#error This file must be compiled with a version of C++ that supports nullptr
26+
#endif
27+
28+
@interface OCMCPlusPlus11Tests : XCTestCase
29+
@end
30+
31+
32+
@implementation OCMCPlusPlus11Tests
33+
34+
- (void)testSetsUpStubReturningNilForIdReturnType
35+
{
36+
id mock = OCMPartialMock([NSArray arrayWithObject:@"Foo"]);
37+
38+
OCMExpect([mock lastObject]).andReturn(nil);
39+
XCTAssertNil([mock lastObject], @"Should have returned stubbed value");
40+
41+
OCMExpect([mock lastObject]).andReturn(Nil);
42+
XCTAssertNil([mock lastObject], @"Should have returned stubbed value");
43+
}
44+
45+
@end
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* Copyright (c) 2020 Erik Doernenburg and contributors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may
5+
* not use these files except in compliance with the License. You may obtain
6+
* a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
* License for the specific language governing permissions and limitations
14+
* under the License.
15+
*/
16+
17+
#import <XCTest/XCTest.h>
18+
#import <OCMock/OCMock.h>
19+
20+
#if !defined(__cplusplus)
21+
#error This file must be compiled with C++
22+
#endif
23+
24+
#if __has_feature(cxx_nullptr)
25+
#error This file must be compiled with a version of C++ (98) that doesn't support nullptr
26+
#endif
27+
28+
@interface OCMCPlusPlus98Tests : XCTestCase
29+
@end
30+
31+
32+
@implementation OCMCPlusPlus98Tests
33+
34+
- (void)testSetsUpStubReturningNilForIdReturnType
35+
{
36+
id mock = OCMPartialMock([NSArray arrayWithObject:@"Foo"]);
37+
38+
OCMExpect([mock lastObject]).andReturn(nil);
39+
XCTAssertNil([mock lastObject], @"Should have returned stubbed value");
40+
41+
OCMExpect([mock lastObject]).andReturn(Nil);
42+
XCTAssertNil([mock lastObject], @"Should have returned stubbed value");
43+
}
44+
45+
@end

Source/OCMockTests/OCMockObjectMacroTests.m

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,22 @@ - (NSDecimalNumber*)method {
5050

5151
@end
5252

53+
@interface TestClassWithClassReturnMethod : NSObject
54+
55+
- (Class)method;
56+
57+
@end
58+
59+
@implementation TestClassWithClassReturnMethod
60+
61+
- (Class)method
62+
{
63+
return [self class];
64+
}
65+
66+
@end
67+
68+
5369

5470
// implemented in OCMockObjectClassMethodMockingTests
5571

@@ -177,11 +193,24 @@ - (void)testSetsUpStubsWithStructureReturnValues
177193

178194
- (void)testSetsUpStubReturningNilForIdReturnType
179195
{
180-
id mock = OCMClassMock([NSString class]);
196+
id mock = OCMPartialMock([NSArray arrayWithObject:@"Foo"]);
197+
198+
OCMExpect([mock lastObject]).andReturn(nil);
199+
XCTAssertNil([mock lastObject], @"Should have returned stubbed value");
200+
201+
OCMExpect([mock lastObject]).andReturn(Nil);
202+
XCTAssertNil([mock lastObject], @"Should have returned stubbed value");
203+
}
204+
205+
- (void)testSetsUpStubReturningNilForClassReturnType
206+
{
207+
id mock = OCMPartialMock([[TestClassWithClassReturnMethod alloc] init]);
181208

182-
OCMStub([mock lowercaseString]).andReturn(nil);
209+
OCMExpect([mock method]).andReturn(nil);
210+
XCTAssertNil([mock method], @"Should have returned stubbed value");
183211

184-
XCTAssertNil([mock lowercaseString], @"Should have returned stubbed value");
212+
OCMExpect([mock method]).andReturn(Nil);
213+
XCTAssertNil([mock method], @"Should have returned stubbed value");
185214
}
186215

187216
- (void)testSetsUpExceptionThrowing

0 commit comments

Comments
 (0)