xref: /aosp_15_r20/external/leakcanary2/shark-graph/src/test/java/shark/HprofPrimitiveArrayStripperTest.kt (revision d9e8da70d8c9df9a41d7848ae506fb3115cae6e6)

<lambda>null1 package shark
2 
3 import java.io.File
4 import okio.Buffer
5 import org.assertj.core.api.Assertions.assertThat
6 import org.junit.Rule
7 import org.junit.Test
8 import org.junit.rules.TemporaryFolder
9 import shark.HeapObject.HeapPrimitiveArray
10 import shark.HprofHeapGraph.Companion.openHeapGraph
11 import shark.HprofRecord.HeapDumpRecord.ObjectRecord.PrimitiveArrayDumpRecord.BooleanArrayDump
12 import shark.HprofRecord.HeapDumpRecord.ObjectRecord.PrimitiveArrayDumpRecord.CharArrayDump
13 import shark.PrimitiveType.BOOLEAN
14 import shark.PrimitiveType.CHAR
15 
16 class HprofPrimitiveArrayStripperTest {
17 
18   @get:Rule
19   var testFolder = TemporaryFolder()
20 
21   private var lastId = 0L
22   private val id: Long
23     get() = ++lastId
24 
25   @Test
26   fun stripHprof() {
27     val booleanArray = BooleanArrayDump(id, 1, booleanArrayOf(true, false, true, true))
28     val charArray = CharArrayDump(id, 1, "Hello World!".toCharArray())
29     val hprofBytes = listOf(booleanArray, charArray).asHprofBytes()
30 
31     val stripper = HprofPrimitiveArrayStripper()
32 
33     val strippedBuffer = Buffer()
34     stripper.stripPrimitiveArrays(hprofBytes, strippedBuffer)
35 
36     val strippedSource = ByteArraySourceProvider(strippedBuffer.readByteArray())
37 
38     strippedSource.openHeapGraph().use { graph ->
39       val booleanArrays = graph.objects
40         .filter { it is HeapPrimitiveArray && it.primitiveType == BOOLEAN }
41         .map { it.readRecord() as BooleanArrayDump }
42         .toList()
43       assertThat(booleanArrays).hasSize(1)
44       assertThat(booleanArrays[0].id).isEqualTo(booleanArray.id)
45       assertThat(booleanArrays[0].array).isEqualTo(booleanArrayOf(false, false, false, false))
46 
47       val charArrays = graph.objects
48         .filter { it is HeapPrimitiveArray && it.primitiveType == CHAR }
49         .map { it.readRecord() as CharArrayDump }
50         .toList()
51       assertThat(charArrays).hasSize(1)
52       assertThat(charArrays[0].id).isEqualTo(charArray.id)
53       assertThat(charArrays[0].array).isEqualTo("????????????".toCharArray())
54     }
55   }
56 
57   @Test
58   fun `ByteArray based String content is replaced with question marks`() {
59     val hprofFolder = testFolder.newFolder()
60     val hprofFile = File(hprofFolder, "jvm_heap.hprof")
61     val stringSavedToDump = "Yo!"
62     hold(TestStringHolder(stringSavedToDump)) {
63       JvmTestHeapDumper.dumpHeap(hprofFile.absolutePath)
64     }
65 
66     val strippedFile = HprofPrimitiveArrayStripper().stripPrimitiveArrays(hprofFile)
67 
68     val initialString = hprofFile.readHolderString()
69     val strippedString = strippedFile.readHolderString()
70     assertThat(initialString).isEqualTo(stringSavedToDump)
71     assertThat(strippedString).isEqualTo("?".repeat(stringSavedToDump.length))
72   }
73 
74   private class TestStringHolder(val string: String)
75 
76   private fun File.readHolderString() = openHeapGraph().use { graph ->
77     val className = "shark.HprofPrimitiveArrayStripperTest\$TestStringHolder"
78     val holderClass = graph.findClassByName(className)!!
79     val holderInstance = holderClass.instances.single()
80     holderInstance[className, "string"]!!.value.readAsJavaString()!!
81   }
82 
83   private fun hold(held: Any, block: () -> Unit) {
84     try {
85       block()
86     } finally {
87       if (System.identityHashCode(held) * 0 > 0f) {
88         error("this will never happen")
89       }
90     }
91   }
92 }
93