TestUtils.kt
TLDR
The TestUtils.kt
file provides utility methods for detecting and asserting memory leaks in Android applications.
Methods
assertLeak(expectedLeakClass: Class<*>)
This method asserts that a memory leak of the specified expectedLeakClass
has occurred. It uses the detectLeaks()
method to perform the leak detection. If multiple leaks are found or if the expected leak class does not match the actual leak class, an AssertionError
is thrown.
detectLeaks(): HeapAnalysisSuccess
This method performs the detection of memory leaks using the AndroidDetectLeaksAssert
class. It asserts that the analysis is performed and returns the result as a HeapAnalysisSuccess
. If the analysis is skipped or if the analysis result is not a success, an AssertionError
is thrown. The heap dump file generated during the analysis is also deleted to save disk space on the emulator.
END
package leakcanary
import shark.HeapAnalysis
import shark.HeapAnalysisSuccess
object TestUtils {
fun assertLeak(expectedLeakClass: Class<*>) {
val heapAnalysis = detectLeaks()
val applicationLeaks = heapAnalysis.applicationLeaks
if (applicationLeaks.size != 1) {
throw AssertionError(
"Expected exactly one leak in $heapAnalysis"
)
}
val leak = applicationLeaks.first()
val leakTrace = leak.leakTraces.first()
val className = leakTrace.leakingObject.className
if (className != expectedLeakClass.name) {
throw AssertionError(
"Expected a leak of $expectedLeakClass, not $className in $heapAnalysis"
)
}
}
fun detectLeaks(): HeapAnalysisSuccess {
var heapAnalysisOrNull: HeapAnalysis? = null
AndroidDetectLeaksAssert { heapAnalysis ->
heapAnalysisOrNull = heapAnalysis
}.assertNoLeaks("")
if (heapAnalysisOrNull == null) {
throw AssertionError(
"Expected analysis to be performed but skipped"
)
}
val heapAnalysis = heapAnalysisOrNull
if (heapAnalysis !is HeapAnalysisSuccess) {
throw AssertionError(
"Expected analysis success not $heapAnalysis"
)
}
// Save disk space on emulator
heapAnalysis.heapDumpFile.delete()
return heapAnalysis
}
}