main

square/leakcanary

Last updated at: 29/12/2023 09:38

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
  }
}