# Copyright (C) 2024 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 at # # 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. import os import perfetto.bigtrace.api import subprocess import unittest from perfetto.common.exceptions import PerfettoException class BigtraceTest(unittest.TestCase): @classmethod def setUpClass(self): self.root_dir = os.environ["ROOT_DIR"] self.worker_1 = subprocess.Popen( [os.environ["WORKER_PATH"], "-s", "127.0.0.1:5052"]) self.worker_2 = subprocess.Popen( [os.environ["WORKER_PATH"], "-s", "127.0.0.1:5053"]) self.worker_3 = subprocess.Popen( [os.environ["WORKER_PATH"], "-s", "127.0.0.1:5054"]) self.orchestrator = subprocess.Popen([ os.environ["ORCHESTRATOR_PATH"], "-n", "3", "-w", "127.0.0.1", "-p", "5052" ]) self.client = perfetto.bigtrace.api.Bigtrace( wait_for_ready_for_testing=True) @classmethod def tearDownClass(self): self.worker_1.kill() self.worker_1.wait() self.worker_2.kill() self.worker_2.wait() self.worker_3.kill() self.worker_3.wait() self.orchestrator.kill() self.orchestrator.wait() del self.client def test_simple_valid_request(self): result = self.client.query([ f"/local/{self.root_dir}/test/data/api24_startup_cold.perfetto-trace", f"/local/{self.root_dir}/test/data/api24_startup_hot.perfetto-trace" ], "SELECT count(1) as count FROM slice LIMIT 5") self.assertEqual( result.loc[result['_trace_address'] == f"/local/{self.root_dir}/test/data/" "api24_startup_cold.perfetto-trace", 'count'].iloc[0], 9726) self.assertEqual( result.loc[result['_trace_address'] == f"/local/{self.root_dir}/test/data/" "api24_startup_hot.perfetto-trace", 'count'].iloc[0], 5726) def test_include_perfetto_module_query(self): traces = [ f"/local/{self.root_dir}/test/data/android_startup_real.perfetto_trace" ] result = self.client.query( traces, "INCLUDE PERFETTO MODULE android.binder; " "SELECT client_process FROM android_binder_txns") self.assertEqual(len(result), 15874) self.assertEqual(len(result.columns), 2) def test_empty_trace_list(self): with self.assertRaises(PerfettoException): result = self.client.query([], "SELECT count(1) FROM slice LIMIT 5") def test_empty_sql_string(self): with self.assertRaises(PerfettoException): result = self.client.query([ f"/local/{self.root_dir}/test/data/api24_startup_cold.perfetto-trace", f"/local/{self.root_dir}/test/data/api24_startup_hot.perfetto-trace" ], "") def test_empty_trace_string(self): with self.assertRaises(PerfettoException): result = self.client.query([""], "SELECT count(1) FROM slice LIMIT 5") def test_prefix_present_no_trace_path(self): with self.assertRaises(PerfettoException): result = self.client.query(["/local"], "SELECT count(1) FROM slice LIMIT 5") def test_invalid_prefix_format(self): with self.assertRaises(PerfettoException): result = self.client.query([ f"??{self.root_dir}/test/data/api24_startup_cold.perfetto-trace", ], "") def test_invalid_prefix_name(self): with self.assertRaises(PerfettoException): result = self.client.query([ f"/badprefix/{self.root_dir}/test/data/" "api24_startup_cold.perfetto-trace" ], "SELECT count(1) FROM slice LIMIT 5"), def test_no_prefix(self): with self.assertRaises(PerfettoException): result = self.client.query( [f"/{self.root_dir}/test/data/api24_startup_cold.perfetto-trace"], "SELECT count(1) FROM slice LIMIT 5") def test_unauthenticated_gcs(self): with self.assertRaises(PerfettoException): result = self.client.query( [f"/gcs/trace_bucket_example/o/api24_startup_cold.perfetto-trace"], "SELECT count(1) FROM slice LIMIT 5")