• 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 Parsing(TestSuite):
23  # Contains tests for parsing events which are applicable to more than one
24  # "area". Generally, events here are of high importance (e.g. sched_switch
25  # tested here is and is used by every embedder of trace processor)  Note:
26  # generally *not* advisable to add tests here. Check the guidance provided
27  # http://perfetto/dev/docs/analysis/trace-processor#diff-tests for choosing
28  # folder to add a new test to. TODO(lalitm): some tests here should be moved
29  # of here and into the area folders; they are only here because they predate
30  # modularisation of diff tests. Sched
31  def test_ts_desc_filter_android_sched_and_ps(self):
32    return DiffTestBlueprint(
33        trace=DataPath('android_sched_and_ps.pb'),
34        query="""
35        SELECT ts
36        FROM sched
37        JOIN thread USING(utid)
38        WHERE tid = 23850
39        ORDER BY ts DESC
40        LIMIT 10;
41        """,
42        out=Csv("""
43        "ts"
44        81492536383477
45        81491101817952
46        81491101296858
47        81491101029618
48        81491099541806
49        81491099514618
50        81491099495504
51        81491099477014
52        81491098894566
53        81491096076181
54        """))
55
56  # Sched reason
57  def test_android_sched_and_ps_end_reason_eq(self):
58    return DiffTestBlueprint(
59        trace=DataPath('android_sched_and_ps.pb'),
60        query="""
61        SELECT end_state, count(*)
62        FROM sched
63        WHERE end_state = 'D'
64        GROUP BY end_state;
65        """,
66        out=Csv("""
67        "end_state","count(*)"
68        "D",10503
69        """))
70
71  def test_android_sched_and_ps_end_reason_neq(self):
72    return DiffTestBlueprint(
73        trace=DataPath('android_sched_and_ps.pb'),
74        query="""
75        SELECT end_state, count(*)
76        FROM sched
77        WHERE end_state != 'D'
78        GROUP BY end_state;
79        """,
80        out=Csv("""
81        "end_state","count(*)"
82        "DK",30
83        "R",91189
84        "R+",9428
85        "S",110560
86        "x",82
87        """))
88
89  # CPU Frequency
90  def test_cpu_counters_b120487929(self):
91    return DiffTestBlueprint(
92        trace=DataPath('cpu_counters.pb'),
93        query=Path('b120487929_test.sql'),
94        out=Path('cpu_counters_b120487929.out'))
95
96  # Test the filtering of ftrace events before tracing_start.
97  def test_ftrace_with_tracing_start_list_sched_slice_spans(self):
98    return DiffTestBlueprint(
99        trace=Path('ftrace_with_tracing_start.py'),
100        query="""
101        SELECT ts, dur, tid
102        FROM sched
103        JOIN thread USING(utid)
104        ORDER BY ts;
105        """,
106        out=Csv("""
107        "ts","dur","tid"
108        100,10,1
109        110,-1,2
110        """))
111
112  # Scheduling slices from sched_switch events. There are two tests, one for
113  # typical encoding of sched_switch events, and one for the same trace
114  # in the compact format. The output should be identical apart from the
115  # having one slice fewer for each cpu (the first compact sched_switch event
116  # start a slice). Six slices in this case.
117  def test_sched_slices_sched_switch_original(self):
118    return DiffTestBlueprint(
119        trace=DataPath('sched_switch_original.pb'),
120        query="""
121        SELECT ts, cpu, dur, ts_end, end_state, priority, tid, name
122        FROM sched JOIN thread ON sched.utid = thread.utid
123        ORDER BY cpu, sched.ts ASC;
124        """,
125        out=Path('sched_slices_sched_switch_original.out'))
126
127  def test_sched_slices_sched_switch_compact(self):
128    return DiffTestBlueprint(
129        trace=DataPath('sched_switch_compact.pb'),
130        query="""
131        SELECT ts, cpu, dur, ts_end, end_state, priority, tid, name
132        FROM sched JOIN thread ON sched.utid = thread.utid
133        ORDER BY cpu, sched.ts ASC;
134        """,
135        out=Path('sched_slices_sched_switch_compact.out'))
136
137  # Decoding of sched_waking events from a trace with compact scheduling
138  # Verifies the contents of raw & instants tables.
139  def test_sched_waking_raw_compact_sched(self):
140    return DiffTestBlueprint(
141        trace=DataPath('compact_sched.pb'),
142        query=Path('sched_waking_raw_test.sql'),
143        out=Path('sched_waking_raw_compact_sched.out'))
144
145  def test_sched_waking_instants_compact_sched(self):
146    return DiffTestBlueprint(
147        trace=DataPath('compact_sched.pb'),
148        query="""
149        SELECT ts, thread.name, thread.tid
150        FROM thread_state
151        JOIN thread USING (utid)
152        WHERE state = 'R'
153        ORDER BY ts;
154        """,
155        out=Path('sched_waking_instants_compact_sched.out'))
156
157  # Mm Event
158  def test_mm_event(self):
159    return DiffTestBlueprint(
160        trace=DataPath('mm_event.pb'),
161        query="""
162        SELECT ts, name, value
163        FROM counter
164        JOIN counter_track
165          ON counter.track_id = counter_track.id
166        WHERE name GLOB 'mem.mm.*'
167        ORDER BY ts
168        LIMIT 40;
169        """,
170        out=Path('mm_event.out'))
171
172  # Check the systrace conversion code in the raw table. Print events
173  def test_print_systrace_lmk_userspace(self):
174    return DiffTestBlueprint(
175        trace=DataPath('lmk_userspace.pb'),
176        query="""
177        SELECT to_ftrace(id)
178        FROM ftrace_event;
179        """,
180        out=Path('print_systrace_lmk_userspace.out'))
181
182  def test_kernel_tmw_counter_process_counter_and_track(self):
183    return DiffTestBlueprint(
184        trace=Path('kernel_tmw_counter.textproto'),
185        query="""
186        SELECT ts, pct.name, value, pid
187        FROM counter c
188        JOIN process_counter_track pct ON c.track_id = pct.id
189        JOIN process USING (upid)
190        ORDER BY ts;
191        """,
192        out=Csv("""
193        "ts","name","value","pid"
194        795572805481,"g2d_frame_hw#15",0.000000,237
195        795572870504,"g2d_frame_sw#15",0.000000,237
196        795620516581,"g2d_frame_sw#15",1.000000,237
197        795620943421,"g2d_frame_hw#15",1.000000,237
198        795623633810,"g2d_frame_hw#15",0.000000,237
199        795623633810,"g2d_frame_hw#15",0.000000,237
200        795623739848,"g2d_frame_sw#15",0.000000,237
201        """))
202
203  def test_kernel_dpu_tmw_counter_process_counter_and_track(self):
204    return DiffTestBlueprint(
205        trace=TextProto(r"""
206        packet {
207          ftrace_events {
208            cpu: 2
209            event {
210              timestamp: 795572805481
211              pid: 237
212              dpu_tracing_mark_write {
213                pid: 237
214                name: "dpu_vote_clock"
215                type: 67
216                value: 123
217              }
218            }
219            event {
220              timestamp: 795572870504
221              pid: 515
222              dpu_tracing_mark_write {
223                pid: 237
224                name: "dpu_vote_clock"
225                type: 67
226                value: 100
227              }
228            }
229            event {
230              timestamp: 795620516581
231              pid: 237
232              dpu_tracing_mark_write {
233                pid: 237
234                name: "dpu_vote_clock"
235                type: 67
236                value: 125
237              }
238            }
239            event {
240              timestamp: 795620943421
241              pid: 515
242              dpu_tracing_mark_write {
243                pid: 237
244                name: "dpu_vote_clock"
245                type: 67
246                value: 100
247              }
248            }
249          }
250          trusted_uid: 9999
251          trusted_packet_sequence_id: 3
252        }
253        """),
254        query="""
255        SELECT ts, pct.name, value, pid
256        FROM counter c
257        JOIN process_counter_track pct ON c.track_id = pct.id
258        JOIN process USING (upid)
259        ORDER BY ts;
260        """,
261        out=Csv("""
262        "ts","name","value","pid"
263        795572805481,"dpu_vote_clock",123.000000,237
264        795572870504,"dpu_vote_clock",100.000000,237
265        795620516581,"dpu_vote_clock",125.000000,237
266        795620943421,"dpu_vote_clock",100.000000,237
267        """))
268
269  # Unsigned integers
270  def test_print_systrace_unsigned(self):
271    return DiffTestBlueprint(
272        trace=Path('print_systrace_unsigned.py'),
273        query="""
274        SELECT to_ftrace(id)
275        FROM ftrace_event;
276        """,
277        out=Path('print_systrace_unsigned.out'))
278
279  # cgroup_attach_task systrace conversion.
280  def test_cgroup_attach_task_pre_s_print_systrace(self):
281    return DiffTestBlueprint(
282        trace=TextProto(r"""
283        packet {
284            ftrace_events {
285              cpu: 3
286              event {
287                timestamp: 74289018336
288                pid: 1
289                cgroup_attach_task {
290                  dst_root: 1
291                  dst_id: 2
292                  pid: 3
293                  comm: "foo"
294                  cname: "bar"
295                }
296              }
297            }
298          }
299        """),
300        query="""
301        SELECT to_ftrace(id)
302        FROM ftrace_event;
303        """,
304        out=Path('cgroup_attach_task_pre_s_print_systrace.out'))
305
306  def test_cgroup_attach_task_post_s_print_systrace(self):
307    return DiffTestBlueprint(
308        trace=TextProto(r"""
309        packet {
310            ftrace_events {
311              cpu: 3
312              event {
313                timestamp: 74289018336
314                pid: 1
315                cgroup_attach_task {
316                  dst_root: 1
317                  dst_id: 2
318                  pid: 3
319                  comm: "foo"
320                  dst_level: 4
321                  dst_path: "bar"
322                }
323              }
324            }
325          }
326        """),
327        query="""
328        SELECT to_ftrace(id)
329        FROM ftrace_event;
330        """,
331        out=Path('cgroup_attach_task_post_s_print_systrace.out'))
332
333  # Parsing systrace files
334  def test_systrace_html(self):
335    return DiffTestBlueprint(
336        trace=DataPath('systrace.html'),
337        query="""
338        SELECT ts, cpu, dur, ts_end, utid, end_state, priority, upid, name, tid
339        FROM sched
340        JOIN thread USING(utid)
341        ORDER BY ts, sched.id;
342        """,
343        out=Path('systrace_html.out'))
344
345  def test_sched_smoke_trailing_empty(self):
346    return DiffTestBlueprint(
347        trace=DataPath('trailing_empty.systrace'),
348        query="""
349        SELECT COUNT(1)
350        FROM sched;
351        """,
352        out=Csv("""
353        "COUNT(1)"
354        2
355        """))
356
357  # LMK handling
358  def test_lmk_userspace_lmk(self):
359    return DiffTestBlueprint(
360        trace=DataPath('lmk_userspace.pb'),
361        query="""
362        SELECT ts, process.pid
363        FROM instant
364        JOIN process_track ON instant.track_id = process_track.id
365        JOIN process USING (upid);
366        """,
367        out=Csv("""
368        "ts","pid"
369        732246100696424,17924
370        732246180149452,21090
371        732246388596557,21120
372        732246415955101,21151
373        """))
374
375  def test_oom_kill(self):
376    return DiffTestBlueprint(
377        trace=TextProto(r"""
378        packet {
379          process_tree {
380            processes {
381              pid: 1000
382              ppid: 1
383              cmdline: "com.google.android.gm"
384            }
385            threads {
386              tid: 1001
387              tgid: 1000
388            }
389          }
390        }
391        packet {
392          ftrace_events {
393            cpu: 4
394            event {
395              timestamp: 1234
396              pid: 4321
397              mark_victim {
398                pid: 1001
399              }
400            }
401          }
402        }
403        """),
404        query="""
405        SELECT ts, instant.name, process.pid, process.name
406        FROM instant
407        JOIN thread_track ON instant.track_id = thread_track.id
408        JOIN thread USING (utid)
409        JOIN process USING (upid);
410        """,
411        out=Csv("""
412        "ts","name","pid","name"
413        1234,"mem.oom_kill",1000,"com.google.android.gm"
414        """))
415
416  # Logcat
417  def test_android_log_counts(self):
418    return DiffTestBlueprint(
419        trace=DataPath('android_log.pb'),
420        query=Path('android_log_counts_test.sql'),
421        out=Csv("""
422        "cnt"
423        2249
424        431
425        264
426        2
427        4
428        31
429        246
430        """))
431
432  def test_android_log_msgs(self):
433    return DiffTestBlueprint(
434        trace=DataPath('android_log.pb'),
435        query=Path('android_log_msgs_test.sql'),
436        out=Path('android_log_msgs.out'))
437
438  def test_android_log_ring_buffer_mode(self):
439    return DiffTestBlueprint(
440        trace=DataPath('android_log_ring_buffer_mode.pb'),
441        query="""
442        SELECT count(*) FROM android_logs;
443        """,
444        out=Csv("""
445        "count(*)"
446        26
447        """))
448
449  # Oom Score
450  def test_synth_oom_oom_query(self):
451    return DiffTestBlueprint(
452        trace=Path('synth_oom.py'),
453        query=Path('oom_query_test.sql'),
454        out=Path('synth_oom_oom_query.out'))
455
456  def test_process_stats_poll_oom_score(self):
457    return DiffTestBlueprint(
458        trace=DataPath('process_stats_poll.pb'),
459        query="""
460        SELECT ts, name, value, upid
461        FROM counter c
462        JOIN process_counter_track t
463          ON c.track_id = t.id
464        WHERE name = "oom_score_adj"
465        ORDER BY ts
466        LIMIT 20;
467        """,
468        out=Path('process_stats_poll_oom_score.out'))
469
470  # Stats
471  def test_android_sched_and_ps_stats(self):
472    return DiffTestBlueprint(
473        trace=DataPath('android_sched_and_ps.pb'),
474        query="""
475        SELECT name, idx, severity, source, value
476        FROM stats WHERE name GLOB 'ftrace_cpu_*' OR name GLOB 'traced_buf_*';
477        """,
478        out=Path('android_sched_and_ps_stats.out'))
479
480  # Syscalls
481  def test_sys_syscall(self):
482    return DiffTestBlueprint(
483        trace=Path('syscall.py'),
484        query="""
485        SELECT ts, dur, name
486        FROM slices
487        LIMIT 10;
488        """,
489        out=Csv("""
490        "ts","dur","name"
491        100,6,"sys_io_setup"
492        105,5,"sys_io_destroy"
493        """))
494
495  # thread_slice tables.
496  def test_thread_time_in_thread_slice(self):
497    return DiffTestBlueprint(
498        trace=Path('flow_events_json_v2.json'),
499        query="""
500        SELECT
501          name, thread_ts, thread_dur
502        FROM slice;
503        """,
504        out=Csv("""
505        "name","thread_ts","thread_dur"
506        "SenderB",1000,5000
507        "Blergh","[NULL]","[NULL]"
508        "SenderA",3005000,7000
509        "OtherSlice",3204000,100000
510        "SomeSlice",3335000,340000
511        "SomeOtherSlice",3335000,996000
512        "SomeOtherSliceInstant","[NULL]","[NULL]"
513        """))
514
515  # Initial display state
516  def test_initial_display_state(self):
517    return DiffTestBlueprint(
518        trace=TextProto(r"""
519        packet: {
520          timestamp: 1
521          initial_display_state: {
522            display_state: 2
523            brightness: 0.5
524          }
525        }
526        packet {
527          ftrace_events {
528            cpu: 0
529            event {
530              timestamp: 1000
531              pid: 1234
532              print {
533                buf: "C|5678|ScreenState|0\n"
534              }
535            }
536          }
537        }
538        """),
539        query="""
540        SELECT t.name,
541               c.ts,
542               c.value
543        FROM counter_track t
544        JOIN counter c ON t.id = c.track_id
545        WHERE t.name = 'ScreenState';
546        """,
547        out=Csv("""
548        "name","ts","value"
549        "ScreenState",1,2.000000
550        "ScreenState",1000,0.000000
551        """))
552
553  # Config & metadata
554  def test_config_metadata(self):
555    return DiffTestBlueprint(
556        trace=TextProto(r"""
557        packet {
558          clock_snapshot {
559            clocks {
560              clock_id: 6
561              timestamp: 101000002
562            }
563            clocks {
564              clock_id: 128
565              timestamp: 2
566            }
567          }
568          timestamp: 101000002
569        }
570        packet {
571          trace_config {
572            trace_uuid_msb: 1314564453825188563
573            trace_uuid_lsb: -6605018796207623390
574          }
575        }
576        packet {
577          system_info {
578            android_build_fingerprint: "the fingerprint"
579          }
580        }
581        """),
582        query="""
583        SELECT name, str_value FROM metadata WHERE str_value IS NOT NULL ORDER BY name;
584        """,
585        out=Csv("""
586        "name","str_value"
587        "android_build_fingerprint","the fingerprint"
588        "trace_config_pbtxt","trace_uuid_msb: 1314564453825188563
589        trace_uuid_lsb: -6605018796207623390"
590        "trace_type","proto"
591        "trace_uuid","123e4567-e89b-12d3-a456-426655443322"
592        """))
593
594  def test_triggers_packets_trigger_packet_trace(self):
595    return DiffTestBlueprint(
596        trace=TextProto(r"""
597        packet {
598          trigger {
599            trigger_name: "test1"
600            trusted_producer_uid: 3
601            producer_name: "producer1"
602          }
603          timestamp: 101000002
604        }
605        packet {
606          trigger {
607            trigger_name: "test2"
608            trusted_producer_uid: 4
609            producer_name: "producer2"
610          }
611          timestamp: 101000004
612        }
613        """),
614        query=Path('triggers_packets_test.sql'),
615        out=Csv("""
616        "ts","name","string_value","int_value"
617        101000002,"test1","producer1",3
618        101000004,"test2","producer2",4
619        """))
620
621  def test_chrome_metadata(self):
622    return DiffTestBlueprint(
623        trace=TextProto(r"""
624        packet {
625          clock_snapshot {
626            clocks {
627              clock_id: 6
628              timestamp: 101000002
629            }
630          }
631          trusted_packet_sequence_id: 1
632          timestamp: 101000002
633        }
634        packet {
635          chrome_trigger {
636            trigger_name_hash: 1595654158
637          }
638          trusted_packet_sequence_id: 1
639          timestamp: 101000002
640        }
641        packet {
642          trusted_packet_sequence_id: 1
643          timestamp: 101000002
644          chrome_metadata {
645            background_tracing_metadata {
646              triggered_rule {
647                name_hash: 1595654158
648              }
649              scenario_name_hash: 3005533841
650            }
651            chrome_version_code: 101
652            enabled_categories: "cat1,cat2,cat3"
653            field_trial_hashes {
654              name: 123
655              group: 456
656            }
657            field_trial_hashes {
658              name: 789
659              group: 120
660            }
661          }
662        }
663        """),
664        query="""
665        SELECT * FROM metadata;
666        """,
667        out=Path('chrome_metadata.out'))
668
669  def test_chrome_metadata_multiple(self):
670    return DiffTestBlueprint(
671        trace=TextProto(r"""
672        packet {
673          clock_snapshot {
674            clocks {
675              clock_id: 6
676              timestamp: 101000002
677            }
678          }
679          trusted_packet_sequence_id: 1
680          timestamp: 101000002
681        }
682        packet {
683          trusted_packet_sequence_id: 1
684          timestamp: 101000002
685          chrome_metadata {
686            chrome_version_code: 101
687            enabled_categories: "cat1,cat2,cat3"
688            field_trial_hashes {
689              name: 123
690              group: 456
691            }
692            field_trial_hashes {
693              name: 789
694              group: 120
695            }
696          }
697        }
698        packet {
699          trusted_packet_sequence_id: 1
700          timestamp: 101000002
701          chrome_metadata {
702            chrome_version_code: 102
703            enabled_categories: "cat3,cat4,cat5"
704            field_trial_hashes {
705              name: 1234
706              group: 5678
707            }
708            field_trial_hashes {
709              name: 9012
710              group: 3456
711            }
712          }
713        }
714        """),
715        query="""
716        SELECT * FROM metadata;
717        """,
718        out=Csv("""
719        "id","type","name","key_type","int_value","str_value"
720        0,"metadata","trace_uuid","single","[NULL]","00000000-0000-0000-0de8-df55233147f0"
721        1,"metadata","trace_time_clock_id","single",6,"[NULL]"
722        2,"metadata","cr-a-playstore_version_code","single",101,"[NULL]"
723        3,"metadata","cr-a-enabled_categories","single","[NULL]","cat1,cat2,cat3"
724        4,"metadata","cr-a-field_trial_hashes","single","[NULL]","{ name: 123, group: 456 } { name: 789, group: 120 } "
725        5,"metadata","cr-b-playstore_version_code","single",102,"[NULL]"
726        6,"metadata","cr-b-enabled_categories","single","[NULL]","cat3,cat4,cat5"
727        7,"metadata","cr-b-field_trial_hashes","single","[NULL]","{ name: 1234, group: 5678 } { name: 9012, group: 3456 } "
728        8,"metadata","trace_size_bytes","single",110,"[NULL]"
729        9,"metadata","trace_type","single","[NULL]","proto"
730        """))
731
732  # CPU info
733  def test_cpu(self):
734    return DiffTestBlueprint(
735        trace=Path('cpu_info.textproto'),
736        query="""
737        SELECT
738          cpu,
739          cluster_id,
740          processor
741        FROM cpu;
742        """,
743        out=Csv("""
744        "cpu","cluster_id","processor"
745        0,0,"AArch64 Processor rev 13 (aarch64)"
746        1,0,"AArch64 Processor rev 13 (aarch64)"
747        2,0,"AArch64 Processor rev 13 (aarch64)"
748        3,0,"AArch64 Processor rev 13 (aarch64)"
749        4,0,"AArch64 Processor rev 13 (aarch64)"
750        5,0,"AArch64 Processor rev 13 (aarch64)"
751        6,1,"AArch64 Processor rev 13 (aarch64)"
752        7,1,"AArch64 Processor rev 13 (aarch64)"
753        """))
754
755  def test_cpu_freq(self):
756    return DiffTestBlueprint(
757        trace=Path('cpu_info.textproto'),
758        query="""
759        SELECT
760          freq,
761          GROUP_CONCAT(cpu) AS cpus
762        FROM cpu_frequencies
763        GROUP BY freq
764        ORDER BY freq;
765        """,
766        out=Path('cpu_freq.out'))
767
768  # Trace size
769  def test_android_sched_and_ps_trace_size(self):
770    return DiffTestBlueprint(
771        trace=DataPath('android_sched_and_ps.pb'),
772        query="""
773        SELECT int_value FROM metadata WHERE name = 'trace_size_bytes';
774        """,
775        out=Csv("""
776        "int_value"
777        18761615
778        """))
779
780  # Package list handling
781  def test_android_package_list(self):
782    return DiffTestBlueprint(
783        trace=Path('android_package_list.py'),
784        query=Metric('android_package_list'),
785        out=TextProto(r"""
786        android_package_list {
787          packages {
788            package_name: "com.my.pkg"
789            uid: 123
790            version_code: 456000
791          }
792        }
793        """))
794
795  # Ensures process -> package matching works as expected.
796  def test_process_metadata_matching(self):
797    return DiffTestBlueprint(
798        trace=TextProto(r"""
799        packet {
800          process_tree {
801            processes {
802              pid: 1
803              ppid: 0
804              cmdline: "init"
805              uid: 0
806            }
807            processes {
808              pid: 2
809              ppid: 1
810              cmdline: "system_server"
811              uid: 1000
812            }
813            processes {
814              pid: 3
815              ppid: 1
816              cmdline: "com.google.android.gms"
817              uid: 10100
818            }
819            processes {
820              pid: 4
821              ppid: 1
822              cmdline: "com.google.android.gms.persistent"
823              uid: 10100
824            }
825            processes {
826              pid: 5
827              ppid: 1
828              cmdline: "com.google.android.gms"
829              uid: 1010100
830            }
831          }
832        }
833        packet {
834          packages_list {
835            packages {
836              name: "com.google.android.gms"
837              uid: 10100
838              version_code: 1234
839            }
840            packages {
841              name: "com.google.android.gsf"
842              uid: 10100
843              version_code: 1
844            }
845          }
846        }
847        """),
848        query="""
849        SELECT RUN_METRIC('android/process_metadata.sql');
850
851        SELECT upid, process_name, uid, shared_uid, package_name, version_code
852        FROM process_metadata_table
853        WHERE upid != 0;
854        """,
855        out=Csv("""
856        "upid","process_name","uid","shared_uid","package_name","version_code"
857        1,"init",0,"[NULL]","[NULL]","[NULL]"
858        2,"system_server",1000,"[NULL]","[NULL]","[NULL]"
859        3,"com.google.android.gms",10100,1,"com.google.android.gms",1234
860        4,"com.google.android.gms.persistent",10100,1,"com.google.android.gms",1234
861        5,"com.google.android.gms",10100,1,"com.google.android.gms",1234
862        """))
863
864  # Flow events importing from json
865  def test_flow_events_json_v1(self):
866    return DiffTestBlueprint(
867        trace=Path('flow_events_json_v1.json'),
868        query="""
869        SELECT t1.name AS slice_out, t2.name AS slice_in FROM flow t
870        JOIN slice t1 ON t.slice_out = t1.slice_id
871        JOIN slice t2 ON t.slice_in = t2.slice_id;
872        """,
873        out=Csv("""
874        "slice_out","slice_in"
875        "SenderB","Blergh"
876        "SenderA","OtherSlice"
877        "OtherSlice","SomeSlice"
878        """))
879
880  def test_flow_events_json_v2(self):
881    return DiffTestBlueprint(
882        trace=Path('flow_events_json_v2.json'),
883        query="""
884        SELECT t1.name AS slice_out, t2.name AS slice_in FROM flow t
885        JOIN slice t1 ON t.slice_out = t1.slice_id
886        JOIN slice t2 ON t.slice_in = t2.slice_id;
887        """,
888        out=Csv("""
889        "slice_out","slice_in"
890        "SenderB","Blergh"
891        "SenderA","OtherSlice"
892        "OtherSlice","SomeSlice"
893        "OtherSlice","SomeOtherSlice"
894        """))
895
896  # Importing displayTimeUnit
897  def test_display_time_unit_slices(self):
898    return DiffTestBlueprint(
899        trace=Json(r"""
900        {"displayTimeUnit":"ns","traceEvents":[
901          {
902            "name": "process_name",
903            "pid": 1,
904            "ph": "M",
905            "args": {
906              "name": "api-service-65fc94b8c7-68w9w"
907            }
908          },
909          {
910            "name": "add_graph",
911            "pid": 1,
912            "tid": 1,
913            "ph": "B",
914            "ts": 1597071955492308
915          },
916          {
917            "name": "add_graph",
918            "pid": 1,
919            "tid": 1,
920            "ph": "E",
921            "ts": 1597071955703771
922          }
923        ]
924        }
925        """),
926        query="""
927        SELECT ts, dur, name FROM slice ORDER BY ts DESC;
928        """,
929        out=Csv("""
930        "ts","dur","name"
931        1597071955492308000,211463000,"add_graph"
932        """))
933
934  # Parsing sched_blocked_reason
935  def test_sched_blocked_proto_sched_blocked_reason(self):
936    return DiffTestBlueprint(
937        trace=Path('sched_blocked_proto.py'),
938        query="""
939        SELECT ts, tid, io_wait
940        FROM thread_state
941        JOIN thread USING (utid)
942        WHERE state = 'D'
943        ORDER BY ts;
944        """,
945        out=Csv("""
946        "ts","tid","io_wait"
947        100,1,0
948        110,2,1
949        """))
950
951  def test_sched_blocked_systrace_sched_blocked_reason(self):
952    return DiffTestBlueprint(
953        trace=Path('sched_blocked_systrace.systrace'),
954        query="""
955        SELECT ts, tid, io_wait
956        FROM thread_state
957        JOIN thread USING (utid)
958        WHERE state = 'D'
959        ORDER BY ts;
960        """,
961        out=Csv("""
962        "ts","tid","io_wait"
963        20258854000,269,0
964        21123838000,2172,1
965        """))
966
967  # Kernel symbolization
968  def test_sched_blocked_reason_symbolized_sched_blocked_reason_function(self):
969    return DiffTestBlueprint(
970        trace=Path('sched_blocked_reason_symbolized.textproto'),
971        query="""
972        SELECT
973          ts,
974          thread.tid AS pid,
975          blocked_function AS func
976        FROM thread_state
977        JOIN thread USING (utid)
978        WHERE state = 'D'
979        ORDER BY ts;
980        """,
981        out=Csv("""
982        "ts","pid","func"
983        999000,105,"some_fn"
984        999000,102,"filemap_fault"
985        1000000,100,"filemap_fault"
986        1001000,101,"[NULL]"
987        1002000,103,"[NULL]"
988        1003000,100,"some_other_fn"
989        1005000,104,"filemap_fault"
990        """))
991
992  def test_sched_blocked_reason_symbolized_to_systrace(self):
993    return DiffTestBlueprint(
994        trace=Path('sched_blocked_reason_symbolized.textproto'),
995        query="""
996        SELECT to_ftrace(id) AS line
997        FROM ftrace_event;
998        """,
999        out=Path('sched_blocked_reason_symbolized_to_systrace.out'))
1000
1001  # Floating point numbers
1002  def test_decimal_timestamp_slices(self):
1003    return DiffTestBlueprint(
1004        trace=Json(r"""
1005        {
1006          "traceEvents": [{
1007            "pid": 1234,
1008            "tid": 1234,
1009            "ts": 5.1,
1010            "dur": 500.1,
1011            "name": "name.exec",
1012            "ph": "XXX",
1013            "cat": "aaa"
1014          }]
1015        }
1016        """),
1017        query="""
1018        SELECT ts, dur, name FROM slice ORDER BY ts DESC;
1019        """,
1020        out=Csv("""
1021        "ts","dur","name"
1022        5100,500100,"name.exec"
1023        """))
1024
1025  # JSON instants and counters
1026  def test_counters_json_counters(self):
1027    return DiffTestBlueprint(
1028        trace=Json(r"""
1029
1030        [
1031            {"pid": "1000", "name": "ctr", "ph": "C", "ts":  0, "args": {"cats":  0}},
1032            {"pid": "1000", "name": "ctr", "ph": "C", "ts": 10, "args": {"cats": 10}},
1033            {"pid": "1000", "name": "ctr", "ph": "C", "ts": 20, "args": {"cats":  0}}
1034        ]
1035        """),
1036        query="""
1037        SELECT
1038          process_counter_track.name,
1039          counter.ts,
1040          counter.value
1041        FROM counter
1042        JOIN process_counter_track ON (counter.track_id = process_counter_track.id);
1043        """,
1044        out=Csv("""
1045        "name","ts","value"
1046        "ctr cats",0,0.000000
1047        "ctr cats",10000,10.000000
1048        "ctr cats",20000,0.000000
1049        """))
1050
1051  def test_instants_json_instants(self):
1052    return DiffTestBlueprint(
1053        trace=DataPath('instants.json'),
1054        query="""
1055        SELECT
1056          slice.ts,
1057          slice.name AS slice_name,
1058          thread.tid,
1059          process.pid
1060        FROM slice
1061        JOIN track ON (slice.track_id = track.id)
1062        LEFT JOIN thread_track ON (slice.track_id = thread_track.id)
1063        LEFT JOIN thread ON (thread_track.utid = thread.utid)
1064        LEFT JOIN process_track ON (slice.track_id = process_track.id)
1065        LEFT JOIN process ON (process_track.upid = process.upid)
1066        WHERE dur = 0;
1067        """,
1068        out=Csv("""
1069        "ts","slice_name","tid","pid"
1070        1234523300,"Thread",2347,"[NULL]"
1071        1235523300,"Global","[NULL]","[NULL]"
1072        1236523300,"Process","[NULL]",2320
1073        1237523300,"Nonei",6790,"[NULL]"
1074        1238523300,"NoneI",6790,"[NULL]"
1075        1239523300,"NoneR",6790,"[NULL]"
1076        """))
1077
1078  # Trace quality metric
1079  def test_very_long_sched_android_trace_quality(self):
1080    return DiffTestBlueprint(
1081        trace=Path('very_long_sched.py'),
1082        query=Metric('android_trace_quality'),
1083        out=TextProto(r"""
1084        android_trace_quality {
1085          failures {
1086            name: "sched_slice_too_long"
1087          }
1088        }
1089        """))
1090
1091  # Regression test for b/193721088 (infra prepending " done\n" to atrace)
1092  def test_sched_smoke_trailing_empty_2(self):
1093    return DiffTestBlueprint(
1094        trace=DataPath('atrace_b_193721088.atr'),
1095        query="""
1096        SELECT COUNT(1)
1097        FROM sched;
1098        """,
1099        out=Csv("""
1100        "COUNT(1)"
1101        2
1102        """))
1103
1104  # Multiuser
1105  def test_android_multiuser_switch(self):
1106    return DiffTestBlueprint(
1107        trace=Path('android_multiuser_switch.textproto'),
1108        query=Metric('android_multiuser'),
1109        out=TextProto(r"""
1110        android_multiuser: {
1111          user_switch: {
1112            duration_ms: 4900
1113          }
1114        }
1115        """))
1116
1117  # Output of atrace -z.
1118  def test_atrace_compressed_sched_count(self):
1119    return DiffTestBlueprint(
1120        trace=DataPath('atrace_compressed.ctrace'),
1121        query="""
1122        SELECT COUNT(1)
1123        FROM sched;
1124        """,
1125        out=Csv("""
1126        "COUNT(1)"
1127        1120
1128        """))
1129
1130  # Output of adb shell "atrace -t 1 sched" > out.txt". It has extra garbage
1131  # from stderr before the TRACE: marker. See b/208691037.
1132  def test_atrace_uncompressed_sched_count(self):
1133    return DiffTestBlueprint(
1134        trace=DataPath('atrace_uncompressed_b_208691037'),
1135        query="""
1136        SELECT COUNT(1)
1137        FROM sched;
1138        """,
1139        out=Csv("""
1140        "COUNT(1)"
1141        9
1142        """))
1143
1144  def test_otheruuids_android_other_traces(self):
1145    return DiffTestBlueprint(
1146        trace=Path('otheruuids.textproto'),
1147        query=Metric('android_other_traces'),
1148        out=TextProto(r"""
1149        android_other_traces {
1150          finalized_traces_uuid: "75e4c6d0-d8f6-4f82-fa4b-9e09c5512288"
1151          finalized_traces_uuid: "ad836701-3113-3fb1-be4f-f7731e23fbbf"
1152          finalized_traces_uuid: "0de1a010-efa1-a081-2345-969b1186a6ab"
1153        }
1154        """))
1155
1156  # Per-process Binder transaction metrics
1157  def test_android_binder(self):
1158    return DiffTestBlueprint(
1159        trace=Path('android_binder.py'),
1160        query=Metric('android_binder'),
1161        out=TextProto(r"""
1162        android_binder {
1163          process_breakdown {
1164            process_name: "test_process_a"
1165            pid: 1
1166            slice_name: "binder transaction"
1167            count: 2
1168          }
1169          process_breakdown {
1170            process_name: "test_process_b"
1171            pid: 2
1172            slice_name: "binder reply"
1173            count: 1
1174          }
1175          process_breakdown {
1176            process_name: "test_process_c"
1177            pid: 3
1178            slice_name: "binder reply"
1179            count: 1
1180          }
1181        }
1182        """))
1183
1184  # Statsd Atoms
1185  def test_statsd_atoms_all_atoms(self):
1186    return DiffTestBlueprint(
1187        trace=DataPath('statsd_atoms.pb'),
1188        query=Path('all_atoms_test.sql'),
1189        out=Path('statsd_atoms_all_atoms.out'))
1190
1191  # Statsd Atoms
1192  def test_statsd_atoms_unknown_atoms(self):
1193    return DiffTestBlueprint(
1194        trace=DataPath('statsd_atoms_oem.pb'),
1195        query=Path('all_atoms_test.sql'),
1196        out=Csv("""
1197          "name","key","display_value"
1198          "atom_202001","field_1","1"
1199        """))
1200
1201  # Kernel function tracing.
1202  def test_funcgraph_trace_funcgraph(self):
1203    return DiffTestBlueprint(
1204        trace=Path('funcgraph_trace.textproto'),
1205        query="""
1206        SELECT ts, dur, tid, s.name, depth
1207        FROM slices s
1208        JOIN thread_track tt ON (s.track_id = tt.id)
1209        JOIN thread USING (utid)
1210        WHERE tid = 385482;
1211        """,
1212        out=Csv("""
1213        "ts","dur","tid","name","depth"
1214        679375600673065,3797,385482,"__handle_mm_fault",0
1215        679375600673769,1726,385482,"alloc_pages_vma",1
1216        """))
1217
1218  # Kernel task_newtask waker_utid parsing
1219  def test_task_newtask_waker_utid(self):
1220    return DiffTestBlueprint(
1221        trace=TextProto(r"""
1222        packet {
1223          first_packet_on_sequence: true
1224          ftrace_events {
1225            cpu: 1
1226            event {
1227              timestamp: 201315132677
1228              pid: 518
1229              task_newtask {
1230                pid: 3294
1231                comm: "adbd"
1232                clone_flags: 18874368
1233                oom_score_adj: -1000
1234              }
1235            }
1236            event {
1237              timestamp: 201319417828
1238              pid: 518
1239              task_newtask {
1240                pid: 3295
1241                comm: "adbd"
1242                clone_flags: 4001536
1243                oom_score_adj: -1000
1244              }
1245            }
1246          }
1247          trusted_uid: 9999
1248          trusted_packet_sequence_id: 2
1249          trusted_pid: 521
1250          previous_packet_dropped: true
1251        }
1252        """),
1253        query="""
1254        SELECT waker_utid FROM thread_state
1255        """,
1256        out=Csv("""
1257        "waker_utid"
1258        1
1259        1
1260        """))
1261
1262  # Parsing of mdss/tracing_mark_write events
1263  def test_slice_mdss_tracing_mark_write(self):
1264    # Note that tracing_mark_write below is an ftrace event from the mdss
1265    # group (see mdss.proto and aosp/2622569). Events with the same name
1266    # from other groups (e.g. sde) listed after mdss in ftrace_proto_gen
1267    # are prefixed with the group name to avoid conflicts.
1268    return DiffTestBlueprint(
1269        trace=TextProto(r"""
1270        packet {
1271          ftrace_events {
1272            cpu: 0
1273            event {
1274              timestamp: 100
1275              pid: 584
1276              tracing_mark_write {
1277                pid: 584
1278                trace_name: "test_event"
1279                trace_begin: 1
1280              }
1281            }
1282            event {
1283              timestamp: 200
1284              pid: 584
1285              tracing_mark_write {
1286                pid: 584
1287                trace_name: "test_event"
1288                trace_begin: 0
1289              }
1290            }
1291          }
1292        }
1293        """),
1294        query="""
1295        SELECT s.name, dur, tid
1296        FROM slice s
1297        JOIN thread_track t ON s.track_id = t.id
1298        JOIN thread USING(utid)
1299        """,
1300        out=Csv("""
1301        "name","dur","tid"
1302        "test_event",100,584
1303        """))
1304
1305  def test_all_data_source_flushed_metadata(self):
1306    return DiffTestBlueprint(
1307        trace=TextProto(r"""
1308        packet {
1309          timestamp: 12344
1310          service_event {
1311            all_data_sources_flushed: true
1312          }
1313        }
1314        packet {
1315          timestamp: 12345
1316          service_event {
1317            all_data_sources_flushed: true
1318          }
1319        }
1320        """),
1321        query="""
1322        SELECT name, int_value FROM metadata WHERE name = 'all_data_source_flushed_ns'""",
1323        out=Csv("""
1324        "name","int_value"
1325        "all_data_source_flushed_ns",12344
1326        "all_data_source_flushed_ns",12345
1327        """))
1328
1329  def test_ftrace_abi_errors_skipped_zero_data_length(self):
1330    return DiffTestBlueprint(
1331        trace=TextProto(r"""
1332        packet {
1333          ftrace_stats {
1334            phase: END_OF_TRACE
1335            cpu_stats {
1336              cpu: 0
1337              entries: 14
1338              overrun: 0
1339              commit_overrun: 0
1340              bytes_read: 840
1341              oldest_event_ts: 86557.552705
1342              now_ts: 86557.574310
1343              dropped_events: 0
1344              read_events: 199966062
1345            }
1346            kernel_symbols_parsed: 128611
1347            kernel_symbols_mem_kb: 1322
1348            ftrace_parse_errors: FTRACE_STATUS_ABI_ZERO_DATA_LENGTH
1349          }
1350          trusted_uid: 9999
1351          trusted_packet_sequence_id: 2
1352          trusted_pid: 1069
1353        }
1354        """),
1355        query="""
1356        select name, severity, value
1357        from stats
1358        where name = "ftrace_abi_errors_skipped_zero_data_length"
1359        """,
1360        out=Csv("""
1361        "name","severity","value"
1362        "ftrace_abi_errors_skipped_zero_data_length","info",1
1363        """))
1364
1365  # CPU info
1366  def test_cpu_machine_id(self):
1367    return DiffTestBlueprint(
1368        trace=Path('cpu_info.textproto'),
1369        trace_modifier=TraceInjector(['cpu_info'], {'machine_id': 1001}),
1370        query="""
1371        SELECT
1372          cpu,
1373          cluster_id,
1374          processor
1375        FROM cpu
1376        WHERE machine_id is not NULL;
1377        """,
1378        out=Csv("""
1379        "cpu","cluster_id","processor"
1380        0,0,"AArch64 Processor rev 13 (aarch64)"
1381        1,0,"AArch64 Processor rev 13 (aarch64)"
1382        2,0,"AArch64 Processor rev 13 (aarch64)"
1383        3,0,"AArch64 Processor rev 13 (aarch64)"
1384        4,0,"AArch64 Processor rev 13 (aarch64)"
1385        5,0,"AArch64 Processor rev 13 (aarch64)"
1386        6,1,"AArch64 Processor rev 13 (aarch64)"
1387        7,1,"AArch64 Processor rev 13 (aarch64)"
1388        """))
1389
1390  def test_cpu_freq_machine_id(self):
1391    return DiffTestBlueprint(
1392        trace=Path('cpu_info.textproto'),
1393        trace_modifier=TraceInjector(['cpu_info'], {'machine_id': 1001}),
1394        query="""
1395        SELECT
1396          freq,
1397          GROUP_CONCAT(cpu.cpu) AS cpus
1398        FROM cpu_frequencies
1399        JOIN cpu using (ucpu)
1400        WHERE machine_id is not NULL
1401        GROUP BY freq
1402        ORDER BY freq;
1403        """,
1404        out=Path('cpu_freq.out'))
1405
1406  def test_sched_waking_instants_compact_sched_machine_id(self):
1407    return DiffTestBlueprint(
1408        trace=DataPath('compact_sched.pb'),
1409        trace_modifier=TraceInjector(
1410            ['ftrace_events', 'ftrace_stats', 'system_info'],
1411            {'machine_id': 1001}),
1412        query="""
1413        SELECT ts, thread.name, thread.tid
1414        FROM thread_state
1415        JOIN thread USING (utid)
1416        WHERE state = 'R' AND thread.machine_id is not NULL
1417        ORDER BY ts;
1418        """,
1419        out=Path('sched_waking_instants_compact_sched.out'))
1420