FailTestOnLeakRunListener does not appear to function at all in instrumentation tests when obfuscation is enabled.
Run the following command on master (revision 2aacb8b46) of this project:
~./gradlew leakcanary-android-example:connectedCheck -Pminify~
Expected behavior:
Tests pass
Tests fail with this:
Starting 0 tests on Nexus_5_API_Q(AVD) - 10
Tests on Nexus_5_API_Q(AVD) - 10 failed: There was 1 failure:
1) Fatal exception when running tests
java.lang.NoSuchMethodError: No static method copy$default(Lc/a$a;ZZZZJILjava/lang/Object;)Lc/a$a; in class Lc/a$a; or its super classes (declaration of 'c.a$a' appears in /data/app/com.example.leakcanary-QAdW6_QGYEoCz4zbR2QTkg==/base.apk)
at leakcanary.InstrumentationLeakDetector$Companion.updateConfig(InstrumentationLeakDetector.kt:195)
at leakcanary.FailTestOnLeakRunListener.testRunStarted(FailTestOnLeakRunListener.kt:92)
at org.junit.runner.notification.SynchronizedRunListener.testRunStarted(SynchronizedRunListener.java:35)
at org.junit.runner.notification.RunNotifier$1.notifyListener(RunNotifier.java:91)
at org.junit.runner.notification.RunNotifier$SafeNotifier.run(RunNotifier.java:72)
at org.junit.runner.notification.RunNotifier.fireTestRunStarted(RunNotifier.java:88)
at org.junit.runner.JUnitCore.run(JUnitCore.java:136)
at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
at androidx.test.internal.runner.TestExecutor.execute(TestExecutor.java:56)
at androidx.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:388)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2189)
FAILURES!!!
Tests run: 0, Failures: 1
Can you reproduce that with the sample app? We added support for obfuscation to it.
Isn't leakcanary-android-sample the sample app? Oh I guess I typoed above. The command is:
./gradlew leakcanary-android-sample:connectedCheck -Pminify
Reproduced with ./gradlew leakcanary-android-sample:connectedCheck -Pminify :
1) Fatal exception when running tests
java.lang.NoSuchMethodError: No static method copy$default(Lc/a$a;ZZZZJILjava/lang/Object;)Lc/a$a; in class Lc/a$a; or its super classes (declaration of 'c.a$a' appears in /data/app/com.example.leakcanary-1/base.apk)
at leakcanary.InstrumentationLeakDetector$Companion.updateConfig(InstrumentationLeakDetector.kt:195)
at leakcanary.FailTestOnLeakRunListener.testRunStarted(FailTestOnLeakRunListener.kt:92)
at org.junit.runner.notification.SynchronizedRunListener.testRunStarted(SynchronizedRunListener.java:35)
at org.junit.runner.notification.RunNotifier$1.notifyListener(RunNotifier.java:91)
at org.junit.runner.notification.RunNotifier$SafeNotifier.run(RunNotifier.java:72)
at org.junit.runner.notification.RunNotifier.fireTestRunStarted(RunNotifier.java:88)
at org.junit.runner.JUnitCore.run(JUnitCore.java:136)
at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
at androidx.test.internal.runner.TestExecutor.execute(TestExecutor.java:56)
at androidx.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:388)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1932)
Looking into this, InstrumentationLeakDetector is in the test APK and the AppWatcher.Config.copy is in the main APK. @adamfit pointed me to https://slackhq.github.io/keeper/ and it looks like it's exactly solving that issue.
I need to double check, but if that's the case I don't think LeakCanary can do anything about it except documenting. Otherwise we'd have to make it keep all APIs, which isn't great either.
I set up Keeper but it did not infer the proper rules, most likely because of https://github.com/slackhq/keeper/issues/18#issuecomment-580522161
Gave this a spin and unfortunately I think keeper is working correctly here. That dependency is an androidTest dependency only, not in the main APK (so keeper's use here is irrelevant). I was able to get Py's repro branch working with the below patch.
Index: leakcanary-android-sample/build.gradle
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- leakcanary-android-sample/build.gradle (revision 59bb7270fc6dd9db3bc5e5f3e5b8e36695fb7310)
+++ leakcanary-android-sample/build.gradle (date 1580694279000)
@@ -47,17 +47,21 @@
}
buildTypes {
+ release {
+ signingConfig signingConfigs.debug
+ minifyEnabled true
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt')
+ }
+ releaseTest {
+ initWith release
+ debuggable true
+ matchingFallbacks = ['release']
+ }
+
// Build with ./gradlew leakcanary-android-sample:installDebug -Pminify
if (project.hasProperty('minify')) {
- debug {
- minifyEnabled true
- proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
- }
- } else {
- debug
+ testBuildType "releaseTest"
}
-
- release
}
dexOptions {
We chatted some more and it seems likely that defining release builds wouldn't trigger this bug.
Keeper 0.2 fixes this issue!
Most helpful comment
Keeper 0.2 fixes this issue!