<lambda>null1 package shark
2
3 import org.assertj.core.api.Assertions.assertThat
4 import org.junit.Before
5 import org.junit.Rule
6 import org.junit.Test
7 import org.junit.rules.TemporaryFolder
8 import shark.ValueHolder.IntHolder
9 import java.io.File
10
11 class HprofDeobfuscatorTest {
12
13 @get:Rule
14 var testFolder = TemporaryFolder()
15 private lateinit var hprofFile: File
16
17 @Before
18 fun setUp() {
19 hprofFile = testFolder.newFile("temp.hprof")
20 }
21
22 @Test
23 fun deobfuscateHprofClassName() {
24 val proguardMapping = ProguardMapping().create {
25 clazz("Foo" to "a")
26 }
27
28 hprofFile.dump {
29 "a" clazz {}
30 }
31
32 val deobfuscator = HprofDeobfuscator()
33 val deobfuscatedFile = deobfuscator.deobfuscate(proguardMapping, hprofFile)
34
35 deobfuscatedFile.readHprof { graph ->
36 val fooClass = graph.findClassByName("Foo")
37 assertThat(fooClass).isNotNull
38 }
39 }
40
41 @Test
42 fun deobfuscateHprofStaticFieldName() {
43 val proguardMapping = ProguardMapping().create {
44 clazz("Foo" to "a") {
45 field { "staticField" to "b" }
46 }
47 }
48
49 hprofFile.dump {
50 "a" clazz {
51 staticField["b"] = IntHolder(42)
52 }
53 }
54
55 val deobfuscator = HprofDeobfuscator()
56 val deobfuscatedFile = deobfuscator.deobfuscate(proguardMapping, hprofFile)
57
58 deobfuscatedFile.readHprof { graph ->
59 val fooClass = graph.findClassByName("Foo")!!
60
61 assertThat(
62 fooClass.readStaticFields()
63 .map { it.name }
64 .toList()
65 ).contains("staticField")
66 }
67 }
68
69 @Test
70 fun deobfuscateHprofMemberFieldName() {
71 val proguardMapping = ProguardMapping().create {
72 clazz("Foo" to "a") {
73 field { "instanceField" to "b" }
74 }
75 }
76
77 hprofFile.dump {
78 val classId = clazz(
79 className = "a",
80 fields = listOf("b" to IntHolder::class)
81 )
82 instance(classId, listOf(IntHolder(0)))
83 }
84
85 val deobfuscator = HprofDeobfuscator()
86 val deobfuscatedFile = deobfuscator.deobfuscate(proguardMapping, hprofFile)
87
88 deobfuscatedFile.readHprof { graph ->
89 val instance = graph.instances.find { heapInstance ->
90 heapInstance.instanceClassName == "Foo"
91 }!!
92
93 assertThat(
94 instance.readFields()
95 .map { it.name }
96 .toList()
97 ).contains("instanceField")
98 }
99 }
100
101 @Test
102 fun deobfuscateHprofClassNameUsedAsFieldName() {
103 val proguardMapping = ProguardMapping().create {
104 clazz("Foo" to "a") {
105 field { "instanceField" to "a" }
106 }
107 }
108
109 hprofFile.dump {
110 val classNameRecord = stringRecord("a")
111
112 val classId = clazz(
113 classNameRecord = classNameRecord,
114 fields = listOf(classNameRecord.id to IntHolder::class)
115 )
116 instance(classId, listOf(IntHolder(0)))
117 }
118
119 val deobfuscator = HprofDeobfuscator()
120 val deobfuscatedFile = deobfuscator.deobfuscate(proguardMapping, hprofFile)
121
122 deobfuscatedFile.readHprof { graph ->
123 val instance = graph.instances.find { heapInstance ->
124 heapInstance.instanceClassName == "Foo"
125 }!!
126
127 assertThat(
128 instance.readFields()
129 .map { it.name }
130 .toList()
131 ).contains("instanceField")
132 }
133 }
134
135 @Test
136 fun deobfuscateHprofClassNameUsedAsStaticFieldName() {
137 val proguardMapping = ProguardMapping().create {
138 clazz("Foo" to "a") {
139 field { "staticField" to "a" }
140 }
141 }
142
143 hprofFile.dump {
144 val classNameRecord = stringRecord("a")
145
146 clazz(
147 classNameRecord = classNameRecord,
148 staticFields = listOf(classNameRecord.id to IntHolder(42))
149 )
150 }
151
152 val deobfuscator = HprofDeobfuscator()
153 val deobfuscatedFile = deobfuscator.deobfuscate(proguardMapping, hprofFile)
154
155 deobfuscatedFile.readHprof { graph ->
156 val fooClass = graph.findClassByName("Foo")!!
157
158 assertThat(
159 fooClass.readStaticFields()
160 .map { it.name }
161 .toList()
162 ).contains("staticField")
163 }
164 }
165
166 @Test
167 fun deobfuscateHprofTwoFieldsWithSameName() {
168 val proguardMapping = ProguardMapping().create {
169 clazz("Foo" to "a") {
170 field { "instanceField1" to "c" }
171 }
172 clazz("Bar" to "b") {
173 field { "instanceField2" to "c" }
174 }
175 }
176
177 hprofFile.dump {
178 val fooClassNameRecord = stringRecord("a")
179 val barClassNameRecord = stringRecord("b")
180 val fieldNameRecord = stringRecord("c")
181
182 val fooClassId = clazz(
183 classNameRecord = fooClassNameRecord,
184 fields = listOf(fieldNameRecord.id to IntHolder::class)
185 )
186 instance(fooClassId, listOf(IntHolder(0)))
187
188 val barClassId = clazz(
189 classNameRecord = barClassNameRecord,
190 fields = listOf(fieldNameRecord.id to IntHolder::class)
191 )
192 instance(barClassId, listOf(IntHolder(0)))
193 }
194
195 val deobfuscator = HprofDeobfuscator()
196 val deobfuscatedFile = deobfuscator.deobfuscate(proguardMapping, hprofFile)
197
198 deobfuscatedFile.readHprof { graph ->
199 val fooInstance = graph.instances.find { heapInstance ->
200 heapInstance.instanceClassName == "Foo"
201 }!!
202
203 assertThat(
204 fooInstance.readFields()
205 .map { it.name }
206 .toList()
207 ).contains("instanceField1")
208
209 val barInstance = graph.instances.find { heapInstance ->
210 heapInstance.instanceClassName == "Bar"
211 }!!
212
213 assertThat(
214 barInstance.readFields()
215 .map { it.name }
216 .toList()
217 ).contains("instanceField2")
218 }
219 }
220
221 private fun File.readHprof(block: (HeapGraph) -> Unit) {
222 Hprof.open(this)
223 .use { hprof ->
224 block(HprofHeapGraph.indexHprof(hprof))
225 }
226 }
227 }