Skip to content

Commit

Permalink
Disable heap dumping during UI tests (#1436)
Browse files Browse the repository at this point in the history
This makes the assumption that most apps use Android X for UI tests.

Fixes #1382
  • Loading branch information
pyricau authored Jul 3, 2019
1 parent a4fd526 commit 5774068
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -74,12 +74,13 @@ internal class HeapDumpTrigger(
}

private fun checkRetainedInstances(reason: String) {
CanaryLog.d("Checking retained instances because %s", reason)
val config = configProvider()
// A tick will be rescheduled when this is turned back on.
if (!config.dumpHeap) {
CanaryLog.d("No checking for retained instance: LeakCanary.Config.dumpHeap is false")
return
}
CanaryLog.d("Checking retained instances because %s", reason)

var retainedReferenceCount = refWatcher.retainedInstanceCount

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package leakcanary.internal

import android.app.Application
import android.app.Instrumentation
import android.content.ComponentName
import android.content.Intent
import android.content.pm.ShortcutInfo.Builder
Expand All @@ -17,6 +18,7 @@ import leakcanary.LeakCanary
import leakcanary.LeakCanary.Config
import leakcanary.LeakSentry
import leakcanary.internal.activity.LeakActivity
import java.util.concurrent.atomic.AtomicReference

internal object InternalLeakCanary : LeakSentryListener {

Expand Down Expand Up @@ -66,6 +68,36 @@ internal object InternalLeakCanary : LeakSentryListener {
heapDumpTrigger.onApplicationVisibilityChanged(applicationVisible)
}
addDynamicShortcut(application)

disableDumpHeapInInstrumentationTests()
}

private fun disableDumpHeapInInstrumentationTests() {
// This is called before Application.onCreate(), so InstrumentationRegistry has no reference to
// the instrumentation yet. That happens immediately after the content providers are created,
// in the same main thread message, so by posting to the end of the main thread queue we're
// guaranteed that the instrumentation will be in place.
Handler().post {
val runningInInstrumentationTests = try {
// This is assuming all UI tests rely on InstrumentationRegistry. Should be mostly true
// these days (especially since we force the Android X dependency on consumers).
val registryClass = Class.forName("androidx.test.platform.app.InstrumentationRegistry")
val instrumentationRefField = registryClass.getDeclaredField("instrumentationRef")
instrumentationRefField.isAccessible = true
@Suppress("UNCHECKED_CAST")
val instrumentationRef = instrumentationRefField.get(
null
) as AtomicReference<Instrumentation>
instrumentationRef.get() != null
} catch (ignored: Throwable) {
false
}

if (runningInInstrumentationTests) {
CanaryLog.d("Instrumentation test detected, setting LeakCanary.Config.dumpHeap to false")
LeakCanary.config = LeakCanary.config.copy(dumpHeap = false)
}
}
}

private fun addDynamicShortcut(application: Application) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,6 @@ class InstrumentationLeakDetector {
* [FailTestOnLeakRunListener] when the tests start running.
*/
fun updateConfig() {
LeakCanary.config = LeakCanary.config.copy(dumpHeap = false)
LeakSentry.config = LeakSentry.config.copy(enabled = true)
}
}
Expand Down

0 comments on commit 5774068

Please sign in to comment.