• 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, TraceInjector
19from python.generators.diff_tests.testing import TestSuite
20
21
22class Tables(TestSuite):
23  # Contains tests for the handling of tables by trace processor. The focus of
24  # here is to check that trace processor is correctly returning and handling
25  # on the really important tables in trace processor.  Note: It's generally
26  # advisable to add tests here. Check the guidance provided by
27  # for choosing which folder to add a new test to. Window table
28  def test_android_sched_and_ps_smoke_window(self):
29    return DiffTestBlueprint(
30        trace=DataPath('android_sched_and_ps.pb'),
31        query="""
32        SELECT * FROM "window";
33        """,
34        out=Csv("""
35        "ts","dur","quantum_ts"
36        0,9223372036854775807,0
37        """))
38
39  def test_simple_interval_intersect_rev(self):
40    return DiffTestBlueprint(
41        trace=TextProto(""),
42        query="""
43
44        CREATE PERFETTO TABLE A AS
45          WITH data(id, ts, ts_end, c0, c1) AS (
46            VALUES
47            (0, 1, 7, 10, 3)
48          )
49          SELECT * FROM data;
50
51        CREATE PERFETTO TABLE B AS
52          WITH data(id, ts, ts_end, c0, c2) AS (
53            VALUES
54            (0, 0, 2, 10, 100),
55            (1, 3, 5, 10, 200),
56            (2, 6, 8, 20, 300)
57          )
58          SELECT * FROM data;
59
60        SELECT a.id AS a_id, b.id AS b_id
61        FROM __intrinsic_ii_with_interval_tree('A', 'c0, c1') a
62        JOIN __intrinsic_ii_with_interval_tree('B', 'c0, c2') b
63        WHERE a.ts < b.ts_end AND a.ts_end > b.ts
64        """,
65        out=Csv("""
66        "a_id","b_id"
67        0,1
68        0,0
69        0,2
70        """))
71
72  def test_compare_with_ii_macro(self):
73    return DiffTestBlueprint(
74        trace=DataPath('example_android_trace_30s.pb'),
75        query="""
76        INCLUDE PERFETTO MODULE intervals.intersect;
77
78        CREATE PERFETTO TABLE big_foo AS
79        SELECT
80          ts,
81          ts + dur as ts_end,
82          id * 10 AS id
83        FROM sched
84        WHERE utid == 1;
85
86        CREATE PERFETTO TABLE small_foo AS
87        SELECT
88        ts + 1000 AS ts,
89        ts + dur + 1000 AS ts_end,
90        id
91        FROM sched
92        WHERE utid == 1;
93
94        CREATE PERFETTO TABLE small_foo_for_ii AS
95        SELECT id, ts, ts_end - ts AS dur
96        FROM small_foo;
97
98        CREATE PERFETTO TABLE big_foo_for_ii AS
99        SELECT id, ts, ts_end - ts AS dur
100        FROM big_foo;
101
102        CREATE PERFETTO TABLE both AS
103        SELECT
104          left_id,
105          right_id,
106          cat,
107          count() AS c,
108          MAX(ts) AS max_ts, MAX(dur) AS max_dur
109        FROM (
110          SELECT a.id AS left_id, b.id AS right_id, 0 AS ts, 0 AS dur, "it" AS cat
111          FROM __intrinsic_ii_with_interval_tree('big_foo', '') a
112          JOIN __intrinsic_ii_with_interval_tree('small_foo', '') b
113          WHERE a.ts < b.ts_end AND a.ts_end > b.ts
114          UNION
115          SELECT left_id, right_id, ts, dur, "ii" AS cat
116          FROM _interval_intersect!(big_foo_for_ii, small_foo_for_ii)
117          WHERE dur != 0
118        )
119          GROUP BY left_id, right_id;
120
121        SELECT
122          SUM(c) FILTER (WHERE c == 2) AS good,
123          SUM(c) FILTER (WHERE c != 2) AS bad
124        FROM both;
125        """,
126        out=Csv("""
127          "good","bad"
128          314,"[NULL]"
129        """))
130
131  def test_compare_with_span_join(self):
132    return DiffTestBlueprint(
133        trace=DataPath('example_android_trace_30s.pb'),
134        query="""
135        INCLUDE PERFETTO MODULE intervals.intersect;
136
137        CREATE PERFETTO TABLE big_foo AS
138        SELECT
139          ts,
140          ts + dur as ts_end,
141          id * 10 AS id,
142          cpu AS c0
143        FROM sched
144        WHERE dur != -1;
145
146        CREATE PERFETTO TABLE small_foo AS
147        SELECT
148          ts + 1000 AS ts,
149          ts + dur + 1000 AS ts_end,
150          id,
151          cpu AS c0
152        FROM sched
153        WHERE dur != -1;
154
155        CREATE PERFETTO TABLE small_foo_for_sj AS
156        SELECT
157          id AS small_id,
158          ts,
159          ts_end - ts AS dur,
160          c0
161        FROM small_foo
162        WHERE dur != 0;
163
164        CREATE PERFETTO TABLE big_foo_for_sj AS
165        SELECT
166          id AS big_id,
167          ts,
168          ts_end - ts AS dur,
169          c0
170        FROM big_foo
171        WHERE dur != 0;
172
173        CREATE VIRTUAL TABLE sj_res
174        USING SPAN_JOIN(
175          small_foo_for_sj PARTITIONED c0,
176          big_foo_for_sj PARTITIONED c0);
177
178        CREATE PERFETTO TABLE both AS
179        SELECT
180          left_id,
181          right_id,
182          cat,
183          count() AS c,
184          MAX(ts) AS max_ts, MAX(dur) AS max_dur
185        FROM (
186          SELECT a.id AS left_id, b.id AS right_id, 0 AS ts, 0 AS dur, "it" AS cat
187          FROM __intrinsic_ii_with_interval_tree('big_foo', 'c0') a
188          JOIN __intrinsic_ii_with_interval_tree('small_foo', 'c0') b
189          USING (c0)
190          WHERE a.ts < b.ts_end AND a.ts_end > b.ts
191          UNION
192          SELECT big_id AS left_id, small_id AS right_id, ts, dur, "sj" AS cat FROM sj_res
193        )
194          GROUP BY left_id, right_id;
195
196        SELECT
197          SUM(c) FILTER (WHERE c == 2) AS good,
198          SUM(c) FILTER (WHERE c != 2) AS bad
199        FROM both;
200        """,
201        out=Csv("""
202          "good","bad"
203          1538288,"[NULL]"
204        """))
205
206  def test_ii_partitioned_big(self):
207    return DiffTestBlueprint(
208        trace=DataPath('example_android_trace_30s.pb'),
209        query="""
210        INCLUDE PERFETTO MODULE intervals.intersect;
211
212        CREATE PERFETTO TABLE big_foo AS
213        SELECT
214          ts,
215          ts + dur as ts_end,
216          id * 10 AS id,
217          cpu AS c0
218        FROM sched
219        WHERE dur != -1;
220
221        CREATE PERFETTO TABLE small_foo AS
222        SELECT
223          ts + 1000 AS ts,
224          ts + dur + 1000 AS ts_end,
225          id,
226          cpu AS c0
227        FROM sched
228        WHERE dur != -1;
229
230        CREATE PERFETTO TABLE res AS
231        SELECT a.id AS a_id, b.id AS b_id
232        FROM __intrinsic_ii_with_interval_tree('small_foo', 'c0') a
233        JOIN __intrinsic_ii_with_interval_tree('big_foo', 'c0') b
234        USING (c0)
235        WHERE a.ts < b.ts_end AND a.ts_end > b.ts;
236
237        SELECT * FROM res
238        ORDER BY a_id, b_id
239        LIMIT 10;
240        """,
241        out=Csv("""
242        "a_id","b_id"
243        0,0
244        0,10
245        1,10
246        1,430
247        2,20
248        2,30
249        3,30
250        3,40
251        4,40
252        4,50
253        """))
254
255
256  def test_ii_operator_big(self):
257    return DiffTestBlueprint(
258        trace=DataPath('example_android_trace_30s.pb'),
259        query="""
260        CREATE PERFETTO TABLE big_foo AS
261        SELECT
262          id,
263          ts,
264          ts+dur AS ts_end
265        FROM sched
266        WHERE dur != -1
267        ORDER BY ts;
268
269        CREATE PERFETTO TABLE small_foo AS
270        SELECT
271        id * 10 AS id,
272        ts + 1000 AS ts,
273        ts_end + 1000 AS ts_end
274        FROM big_foo
275        LIMIT 10
276        OFFSET 5;
277
278        CREATE PERFETTO TABLE res AS
279        SELECT a.id AS a_id, b.id AS b_id
280        FROM __intrinsic_ii_with_interval_tree('small_foo', '') a
281        JOIN __intrinsic_ii_with_interval_tree('big_foo', '') b
282        WHERE a.ts < b.ts_end AND a.ts_end > b.ts;
283
284        SELECT * FROM res
285        ORDER BY a_id, b_id
286        LIMIT 10;
287        """,
288        out=Csv("""
289        "a_id","b_id"
290        50,1
291        50,5
292        50,6
293        60,1
294        60,6
295        60,7
296        60,8
297        70,1
298        70,6
299        70,7
300        """))
301
302  # Null printing
303  def test_nulls(self):
304    return DiffTestBlueprint(
305        trace=Path('../common/synth_1.py'),
306        query="""
307        CREATE TABLE null_test (
308          primary_key INTEGER PRIMARY KEY,
309          int_nulls INTEGER,
310          string_nulls STRING,
311          double_nulls DOUBLE,
312          start_int_nulls INTEGER,
313          start_string_nulls STRING,
314          start_double_nulls DOUBLE,
315          all_nulls INTEGER
316        );
317
318        INSERT INTO null_test(
319          int_nulls,
320          string_nulls,
321          double_nulls,
322          start_int_nulls,
323          start_string_nulls,
324          start_double_nulls
325        )
326        VALUES
327        (1, "test", 2.0, NULL, NULL, NULL),
328        (2, NULL, NULL, NULL, "test", NULL),
329        (1, "other", NULL, NULL, NULL, NULL),
330        (4, NULL, NULL, NULL, NULL, 1.0),
331        (NULL, "test", 1.0, 1, NULL, NULL);
332
333        SELECT * FROM null_test;
334        """,
335        out=Path('nulls.out'))
336
337  # Thread table
338  def test_thread_main_thread(self):
339    return DiffTestBlueprint(
340        trace=TextProto(r"""
341        packet {
342          timestamp: 1
343          process_tree {
344            processes {
345              pid: 5
346              ppid: 1
347              cmdline: "com.google.pid5"
348            }
349            threads {
350              tid: 5
351              tgid: 5
352            }
353            threads {
354              tid: 7
355              tgid: 5
356              name: "tid7"
357            }
358            processes {
359              pid: 11
360              ppid: 1
361              cmdline: "com.google.pid11"
362            }
363            threads {
364              tid: 11
365              tgid: 11
366              name: "tid11"
367            }
368            threads {
369              tid: 12
370              tgid: 11
371              name: "tid12"
372            }
373          }
374        }
375        packet {
376          timestamp: 2
377          ftrace_events {
378            cpu: 0
379            event {
380              timestamp: 2
381              pid: 99
382              lowmemory_kill {
383                pid: 99
384              }
385            }
386          }
387        }
388        """),
389        query="""
390        SELECT
391          tid,
392          is_main_thread
393        FROM thread
394        WHERE tid IN (5, 7, 11, 12, 99)
395        ORDER BY tid;
396        """,
397        out=Csv("""
398        "tid","is_main_thread"
399        5,1
400        7,0
401        11,1
402        12,0
403        99,"[NULL]"
404        """))
405
406  # Json output
407  def test_trace_metadata(self):
408    return DiffTestBlueprint(
409        trace=DataPath('memory_counters.pb'),
410        query=Metric('trace_metadata'),
411        out=Path('trace_metadata.json.out'))
412
413  # Processes as a metric
414  def test_android_task_names(self):
415    return DiffTestBlueprint(
416        trace=TextProto(r"""
417        packet {
418          process_tree {
419            processes {
420              pid: 1
421              ppid: 0
422              cmdline: "init"
423              uid: 0
424            }
425            processes {
426              pid: 2
427              ppid: 1
428              cmdline: "com.google.android.gm:process"
429              uid: 10001
430            }
431          }
432        }
433        packet {
434          packages_list {
435            packages {
436              name: "com.google.android.gm"
437              uid: 10001
438            }
439          }
440        }
441        """),
442        query=Metric('android_task_names'),
443        out=TextProto(r"""
444        android_task_names {
445          process {
446            pid: 1
447            process_name: "init"
448            uid: 0
449          }
450          process {
451            pid: 2
452            process_name: "com.google.android.gm:process"
453            uid: 10001
454            uid_package_name: "com.google.android.gm"
455          }
456        }
457        """))
458
459  # Ftrace stats imports in metadata and stats tables
460  def test_ftrace_setup_errors(self):
461    return DiffTestBlueprint(
462        trace=DataPath('ftrace_error_stats.pftrace'),
463        query="""
464        SELECT value FROM stats WHERE name = 'ftrace_setup_errors'
465        UNION ALL
466        SELECT str_value FROM metadata WHERE name = 'ftrace_setup_errors';
467        """,
468        out=Csv("""
469        "value"
470        3
471        "Ftrace event unknown: foo/bar
472        Ftrace event unknown: sched/foobar
473        Atrace failures: error: unknown tracing category "bar"
474        error enabling tracing category "bar"
475        "
476        """))
477
478  # Ftrace stats imports in metadata and stats tables
479  def test_filter_stats(self):
480    return DiffTestBlueprint(
481        trace=TextProto("""
482          packet { trace_stats{ filter_stats {
483            input_packets: 836
484            input_bytes: 25689644
485            output_bytes: 24826981
486            errors: 12
487            time_taken_ns: 1228178548
488            bytes_discarded_per_buffer: 1
489            bytes_discarded_per_buffer: 34
490            bytes_discarded_per_buffer: 29
491            bytes_discarded_per_buffer: 0
492            bytes_discarded_per_buffer: 862588
493          }}}"""),
494        query="""
495        SELECT name, value FROM stats
496        WHERE name like 'filter_%' OR name = 'traced_buf_bytes_filtered_out'
497        ORDER by name ASC
498        """,
499        out=Csv("""
500        "name","value"
501        "filter_errors",12
502        "filter_input_bytes",25689644
503        "filter_input_packets",836
504        "filter_output_bytes",24826981
505        "filter_time_taken_ns",1228178548
506        "traced_buf_bytes_filtered_out",1
507        "traced_buf_bytes_filtered_out",34
508        "traced_buf_bytes_filtered_out",29
509        "traced_buf_bytes_filtered_out",0
510        "traced_buf_bytes_filtered_out",862588
511        """))
512
513  # cpu_track table
514  def test_cpu_track_table(self):
515    return DiffTestBlueprint(
516        trace=TextProto(r"""
517        packet {
518          ftrace_events {
519            cpu: 1
520            event {
521              timestamp: 100001000000
522              pid: 10
523              irq_handler_entry {
524                irq: 100
525                name : "resource1"
526              }
527            }
528            event {
529              timestamp: 100002000000
530              pid: 10
531              irq_handler_exit {
532                irq: 100
533                ret: 1
534              }
535            }
536          }
537        }
538        packet {
539          ftrace_events {
540            cpu: 0
541            event {
542              timestamp: 100003000000
543              pid: 15
544              irq_handler_entry {
545                irq: 100
546                name : "resource1"
547              }
548            }
549          }
550        }
551        """),
552        query="""
553        SELECT
554          type,
555          cpu
556        FROM cpu_track
557        ORDER BY type, cpu;
558        """,
559        out=Csv("""
560        "type","cpu"
561        "cpu_track",0
562        "cpu_track",1
563        """))
564
565  def test_thread_state_flattened_aggregated(self):
566    return DiffTestBlueprint(
567        trace=DataPath('android_monitor_contention_trace.atr'),
568        query="""
569      INCLUDE PERFETTO MODULE sched.thread_state_flattened;
570      select * from _get_flattened_thread_state_aggregated(11155, NULL);
571      """,
572        out=Path('thread_state_flattened_aggregated_csv.out'))
573
574  def test_thread_state_flattened(self):
575    return DiffTestBlueprint(
576        trace=DataPath('android_monitor_contention_trace.atr'),
577        query="""
578      INCLUDE PERFETTO MODULE sched.thread_state_flattened;
579      select * from _get_flattened_thread_state(11155, NULL);
580      """,
581        out=Path('thread_state_flattened_csv.out'))
582
583  def test_metadata(self):
584    return DiffTestBlueprint(
585        trace=TextProto(r"""
586        packet {
587          system_info {
588            tracing_service_version: "Perfetto v38.0-0bb49ab54 (0bb49ab54dbe55ce5b9dfea3a2ada68b87aecb65)"
589            timezone_off_mins: 60
590            utsname {
591              sysname: "Darwin"
592              version: "Foobar"
593              machine: "x86_64"
594              release: "22.6.0"
595            }
596          }
597          trusted_uid: 158158
598          trusted_packet_sequence_id: 1
599        }
600        """),
601        query=r"""SELECT name, COALESCE(str_value, int_value) as val
602              FROM metadata
603              WHERE name IN (
604                  "system_name", "system_version", "system_machine",
605                  "system_release", "timezone_off_mins")
606              ORDER BY name
607        """,
608        out=Csv(r"""
609                "name","val"
610                "system_machine","x86_64"
611                "system_name","Darwin"
612                "system_release","22.6.0"
613                "system_version","Foobar"
614                "timezone_off_mins",60
615                """))
616
617  def test_flow_table_trace_id(self):
618    return DiffTestBlueprint(
619        trace=TextProto("""
620          packet {
621            timestamp: 0
622            track_event {
623              name: "Track 0 Event"
624              type: TYPE_SLICE_BEGIN
625              track_uuid: 10
626              flow_ids: 57
627            }
628            trusted_packet_sequence_id: 123
629          }
630          packet {
631            timestamp: 10
632            track_event {
633              name: "Track 0 Nested Event"
634              type: TYPE_SLICE_BEGIN
635              track_uuid: 10
636              flow_ids: 57
637            }
638            trusted_packet_sequence_id: 123
639          }
640          packet {
641            timestamp: 50
642            track_event {
643              name: "Track 0 Short Event"
644              type: TYPE_SLICE_BEGIN
645              track_uuid: 10
646              terminating_flow_ids: 57
647            }
648            trusted_packet_sequence_id: 123
649          }
650        """),
651        query="SELECT * FROM flow;",
652        out=Csv("""
653          "id","type","slice_out","slice_in","trace_id","arg_set_id"
654          0,"flow",0,1,57,0
655          1,"flow",1,2,57,0
656                """))
657
658  def test_clock_snapshot_table_multiplier(self):
659    return DiffTestBlueprint(
660        trace=TextProto("""
661          packet {
662            clock_snapshot {
663              clocks {
664                clock_id: 1
665                timestamp: 42
666                unit_multiplier_ns: 10
667              }
668              clocks {
669                clock_id: 6
670                timestamp: 0
671              }
672            }
673          }
674        """),
675        query="SELECT TO_REALTIME(0);",
676        out=Csv("""
677          "TO_REALTIME(0)"
678          420
679        """))
680
681  # Test cpu_track with machine_id ID.
682  def test_cpu_track_table_machine_id(self):
683    return DiffTestBlueprint(
684        trace=TextProto(r"""
685        packet {
686          ftrace_events {
687            cpu: 1
688            event {
689              timestamp: 100001000000
690              pid: 10
691              irq_handler_entry {
692                irq: 100
693                name : "resource1"
694              }
695            }
696            event {
697              timestamp: 100002000000
698              pid: 10
699              irq_handler_exit {
700                irq: 100
701                ret: 1
702              }
703            }
704          }
705          machine_id: 1001
706        }
707        packet {
708          ftrace_events {
709            cpu: 0
710            event {
711              timestamp: 100003000000
712              pid: 15
713              irq_handler_entry {
714                irq: 100
715                name : "resource1"
716              }
717            }
718          }
719          machine_id: 1001
720        }
721        """),
722        query="""
723        SELECT
724          type,
725          cpu,
726          machine_id
727        FROM cpu_track
728        ORDER BY type, cpu
729        """,
730        out=Csv("""
731        "type","cpu","machine_id"
732        "cpu_track",0,1
733        "cpu_track",1,1
734        """))
735