blob: dbcc34e6a71cde5a8e37e513a8286a07d936298f [file] [log] [blame] [edit]
/*
* Copyright (c) 2020-2021 Erik Doernenburg and contributors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use these files except in compliance with the License. You may obtain
* a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
#import <XCTest/XCTest.h>
#import "OCMFunctionsPrivate.h"
#import "OCMock.h"
@interface NSString (NoEscapeBlock)
@end
@implementation NSString (NoEscapeBlock)
- (void)methodWithNoEscapeBlock:(void(NS_NOESCAPE ^)(void))block
{
}
@end
// Verifies that the block being passed in is a noescape block.
@interface BlockCapturer : NSProxy
@end
@implementation BlockCapturer
{
XCTestExpectation *expectation;
}
- (instancetype)initWithExpectation:(XCTestExpectation *)anExpectation
{
expectation = anExpectation;
return self;
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector
{
return [NSString instanceMethodSignatureForSelector:selector];
}
- (void)forwardInvocation:(NSInvocation *)invocation
{
__unsafe_unretained id block;
[invocation getArgument:&block atIndex:2];
if(OCMIsNonEscapingBlock(block))
{
[expectation fulfill];
}
}
@end
@interface OCMNoEscapeBlockTests : XCTestCase
@end
@implementation OCMNoEscapeBlockTests
- (void)testThatBlocksAreNoEscape
{
// This tests that this file is compiled with
// `-Xclang -fexperimental-optimized-noescape` or equivalent.
XCTestExpectation *expectation = [self expectationWithDescription:@"Block should be noescape"];
id blockCapturer = [[BlockCapturer alloc] initWithExpectation:expectation];
int i = 0;
[blockCapturer methodWithNoEscapeBlock:^{
// Force i to be pulled into the closure.
(void)i;
}];
[self waitForExpectationsWithTimeout:0 handler:nil];
}
- (void)testNoEscapeBlocksAreNotRetained
{
// This tests that OCMock can handle noescape blocks.
// It crashes if it fails
id mock = [OCMockObject mockForClass:[NSString class]];
[[mock stub] methodWithNoEscapeBlock:[OCMArg invokeBlock]];
int i = 0;
[mock methodWithNoEscapeBlock:^{
// Force i to be pulled into the closure.
(void)i;
}];
}
@end