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 DynamicTables(TestSuite): 23 # Tests for custom dynamic tables. Ancestor slice table. 24 def test_ancestor_slice(self): 25 return DiffTestBlueprint( 26 trace=Path('relationship_tables.textproto'), 27 query=""" 28 SELECT slice.name AS currentSliceName, ancestor.name AS ancestorSliceName 29 FROM slice LEFT JOIN ancestor_slice(slice.id) AS ancestor 30 ORDER BY slice.ts ASC, ancestor.ts ASC, slice.name ASC, ancestor.name ASC; 31 """, 32 out=Path('ancestor_slice.out')) 33 34 # Descendant slice table. 35 def test_descendant_slice(self): 36 return DiffTestBlueprint( 37 trace=Path('relationship_tables.textproto'), 38 query=""" 39 SELECT slice.name AS currentSliceName, descendant.name AS descendantSliceName 40 FROM slice LEFT JOIN descendant_slice(slice.id) AS descendant 41 ORDER BY slice.ts ASC, descendant.ts ASC, slice.name ASC, descendant.name ASC; 42 """, 43 out=Path('descendant_slice.out')) 44 45 # Ancestor slice by stack table. 46 def test_ancestor_slice_by_stack(self): 47 return DiffTestBlueprint( 48 trace=Path('slice_stacks.textproto'), 49 query=""" 50 SELECT ts, name FROM ancestor_slice_by_stack(( 51 SELECT stack_id FROM slice 52 WHERE name = 'event_depth_2' 53 LIMIT 1 54 )); 55 """, 56 out=Csv(""" 57 "ts","name" 58 1000,"event_depth_0" 59 2000,"event_depth_1" 60 8000,"event_depth_0" 61 9000,"event_depth_1" 62 """)) 63 64 # Descendant slice by stack table. 65 def test_descendant_slice_by_stack(self): 66 return DiffTestBlueprint( 67 trace=Path('slice_stacks.textproto'), 68 query=""" 69 SELECT ts, name FROM descendant_slice_by_stack(( 70 SELECT stack_id FROM slice 71 WHERE name = 'event_depth_0' 72 LIMIT 1 73 )); 74 """, 75 out=Csv(""" 76 "ts","name" 77 2000,"event_depth_1" 78 3000,"event_depth_2" 79 9000,"event_depth_1" 80 10000,"event_depth_2" 81 """)) 82 83 # Connected/Following/Perceeding flow table. 84 def test_connected_flow(self): 85 return DiffTestBlueprint( 86 trace=Path('connected_flow_data.json'), 87 query=Path('connected_flow_test.sql'), 88 out=Path('connected_flow.out')) 89 90 # Annotated callstacks. 91 def test_perf_sample_sc_annotated_callstack(self): 92 return DiffTestBlueprint( 93 trace=DataPath('perf_sample_sc.pb'), 94 query=""" 95 SELECT eac.id, eac.depth, eac.frame_id, eac.annotation, 96 spf.name 97 FROM experimental_annotated_callstack eac 98 JOIN perf_sample ps 99 ON (eac.start_id = ps.callsite_id) 100 JOIN stack_profile_frame spf 101 ON (eac.frame_id = spf.id) 102 ORDER BY eac.start_id ASC, eac.depth ASC; 103 """, 104 out=Path('perf_sample_sc_annotated_callstack.out')) 105 106 # ABS_TIME_STR function 107 def test_various_clocks_abs_time_str(self): 108 return DiffTestBlueprint( 109 trace=Path('various_clocks.textproto'), 110 query=""" 111 SELECT 112 ABS_TIME_STR(15) AS t15, 113 ABS_TIME_STR(25) AS t25, 114 ABS_TIME_STR(35) AS t35; 115 """, 116 out=Csv(""" 117 "t15","t25","t35" 118 "1970-01-01T00:00:00.000000005","2022-05-18T19:59:59.999999995","2022-05-18T20:00:00.000000000" 119 """)) 120 121 def test_empty_abs_time_str(self): 122 return DiffTestBlueprint( 123 trace=TextProto(r""" 124 125 """), 126 query=""" 127 SELECT 128 ABS_TIME_STR(15) AS t15, 129 ABS_TIME_STR(25) AS t25, 130 ABS_TIME_STR(35) AS t35; 131 """, 132 out=Csv(""" 133 "t15","t25","t35" 134 "[NULL]","[NULL]","[NULL]" 135 """)) 136 137 # TO_REALTIME function 138 def test_various_clocks_to_realtime(self): 139 return DiffTestBlueprint( 140 trace=Path('various_clocks.textproto'), 141 query=""" 142 SELECT 143 TO_REALTIME(15) AS t15, 144 TO_REALTIME(25) AS t25, 145 TO_REALTIME(35) AS t35; 146 """, 147 out=Csv(""" 148 "t15","t25","t35" 149 5,1652903999999999995,1652904000000000000 150 """)) 151 152 def test_empty_to_realtime(self): 153 return DiffTestBlueprint( 154 trace=TextProto(r""" 155 156 """), 157 query=""" 158 SELECT 159 TO_REALTIME(15) AS t15, 160 TO_REALTIME(25) AS t25, 161 TO_REALTIME(35) AS t35; 162 """, 163 out=Csv(""" 164 "t15","t25","t35" 165 "[NULL]","[NULL]","[NULL]" 166 """)) 167 168 # TO_MONOTONIC function 169 def test_various_clocks_to_monotonic(self): 170 return DiffTestBlueprint( 171 trace=Path('various_clocks.textproto'), 172 query=""" 173 SELECT 174 TO_MONOTONIC(25) AS t15, 175 TO_MONOTONIC(35) AS t20, 176 TO_MONOTONIC(50) AS t25; 177 """, 178 out=Csv(""" 179 "t15","t20","t25" 180 15,20,25 181 """)) 182 183 def test_empty_to_monotonic(self): 184 return DiffTestBlueprint( 185 trace=TextProto(r""" 186 187 """), 188 query=""" 189 SELECT 190 TO_MONOTONIC(25) AS t15, 191 TO_MONOTONIC(35) AS t20, 192 TO_MONOTONIC(50) AS t25; 193 """, 194 out=Csv(""" 195 "t15","t20","t25" 196 "[NULL]","[NULL]","[NULL]" 197 """)) 198 199 # TO_TIMECODE function 200 def test_various_clocks_to_timecode(self): 201 return DiffTestBlueprint( 202 trace=Path('various_clocks.textproto'), 203 query=""" 204 SELECT 205 TO_TIMECODE(0) AS t0, 206 TO_TIMECODE(3599123456789) AS t1, 207 TO_TIMECODE(3600123456789) AS t2 208 """, 209 out=Csv(""" 210 "t0","t1","t2" 211 "00:00:00 000 000 000","00:59:59 123 456 789","01:00:00 123 456 789" 212 """)) 213