1 /* 2 * Copyright 2017 Google Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * https://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package trebuchet.importers.ftrace 18 19 import org.junit.Assert.* 20 import org.junit.Test 21 import trebuchet.importers.FatalImportFeedback 22 import trebuchet.io.StreamingReader 23 import trebuchet.model.Model 24 import trebuchet.testutils.makeReader 25 26 class FtraceImporterTest { 27 Stringnull28 fun String.makeLoadedReader(): StreamingReader { 29 val reader = this.makeReader() 30 reader.loadIndex(reader.keepLoadedSize.toLong()) 31 return reader 32 } 33 testImporterFornull34 @Test fun testImporterFor() { 35 val line1 = "atrace-7100 ( 7100) [001] ...1 4492.047398: tracing_mark_write: trace_event_clock_sync: parent_ts=4492.069824" 36 val line2 = "<idle>-0 (-----) [001] dN.4 4492.047448: sched_wakeup: comm=ksoftirqd/1 pid=15 prio=120 success=1 target_cpu=001" 37 val traceData = withHeader(line1, line2) 38 assertNotNull(FtraceImporter.Factory.importerFor(HEADER.makeLoadedReader(), FatalImportFeedback)) 39 assertNotNull(FtraceImporter.Factory.importerFor(traceData.makeLoadedReader(), FatalImportFeedback)) 40 assertNull(FtraceImporter.Factory.importerFor(HEADER.makeReader(), FatalImportFeedback)) 41 assertNull(FtraceImporter.Factory.importerFor(traceData.makeReader(), FatalImportFeedback)) 42 assertNull(FtraceImporter.Factory.importerFor("Hello, World!".makeLoadedReader(), FatalImportFeedback)) 43 assertNull(FtraceImporter.Factory.importerFor(line1.makeLoadedReader(), FatalImportFeedback)) 44 } 45 testImporterTimestampnull46 @Test fun testImporterTimestamp() { 47 val traceData = withHeader( 48 "equicksearchbox-6381 ( 6381) [004] ...1 4493.734816: tracing_mark_write: trace_event_clock_sync: parent_ts=23816.083984", 49 "equicksearchbox-6381 ( 6381) [004] ...1 4493.734855: tracing_mark_write: trace_event_clock_sync: realtime_ts=1491850748338") 50 val importer = FtraceImporter(FatalImportFeedback) 51 val modelFragment = importer.import(traceData.makeReader()) 52 assertNotNull(modelFragment) 53 if (modelFragment == null) return // just to make Kotlin happy 54 assertEquals(23816.083984, modelFragment.parentTimestamp, .001) 55 assertEquals(1491850748338, modelFragment.realtimeTimestamp) 56 } 57 testImportBeginEndnull58 @Test fun testImportBeginEnd() { 59 val traceData = withHeader( 60 " equicksearchbox-6381 ( 6381) [004] ...1 4493.734816: tracing_mark_write: E", 61 " equicksearchbox-6381 ( 6381) [005] ...1 4493.730786: tracing_mark_write: B|6381|Choreographer#doFrame", 62 " equicksearchbox-6381 ( 6381) [005] ...1 4493.730824: tracing_mark_write: B|6381|input", 63 " equicksearchbox-6381 ( 6381) [005] ...1 4493.732287: tracing_mark_write: E", 64 " equicksearchbox-6381 ( 6381) [005] ...1 4493.732310: tracing_mark_write: B|6381|traversal", 65 " equicksearchbox-6381 ( 6381) [005] ...1 4493.732410: tracing_mark_write: B|6381|draw", 66 " equicksearchbox-6381 ( 6381) [004] ...1 4493.734816: tracing_mark_write: E", 67 " equicksearchbox-6381 ( 6381) [004] ...1 4493.734828: tracing_mark_write: E", 68 " equicksearchbox-6381 ( 6381) [004] ...1 4493.734855: tracing_mark_write: E") 69 val importer = FtraceImporter(FatalImportFeedback) 70 val modelFragment = importer.import(traceData.makeReader()) 71 assertNotNull(modelFragment) 72 if (modelFragment == null) return // just to make Kotlin happy 73 assertEquals(1, modelFragment.processes.size) 74 val process = modelFragment.processes[0] 75 assertEquals(6381, process.id) 76 assertEquals("equicksearchbox", process.name) 77 assertEquals(1, process.threads.size) 78 val thread = process.threads.first() 79 assertEquals(6381, thread.id) 80 assertEquals("equicksearchbox", thread.name) 81 val sliceGroup = thread.slicesBuilder 82 assertFalse(sliceGroup.hasOpenSlices()) 83 assertEquals(1, sliceGroup.slices.size) 84 val doFrameSlice = sliceGroup.slices[0] 85 assertEquals("Choreographer#doFrame", doFrameSlice.name) 86 assertEquals(2, doFrameSlice.children.size) 87 assertEquals("input", doFrameSlice.children[0].name) 88 assertEquals(0, doFrameSlice.children[0].children.size) 89 assertEquals("traversal", doFrameSlice.children[1].name) 90 assertEquals(1, doFrameSlice.children[1].children.size) 91 assertEquals("draw", doFrameSlice.children[1].children[0].name) 92 } 93 testImportBeginEndNoTgidsnull94 @Test fun testImportBeginEndNoTgids() { 95 val traceData = withHeader( 96 " equicksearchbox-6381 (-----) [004] ...1 4493.734828: tracing_mark_write: E", 97 " equicksearchbox-6381 (-----) [005] ...1 4493.730786: tracing_mark_write: B|6381|Choreographer#doFrame", 98 " equicksearchbox-6381 (-----) [005] ...1 4493.730824: tracing_mark_write: B|6381|input", 99 " equicksearchbox-6381 (-----) [005] ...1 4493.732287: tracing_mark_write: E", 100 " equicksearchbox-6381 (-----) [005] ...1 4493.732310: tracing_mark_write: B|6381|traversal", 101 " equicksearchbox-6381 (-----) [005] ...1 4493.732410: tracing_mark_write: B|6381|draw", 102 " equicksearchbox-6381 (-----) [004] ...1 4493.734816: tracing_mark_write: E", 103 " equicksearchbox-6381 (-----) [004] ...1 4493.734828: tracing_mark_write: E", 104 " equicksearchbox-6381 (-----) [004] ...1 4493.734855: tracing_mark_write: E") 105 val importer = FtraceImporter(FatalImportFeedback) 106 val modelFragment = importer.import(traceData.makeReader()) 107 assertNotNull(modelFragment) 108 if (modelFragment == null) return // just to make Kotlin happy 109 assertEquals(1, modelFragment.processes.size) 110 val process = modelFragment.processes[0] 111 assertEquals(6381, process.id) 112 assertEquals("equicksearchbox", process.name) 113 assertEquals(1, process.threads.size) 114 val thread = process.threads.first() 115 assertEquals(6381, thread.id) 116 assertEquals("equicksearchbox", thread.name) 117 val sliceGroup = thread.slicesBuilder 118 assertFalse(sliceGroup.hasOpenSlices()) 119 assertEquals(1, sliceGroup.slices.size) 120 val doFrameSlice = sliceGroup.slices[0] 121 assertEquals("Choreographer#doFrame", doFrameSlice.name) 122 assertEquals(2, doFrameSlice.children.size) 123 assertEquals("input", doFrameSlice.children[0].name) 124 assertEquals(0, doFrameSlice.children[0].children.size) 125 assertEquals("traversal", doFrameSlice.children[1].name) 126 assertEquals(1, doFrameSlice.children[1].children.size) 127 assertEquals("draw", doFrameSlice.children[1].children[0].name) 128 } 129 testCountersnull130 @Test fun testCounters() { 131 val model = parse( 132 " <...>-4932 (-----) [000] ...1 4493.660106: tracing_mark_write: C|3691|iq|1", 133 "InputDispatcher-4931 ( 3691) [000] ...1 4493.660790: tracing_mark_write: C|3691|iq|0") 134 assertEquals(1, model.processes.size) 135 val p = model.processes[3691]!! 136 assertEquals(3691, p.id) 137 assertEquals(3, p.threads.size) 138 assertTrue(p.threads.any { it.id == 3691 }) 139 assertTrue(p.threads.any { it.id == 4931 }) 140 assertTrue(p.threads.any { it.id == 4932 }) 141 assertEquals(1, p.counters.size) 142 val c = p.counters[0] 143 assertEquals(2, c.events.size) 144 assertEquals(4493.660106, c.events[0].timestamp, .1) 145 assertEquals(1, c.events[0].count) 146 assertEquals(4493.660790, c.events[1].timestamp, .1) 147 assertEquals(0, c.events[1].count) 148 149 } 150 testKernel515Changesnull151 @Test fun testKernel515Changes() { 152 val trace = """ # tracer: nop 153 > # ||| / _-=> migrate-disable 154 > # |||| / delay 155 > # TASK-PID TGID CPU# ||||| TIMESTAMP FUNCTION 156 > # | | | | ||||| | | 157 > atrace-6950 ( 6950) [001] ..... 7048.491867: tracing_mark_write: trace_event_clock_sync: parent_ts=7048.491699 158 > atrace-6950 ( 6950) [001] ..... 7048.491873: tracing_mark_write: trace_event_clock_sync: realtime_ts=1648582795693 159 > roidJUnitRunner-6981 ( 6966) [000] ..... 7048.755913: tracing_mark_write: S|6966|AtraceDeviceTest::asyncBeginEndSection|42 160 > roidJUnitRunner-6981 ( 6966) [000] ..... 7048.755920: tracing_mark_write: F|6966|AtraceDeviceTest::asyncBeginEndSection|42 161 > roidJUnitRunner-6981 ( 6966) [000] ..... 7048.755924: tracing_mark_write: S|6966|ndk::asyncBeginEndSection|4770 162 > roidJUnitRunner-6981 ( 6966) [000] ..... 7048.755926: tracing_mark_write: F|6966|ndk::asyncBeginEndSection|4770 163 """.trimMargin(">") 164 165 val importer = FtraceImporter(FatalImportFeedback) 166 val modelFragment = importer.import(trace.makeReader()) 167 assertNotNull(modelFragment) 168 val model = Model(modelFragment!!) 169 assertNotNull(model) 170 val p = model.processes[6966].also { 171 assertNotNull(it) 172 }!! 173 assertEquals(6966, p.id) 174 assertEquals(1, p.threads.size) 175 } 176 parsenull177 fun parse(vararg lines: String): Model { 178 val traceData = withHeader(*lines) 179 val importer = FtraceImporter(FatalImportFeedback) 180 val modelFragment = importer.import(traceData.makeReader()) 181 assertNotNull(modelFragment) 182 return Model(modelFragment!!) 183 } 184 withHeadernull185 fun withHeader(vararg lines: String): String { 186 return lines.joinToString("\n", HEADER) 187 } 188 189 val HEADER = """TRACE: 190 # tracer: nop 191 # 192 # entries-in-buffer/entries-written: 69580/69580 #P:8 193 # 194 # _-----=> irqs-off 195 # / _----=> need-resched 196 # | / _---=> hardirq/softirq 197 # || / _--=> preempt-depth 198 # ||| / delay 199 # TASK-PID TGID CPU# |||| TIMESTAMP FUNCTION 200 # | | | | |||| | | 201 """ 202 }