#!/usr/bin/env python3
#
# Copyright (C) 2021 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 collections
import json
import os
import tempfile
from typing import Any, Dict, List, Set

from binary_cache_builder import BinaryCacheBuilder
from . test_utils import TestBase, TestHelper


class TestReportHtml(TestBase):
    def test_long_callchain(self):
        self.run_cmd(['report_html.py', '-i',
                      TestHelper.testdata_path('perf_with_long_callchain.data')])

    def test_aggregated_by_thread_name(self):
        # Calculate event_count for each thread name before aggregation.
        event_count_for_thread_name = collections.defaultdict(lambda: 0)
        # use "--min_func_percent 0" to avoid cutting any thread.
        record_data = self.get_record_data(['--min_func_percent', '0', '-i',
                                            TestHelper.testdata_path('aggregatable_perf1.data'),
                                            TestHelper.testdata_path('aggregatable_perf2.data')])
        event = record_data['sampleInfo'][0]
        for process in event['processes']:
            for thread in process['threads']:
                thread_name = record_data['threadNames'][str(thread['tid'])]
                event_count_for_thread_name[thread_name] += thread['eventCount']

        # Check event count for each thread after aggregation.
        record_data = self.get_record_data(['--aggregate-by-thread-name',
                                            '--min_func_percent', '0', '-i',
                                            TestHelper.testdata_path('aggregatable_perf1.data'),
                                            TestHelper.testdata_path('aggregatable_perf2.data')])
        event = record_data['sampleInfo'][0]
        hit_count = 0
        for process in event['processes']:
            for thread in process['threads']:
                thread_name = record_data['threadNames'][str(thread['tid'])]
                self.assertEqual(thread['eventCount'],
                                 event_count_for_thread_name[thread_name])
                hit_count += 1
        self.assertEqual(hit_count, len(event_count_for_thread_name))

    def test_no_empty_process(self):
        """ Test not showing a process having no threads. """
        perf_data = TestHelper.testdata_path('two_process_perf.data')
        record_data = self.get_record_data(['-i', perf_data])
        processes = record_data['sampleInfo'][0]['processes']
        self.assertEqual(len(processes), 2)

        # One process is removed because all its threads are removed for not
        # reaching the min_func_percent limit.
        record_data = self.get_record_data(['-i', perf_data, '--min_func_percent', '20'])
        processes = record_data['sampleInfo'][0]['processes']
        self.assertEqual(len(processes), 1)

    def test_proguard_mapping_file(self):
        """ Test --proguard-mapping-file option. """
        testdata_file = TestHelper.testdata_path('perf_need_proguard_mapping.data')
        proguard_mapping_file = TestHelper.testdata_path('proguard_mapping.txt')
        original_methodname = 'androidx.fragment.app.FragmentActivity.startActivityForResult'
        # Can't show original method name without proguard mapping file.
        record_data = self.get_record_data(['-i', testdata_file])
        self.assertNotIn(original_methodname, json.dumps(record_data))
        # Show original method name with proguard mapping file.
        record_data = self.get_record_data(
            ['-i', testdata_file, '--proguard-mapping-file', proguard_mapping_file])
        self.assertIn(original_methodname, json.dumps(record_data))

    def get_record_data(self, options: List[str]) -> Dict[str, Any]:
        json_data = self.get_record_data_string(options)
        return json.loads(json_data)

    def get_record_data_string(self, options: List[str]) -> str:
        args = ['report_html.py'] + options
        if TestHelper.ndk_path:
            args += ['--ndk_path', TestHelper.ndk_path]
        self.run_cmd(args)
        with open('report.html', 'r') as fh:
            data = fh.read()
        start_str = 'type="application/json"'
        end_str = '</script>'
        start_pos = data.find(start_str)
        self.assertNotEqual(start_pos, -1)
        start_pos = data.find('>', start_pos)
        self.assertNotEqual(start_pos, -1)
        start_pos += 1
        end_pos = data.find(end_str, start_pos)
        self.assertNotEqual(end_pos, -1)
        return data[start_pos:end_pos]

    def test_add_source_code(self):
        """ Test --add_source_code option. """
        testdata_file = TestHelper.testdata_path('runtest_two_functions_arm64_perf.data')

        # Build binary_cache.
        binary_cache_builder = BinaryCacheBuilder(TestHelper.ndk_path, False)
        binary_cache_builder.build_binary_cache(testdata_file, [TestHelper.testdata_dir])

        # Generate report.html.
        source_dir = TestHelper.testdata_dir
        record_data = self.get_record_data(
            ['-i', testdata_file, '--add_source_code', '--source_dirs', str(source_dir)])

        # Check source code info in samples.
        source_code_list = []
        thread = record_data['sampleInfo'][0]['processes'][0]['threads'][0]
        for lib in thread['libs']:
            for function in lib['functions']:
                for source_code_info in function.get('s') or []:
                    source_file = record_data['sourceFiles'][source_code_info['f']]
                    file_path = source_file['path']
                    line_number = source_code_info['l']
                    line_content = source_file['code'][str(line_number)]
                    event_count = source_code_info['e']
                    subtree_event_count = source_code_info['s']
                    s = (f'{file_path}:{line_number}:{line_content}:' +
                         f'{event_count}:{subtree_event_count}')
                    source_code_list.append(s)
        check_items = ['two_functions.cpp:9:    *p = i;\n:590184:590184',
                       'two_functions.cpp:16:    *p = i;\n:591577:591577',
                       'two_functions.cpp:22:    Function1();\n:0:590184',
                       'two_functions.cpp:23:    Function2();\n:0:591577']
        for item in check_items:
            found = False
            for source_code in source_code_list:
                if item in source_code:
                    found = True
                    break
            self.assertTrue(found, item)

    def test_add_disassembly(self):
        """ Test --add_disassembly option. """
        testdata_file = TestHelper.testdata_path('runtest_two_functions_arm64_perf.data')

        # Build binary_cache.
        binary_cache_builder = BinaryCacheBuilder(TestHelper.ndk_path, False)
        binary_cache_builder.build_binary_cache(testdata_file, [TestHelper.testdata_dir])

        # Generate report.html.
        record_data = self.get_record_data(['-i', testdata_file, '--add_disassembly'])

        # Check disassembly in samples.
        disassembly_list = []
        thread = record_data['sampleInfo'][0]['processes'][0]['threads'][0]
        for lib in thread['libs']:
            lib_name = record_data['libList'][lib['libId']]
            for function in lib['functions']:
                for addr_info in function.get('a') or []:
                    addr = addr_info['a']
                    event_count = addr_info['e']
                    subtree_event_count = addr_info['s']
                    function_data = record_data['functionMap'][str(function['f'])]
                    function_name = function_data['f']
                    for dis_line, dis_addr in function_data.get('d') or []:
                        if addr == dis_addr:
                            s = (f'{lib_name}:{function_name}:{addr}:' +
                                 f'{event_count}:{subtree_event_count}')
                            disassembly_list.append(s)

        check_items = ['simpleperf_runtest_two_functions_arm64:Function1():0x1094:590184:590184',
                       'simpleperf_runtest_two_functions_arm64:Function2():0x1104:591577:591577',
                       'simpleperf_runtest_two_functions_arm64:main:0x113c:0:590184',
                       'simpleperf_runtest_two_functions_arm64:main:0x1140:0:591577']
        for item in check_items:
            found = False
            for disassembly in disassembly_list:
                if item in disassembly:
                    found = True
                    break
            self.assertTrue(found, item)

    def test_trace_offcpu(self):
        """ Test --trace-offcpu option. """
        testdata_file = TestHelper.testdata_path('perf_with_trace_offcpu_v2.data')
        record_data = self.get_record_data(['-i', testdata_file, '--trace-offcpu', 'on-cpu'])
        self.assertEqual(len(record_data['sampleInfo']), 1)
        self.assertEqual(record_data['sampleInfo'][0]['eventName'], 'cpu-clock:u')
        self.assertEqual(record_data['sampleInfo'][0]['eventCount'], 52000000)

        record_data = self.get_record_data(['-i', testdata_file, '--trace-offcpu', 'off-cpu'])
        self.assertEqual(len(record_data['sampleInfo']), 1)
        self.assertEqual(record_data['sampleInfo'][0]['eventName'], 'sched:sched_switch')
        self.assertEqual(record_data['sampleInfo'][0]['eventCount'], 344124304)

        record_data = self.get_record_data(['-i', testdata_file, '--trace-offcpu', 'on-off-cpu'])
        self.assertEqual(len(record_data['sampleInfo']), 2)
        self.assertEqual(record_data['sampleInfo'][0]['eventName'], 'cpu-clock:u')
        self.assertEqual(record_data['sampleInfo'][0]['eventCount'], 52000000)
        self.assertEqual(record_data['sampleInfo'][1]['eventName'], 'sched:sched_switch')
        self.assertEqual(record_data['sampleInfo'][1]['eventCount'], 344124304)

        record_data = self.get_record_data(
            ['-i', testdata_file, '--trace-offcpu', 'mixed-on-off-cpu'])
        self.assertEqual(len(record_data['sampleInfo']), 1)
        self.assertEqual(record_data['sampleInfo'][0]['eventName'], 'cpu-clock:u')
        self.assertEqual(record_data['sampleInfo'][0]['eventCount'], 396124304)

    def test_sample_filters(self):
        def get_threads_for_filter(filter: str) -> Set[int]:
            record_data = self.get_record_data(
                ['-i', TestHelper.testdata_path('perf_display_bitmaps.data')] + filter.split())
            threads = set()
            try:
                for thread in record_data['sampleInfo'][0]['processes'][0]['threads']:
                    threads.add(thread['tid'])
            except IndexError:
                pass
            return threads

        self.assertNotIn(31850, get_threads_for_filter('--exclude-pid 31850'))
        self.assertIn(31850, get_threads_for_filter('--include-pid 31850'))
        self.assertIn(31850, get_threads_for_filter('--pid 31850'))
        self.assertNotIn(31881, get_threads_for_filter('--exclude-tid 31881'))
        self.assertIn(31881, get_threads_for_filter('--include-tid 31881'))
        self.assertIn(31881, get_threads_for_filter('--tid 31881'))
        self.assertNotIn(31881, get_threads_for_filter(
            '--exclude-process-name com.example.android.displayingbitmaps'))
        self.assertIn(31881, get_threads_for_filter(
            '--include-process-name com.example.android.displayingbitmaps'))
        self.assertNotIn(31850, get_threads_for_filter(
            '--exclude-thread-name com.example.android.displayingbitmaps'))
        self.assertIn(31850, get_threads_for_filter(
            '--include-thread-name com.example.android.displayingbitmaps'))

        with tempfile.NamedTemporaryFile('w', delete=False) as filter_file:
            filter_file.write('GLOBAL_BEGIN 684943449406175\nGLOBAL_END 684943449406176')
            filter_file.flush()
            threads = get_threads_for_filter('--filter-file ' + filter_file.name)
            self.assertIn(31881, threads)
            self.assertNotIn(31850, threads)
        os.unlink(filter_file.name)

    def test_show_art_frames(self):
        art_frame_str = 'art::interpreter::DoCall'
        options = ['-i', TestHelper.testdata_path('perf_with_interpreter_frames.data')]
        report = self.get_record_data_string(options)
        self.assertNotIn(art_frame_str, report)
        report = self.get_record_data_string(options + ['--show-art-frames'])
        self.assertIn(art_frame_str, report)
