blob: 212414883f9708ef2679db7edeed0f2f0353b999 [file] [log] [blame]
#!/usr/bin/env fuchsia-vendored-python
# Copyright 2021 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import argparse
import os
import sys
import unittest
from unittest import mock
from parameterized import parameterized
import fidl_api_mapper
parser = argparse.ArgumentParser()
parser.add_argument(
"--test_dir_path", help="Path to the test data directory.", required=True
)
args = parser.parse_args()
TEST_DIR_PATH = args.test_dir_path
TEST_FILE_NAME = "fidl.h"
# The python_host_test build rule calls `unittest.main`.
# So we need to get rid of the test arguments in order
# to prevent them from interfering with `unittest`'s args.
#
# Pop twice to get rid of the `--test_dir_path` flag and
# its value.
sys.argv.pop()
sys.argv.pop()
class DwarfdumpStreamingParserTest(unittest.TestCase):
@parameterized.expand(
[
(
"not_subprogram_skipped",
[
"0x01: DW_TAG_member",
' DW_AT_name ("member_name")',
" DW_AT_decl_line (1)",
"",
],
{},
),
(
"one_subprogram",
[
"0x01: DW_TAG_subprogram",
' DW_AT_name ("function_name")',
" DW_AT_decl_line (1)",
"",
],
{
"0x01": {
"DW_AT_name": '"function_name"',
"DW_AT_decl_line": "1",
}
},
),
(
"two_subprograms_sandwiching_non_subprogram",
[
"0x01: DW_TAG_subprogram",
' DW_AT_name ("function_name_1")',
" DW_AT_decl_line (1)",
"",
"0x99: DW_TAG_member",
' DW_AT_name ("member_name")',
" DW_AT_decl_line (1)",
"",
"0x02: DW_TAG_subprogram",
' DW_AT_name ("function_name_2")',
" DW_AT_decl_line (2)",
"",
],
{
"0x01": {
"DW_AT_name": '"function_name_1"',
"DW_AT_decl_line": "1",
},
"0x02": {
"DW_AT_name": '"function_name_2"',
"DW_AT_decl_line": "2",
},
},
),
]
)
def test_parse_line(self, name, dwarfdump_lines, expected_subprograms_dict):
parser = fidl_api_mapper.DwarfdumpStreamingParser()
for line in dwarfdump_lines:
parser.parse_line(line)
self.assertEqual(parser.get_subprograms(), expected_subprograms_dict)
class FidlApiResolverTest(unittest.TestCase):
TEST_DATA_PATH = "unknown"
FIDL_HEADER_FILE_CONTENT = "\n".join(
[
"// cts-coverage-fidl-name:line_2",
"first_method()",
"// cts-coverage-fidl-name:line_4",
"middle_method()",
"non_fidl_method()",
"// cts-coverage-fidl-name:line_7",
"last_method()",
]
)
@parameterized.expand(
[
("empty_subprograms_dict", {}, {}, {}),
(
"successfully_resolved_first_line",
{
"0x1": {
"DW_AT_decl_file": '"fidl.h"',
"DW_AT_decl_line": "2",
"DW_AT_linkage_name": '"mangled_name"',
}
},
{},
{"mangled_name": "line_2"},
),
(
"successfully_resolved_middle_line",
{
"0x1": {
"DW_AT_decl_file": '"fidl.h"',
"DW_AT_decl_line": "4",
"DW_AT_linkage_name": '"mangled_name"',
}
},
{},
{"mangled_name": "line_4"},
),
(
"successfully_resolved_last_line",
{
"0x1": {
"DW_AT_decl_file": '"fidl.h"',
"DW_AT_decl_line": "7",
"DW_AT_linkage_name": '"mangled_name"',
}
},
{},
{"mangled_name": "line_7"},
),
(
"non_annotated_function_is_skipped",
{
"0x1": {
"DW_AT_decl_file": '"fidl.h"',
"DW_AT_decl_line": "5",
"DW_AT_linkage_name": '"mangled_name"',
}
},
{},
{},
),
(
"line_number_too_large",
{
"0x1": {
"DW_AT_decl_file": '"fidl.h"',
"DW_AT_decl_line": "100",
"DW_AT_linkage_name": '"mangled_name"',
}
},
{},
{},
),
(
"subprogram_missing_filepath",
{
"0x1": {
"DW_AT_decl_line": "1",
"DW_AT_linkage_name": '"mangled_name"',
}
},
{},
{},
),
(
"subprogram_missing_line_number",
{
"0x1": {
"DW_AT_decl_file": '"fidl.h"',
"DW_AT_linkage_name": '"mangled_name"',
}
},
{},
{},
),
(
"subprogram_is_not_in_fidl_header",
{
"0x1": {
"DW_AT_decl_file": '"fidl.cc"',
"DW_AT_decl_line": "1",
"DW_AT_linkage_name": '"mangled_name"',
}
},
{},
{},
),
(
"subprogram_missing_mangled_name",
{
"0x1": {
"DW_AT_decl_file": '"fidl.h"',
"DW_AT_decl_line": "1",
}
},
{},
{},
),
(
"subprogram_already_in_mapping",
{
"0x1": {
"DW_AT_decl_file": '"fidl.h"',
"DW_AT_decl_line": "1",
"DW_AT_linkage_name": '"mangled_name"',
}
},
{"mangled_name": "fidl_api_name"},
{"mangled_name": "fidl_api_name"},
),
]
)
def test_add_new_mappings(
self, name, subprograms_dict, input_mapping_dict, expect_mapping_dict
):
resolver = fidl_api_mapper.FidlApiResolver(
subprograms_dict, input_mapping_dict
)
with mock.patch(
"builtins.open",
mock.mock_open(read_data=self.FIDL_HEADER_FILE_CONTENT),
):
resolver.add_new_mappings()
self.assertEqual(input_mapping_dict, expect_mapping_dict)
def test_add_new_mappings_snapshot_fidl_file(self):
# This testcase differs from "test_add_new_mappings" in that it uses
# a real generated FIDL binding header file snapshotted at a particular
# revision. So there's no need to mock the content of the file and we
# can just directly read it instead.
testdata_path = os.path.join(TEST_DIR_PATH, "snapshot", TEST_FILE_NAME)
subprograms_dict = {
"0x1": {
"DW_AT_decl_file": '"%s"' % testdata_path,
"DW_AT_decl_line": "652",
"DW_AT_linkage_name": '"mangled_name"',
}
}
expect_mapping_dict = {
"mangled_name": "fuchsia.diagnostics.stream/Source.RetireBuffer"
}
mapping_dict = {}
resolver = fidl_api_mapper.FidlApiResolver(
subprograms_dict, mapping_dict
)
resolver.add_new_mappings()
self.assertEqual(mapping_dict, expect_mapping_dict)
def test_add_new_mappings_generated_fidl_file(self):
# Test against generated fidl headers from the current build.
# Since the line of function declaration can change, we can just
# the following assertions:
# 1) At least 1 mapping can be added from iterating through all
# lines in the generated fidl header.
# 2) No crashes from iterating all lines.
testdata_path = os.path.join(TEST_DIR_PATH, "generated", TEST_FILE_NAME)
num_lines = len(open(testdata_path).readlines())
subprograms_dict = {}
mapping_dict = {}
for line_num in range(1, num_lines + 1):
subprograms_dict = {
"0x1": {
"DW_AT_decl_file": '"%s"' % testdata_path,
"DW_AT_decl_line": "%d" % line_num,
"DW_AT_linkage_name": '"mangled_name_%d"' % line_num,
}
}
resolver = fidl_api_mapper.FidlApiResolver(
subprograms_dict, mapping_dict
)
resolver.add_new_mappings()
self.assertTrue(mapping_dict)