1*6dbdd20aSAndroid Build Coastguard Worker#!/usr/bin/env python3 2*6dbdd20aSAndroid Build Coastguard Worker# Copyright (C) 2020 The Android Open Source Project 3*6dbdd20aSAndroid Build Coastguard Worker# 4*6dbdd20aSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 5*6dbdd20aSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 6*6dbdd20aSAndroid Build Coastguard Worker# You may obtain a copy of the License at 7*6dbdd20aSAndroid Build Coastguard Worker# 8*6dbdd20aSAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 9*6dbdd20aSAndroid Build Coastguard Worker# 10*6dbdd20aSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 11*6dbdd20aSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 12*6dbdd20aSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*6dbdd20aSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 14*6dbdd20aSAndroid Build Coastguard Worker# limitations under the License. 15*6dbdd20aSAndroid Build Coastguard Worker 16*6dbdd20aSAndroid Build Coastguard Workerimport io 17*6dbdd20aSAndroid Build Coastguard Workerimport os 18*6dbdd20aSAndroid Build Coastguard Workerimport tempfile 19*6dbdd20aSAndroid Build Coastguard Workerimport unittest 20*6dbdd20aSAndroid Build Coastguard Workerfrom typing import Optional 21*6dbdd20aSAndroid Build Coastguard Worker 22*6dbdd20aSAndroid Build Coastguard Workerimport pandas as pd 23*6dbdd20aSAndroid Build Coastguard Worker 24*6dbdd20aSAndroid Build Coastguard Workerfrom perfetto.batch_trace_processor.api import BatchTraceProcessor 25*6dbdd20aSAndroid Build Coastguard Workerfrom perfetto.batch_trace_processor.api import BatchTraceProcessorConfig 26*6dbdd20aSAndroid Build Coastguard Workerfrom perfetto.batch_trace_processor.api import FailureHandling 27*6dbdd20aSAndroid Build Coastguard Workerfrom perfetto.batch_trace_processor.api import Metadata 28*6dbdd20aSAndroid Build Coastguard Workerfrom perfetto.batch_trace_processor.api import TraceListReference 29*6dbdd20aSAndroid Build Coastguard Workerfrom perfetto.trace_processor.api import PLATFORM_DELEGATE 30*6dbdd20aSAndroid Build Coastguard Workerfrom perfetto.trace_processor.api import TraceProcessor 31*6dbdd20aSAndroid Build Coastguard Workerfrom perfetto.trace_processor.api import TraceProcessorException 32*6dbdd20aSAndroid Build Coastguard Workerfrom perfetto.trace_processor.api import TraceProcessorConfig 33*6dbdd20aSAndroid Build Coastguard Workerfrom perfetto.trace_processor.api import TraceReference 34*6dbdd20aSAndroid Build Coastguard Workerfrom perfetto.trace_uri_resolver.resolver import TraceUriResolver 35*6dbdd20aSAndroid Build Coastguard Workerfrom perfetto.trace_uri_resolver.path import PathUriResolver 36*6dbdd20aSAndroid Build Coastguard Worker 37*6dbdd20aSAndroid Build Coastguard Worker 38*6dbdd20aSAndroid Build Coastguard Workerclass SimpleResolver(TraceUriResolver): 39*6dbdd20aSAndroid Build Coastguard Worker PREFIX = 'simple' 40*6dbdd20aSAndroid Build Coastguard Worker 41*6dbdd20aSAndroid Build Coastguard Worker def __init__(self, path, skip_resolve_file=False): 42*6dbdd20aSAndroid Build Coastguard Worker self.path = path 43*6dbdd20aSAndroid Build Coastguard Worker self.file = open(example_android_trace_path(), 'rb') 44*6dbdd20aSAndroid Build Coastguard Worker self.skip_resolve_file = skip_resolve_file 45*6dbdd20aSAndroid Build Coastguard Worker 46*6dbdd20aSAndroid Build Coastguard Worker def file_gen(self): 47*6dbdd20aSAndroid Build Coastguard Worker with open(example_android_trace_path(), 'rb') as f: 48*6dbdd20aSAndroid Build Coastguard Worker yield f.read() 49*6dbdd20aSAndroid Build Coastguard Worker 50*6dbdd20aSAndroid Build Coastguard Worker def resolve(self): 51*6dbdd20aSAndroid Build Coastguard Worker res = [ 52*6dbdd20aSAndroid Build Coastguard Worker TraceUriResolver.Result( 53*6dbdd20aSAndroid Build Coastguard Worker self.file_gen(), metadata={'source': 'generator'}), 54*6dbdd20aSAndroid Build Coastguard Worker TraceUriResolver.Result( 55*6dbdd20aSAndroid Build Coastguard Worker example_android_trace_path(), metadata={'source': 'path'}), 56*6dbdd20aSAndroid Build Coastguard Worker ] 57*6dbdd20aSAndroid Build Coastguard Worker if not self.skip_resolve_file: 58*6dbdd20aSAndroid Build Coastguard Worker res.extend([ 59*6dbdd20aSAndroid Build Coastguard Worker TraceUriResolver.Result( 60*6dbdd20aSAndroid Build Coastguard Worker PathUriResolver(example_android_trace_path()), 61*6dbdd20aSAndroid Build Coastguard Worker metadata={'source': 'path_resolver'}), 62*6dbdd20aSAndroid Build Coastguard Worker TraceUriResolver.Result(self.file, metadata={'source': 'file'}), 63*6dbdd20aSAndroid Build Coastguard Worker ]) 64*6dbdd20aSAndroid Build Coastguard Worker return res 65*6dbdd20aSAndroid Build Coastguard Worker 66*6dbdd20aSAndroid Build Coastguard Worker 67*6dbdd20aSAndroid Build Coastguard Workerclass RecursiveResolver(SimpleResolver): 68*6dbdd20aSAndroid Build Coastguard Worker PREFIX = 'recursive' 69*6dbdd20aSAndroid Build Coastguard Worker 70*6dbdd20aSAndroid Build Coastguard Worker def __init__(self, path, skip_resolve_file): 71*6dbdd20aSAndroid Build Coastguard Worker super().__init__(path=path, skip_resolve_file=skip_resolve_file) 72*6dbdd20aSAndroid Build Coastguard Worker 73*6dbdd20aSAndroid Build Coastguard Worker def resolve(self): 74*6dbdd20aSAndroid Build Coastguard Worker srf = self.skip_resolve_file 75*6dbdd20aSAndroid Build Coastguard Worker return [ 76*6dbdd20aSAndroid Build Coastguard Worker TraceUriResolver.Result( 77*6dbdd20aSAndroid Build Coastguard Worker self.file_gen(), metadata={'source': 'recursive_gen'}), 78*6dbdd20aSAndroid Build Coastguard Worker TraceUriResolver.Result( 79*6dbdd20aSAndroid Build Coastguard Worker f'simple:path={self.path};skip_resolve_file={srf}', 80*6dbdd20aSAndroid Build Coastguard Worker metadata={ 81*6dbdd20aSAndroid Build Coastguard Worker 'source': 'recursive_path', 82*6dbdd20aSAndroid Build Coastguard Worker 'root_source': 'recursive_path' 83*6dbdd20aSAndroid Build Coastguard Worker }), 84*6dbdd20aSAndroid Build Coastguard Worker TraceUriResolver.Result( 85*6dbdd20aSAndroid Build Coastguard Worker SimpleResolver( 86*6dbdd20aSAndroid Build Coastguard Worker path=self.path, skip_resolve_file=self.skip_resolve_file), 87*6dbdd20aSAndroid Build Coastguard Worker metadata={ 88*6dbdd20aSAndroid Build Coastguard Worker 'source': 'recursive_obj', 89*6dbdd20aSAndroid Build Coastguard Worker 'root_source': 'recursive_obj' 90*6dbdd20aSAndroid Build Coastguard Worker }), 91*6dbdd20aSAndroid Build Coastguard Worker ] 92*6dbdd20aSAndroid Build Coastguard Worker 93*6dbdd20aSAndroid Build Coastguard Worker 94*6dbdd20aSAndroid Build Coastguard Workerclass SimpleObserver(BatchTraceProcessor.Observer): 95*6dbdd20aSAndroid Build Coastguard Worker 96*6dbdd20aSAndroid Build Coastguard Worker def __init__(self): 97*6dbdd20aSAndroid Build Coastguard Worker self.execution_times = [] 98*6dbdd20aSAndroid Build Coastguard Worker 99*6dbdd20aSAndroid Build Coastguard Worker def trace_processed(self, metadata: Metadata, execution_time_seconds: float): 100*6dbdd20aSAndroid Build Coastguard Worker self.execution_times.append(execution_time_seconds) 101*6dbdd20aSAndroid Build Coastguard Worker 102*6dbdd20aSAndroid Build Coastguard Worker 103*6dbdd20aSAndroid Build Coastguard Workerdef create_batch_tp( 104*6dbdd20aSAndroid Build Coastguard Worker traces: TraceListReference, 105*6dbdd20aSAndroid Build Coastguard Worker load_failure_handling: FailureHandling = FailureHandling.RAISE_EXCEPTION, 106*6dbdd20aSAndroid Build Coastguard Worker execute_failure_handling: FailureHandling = FailureHandling.RAISE_EXCEPTION, 107*6dbdd20aSAndroid Build Coastguard Worker observer: Optional[BatchTraceProcessor.Observer] = None): 108*6dbdd20aSAndroid Build Coastguard Worker registry = PLATFORM_DELEGATE().default_resolver_registry() 109*6dbdd20aSAndroid Build Coastguard Worker registry.register(SimpleResolver) 110*6dbdd20aSAndroid Build Coastguard Worker registry.register(RecursiveResolver) 111*6dbdd20aSAndroid Build Coastguard Worker config = BatchTraceProcessorConfig( 112*6dbdd20aSAndroid Build Coastguard Worker load_failure_handling=load_failure_handling, 113*6dbdd20aSAndroid Build Coastguard Worker execute_failure_handling=execute_failure_handling, 114*6dbdd20aSAndroid Build Coastguard Worker tp_config=TraceProcessorConfig( 115*6dbdd20aSAndroid Build Coastguard Worker bin_path=os.environ["SHELL_PATH"], resolver_registry=registry)) 116*6dbdd20aSAndroid Build Coastguard Worker return BatchTraceProcessor(traces=traces, config=config, observer=observer) 117*6dbdd20aSAndroid Build Coastguard Worker 118*6dbdd20aSAndroid Build Coastguard Worker 119*6dbdd20aSAndroid Build Coastguard Workerdef create_tp(trace: TraceReference): 120*6dbdd20aSAndroid Build Coastguard Worker return TraceProcessor( 121*6dbdd20aSAndroid Build Coastguard Worker trace=trace, 122*6dbdd20aSAndroid Build Coastguard Worker config=TraceProcessorConfig(bin_path=os.environ["SHELL_PATH"])) 123*6dbdd20aSAndroid Build Coastguard Worker 124*6dbdd20aSAndroid Build Coastguard Worker 125*6dbdd20aSAndroid Build Coastguard Workerdef example_android_trace_path(): 126*6dbdd20aSAndroid Build Coastguard Worker return os.path.join(os.environ["ROOT_DIR"], 'test', 'data', 127*6dbdd20aSAndroid Build Coastguard Worker 'example_android_trace_30s.pb') 128*6dbdd20aSAndroid Build Coastguard Worker 129*6dbdd20aSAndroid Build Coastguard Worker 130*6dbdd20aSAndroid Build Coastguard Workerclass TestApi(unittest.TestCase): 131*6dbdd20aSAndroid Build Coastguard Worker 132*6dbdd20aSAndroid Build Coastguard Worker def test_invalid_trace(self): 133*6dbdd20aSAndroid Build Coastguard Worker f = io.BytesIO(b'<foo></foo>') 134*6dbdd20aSAndroid Build Coastguard Worker with self.assertRaises(TraceProcessorException): 135*6dbdd20aSAndroid Build Coastguard Worker _ = create_tp(trace=f) 136*6dbdd20aSAndroid Build Coastguard Worker 137*6dbdd20aSAndroid Build Coastguard Worker def test_runtime_error(self): 138*6dbdd20aSAndroid Build Coastguard Worker # We emulate a situation when TP returns an error by passing the --version 139*6dbdd20aSAndroid Build Coastguard Worker # flag. This makes TP output version information and exit, instead of 140*6dbdd20aSAndroid Build Coastguard Worker # starting an http server. 141*6dbdd20aSAndroid Build Coastguard Worker config = TraceProcessorConfig( 142*6dbdd20aSAndroid Build Coastguard Worker bin_path=os.environ["SHELL_PATH"], extra_flags=["--version"]) 143*6dbdd20aSAndroid Build Coastguard Worker with self.assertRaisesRegex( 144*6dbdd20aSAndroid Build Coastguard Worker TraceProcessorException, 145*6dbdd20aSAndroid Build Coastguard Worker expected_regex='.*Trace Processor RPC API version:.*'): 146*6dbdd20aSAndroid Build Coastguard Worker TraceProcessor(trace=io.BytesIO(b''), config=config) 147*6dbdd20aSAndroid Build Coastguard Worker 148*6dbdd20aSAndroid Build Coastguard Worker def test_trace_path(self): 149*6dbdd20aSAndroid Build Coastguard Worker # Get path to trace_processor_shell and construct TraceProcessor 150*6dbdd20aSAndroid Build Coastguard Worker tp = create_tp(trace=example_android_trace_path()) 151*6dbdd20aSAndroid Build Coastguard Worker qr_iterator = tp.query('select * from slice limit 10') 152*6dbdd20aSAndroid Build Coastguard Worker dur_result = [ 153*6dbdd20aSAndroid Build Coastguard Worker 178646, 119740, 58073, 155000, 173177, 20209377, 3589167, 90104, 275312, 154*6dbdd20aSAndroid Build Coastguard Worker 65313 155*6dbdd20aSAndroid Build Coastguard Worker ] 156*6dbdd20aSAndroid Build Coastguard Worker 157*6dbdd20aSAndroid Build Coastguard Worker for num, row in enumerate(qr_iterator): 158*6dbdd20aSAndroid Build Coastguard Worker self.assertEqual(row.type, '__intrinsic_slice') 159*6dbdd20aSAndroid Build Coastguard Worker self.assertEqual(row.dur, dur_result[num]) 160*6dbdd20aSAndroid Build Coastguard Worker 161*6dbdd20aSAndroid Build Coastguard Worker # Test the batching logic by issuing a large query and ensuring we receive 162*6dbdd20aSAndroid Build Coastguard Worker # all rows, not just a truncated subset. 163*6dbdd20aSAndroid Build Coastguard Worker qr_iterator = tp.query('select count(*) as cnt from slice') 164*6dbdd20aSAndroid Build Coastguard Worker expected_count = next(qr_iterator).cnt 165*6dbdd20aSAndroid Build Coastguard Worker self.assertGreater(expected_count, 0) 166*6dbdd20aSAndroid Build Coastguard Worker 167*6dbdd20aSAndroid Build Coastguard Worker qr_iterator = tp.query('select * from slice') 168*6dbdd20aSAndroid Build Coastguard Worker count = sum(1 for _ in qr_iterator) 169*6dbdd20aSAndroid Build Coastguard Worker self.assertEqual(count, expected_count) 170*6dbdd20aSAndroid Build Coastguard Worker 171*6dbdd20aSAndroid Build Coastguard Worker tp.close() 172*6dbdd20aSAndroid Build Coastguard Worker 173*6dbdd20aSAndroid Build Coastguard Worker def test_trace_byteio(self): 174*6dbdd20aSAndroid Build Coastguard Worker f = io.BytesIO( 175*6dbdd20aSAndroid Build Coastguard Worker b'\n(\n&\x08\x00\x12\x12\x08\x01\x10\xc8\x01\x1a\x0b\x12\t' 176*6dbdd20aSAndroid Build Coastguard Worker b'B|200|foo\x12\x0e\x08\x02\x10\xc8\x01\x1a\x07\x12\x05E|200') 177*6dbdd20aSAndroid Build Coastguard Worker with create_tp(trace=f) as tp: 178*6dbdd20aSAndroid Build Coastguard Worker qr_iterator = tp.query('select * from slice limit 10') 179*6dbdd20aSAndroid Build Coastguard Worker res = list(qr_iterator) 180*6dbdd20aSAndroid Build Coastguard Worker 181*6dbdd20aSAndroid Build Coastguard Worker self.assertEqual(len(res), 1) 182*6dbdd20aSAndroid Build Coastguard Worker 183*6dbdd20aSAndroid Build Coastguard Worker row = res[0] 184*6dbdd20aSAndroid Build Coastguard Worker self.assertEqual(row.ts, 1) 185*6dbdd20aSAndroid Build Coastguard Worker self.assertEqual(row.dur, 1) 186*6dbdd20aSAndroid Build Coastguard Worker self.assertEqual(row.name, 'foo') 187*6dbdd20aSAndroid Build Coastguard Worker 188*6dbdd20aSAndroid Build Coastguard Worker def test_trace_file(self): 189*6dbdd20aSAndroid Build Coastguard Worker with open(example_android_trace_path(), 'rb') as file: 190*6dbdd20aSAndroid Build Coastguard Worker with create_tp(trace=file) as tp: 191*6dbdd20aSAndroid Build Coastguard Worker qr_iterator = tp.query('select * from slice limit 10') 192*6dbdd20aSAndroid Build Coastguard Worker dur_result = [ 193*6dbdd20aSAndroid Build Coastguard Worker 178646, 119740, 58073, 155000, 173177, 20209377, 3589167, 90104, 194*6dbdd20aSAndroid Build Coastguard Worker 275312, 65313 195*6dbdd20aSAndroid Build Coastguard Worker ] 196*6dbdd20aSAndroid Build Coastguard Worker 197*6dbdd20aSAndroid Build Coastguard Worker for num, row in enumerate(qr_iterator): 198*6dbdd20aSAndroid Build Coastguard Worker self.assertEqual(row.dur, dur_result[num]) 199*6dbdd20aSAndroid Build Coastguard Worker 200*6dbdd20aSAndroid Build Coastguard Worker def test_trace_generator(self): 201*6dbdd20aSAndroid Build Coastguard Worker 202*6dbdd20aSAndroid Build Coastguard Worker def reader_generator(): 203*6dbdd20aSAndroid Build Coastguard Worker with open(example_android_trace_path(), 'rb') as file: 204*6dbdd20aSAndroid Build Coastguard Worker yield file.read(1024) 205*6dbdd20aSAndroid Build Coastguard Worker 206*6dbdd20aSAndroid Build Coastguard Worker with create_tp(trace=reader_generator()) as tp: 207*6dbdd20aSAndroid Build Coastguard Worker qr_iterator = tp.query('select * from slice limit 10') 208*6dbdd20aSAndroid Build Coastguard Worker dur_result = [ 209*6dbdd20aSAndroid Build Coastguard Worker 178646, 119740, 58073, 155000, 173177, 20209377, 3589167, 90104, 210*6dbdd20aSAndroid Build Coastguard Worker 275312, 65313 211*6dbdd20aSAndroid Build Coastguard Worker ] 212*6dbdd20aSAndroid Build Coastguard Worker 213*6dbdd20aSAndroid Build Coastguard Worker for num, row in enumerate(qr_iterator): 214*6dbdd20aSAndroid Build Coastguard Worker self.assertEqual(row.dur, dur_result[num]) 215*6dbdd20aSAndroid Build Coastguard Worker 216*6dbdd20aSAndroid Build Coastguard Worker def test_simple_resolver(self): 217*6dbdd20aSAndroid Build Coastguard Worker dur = [178646, 178646, 178646, 178646] 218*6dbdd20aSAndroid Build Coastguard Worker source = ['generator', 'path', 'path_resolver', 'file'] 219*6dbdd20aSAndroid Build Coastguard Worker expected = pd.DataFrame(list(zip(dur, source)), columns=['dur', 'source']) 220*6dbdd20aSAndroid Build Coastguard Worker 221*6dbdd20aSAndroid Build Coastguard Worker with create_batch_tp( 222*6dbdd20aSAndroid Build Coastguard Worker traces='simple:path={}'.format(example_android_trace_path())) as btp: 223*6dbdd20aSAndroid Build Coastguard Worker df = btp.query_and_flatten('select dur from slice limit 1') 224*6dbdd20aSAndroid Build Coastguard Worker pd.testing.assert_frame_equal(df, expected, check_dtype=False) 225*6dbdd20aSAndroid Build Coastguard Worker 226*6dbdd20aSAndroid Build Coastguard Worker with create_batch_tp( 227*6dbdd20aSAndroid Build Coastguard Worker traces=SimpleResolver(path=example_android_trace_path())) as btp: 228*6dbdd20aSAndroid Build Coastguard Worker df = btp.query_and_flatten('select dur from slice limit 1') 229*6dbdd20aSAndroid Build Coastguard Worker pd.testing.assert_frame_equal(df, expected, check_dtype=False) 230*6dbdd20aSAndroid Build Coastguard Worker 231*6dbdd20aSAndroid Build Coastguard Worker def test_query_timing(self): 232*6dbdd20aSAndroid Build Coastguard Worker observer = SimpleObserver() 233*6dbdd20aSAndroid Build Coastguard Worker with create_batch_tp( 234*6dbdd20aSAndroid Build Coastguard Worker traces='simple:path={}'.format(example_android_trace_path()), 235*6dbdd20aSAndroid Build Coastguard Worker observer=observer) as btp: 236*6dbdd20aSAndroid Build Coastguard Worker btp.query_and_flatten('select dur from slice limit 1') 237*6dbdd20aSAndroid Build Coastguard Worker self.assertTrue( 238*6dbdd20aSAndroid Build Coastguard Worker all([x > 0 for x in observer.execution_times]), 239*6dbdd20aSAndroid Build Coastguard Worker 'Running time should be positive') 240*6dbdd20aSAndroid Build Coastguard Worker 241*6dbdd20aSAndroid Build Coastguard Worker def test_recursive_resolver(self): 242*6dbdd20aSAndroid Build Coastguard Worker dur = [ 243*6dbdd20aSAndroid Build Coastguard Worker 178646, 178646, 178646, 178646, 178646, 178646, 178646, 178646, 178646 244*6dbdd20aSAndroid Build Coastguard Worker ] 245*6dbdd20aSAndroid Build Coastguard Worker source = ['recursive_gen', 'generator', 'path', 'generator', 'path'] 246*6dbdd20aSAndroid Build Coastguard Worker root_source = [ 247*6dbdd20aSAndroid Build Coastguard Worker None, 'recursive_path', 'recursive_path', 'recursive_obj', 248*6dbdd20aSAndroid Build Coastguard Worker 'recursive_obj' 249*6dbdd20aSAndroid Build Coastguard Worker ] 250*6dbdd20aSAndroid Build Coastguard Worker expected = pd.DataFrame( 251*6dbdd20aSAndroid Build Coastguard Worker list(zip(dur, source, root_source)), 252*6dbdd20aSAndroid Build Coastguard Worker columns=['dur', 'source', 'root_source']) 253*6dbdd20aSAndroid Build Coastguard Worker 254*6dbdd20aSAndroid Build Coastguard Worker uri = 'recursive:path={};skip_resolve_file=true'.format( 255*6dbdd20aSAndroid Build Coastguard Worker example_android_trace_path()) 256*6dbdd20aSAndroid Build Coastguard Worker with create_batch_tp(traces=uri) as btp: 257*6dbdd20aSAndroid Build Coastguard Worker df = btp.query_and_flatten('select dur from slice limit 1') 258*6dbdd20aSAndroid Build Coastguard Worker pd.testing.assert_frame_equal(df, expected, check_dtype=False) 259*6dbdd20aSAndroid Build Coastguard Worker 260*6dbdd20aSAndroid Build Coastguard Worker with create_batch_tp( 261*6dbdd20aSAndroid Build Coastguard Worker traces=RecursiveResolver( 262*6dbdd20aSAndroid Build Coastguard Worker path=example_android_trace_path(), skip_resolve_file=True)) as btp: 263*6dbdd20aSAndroid Build Coastguard Worker df = btp.query_and_flatten('select dur from slice limit 1') 264*6dbdd20aSAndroid Build Coastguard Worker pd.testing.assert_frame_equal(df, expected, check_dtype=False) 265*6dbdd20aSAndroid Build Coastguard Worker 266*6dbdd20aSAndroid Build Coastguard Worker def test_btp_load_failure(self): 267*6dbdd20aSAndroid Build Coastguard Worker f = io.BytesIO(b'<foo></foo>') 268*6dbdd20aSAndroid Build Coastguard Worker with self.assertRaises(TraceProcessorException): 269*6dbdd20aSAndroid Build Coastguard Worker _ = create_batch_tp(traces=f) 270*6dbdd20aSAndroid Build Coastguard Worker 271*6dbdd20aSAndroid Build Coastguard Worker def test_btp_load_failure_increment_stat(self): 272*6dbdd20aSAndroid Build Coastguard Worker f = io.BytesIO(b'<foo></foo>') 273*6dbdd20aSAndroid Build Coastguard Worker btp = create_batch_tp( 274*6dbdd20aSAndroid Build Coastguard Worker traces=f, load_failure_handling=FailureHandling.INCREMENT_STAT) 275*6dbdd20aSAndroid Build Coastguard Worker self.assertEqual(btp.stats().load_failures, 1) 276*6dbdd20aSAndroid Build Coastguard Worker 277*6dbdd20aSAndroid Build Coastguard Worker def test_btp_query_failure(self): 278*6dbdd20aSAndroid Build Coastguard Worker btp = create_batch_tp(traces=example_android_trace_path()) 279*6dbdd20aSAndroid Build Coastguard Worker with self.assertRaises(TraceProcessorException): 280*6dbdd20aSAndroid Build Coastguard Worker _ = btp.query('select * from sl') 281*6dbdd20aSAndroid Build Coastguard Worker 282*6dbdd20aSAndroid Build Coastguard Worker def test_btp_query_failure_increment_stat(self): 283*6dbdd20aSAndroid Build Coastguard Worker btp = create_batch_tp( 284*6dbdd20aSAndroid Build Coastguard Worker traces=example_android_trace_path(), 285*6dbdd20aSAndroid Build Coastguard Worker execute_failure_handling=FailureHandling.INCREMENT_STAT) 286*6dbdd20aSAndroid Build Coastguard Worker _ = btp.query('select * from sl') 287*6dbdd20aSAndroid Build Coastguard Worker self.assertEqual(btp.stats().execute_failures, 1) 288*6dbdd20aSAndroid Build Coastguard Worker 289*6dbdd20aSAndroid Build Coastguard Worker def test_btp_query_failure_message(self): 290*6dbdd20aSAndroid Build Coastguard Worker btp = create_batch_tp( 291*6dbdd20aSAndroid Build Coastguard Worker traces='simple:path={}'.format(example_android_trace_path())) 292*6dbdd20aSAndroid Build Coastguard Worker with self.assertRaisesRegex( 293*6dbdd20aSAndroid Build Coastguard Worker TraceProcessorException, expected_regex='.*source.*generator.*'): 294*6dbdd20aSAndroid Build Coastguard Worker _ = btp.query('select * from sl') 295*6dbdd20aSAndroid Build Coastguard Worker 296*6dbdd20aSAndroid Build Coastguard Worker def test_extra_flags(self): 297*6dbdd20aSAndroid Build Coastguard Worker with tempfile.TemporaryDirectory() as temp_dir: 298*6dbdd20aSAndroid Build Coastguard Worker test_module_dir = os.path.join(temp_dir, 'ext') 299*6dbdd20aSAndroid Build Coastguard Worker os.makedirs(test_module_dir) 300*6dbdd20aSAndroid Build Coastguard Worker test_module = os.path.join(test_module_dir, 'module.sql') 301*6dbdd20aSAndroid Build Coastguard Worker with open(test_module, 'w') as f: 302*6dbdd20aSAndroid Build Coastguard Worker f.write('CREATE TABLE test_table AS SELECT 123 AS test_value\n') 303*6dbdd20aSAndroid Build Coastguard Worker config = TraceProcessorConfig( 304*6dbdd20aSAndroid Build Coastguard Worker bin_path=os.environ["SHELL_PATH"], 305*6dbdd20aSAndroid Build Coastguard Worker extra_flags=['--add-sql-module', test_module_dir]) 306*6dbdd20aSAndroid Build Coastguard Worker with TraceProcessor(trace=io.BytesIO(b''), config=config) as tp: 307*6dbdd20aSAndroid Build Coastguard Worker qr_iterator = tp.query( 308*6dbdd20aSAndroid Build Coastguard Worker 'SELECT IMPORT("ext.module"); SELECT test_value FROM test_table') 309*6dbdd20aSAndroid Build Coastguard Worker self.assertEqual(next(qr_iterator).test_value, 123) 310