1#!/usr/bin/env python3 2# Copyright (C) 2023 The Android Open Source Project 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 a 7# 8# http://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 16from python.generators.diff_tests.testing import Path, DataPath, Metric 17from python.generators.diff_tests.testing import Csv, Json, TextProto 18from python.generators.diff_tests.testing import DiffTestBlueprint 19from python.generators.diff_tests.testing import TestSuite 20 21 22class ProcessTracking(TestSuite): 23 # Tests for the core process and thread tracking logic. Smoke tests 24 def test_process_tracking(self): 25 return DiffTestBlueprint( 26 trace=Path('synth_process_tracking.py'), 27 query=""" 28 SELECT tid, pid, process.name AS pname, thread.name AS tname 29 FROM thread 30 LEFT JOIN process USING(upid) 31 WHERE tid > 0 32 ORDER BY tid; 33 """, 34 out=Csv(""" 35 "tid","pid","pname","tname" 36 10,10,"process1","p1-t0" 37 11,"[NULL]","[NULL]","p1-t1" 38 12,10,"process1","p1-t2" 39 20,20,"process_2","p2-t0" 40 21,20,"process_2","p2-t1" 41 22,20,"process_2","p2-t2" 42 30,30,"process_3","p3-t0" 43 31,30,"process_3","p3-t1" 44 31,40,"process_4","p4-t1" 45 32,30,"process_3","p3-t2" 46 33,30,"process_3","p3-t3" 47 34,30,"process_3","p3-t4" 48 40,40,"process_4","p4-t0" 49 """)) 50 51 # Short lived threads/processes 52 def test_process_tracking_process_tracking_short_lived_1(self): 53 return DiffTestBlueprint( 54 trace=Path('process_tracking_short_lived_1.py'), 55 query=""" 56 SELECT tid, pid, process.name AS pname, thread.name AS tname 57 FROM thread 58 LEFT JOIN process USING(upid) 59 WHERE tid > 0 60 ORDER BY tid; 61 """, 62 out=Csv(""" 63 "tid","pid","pname","tname" 64 10,10,"parent","parent" 65 11,11,"child","child" 66 """)) 67 68 def test_process_tracking_process_tracking_short_lived_2(self): 69 return DiffTestBlueprint( 70 trace=Path('process_tracking_short_lived_2.py'), 71 query=""" 72 SELECT tid, pid, process.name AS pname, thread.name AS tname 73 FROM thread 74 LEFT JOIN process USING(upid) 75 WHERE tid > 0 76 ORDER BY tid; 77 """, 78 out=Csv(""" 79 "tid","pid","pname","tname" 80 10,10,"parent","parent" 81 11,11,"true_name","true_name" 82 """)) 83 84 # Process uid handling 85 def test_process_tracking_uid(self): 86 return DiffTestBlueprint( 87 trace=Path('synth_process_tracking.py'), 88 query=""" 89 SELECT pid, uid 90 FROM process 91 ORDER BY pid; 92 """, 93 out=Csv(""" 94 "pid","uid" 95 0,"[NULL]" 96 10,1001 97 20,1002 98 30,"[NULL]" 99 40,"[NULL]" 100 """)) 101 102 # Tracking across execs 103 def test_process_tracking_process_tracking_exec(self): 104 return DiffTestBlueprint( 105 trace=Path('process_tracking_exec.py'), 106 query=""" 107 SELECT tid, pid, process.name AS pname, thread.name AS tname 108 FROM thread 109 LEFT JOIN process USING(upid) 110 WHERE tid > 0 111 ORDER BY tid; 112 """, 113 out=Csv(""" 114 "tid","pid","pname","tname" 115 10,10,"parent","parent" 116 11,11,"true_process_name","true_name" 117 """)) 118 119 # Tracking parent threads 120 def test_process_parent_pid_process_parent_pid_tracking_1(self): 121 return DiffTestBlueprint( 122 trace=Path('process_parent_pid_tracking_1.py'), 123 query=""" 124 SELECT 125 child.pid AS child_pid, 126 parent.pid AS parent_pid 127 FROM process AS child 128 JOIN process AS parent 129 ON child.parent_upid = parent.upid 130 ORDER BY child_pid; 131 """, 132 out=Csv(""" 133 "child_pid","parent_pid" 134 10,0 135 20,10 136 """)) 137 138 def test_process_parent_pid_process_parent_pid_tracking_2(self): 139 return DiffTestBlueprint( 140 trace=Path('process_parent_pid_tracking_2.py'), 141 query=""" 142 SELECT 143 child.pid AS child_pid, 144 parent.pid AS parent_pid 145 FROM process AS child 146 JOIN process AS parent 147 ON child.parent_upid = parent.upid 148 ORDER BY child_pid; 149 """, 150 out=Csv(""" 151 "child_pid","parent_pid" 152 10,0 153 20,10 154 """)) 155 156 # Tracking thread reuse 157 def test_process_tracking_reused_thread_print(self): 158 return DiffTestBlueprint( 159 trace=Path('reused_thread_print.py'), 160 query=""" 161 SELECT tid, pid, process.name AS pname, thread.name AS tname 162 FROM thread 163 LEFT JOIN process USING(upid) 164 WHERE tid > 0 165 ORDER BY tid; 166 """, 167 out=Csv(""" 168 "tid","pid","pname","tname" 169 10,10,"parent","[NULL]" 170 11,11,"short_lived","[NULL]" 171 11,10,"parent","true_name" 172 """)) 173 174 # TODO(lalitm): move this out of this folder. 175 def test_slice_with_pid_sde_tracing_mark_write(self): 176 return DiffTestBlueprint( 177 trace=TextProto(r""" 178 packet { 179 ftrace_events { 180 cpu: 0 181 event { 182 timestamp: 100 183 pid: 403 184 sde_tracing_mark_write { 185 pid: 403 186 trace_name: "test_event" 187 trace_begin: 1 188 } 189 } 190 event { 191 timestamp: 101 192 pid: 403 193 sde_tracing_mark_write { 194 pid: 403 195 trace_name: "test_event" 196 trace_begin: 0 197 } 198 } 199 } 200 } 201 """), 202 query=""" 203 SELECT s.name, dur, tid, pid 204 FROM slice s 205 JOIN thread_track t ON s.track_id = t.id 206 JOIN thread USING(utid) 207 LEFT JOIN process USING(upid); 208 """, 209 out=Csv(""" 210 "name","dur","tid","pid" 211 "test_event",1,403,403 212 """)) 213 214 # Check that a <...> thread name doesn't overwrite a useful thread name 215 def test_unknown_thread_name_tracking(self): 216 return DiffTestBlueprint( 217 trace=Path('unknown_thread_name.systrace'), 218 query=""" 219 SELECT tid, pid, process.name AS pname, thread.name AS tname 220 FROM thread 221 LEFT JOIN process USING(upid) 222 WHERE tid > 0 223 ORDER BY tid; 224 """, 225 out=Csv(""" 226 "tid","pid","pname","tname" 227 19999,"[NULL]","[NULL]","real_name" 228 """)) 229