<lambda>null1package shark 2 3 import org.assertj.core.api.Assertions.assertThat 4 import org.junit.Test 5 import shark.LeakTraceObject.LeakingStatus.LEAKING 6 import shark.LeakTraceObject.LeakingStatus.NOT_LEAKING 7 import shark.LeakTraceObject.ObjectType.INSTANCE 8 9 class AndroidObjectInspectorsTest { 10 11 @Test fun `RECOMPOSER leaking status relies on state`() { 12 val hprofFile = "compose_leak.hprof".classpathFile() 13 val heapAnalyzer = HeapAnalyzer(OnAnalysisProgressListener.NO_OP) 14 val analysis = heapAnalyzer.analyze( 15 heapDumpFile = hprofFile, 16 leakingObjectFinder = { graph -> 17 val composeViewClass = 18 graph.findClassByName("androidx.compose.ui.platform.AndroidComposeView") 19 composeViewClass!!.instances.filter { instance -> 20 val filter = AndroidObjectInspectors.VIEW.leakingObjectFilter!! 21 filter.invoke(instance) 22 true 23 }.map { it.objectId }.toSet() 24 }, 25 referenceMatchers = AndroidReferenceMatchers.appDefaults, 26 objectInspectors = AndroidObjectInspectors.appDefaults 27 ) 28 println(analysis) 29 analysis as HeapAnalysisSuccess 30 val recomposerNode = analysis.applicationLeaks.single() 31 .leakTraces.single() 32 .referencePath.single { 33 it.originObject.type == INSTANCE 34 && it.owningClassSimpleName == "Recomposer" 35 } 36 assertThat(recomposerNode.originObject.leakingStatus == NOT_LEAKING) 37 assertThat(recomposerNode.originObject.leakingStatusReason == "Recomposer is in state PendingWork") 38 } 39 40 @Test fun `COMPOSITION_IMPL leaking status relies on disposal`() { 41 val hprofFile = "compose_leak.hprof".classpathFile() 42 val heapAnalyzer = HeapAnalyzer(OnAnalysisProgressListener.NO_OP) 43 val analysis = heapAnalyzer.analyze( 44 heapDumpFile = hprofFile, 45 leakingObjectFinder = { graph -> 46 val composeViewClass = 47 graph.findClassByName("androidx.compose.ui.platform.AndroidComposeView") 48 composeViewClass!!.instances.filter { instance -> 49 val filter = AndroidObjectInspectors.VIEW.leakingObjectFilter!! 50 filter.invoke(instance) 51 true 52 }.map { it.objectId }.toSet() 53 }, 54 referenceMatchers = AndroidReferenceMatchers.appDefaults, 55 objectInspectors = AndroidObjectInspectors.appDefaults 56 ) 57 println(analysis) 58 analysis as HeapAnalysisSuccess 59 val recomposerNode = analysis.applicationLeaks.single() 60 .leakTraces.single() 61 .referencePath.single { 62 it.owningClassSimpleName == "CompositionImpl" 63 } 64 assertThat(recomposerNode.originObject.leakingStatus == LEAKING) 65 assertThat(recomposerNode.originObject.leakingStatusReason == "Composition disposed") 66 } 67 } 68