blob: e6ab9a4f6608e2d248fe46589bdbc3b578d4e04d [file] [log] [blame]
#!/usr/bin/env python3
# Copyright (C) 2023 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License a
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from python.generators.diff_tests.testing import Path, DataPath, Metric
from python.generators.diff_tests.testing import Csv, Json, TextProto
from python.generators.diff_tests.testing import DiffTestBlueprint, TraceInjector
from python.generators.diff_tests.testing import TestSuite
class Tables(TestSuite):
# Contains tests for the handling of tables by trace processor. The focus of
# here is to check that trace processor is correctly returning and handling
# on the really important tables in trace processor. Note: It's generally
# advisable to add tests here. Check the guidance provided by
# for choosing which folder to add a new test to. Window table
def test_android_sched_and_ps_smoke_window(self):
return DiffTestBlueprint(
trace=DataPath('android_sched_and_ps.pb'),
query="""
SELECT * FROM "window";
""",
out=Csv("""
"ts","dur","quantum_ts"
0,9223372036854775807,0
"""))
# Null printing
def test_nulls(self):
return DiffTestBlueprint(
trace=Path('../common/synth_1.py'),
query="""
CREATE TABLE null_test (
primary_key INTEGER PRIMARY KEY,
int_nulls INTEGER,
string_nulls STRING,
double_nulls DOUBLE,
start_int_nulls INTEGER,
start_string_nulls STRING,
start_double_nulls DOUBLE,
all_nulls INTEGER
);
INSERT INTO null_test(
int_nulls,
string_nulls,
double_nulls,
start_int_nulls,
start_string_nulls,
start_double_nulls
)
VALUES
(1, "test", 2.0, NULL, NULL, NULL),
(2, NULL, NULL, NULL, "test", NULL),
(1, "other", NULL, NULL, NULL, NULL),
(4, NULL, NULL, NULL, NULL, 1.0),
(NULL, "test", 1.0, 1, NULL, NULL);
SELECT * FROM null_test;
""",
out=Path('nulls.out'))
# Thread table
def test_thread_main_thread(self):
return DiffTestBlueprint(
trace=TextProto(r"""
packet {
timestamp: 1
process_tree {
processes {
pid: 5
ppid: 1
cmdline: "com.google.pid5"
}
threads {
tid: 5
tgid: 5
}
threads {
tid: 7
tgid: 5
name: "tid7"
}
processes {
pid: 11
ppid: 1
cmdline: "com.google.pid11"
}
threads {
tid: 11
tgid: 11
name: "tid11"
}
threads {
tid: 12
tgid: 11
name: "tid12"
}
}
}
packet {
timestamp: 2
ftrace_events {
cpu: 0
event {
timestamp: 2
pid: 99
lowmemory_kill {
pid: 99
}
}
}
}
"""),
query="""
SELECT
tid,
is_main_thread
FROM thread
WHERE tid IN (5, 7, 11, 12, 99)
ORDER BY tid;
""",
out=Csv("""
"tid","is_main_thread"
5,1
7,0
11,1
12,0
99,"[NULL]"
"""))
# Json output
def test_trace_metadata(self):
return DiffTestBlueprint(
trace=DataPath('memory_counters.pb'),
query=Metric('trace_metadata'),
out=Path('trace_metadata.json.out'))
# Processes as a metric
def test_android_task_names(self):
return DiffTestBlueprint(
trace=TextProto(r"""
packet {
process_tree {
processes {
pid: 1
ppid: 0
cmdline: "init"
uid: 0
}
processes {
pid: 2
ppid: 1
cmdline: "com.google.android.gm:process"
uid: 10001
}
}
}
packet {
packages_list {
packages {
name: "com.google.android.gm"
uid: 10001
}
}
}
"""),
query=Metric('android_task_names'),
out=TextProto(r"""
android_task_names {
process {
pid: 1
process_name: "init"
uid: 0
}
process {
pid: 2
process_name: "com.google.android.gm:process"
uid: 10001
uid_package_name: "com.google.android.gm"
}
}
"""))
# Ftrace stats imports in metadata and stats tables
def test_ftrace_setup_errors(self):
return DiffTestBlueprint(
trace=DataPath('ftrace_error_stats.pftrace'),
query="""
SELECT value FROM stats WHERE name = 'ftrace_setup_errors'
UNION ALL
SELECT str_value FROM metadata WHERE name = 'ftrace_setup_errors';
""",
out=Csv("""
"value"
3
"Ftrace event unknown: foo/bar
Ftrace event unknown: sched/foobar
Atrace failures: error: unknown tracing category "bar"
error enabling tracing category "bar"
"
"""))
# Ftrace stats imports in metadata and stats tables
def test_filter_stats(self):
return DiffTestBlueprint(
trace=TextProto("""
packet { trace_stats{ filter_stats {
input_packets: 836
input_bytes: 25689644
output_bytes: 24826981
errors: 12
time_taken_ns: 1228178548
bytes_discarded_per_buffer: 1
bytes_discarded_per_buffer: 34
bytes_discarded_per_buffer: 29
bytes_discarded_per_buffer: 0
bytes_discarded_per_buffer: 862588
}}}"""),
query="""
SELECT name, value FROM stats
WHERE name like 'filter_%' OR name = 'traced_buf_bytes_filtered_out'
ORDER by name ASC
""",
out=Csv("""
"name","value"
"filter_errors",12
"filter_input_bytes",25689644
"filter_input_packets",836
"filter_output_bytes",24826981
"filter_time_taken_ns",1228178548
"traced_buf_bytes_filtered_out",1
"traced_buf_bytes_filtered_out",34
"traced_buf_bytes_filtered_out",29
"traced_buf_bytes_filtered_out",0
"traced_buf_bytes_filtered_out",862588
"""))
# cpu_track table
def test_cpu_track_table(self):
return DiffTestBlueprint(
trace=TextProto(r"""
packet {
ftrace_events {
cpu: 1
event {
timestamp: 100001000000
pid: 10
irq_handler_entry {
irq: 100
name : "resource1"
}
}
event {
timestamp: 100002000000
pid: 10
irq_handler_exit {
irq: 100
ret: 1
}
}
}
}
packet {
ftrace_events {
cpu: 0
event {
timestamp: 100003000000
pid: 15
irq_handler_entry {
irq: 100
name : "resource1"
}
}
}
}
"""),
query="""
SELECT
type,
cpu
FROM cpu_track
ORDER BY type, cpu;
""",
out=Csv("""
"type","cpu"
"__intrinsic_cpu_track",0
"__intrinsic_cpu_track",1
"""))
def test_thread_state_flattened_aggregated(self):
return DiffTestBlueprint(
trace=DataPath('android_monitor_contention_trace.atr'),
query="""
INCLUDE PERFETTO MODULE sched.thread_state_flattened;
select * from _get_flattened_thread_state_aggregated(11155, NULL);
""",
out=Path('thread_state_flattened_aggregated_csv.out'))
def test_thread_state_flattened(self):
return DiffTestBlueprint(
trace=DataPath('android_monitor_contention_trace.atr'),
query="""
INCLUDE PERFETTO MODULE sched.thread_state_flattened;
select * from _get_flattened_thread_state(11155, NULL);
""",
out=Path('thread_state_flattened_csv.out'))
def test_metadata(self):
return DiffTestBlueprint(
trace=TextProto(r"""
packet {
system_info {
tracing_service_version: "Perfetto v38.0-0bb49ab54 (0bb49ab54dbe55ce5b9dfea3a2ada68b87aecb65)"
timezone_off_mins: 60
utsname {
sysname: "Darwin"
version: "Foobar"
machine: "x86_64"
release: "22.6.0"
}
}
trusted_uid: 158158
trusted_packet_sequence_id: 1
}
"""),
query=r"""SELECT name, COALESCE(str_value, int_value) as val
FROM metadata
WHERE name IN (
"system_name", "system_version", "system_machine",
"system_release", "timezone_off_mins")
ORDER BY name
""",
out=Csv(r"""
"name","val"
"system_machine","x86_64"
"system_name","Darwin"
"system_release","22.6.0"
"system_version","Foobar"
"timezone_off_mins",60
"""))
def test_flow_table_trace_id(self):
return DiffTestBlueprint(
trace=TextProto("""
packet {
timestamp: 0
track_event {
name: "Track 0 Event"
type: TYPE_SLICE_BEGIN
track_uuid: 10
flow_ids: 57
}
trusted_packet_sequence_id: 123
}
packet {
timestamp: 10
track_event {
name: "Track 0 Nested Event"
type: TYPE_SLICE_BEGIN
track_uuid: 10
flow_ids: 57
}
trusted_packet_sequence_id: 123
}
packet {
timestamp: 50
track_event {
name: "Track 0 Short Event"
type: TYPE_SLICE_BEGIN
track_uuid: 10
terminating_flow_ids: 57
}
trusted_packet_sequence_id: 123
}
"""),
query="SELECT * FROM flow;",
out=Csv("""
"id","type","slice_out","slice_in","trace_id","arg_set_id"
0,"flow",0,1,57,0
1,"flow",1,2,57,0
"""))
def test_clock_snapshot_table_multiplier(self):
return DiffTestBlueprint(
trace=TextProto("""
packet {
clock_snapshot {
clocks {
clock_id: 1
timestamp: 42
unit_multiplier_ns: 10
}
clocks {
clock_id: 6
timestamp: 0
}
}
}
"""),
query="SELECT TO_REALTIME(0);",
out=Csv("""
"TO_REALTIME(0)"
420
"""))
# Test cpu_track with machine_id ID.
def test_cpu_track_table_machine_id(self):
return DiffTestBlueprint(
trace=TextProto(r"""
packet {
ftrace_events {
cpu: 1
event {
timestamp: 100001000000
pid: 10
irq_handler_entry {
irq: 100
name : "resource1"
}
}
event {
timestamp: 100002000000
pid: 10
irq_handler_exit {
irq: 100
ret: 1
}
}
}
machine_id: 1001
}
packet {
ftrace_events {
cpu: 0
event {
timestamp: 100003000000
pid: 15
irq_handler_entry {
irq: 100
name : "resource1"
}
}
}
machine_id: 1001
}
"""),
query="""
SELECT
ct.type,
ct.ucpu,
c.cpu,
ct.machine_id
FROM cpu_track AS ct
JOIN cpu AS c ON ct.ucpu = c.id
ORDER BY ct.type, c.cpu
""",
out=Csv("""
"type","ucpu","cpu","machine_id"
"__intrinsic_cpu_track",4096,0,1
"__intrinsic_cpu_track",4097,1,1
"""))