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 PerfettoTable(TestSuite): 23 24 def test_create_table(self): 25 return DiffTestBlueprint( 26 trace=TextProto(r''), 27 query=""" 28 CREATE PERFETTO TABLE foo AS SELECT 42 as a; 29 30 SELECT * FROM foo; 31 """, 32 out=Csv(""" 33 "a" 34 42 35 """)) 36 37 def test_replace_table(self): 38 return DiffTestBlueprint( 39 trace=TextProto(r''), 40 query=""" 41 CREATE PERFETTO TABLE foo AS SELECT 42 as a; 42 CREATE OR REPLACE PERFETTO TABLE foo AS SELECT 43 as a; 43 44 SELECT * FROM foo; 45 """, 46 out=Csv(""" 47 "a" 48 43 49 """)) 50 51 def test_create_perfetto_table_double_metric_run(self): 52 return DiffTestBlueprint( 53 trace=TextProto(r''), 54 query=""" 55 SELECT RUN_METRIC('android/cpu_info.sql'); 56 SELECT RUN_METRIC('android/cpu_info.sql'); 57 58 SELECT * FROM cluster_core_type; 59 """, 60 out=Csv(""" 61 "cluster","core_type" 62 0,"little" 63 1,"big" 64 2,"bigger" 65 """)) 66 67 def test_perfetto_table_info_static_table(self): 68 return DiffTestBlueprint( 69 trace=DataPath('android_boot.pftrace'), 70 query=""" 71 SELECT * FROM perfetto_table_info('counter'); 72 """, 73 out=Csv(""" 74 "id","type","name","col_type","nullable","sorted" 75 0,"perfetto_table_info","id","id",0,1 76 1,"perfetto_table_info","type","string",0,0 77 2,"perfetto_table_info","ts","int64",0,1 78 3,"perfetto_table_info","track_id","uint32",0,0 79 4,"perfetto_table_info","value","double",0,0 80 5,"perfetto_table_info","arg_set_id","uint32",1,0 81 """)) 82 83 def test_perfetto_table_info_runtime_table(self): 84 return DiffTestBlueprint( 85 trace=TextProto(''), 86 query=""" 87 CREATE PERFETTO TABLE foo AS 88 SELECT * FROM 89 (SELECT 2 AS c 90 UNION 91 SELECT 0 AS c 92 UNION 93 SELECT 1 AS c) 94 ORDER BY c desc; 95 96 SELECT * from perfetto_table_info('foo'); 97 """, 98 out=Csv(""" 99 "id","type","name","col_type","nullable","sorted" 100 0,"perfetto_table_info","c","int64",0,0 101 """)) 102 103 def test_create_perfetto_table_nullable_column(self): 104 return DiffTestBlueprint( 105 trace=DataPath('android_boot.pftrace'), 106 query=""" 107 CREATE PERFETTO TABLE foo AS 108 SELECT thread_ts FROM slice 109 WHERE thread_ts IS NOT NULL; 110 111 SELECT nullable FROM perfetto_table_info('foo') 112 WHERE name = 'thread_ts'; 113 """, 114 out=Csv(""" 115 "nullable" 116 0 117 """)) 118 119 def test_create_perfetto_table_nullable_column(self): 120 return DiffTestBlueprint( 121 trace=DataPath('android_boot.pftrace'), 122 query=""" 123 CREATE PERFETTO TABLE foo AS 124 SELECT dur FROM slice ORDER BY dur; 125 126 SELECT sorted FROM perfetto_table_info('foo') 127 WHERE name = 'dur'; 128 """, 129 out=Csv(""" 130 "sorted" 131 1 132 """)) 133 134 def test_create_perfetto_table_id_column(self): 135 return DiffTestBlueprint( 136 trace=TextProto(''), 137 query=""" 138 CREATE PERFETTO TABLE foo AS 139 SELECT 2 AS c 140 UNION 141 SELECT 4 142 UNION 143 SELECT 6; 144 145 SELECT col_type FROM perfetto_table_info('foo') 146 WHERE name = 'c'; 147 """, 148 out=Csv(""" 149 "col_type" 150 "id" 151 """)) 152 153 def test_distinct_trivial(self): 154 return DiffTestBlueprint( 155 trace=DataPath('example_android_trace_30s.pb'), 156 query=""" 157 WITH trivial_count AS ( 158 SELECT DISTINCT name FROM slice 159 ), 160 few_results AS ( 161 SELECT DISTINCT depth FROM slice 162 ), 163 simple_nullable AS ( 164 SELECT DISTINCT parent_id FROM slice 165 ), 166 selector AS ( 167 SELECT DISTINCT cpu FROM ftrace_event 168 ) 169 SELECT 170 (SELECT COUNT(*) FROM trivial_count) AS name, 171 (SELECT COUNT(*) FROM few_results) AS depth, 172 (SELECT COUNT(*) FROM simple_nullable) AS parent_id, 173 (SELECT COUNT(*) FROM selector) AS cpu_from_ftrace; 174 """, 175 out=Csv(""" 176 "name","depth","parent_id","cpu_from_ftrace" 177 3073,8,4529,8 178 """)) 179 180 def test_distinct_multi_column(self): 181 return DiffTestBlueprint( 182 trace=TextProto(''), 183 query=""" 184 CREATE PERFETTO TABLE foo AS 185 WITH data(a, b) AS ( 186 VALUES 187 -- Needed to defeat any id/sorted detection. 188 (2, 3), 189 (0, 2), 190 (0, 1) 191 ) 192 SELECT * FROM data; 193 194 CREATE TABLE bar AS 195 SELECT 1 AS b; 196 197 WITH multi_col_distinct AS ( 198 SELECT DISTINCT a FROM foo CROSS JOIN bar USING (b) 199 ), multi_col_group_by AS ( 200 SELECT a FROM foo CROSS JOIN bar USING (b) GROUP BY a 201 ) 202 SELECT 203 (SELECT COUNT(*) FROM multi_col_distinct) AS cnt_distinct, 204 (SELECT COUNT(*) FROM multi_col_group_by) AS cnt_group_by 205 """, 206 out=Csv(""" 207 "cnt_distinct","cnt_group_by" 208 1,1 209 """)) 210 211 def test_limit(self): 212 return DiffTestBlueprint( 213 trace=TextProto(''), 214 query=""" 215 WITH data(a, b) AS ( 216 VALUES 217 (0, 1), 218 (1, 10), 219 (2, 20), 220 (3, 30), 221 (4, 40), 222 (5, 50) 223 ) 224 SELECT * FROM data LIMIT 3; 225 """, 226 out=Csv(""" 227 "a","b" 228 0,1 229 1,10 230 2,20 231 """)) 232 233 def test_limit_and_offset_in_bounds(self): 234 return DiffTestBlueprint( 235 trace=TextProto(''), 236 query=""" 237 WITH data(a, b) AS ( 238 VALUES 239 (0, 1), 240 (1, 10), 241 (2, 20), 242 (3, 30), 243 (4, 40), 244 (5, 50), 245 (6, 60), 246 (7, 70), 247 (8, 80), 248 (9, 90) 249 ) 250 SELECT * FROM data LIMIT 2 OFFSET 3; 251 """, 252 out=Csv(""" 253 "a","b" 254 3,30 255 4,40 256 """)) 257 258 def test_limit_and_offset_not_in_bounds(self): 259 return DiffTestBlueprint( 260 trace=TextProto(''), 261 query=""" 262 WITH data(a, b) AS ( 263 VALUES 264 (0, 1), 265 (1, 10), 266 (2, 20), 267 (3, 30), 268 (4, 40), 269 (5, 50), 270 (6, 60), 271 (7, 70), 272 (8, 80), 273 (9, 90) 274 ) 275 SELECT * FROM data LIMIT 5 OFFSET 6; 276 """, 277 out=Csv(""" 278 "a","b" 279 6,60 280 7,70 281 8,80 282 9,90 283 """)) 284 285 def test_max(self): 286 return DiffTestBlueprint( 287 trace=DataPath('example_android_trace_30s.pb'), 288 query=""" 289 CREATE PERFETTO MACRO max(col ColumnName) 290 RETURNS TableOrSubquery AS ( 291 SELECT id, $col 292 FROM slice 293 ORDER BY $col DESC 294 LIMIT 1 295 ); 296 297 SELECT 298 (SELECT id FROM max!(id)) AS id, 299 (SELECT id FROM max!(dur)) AS numeric, 300 (SELECT id FROM max!(name)) AS string, 301 (SELECT id FROM max!(parent_id)) AS nullable; 302 """, 303 out=Csv(""" 304 "id","numeric","string","nullable" 305 20745,2698,148,20729 306 """)) 307 308 def test_min(self): 309 return DiffTestBlueprint( 310 trace=DataPath('example_android_trace_30s.pb'), 311 query=""" 312 CREATE PERFETTO MACRO min(col ColumnName) 313 RETURNS TableOrSubquery AS ( 314 SELECT id, $col 315 FROM slice 316 ORDER BY $col ASC 317 LIMIT 1 318 ); 319 320 SELECT 321 (SELECT id FROM min!(id)) AS id, 322 (SELECT id FROM min!(dur)) AS numeric, 323 (SELECT id FROM min!(name)) AS string, 324 (SELECT id FROM min!(parent_id)) AS nullable; 325 """, 326 out=Csv(""" 327 "id","numeric","string","nullable" 328 0,3111,460,0 329 """)) 330