• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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