Closed grigorye closed 5 years ago
OK, it looks like it's not a leak rather side effect observed after completion of -testPromiseDelaySuccess
: the promise leaked remains retained for about 1 second due to FBLDelay(1, ...)
. Will do PR that fixes that.
Hi Grigory,
Thank you for taking a closer look at the tests and checking the lib for leaks!
Please keep in mind that test is designed to retain the promise for an extended period of time (1 sec) and tries to reject it afterwards, which normally has no effect because the promise should have been already resolved after the delay of 0.1 sec specified in the delay operation. So the promise stays retained by GCD in FBLDelay after the test succeeds. Not sure why the leaks checker flags that as an issue, but that’s pretty much by design.
To satisfy the leak checker we need to make sure the FBLDelay block has a chance to complete before the test has ended (by using XCTestExpectation, for example). But I’m not sure it’s worth doing really, since it doesn’t add any value to the test and the test doesn’t leak either. WDYT?
Thanks.
Yep, I believe I understand the design of the test. The leaker flags it as a leak because it's naive in assumption that there should be no objects retained after the test execution (and it flags any such an object as a "likely leaked" one).
As for "whether it's worth fixing it" - I'm not sure about your attitude to this, but I would fix it - it's clearly a side effect observed after the test execution. As a side effect it might affect the code (in this case, other tests) executed afterwards. Actually, if I get it correctly, if there's a test afterwards, -reject:
will be executed in context of that next test (or a test after the next test - imagine it). If -reject:
has a problem (e.g. crash or bug), it won't be revealed by -testPromiseDelaySuccess
at all, it will affect some other test and etc. So, it looks like it's not only "delayed retain" but potentially "test reliability" problem.
Let me illustrate it.
I added dummy test that would be executed after -testPromiseDelaySuccess
(the tests seem to be executed in lexicographical order, so all other cases in FBLPromiseDelayTests are executed before -testPromiseDelaySuccess
):
- (void)testPromiseDelaySuccessOtherWay {
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:5]];
}
Added %H %B @self@
non-stopping debugger log action on -initXXX
, -dealloc
and -reject:
in FBLPromise.
Selected just -testPromiseDelaySuccess
and -testPromiseDelaySuccessOtherWay
in schema tests.
Run test action:
Test Suite 'FBLPromiseDelayTests' started at 2018-12-14 08:08:54.235
Test Case '-[FBLPromiseDelayTests testPromiseDelaySuccess]' started.
1 -initWithResolution: 0x7f955e4c26a0
1 -initPending 0x7f955e4c2800
2 -initPending 0x7f955e4c29d0
3 -initPending 0x7f9560815260
1 -dealloc 0x7f955e4c26a0
2 -dealloc 0x7f955e4c29d0
3 -dealloc 0x7f9560815260
Test Case '-[FBLPromiseDelayTests testPromiseDelaySuccess]' passed (1.310 seconds).
Test Case '-[FBLPromiseDelayTests testPromiseDelaySuccessOtherWay]' started.
1 -reject: 0x7f955e4c2800
4 -dealloc 0x7f955e4c2800
Test Case '-[FBLPromiseDelayTests testPromiseDelaySuccessOtherWay]' passed (5.003 seconds).
Test Suite 'FBLPromiseDelayTests' passed at 2018-12-14 08:09:00.551.
As you can see, we get -reject:
for promise allocated in -testPromiseDelaySuccess
executed as part of (completely unrelated/next) -testPromiseDelaySuccessOtherWay
(alongside -dealloc
). That's not a good thing in my opinion...
Thank you for the detailed explanation! That makes sense to me. Wanna make a PR? Thanks.
[Disclaimer: I'm exercising a solution for automatic leak detection in unit tests. Promises was the first framework that I was able to find that has test_spec and suitable tests.]
It looks like potentially there's a FBLPromise leak in FBLPromiseDelayTests.testPromiseDelaySuccess. It is reproducible for both iOS and macOS unit tests.
If you want to reproduce exactly like I reproduced it:
gen/PromisesObjC/PromisesObjC.xcworkspace
:gen/PromisesObjC/PromisesObjC.xcworkspace