diff --git a/infer/models/objc/src/CADisplayLink.h b/infer/models/objc/src/CADisplayLink.h new file mode 100644 index 000000000..278773255 --- /dev/null +++ b/infer/models/objc/src/CADisplayLink.h @@ -0,0 +1,33 @@ +/* +* Copyright (c) 2015 - present Facebook, Inc. +* All rights reserved. +* +* This source code is licensed under the BSD style license found in the +* LICENSE file in the root directory of this source tree. An additional grant +* of patent rights can be found in the PATENTS file in the same directory. +*/ + +#import + +@interface CADisplayLink : NSObject { + + id _target; + SEL _selector; +} + +@property(readonly, nonatomic) CFTimeInterval duration; + +@property(nonatomic) NSInteger frameInterval; + +@property(getter=isPaused, nonatomic) BOOL paused; + +@property(readonly, nonatomic) CFTimeInterval timestamp; + +// Returns a new display link. ++ (CADisplayLink *)displayLinkWithTarget:(id)target + selector:(SEL)sel; + +// Release the target +- (void) invalidate; + +@end diff --git a/infer/models/objc/src/CADisplayLink.m b/infer/models/objc/src/CADisplayLink.m new file mode 100644 index 000000000..c52c22410 --- /dev/null +++ b/infer/models/objc/src/CADisplayLink.m @@ -0,0 +1,31 @@ +/* +* Copyright (c) 2015 - present Facebook, Inc. +* All rights reserved. +* +* This source code is licensed under the BSD style license found in the +* LICENSE file in the root directory of this source tree. An additional grant +* of patent rights can be found in the PATENTS file in the same directory. +*/ + +#import "CADisplayLink.h" + +@implementation CADisplayLink + +// Returns a new display link. +// The model retains strongly the target object. ++ (CADisplayLink *)displayLinkWithTarget:(id)target + selector:(SEL)sel { + + CADisplayLink *c = [CADisplayLink alloc]; + c->_target = target; + c->_selector = sel; + + return c; +} + +// Release the target +- (void) invalidate { + self->_target = nil; +} + +@end diff --git a/infer/tests/codetoanalyze/objc/errors/memory_leaks_benchmark/CADisplayLinkRetainCycle.m b/infer/tests/codetoanalyze/objc/errors/memory_leaks_benchmark/CADisplayLinkRetainCycle.m new file mode 100644 index 000000000..5479c43ef --- /dev/null +++ b/infer/tests/codetoanalyze/objc/errors/memory_leaks_benchmark/CADisplayLinkRetainCycle.m @@ -0,0 +1,58 @@ +/* +* Copyright (c) 2015 - present Facebook, Inc. +* All rights reserved. +* +* This source code is licensed under the BSD style license found in the +* LICENSE file in the root directory of this source tree. An additional grant +* of patent rights can be found in the PATENTS file in the same directory. +*/ + +#import +#import + + +@interface A : NSObject +@property (nonatomic, strong) CADisplayLink *displayLink; + +- (void) bla; +- (void) invalidate; +@end + +@implementation A + +- init { + _displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(bla)]; + + return self; + +} + +- (void) bla {}; + +- (void) invalidate { + // unregister displayLink target + [_displayLink invalidate]; + +}; + +- (void) dealloc { + [self dealloc]; +} + +@end + + +void testCycle() { + + A* a = [[A alloc] init]; + A* b = a; + +} + +void testNoCycle() { + + A* a = [[A alloc] init]; + [a invalidate]; //break the cycle + [a dealloc]; + +} diff --git a/infer/tests/endtoend/objc/CADisplayLinkTest.java b/infer/tests/endtoend/objc/CADisplayLinkTest.java new file mode 100644 index 000000000..f28356cad --- /dev/null +++ b/infer/tests/endtoend/objc/CADisplayLinkTest.java @@ -0,0 +1,65 @@ +/* +* Copyright (c) 2015 - present Facebook, Inc. +* All rights reserved. +* +* This source code is licensed under the BSD style license found in the +* LICENSE file in the root directory of this source tree. An additional grant +* of patent rights can be found in the PATENTS file in the same directory. +*/ + +package endtoend.objc; + +import static org.hamcrest.MatcherAssert.assertThat; +import static utils.matchers.ResultContainsExactly.containsExactly; + +import com.google.common.collect.ImmutableList; + +import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.Test; + +import java.io.IOException; + +import utils.DebuggableTemporaryFolder; +import utils.InferException; +import utils.InferResults; +import utils.InferRunner; + +public class CADisplayLinkTest { + + public static final String CAD_FILE = + "infer/tests/codetoanalyze/objc/errors/memory_leaks_benchmark/CADisplayLinkRetainCycle.m"; + + private static ImmutableList inferCmd; + + public static final String RETAIN_CYCLE = "RETAIN_CYCLE"; + + @ClassRule + public static DebuggableTemporaryFolder folder = new DebuggableTemporaryFolder(); + + @BeforeClass + public static void runInfer() throws InterruptedException, IOException { + inferCmd = InferRunner.createObjCInferCommand( + folder, + CAD_FILE); + } + + @Test + public void RetainCycleShouldBeFound() + throws InterruptedException, IOException, InferException { + InferResults inferResults = InferRunner.runInferObjC(inferCmd); + String[] methods = { + "testCycle", + }; + assertThat( + "Results should contain " + RETAIN_CYCLE, + inferResults, + containsExactly( + RETAIN_CYCLE, + CAD_FILE, + methods + ) + ); + } + +}