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 parsenull151 fun parse(vararg lines: String): Model { 152 val traceData = withHeader(*lines) 153 val importer = FtraceImporter(FatalImportFeedback) 154 val modelFragment = importer.import(traceData.makeReader()) 155 assertNotNull(modelFragment) 156 return Model(modelFragment!!) 157 } 158 withHeadernull159 fun withHeader(vararg lines: String): String { 160 return lines.joinToString("\n", HEADER) 161 } 162 163 val HEADER = """TRACE: 164 # tracer: nop 165 # 166 # entries-in-buffer/entries-written: 69580/69580 #P:8 167 # 168 # _-----=> irqs-off 169 # / _----=> need-resched 170 # | / _---=> hardirq/softirq 171 # || / _--=> preempt-depth 172 # ||| / delay 173 # TASK-PID TGID CPU# |||| TIMESTAMP FUNCTION 174 # | | | | |||| | | 175 """ 176 }