Add test for profiling handler

This commit is contained in:
Christophe Bedard 2019-08-06 09:57:12 +02:00
parent 4cb73fb9b6
commit fdeb4a5d48

View file

@ -0,0 +1,320 @@
# Copyright 2019 Robert Bosch GmbH
#
# 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.
from typing import Any
from typing import Dict
from typing import List
import unittest
from pandas import DataFrame
from pandas.util.testing import assert_frame_equal
from tracetools_analysis.processor import Processor
from tracetools_analysis.processor.profile import ProfileHandler
from tracetools_read import DictEvent
# TEST DATA
#
# + Threads:
# 0: does whatever
# 1: contains one instance of the functions of interest
# 2: contains another instance of the functions of interest
#
# + Functions structure
# function_a
# function_aa
# function_b
#
# + Timeline
# tid 1 2
# func a aa b a aa b
# time
# 0 : whatever
# 3 : sched_switch from tid 0 to tid 1
# 5 : tid 1, func_entry: function_a
# 7 : sched_switch from tid 1 to tid 0 2
# 10 : sched_switch from tid 0 to tid 2
# 11 : tid 2, func_entry: function_a
# 15 : sched_switch from tid 2 to tid 1 4
# 16 : tid 1, func_entry: function_aa 1
# 20 : sched_switch from tid 1 to tid 2 4 4
# 27 : tid 2, func_entry: function_aa 7
# 29 : sched_switch from tid 2 to tid 1 2 2
# 30 : tid 1, func_exit: (function_aa) 1 1
# 32 : sched_switch from tid 1 to tid 0 2
# 34 : sched_switch from tid 0 to tid 2
# 35 : tid 2, func_exit: (function_aa) 1 1
# 37 : tid 2, func_exit: (function_a) 2
# 39 : tid 2, func_entry: function_b
# 40 : tid 2, func_exit: (function_b) 1
# 41 : sched_switch from tid 2 to tid 1
# 42 : tid 1, func_exit: (function_a) 1
# 44 : tid 1, func_entry: function_b
# 47 : sched_switch from tid 1 to tid 0 3
# 49 : sched_switch from tid 0 to tid 1
# 60 : tid 1, func_exit: (function_b) 11
# 69 : sched_switch from tid 1 to tid 0
#
# total 11 5 14 16 3 1
input_events = [
{
'_name': 'sched_switch',
'_timestamp': 3,
'prev_tid': 0,
'next_tid': 1,
},
{
'_name': 'lttng_ust_cyg_profile_fast:func_entry',
'_timestamp': 5,
'vtid': 1,
'addr': '0xfA',
},
{
'_name': 'sched_switch',
'_timestamp': 7,
'prev_tid': 1,
'next_tid': 0,
},
{
'_name': 'sched_switch',
'_timestamp': 10,
'prev_tid': 0,
'next_tid': 2,
},
{
'_name': 'lttng_ust_cyg_profile_fast:func_entry',
'_timestamp': 11,
'vtid': 2,
'addr': '0xfA',
},
{
'_name': 'sched_switch',
'_timestamp': 15,
'prev_tid': 2,
'next_tid': 1,
},
{
'_name': 'lttng_ust_cyg_profile_fast:func_entry',
'_timestamp': 16,
'vtid': 1,
'addr': '0xfAA',
},
{
'_name': 'sched_switch',
'_timestamp': 20,
'prev_tid': 1,
'next_tid': 2,
},
{
'_name': 'lttng_ust_cyg_profile_fast:func_entry',
'_timestamp': 27,
'vtid': 2,
'addr': '0xfAA',
},
{
'_name': 'sched_switch',
'_timestamp': 29,
'prev_tid': 2,
'next_tid': 1,
},
{
'_name': 'lttng_ust_cyg_profile_fast:func_exit',
'_timestamp': 30,
'vtid': 1,
},
{
'_name': 'sched_switch',
'_timestamp': 32,
'prev_tid': 1,
'next_tid': 0,
},
{
'_name': 'sched_switch',
'_timestamp': 34,
'prev_tid': 0,
'next_tid': 2,
},
{
'_name': 'lttng_ust_cyg_profile_fast:func_exit',
'_timestamp': 35,
'vtid': 2,
},
{
'_name': 'lttng_ust_cyg_profile_fast:func_exit',
'_timestamp': 37,
'vtid': 2,
},
{
'_name': 'lttng_ust_cyg_profile_fast:func_entry',
'_timestamp': 39,
'vtid': 2,
'addr': '0xfB',
},
{
'_name': 'lttng_ust_cyg_profile_fast:func_exit',
'_timestamp': 40,
'vtid': 2,
},
{
'_name': 'sched_switch',
'_timestamp': 41,
'prev_tid': 2,
'next_tid': 1,
},
{
'_name': 'lttng_ust_cyg_profile_fast:func_exit',
'_timestamp': 42,
'vtid': 1,
},
{
'_name': 'lttng_ust_cyg_profile_fast:func_entry',
'_timestamp': 44,
'vtid': 1,
'addr': '0xfB',
},
{
'_name': 'sched_switch',
'_timestamp': 47,
'prev_tid': 1,
'next_tid': 0,
},
{
'_name': 'sched_switch',
'_timestamp': 49,
'prev_tid': 0,
'next_tid': 1,
},
{
'_name': 'lttng_ust_cyg_profile_fast:func_exit',
'_timestamp': 60,
'vtid': 1,
},
{
'_name': 'sched_switch',
'_timestamp': 69,
'prev_tid': 1,
'next_tid': 0,
},
]
expected = [
{
'tid': 1,
'depth': 1,
'function_name': '0xfAA',
'parent_name': '0xfA',
'start_timestamp': 16,
'duration': 14,
'actual_duration': 5,
},
{
'tid': 2,
'depth': 1,
'function_name': '0xfAA',
'parent_name': '0xfA',
'start_timestamp': 27,
'duration': 8,
'actual_duration': 3,
},
{
'tid': 2,
'depth': 0,
'function_name': '0xfA',
'parent_name': None,
'start_timestamp': 11,
'duration': 26,
'actual_duration': 16,
},
{
'tid': 2,
'depth': 0,
'function_name': '0xfB',
'parent_name': None,
'start_timestamp': 39,
'duration': 1,
'actual_duration': 1,
},
{
'tid': 1,
'depth': 0,
'function_name': '0xfA',
'parent_name': None,
'start_timestamp': 5,
'duration': 37,
'actual_duration': 11,
},
{
'tid': 1,
'depth': 0,
'function_name': '0xfB',
'parent_name': None,
'start_timestamp': 44,
'duration': 16,
'actual_duration': 14,
},
]
class TestProfileHandler(unittest.TestCase):
def __init__(self, *args) -> None:
super().__init__(
*args,
)
@staticmethod
def build_expected_df(expected_data: List[Dict[str, Any]]) -> DataFrame:
# Make sure the columns are in the same order
expected_df = DataFrame(columns=[
'tid',
'depth',
'function_name',
'parent_name',
'start_timestamp',
'duration',
'actual_duration',
])
return expected_df.append(expected_data, ignore_index=True)
@staticmethod
def add_fake_fields(events: List[DictEvent]) -> None:
# Actual value does not matter here; it just needs to be there
for event in events:
event['cpu_id'] = 69
@classmethod
def setUpClass(cls):
cls.add_fake_fields(input_events)
cls.expected = cls.build_expected_df(expected)
cls.handler = ProfileHandler()
cls.processor = Processor(cls.handler)
cls.processor.process(input_events)
def test_profiling(self) -> None:
handler = self.__class__.handler
expected_df = self.__class__.expected
result_df = handler.get_data_model().times
print('RESULT')
print(result_df.to_string())
print('EXPECTED')
print(expected_df.to_string())
assert_frame_equal(result_df, expected_df)
if __name__ == '__main__':
unittest.main()