<lambda>null1 package shark
2
3 import com.nhaarman.mockitokotlin2.any
4 import com.nhaarman.mockitokotlin2.mock
5 import com.nhaarman.mockitokotlin2.verify
6 import com.nhaarman.mockitokotlin2.whenever
7 import org.assertj.core.api.Assertions.assertThat
8 import org.junit.After
9 import org.junit.Before
10 import org.junit.Rule
11 import org.junit.Test
12 import org.junit.rules.TemporaryFolder
13 import shark.AndroidResourceIdNames.Companion.FIRST_APP_RESOURCE_ID
14 import shark.AndroidResourceIdNames.Companion.RESOURCE_ID_TYPE_ITERATOR
15 import java.io.File
16
17 class AndroidResourceIdNamesTest {
18
19 @get:Rule
20 var testFolder = TemporaryFolder()
21
22 @Before fun setUp() {
23 AndroidResourceIdNames.resetForTests()
24 }
25
26 @After fun tearDown() {
27 AndroidResourceIdNames.resetForTests()
28 }
29
30 @Test fun `saveToMemory call is cached`() {
31 val getResourceTypeName: (Int) -> String? = mock()
32
33 for (i in 0..2) {
34 AndroidResourceIdNames.saveToMemory(
35 getResourceTypeName = getResourceTypeName,
36 getResourceEntryName = { null }
37 )
38 }
39
40 verify(getResourceTypeName).invoke(any())
41 }
42
43 @Test fun `AndroidResourceIdNames available in heap dump when saveToMemory is called`() {
44 AndroidResourceIdNames.saveToMemory(
45 getResourceTypeName = { null }, getResourceEntryName = { null })
46
47 dumpAndReadHeap { resIdNames ->
48 assertThat(resIdNames).isNotNull
49 }
50 }
51
52 @Test fun `AndroidResourceIdNames not available in heap dump when saveToMemory is not called`() {
53 dumpAndReadHeap { resIdNames ->
54 assertThat(resIdNames).isNull()
55 }
56 }
57
58 @Test fun `saveToMemory stores and retrieves resource id`() {
59 val firstIdResourceId = FIRST_APP_RESOURCE_ID
60
61 val getResourceTypeName =
62 createGetResourceTypeName(mapOf(firstIdResourceId to "id"))
63
64 val getResourceEntryName =
65 createGetResourceEntryName(mapOf(FIRST_APP_RESOURCE_ID to "view_container"))
66
67 AndroidResourceIdNames.saveToMemory(getResourceTypeName, getResourceEntryName)
68
69 dumpAndReadHeap { resIdNames ->
70 assertThat(resIdNames!![firstIdResourceId]).isEqualTo("view_container")
71 }
72 }
73
74 @Test fun `id type starts after layout`() {
75 val layoutResourceId = FIRST_APP_RESOURCE_ID
76 val firstIdResourceId = layoutResourceId + RESOURCE_ID_TYPE_ITERATOR
77
78 val getResourceTypeName =
79 createGetResourceTypeName(
80 mapOf(
81 layoutResourceId to "layout",
82 firstIdResourceId to "id"
83 )
84 )
85 val getResourceEntryName =
86 createGetResourceEntryName(mapOf(firstIdResourceId to "view_container"))
87
88 AndroidResourceIdNames.saveToMemory(getResourceTypeName, getResourceEntryName)
89
90 dumpAndReadHeap { resIdNames ->
91 assertThat(resIdNames!![firstIdResourceId]).isEqualTo("view_container")
92 }
93 }
94
95 @Test fun `two consecutive id resource ids`() {
96 val firstIdResourceId = FIRST_APP_RESOURCE_ID
97 val secondIdResourceId = FIRST_APP_RESOURCE_ID + 1
98
99 val getResourceTypeName =
100 createGetResourceTypeName(
101 mapOf(
102 firstIdResourceId to "id"
103 )
104 )
105 val getResourceEntryName = createGetResourceEntryName(
106 mapOf(
107 firstIdResourceId to "view_container",
108 secondIdResourceId to "menu_button"
109 )
110 )
111
112 AndroidResourceIdNames.saveToMemory(getResourceTypeName, getResourceEntryName)
113
114 dumpAndReadHeap { resIdNames ->
115 assertThat(resIdNames!![secondIdResourceId]).isEqualTo("menu_button")
116 }
117 }
118
119 private fun createGetResourceEntryName(resourceIdMap: Map<Int, String>): (Int) -> String? {
120 val getResourceEntryName: (Int) -> String? = mock()
121 resourceIdMap.forEach { (resourceId, resourceName) ->
122 whenever(getResourceEntryName.invoke(resourceId)).thenReturn(resourceName)
123 }
124 return getResourceEntryName
125 }
126
127 private fun createGetResourceTypeName(resourceIdMap: Map<Int, String>): (Int) -> String? {
128 val getResourceTypeName: (Int) -> String? = mock()
129 resourceIdMap.forEach { (resourceId, resourceName) ->
130 whenever(getResourceTypeName.invoke(resourceId)).thenReturn(resourceName)
131 }
132 return getResourceTypeName
133 }
134
135 fun dumpAndReadHeap(block: (AndroidResourceIdNames?) -> Unit) {
136 val hprofFolder = testFolder.newFolder()
137 val hprofFile = File(hprofFolder, "heapdump.hprof")
138 JvmTestHeapDumper.dumpHeap(hprofFile.absolutePath)
139 Hprof.open(hprofFile)
140 .use { hprof ->
141 val graph = HprofHeapGraph.indexHprof(hprof)
142 val idNames = AndroidResourceIdNames.readFromHeap(graph)
143 block(idNames)
144 }
145 }
146 }