Fix the test script for the changes made to section naming. Signed-off-by: Jordan Yates <jordan.yates@data61.csiro.au>
374 lines
14 KiB
Python
Executable file
374 lines
14 KiB
Python
Executable file
#!/usr/bin/env python3
|
|
|
|
# Copyright 2023 Google LLC
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
"""
|
|
Tests for check_init_priorities
|
|
"""
|
|
|
|
import mock
|
|
import pathlib
|
|
import unittest
|
|
|
|
from elftools.elf.relocation import RelocationSection
|
|
from elftools.elf.sections import SymbolTableSection
|
|
|
|
import check_init_priorities
|
|
|
|
class TestPriority(unittest.TestCase):
|
|
"""Tests for the Priority class."""
|
|
|
|
def test_priority_parsing(self):
|
|
prio1 = check_init_priorities.Priority(".rel.z_init_POST_KERNEL12_0_")
|
|
self.assertEqual(prio1._level_priority, (3, 12, 0))
|
|
|
|
prio2 = check_init_priorities.Priority("noisenoise_POST_KERNEL99_00023_")
|
|
self.assertEqual(prio2._level_priority, (3, 99, 23))
|
|
|
|
prio3 = check_init_priorities.Priority("_PRE_KERNEL_10_99999_")
|
|
self.assertEqual(prio3._level_priority, (1, 0, 99999))
|
|
|
|
prio4 = check_init_priorities.Priority("_PRE_KERNEL_110_00001_")
|
|
self.assertEqual(prio4._level_priority, (1, 10, 1))
|
|
|
|
with self.assertRaises(ValueError):
|
|
check_init_priorities.Priority("i-am-not-a-priority")
|
|
check_init_priorities.Priority("_DOESNOTEXIST0_")
|
|
check_init_priorities.Priority(".rel.z_init_POST_KERNEL12_blah")
|
|
check_init_priorities.Priority(".rel.z_init_2_")
|
|
check_init_priorities.Priority(".rel.z_init_POST_KERNEL1_")
|
|
|
|
def test_priority_levels(self):
|
|
prios = [
|
|
check_init_priorities.Priority(".rel.z_init_EARLY0_0_"),
|
|
check_init_priorities.Priority(".rel.z_init_EARLY1_0_"),
|
|
check_init_priorities.Priority(".rel.z_init_EARLY11_0_"),
|
|
check_init_priorities.Priority(".rel.z_init_PRE_KERNEL_10_0_"),
|
|
check_init_priorities.Priority(".rel.z_init_PRE_KERNEL_11_0_"),
|
|
check_init_priorities.Priority(".rel.z_init_PRE_KERNEL_111_0_"),
|
|
check_init_priorities.Priority(".rel.z_init_PRE_KERNEL_111_1_"),
|
|
check_init_priorities.Priority(".rel.z_init_PRE_KERNEL_111_00002_"),
|
|
check_init_priorities.Priority(".rel.z_init_PRE_KERNEL_111_00010_"),
|
|
check_init_priorities.Priority(".rel.z_init_PRE_KERNEL_20_0_"),
|
|
check_init_priorities.Priority(".rel.z_init_PRE_KERNEL_21_0_"),
|
|
check_init_priorities.Priority(".rel.z_init_PRE_KERNEL_211_0_"),
|
|
check_init_priorities.Priority(".rel.z_init_POST_KERNEL0_0_"),
|
|
check_init_priorities.Priority(".rel.z_init_POST_KERNEL1_0_"),
|
|
check_init_priorities.Priority(".rel.z_init_POST_KERNEL11_0_"),
|
|
check_init_priorities.Priority(".rel.z_init_APPLICATION0_0_"),
|
|
check_init_priorities.Priority(".rel.z_init_APPLICATION1_0_"),
|
|
check_init_priorities.Priority(".rel.z_init_APPLICATION11_0_"),
|
|
check_init_priorities.Priority(".rel.z_init_SMP0_0_"),
|
|
check_init_priorities.Priority(".rel.z_init_SMP1_0_"),
|
|
check_init_priorities.Priority(".rel.z_init_SMP11_0_"),
|
|
]
|
|
|
|
self.assertListEqual(prios, sorted(prios))
|
|
|
|
def test_priority_strings(self):
|
|
prio = check_init_priorities.Priority(".rel.z_init_POST_KERNEL12_00023_")
|
|
self.assertEqual(str(prio), "POST_KERNEL 12 23")
|
|
self.assertEqual(repr(prio), "<Priority POST_KERNEL 12 23>")
|
|
|
|
class testZephyrObjectFile(unittest.TestCase):
|
|
"""Tests for the ZephyrObjectFile class."""
|
|
|
|
@mock.patch("check_init_priorities.ZephyrObjectFile.__init__", return_value=None)
|
|
def test_load_symbols(self, mock_zofinit):
|
|
mock_elf = mock.Mock()
|
|
|
|
sts = mock.Mock(spec=SymbolTableSection)
|
|
rel = mock.Mock(spec=RelocationSection)
|
|
mock_elf.iter_sections.return_value = [sts, rel]
|
|
|
|
s0 = mock.Mock()
|
|
s0.name = "a"
|
|
s1 = mock.Mock()
|
|
s1.name = None
|
|
s2 = mock.Mock()
|
|
s2.name = "b"
|
|
sts.iter_symbols.return_value = [s0, s1, s2]
|
|
|
|
obj = check_init_priorities.ZephyrObjectFile("")
|
|
obj._elf = mock_elf
|
|
obj._load_symbols()
|
|
|
|
self.assertDictEqual(obj._symbols, {0: "a", 2: "b"})
|
|
|
|
@mock.patch("check_init_priorities.Priority")
|
|
@mock.patch("check_init_priorities.ZephyrObjectFile._device_ord_from_rel")
|
|
@mock.patch("check_init_priorities.ZephyrObjectFile.__init__", return_value=None)
|
|
def test_find_defined_devices(self, mock_zofinit, mock_dofr, mock_prio):
|
|
mock_elf = mock.Mock()
|
|
|
|
sts = mock.Mock(spec=SymbolTableSection)
|
|
rel1 = mock.Mock(spec=RelocationSection)
|
|
rel1.name = ".rel.z_init_SOMETHING"
|
|
rel2 = mock.Mock(spec=RelocationSection)
|
|
rel2.name = ".rel.something_else"
|
|
mock_elf.iter_sections.return_value = [sts, rel1, rel2]
|
|
|
|
r0 = mock.Mock()
|
|
rel1.iter_relocations.return_value = [r0]
|
|
|
|
mock_dofr.return_value = 123
|
|
|
|
r0_prio = mock.Mock()
|
|
mock_prio.return_value = r0_prio
|
|
|
|
obj = check_init_priorities.ZephyrObjectFile("")
|
|
obj._elf = mock_elf
|
|
obj._find_defined_devices()
|
|
|
|
self.assertDictEqual(obj.defined_devices, {123: r0_prio})
|
|
mock_dofr.assert_called_once_with(r0)
|
|
mock_prio.assert_called_once_with(rel1.name)
|
|
|
|
@mock.patch("check_init_priorities.ZephyrObjectFile.__init__", return_value=None)
|
|
def test_device_ord_from_rel(self, mock_zofinit):
|
|
obj = check_init_priorities.ZephyrObjectFile("")
|
|
|
|
obj._symbols = {
|
|
1: "blah",
|
|
2: "__device_dts_ord_123",
|
|
}
|
|
|
|
self.assertEqual(obj._device_ord_from_rel({"r_info_sym": 0}), None)
|
|
self.assertEqual(obj._device_ord_from_rel({"r_info_sym": 1}), None)
|
|
self.assertEqual(obj._device_ord_from_rel({"r_info_sym": 2}), 123)
|
|
|
|
class testValidator(unittest.TestCase):
|
|
"""Tests for the Validator class."""
|
|
|
|
@mock.patch("check_init_priorities.ZephyrObjectFile")
|
|
@mock.patch("check_init_priorities.Validator._find_build_objfiles")
|
|
@mock.patch("pickle.load")
|
|
def test_initialize(self, mock_pl, mock_fbo, mock_zof):
|
|
mock_fbo.return_value = ["filepath"]
|
|
|
|
mock_log = mock.Mock()
|
|
mock_prio = mock.Mock()
|
|
mock_obj = mock.Mock()
|
|
mock_obj.defined_devices = {123: mock_prio}
|
|
mock_zof.return_value = mock_obj
|
|
|
|
with mock.patch("builtins.open", mock.mock_open()) as mock_open:
|
|
validator = check_init_priorities.Validator("path", "pickle", mock_log)
|
|
|
|
self.assertListEqual(validator._objs, [mock_obj])
|
|
self.assertDictEqual(validator._dev_priorities, {123: mock_prio})
|
|
mock_fbo.assert_called_once_with("path", is_root=True)
|
|
mock_zof.assert_called_once_with("filepath")
|
|
mock_open.assert_called_once_with(pathlib.Path("path/pickle"), "rb")
|
|
|
|
@mock.patch("pathlib.Path")
|
|
@mock.patch("check_init_priorities.Validator.__init__", return_value=None)
|
|
def test_find_build_objfiles(self, mock_vinit, mock_path):
|
|
mock_log = mock.Mock()
|
|
|
|
validator = check_init_priorities.Validator("", "", mock_log)
|
|
|
|
mock_file = mock.Mock()
|
|
mock_file.is_file.return_value = True
|
|
mock_file.is_dir.return_value = False
|
|
mock_file.file.name = "filename.c.obj"
|
|
|
|
mock_dir = mock.Mock()
|
|
mock_dir.is_file.return_value = False
|
|
mock_dir.is_dir.return_value = True
|
|
mock_dir.resolve.return_value = "subdir"
|
|
mock_dir.iterdir.return_value = []
|
|
|
|
mock_nosettingsfile = mock.Mock()
|
|
mock_nosettingsfile.exists.return_value = False
|
|
|
|
mock_path_root = mock.Mock()
|
|
mock_path_root.iterdir.return_value = [mock_file, mock_dir]
|
|
|
|
def mock_path_stubs(*args):
|
|
if args == ("root",):
|
|
return mock_path_root
|
|
elif args == ("subdir",):
|
|
return mock_dir
|
|
elif args == ("subdir", "CMakeCache.txt"):
|
|
return mock_nosettingsfile
|
|
raise ValueError
|
|
mock_path.side_effect = mock_path_stubs
|
|
|
|
ret = list(validator._find_build_objfiles("root", is_root=True))
|
|
self.assertListEqual(ret, [mock_file])
|
|
|
|
mock_nosettingsfile.exists.assert_called_once_with()
|
|
self.assertListEqual(mock_path.call_args_list, [
|
|
mock.call("root"),
|
|
mock.call("subdir", "CMakeCache.txt"),
|
|
mock.call("subdir")
|
|
])
|
|
|
|
@mock.patch("check_init_priorities.Validator.__init__", return_value=None)
|
|
def test_check_dep_same_node(self, mock_vinit):
|
|
validator = check_init_priorities.Validator("", "", None)
|
|
validator.log = mock.Mock()
|
|
|
|
validator._check_dep(123, 123)
|
|
|
|
self.assertFalse(validator.log.info.called)
|
|
self.assertFalse(validator.log.warning.called)
|
|
self.assertFalse(validator.log.error.called)
|
|
|
|
@mock.patch("check_init_priorities.Validator.__init__", return_value=None)
|
|
def test_check_dep_no_prio(self, mock_vinit):
|
|
validator = check_init_priorities.Validator("", "", None)
|
|
validator.log = mock.Mock()
|
|
|
|
validator._ord2node = {1: mock.Mock(), 2: mock.Mock()}
|
|
validator._ord2node[1]._binding = None
|
|
validator._ord2node[2]._binding = None
|
|
|
|
validator._dev_priorities = {1: 10}
|
|
validator._check_dep(1, 2)
|
|
|
|
validator._dev_priorities = {2: 20}
|
|
validator._check_dep(1, 2)
|
|
|
|
self.assertFalse(validator.log.info.called)
|
|
self.assertFalse(validator.log.warning.called)
|
|
self.assertFalse(validator.log.error.called)
|
|
|
|
@mock.patch("check_init_priorities.Validator.__init__", return_value=None)
|
|
def test_check(self, mock_vinit):
|
|
validator = check_init_priorities.Validator("", "", None)
|
|
validator.log = mock.Mock()
|
|
validator.warnings = 0
|
|
validator.errors = 0
|
|
|
|
validator._ord2node = {1: mock.Mock(), 2: mock.Mock(), 3: mock.Mock()}
|
|
validator._ord2node[1]._binding = None
|
|
validator._ord2node[1].path = "/1"
|
|
validator._ord2node[2]._binding = None
|
|
validator._ord2node[2].path = "/2"
|
|
validator._ord2node[3]._binding = None
|
|
validator._ord2node[3].path = "/3"
|
|
|
|
validator._dev_priorities = {1: 10, 2: 10, 3: 20}
|
|
|
|
validator._check_dep(3, 1)
|
|
validator._check_dep(2, 1)
|
|
validator._check_dep(1, 3)
|
|
|
|
validator.log.info.assert_called_once_with("/3 20 > /1 10")
|
|
validator.log.warning.assert_called_once_with("/2 10 == /1 10")
|
|
validator.log.error.assert_called_once_with("/1 10 < /3 20")
|
|
self.assertEqual(validator.warnings, 1)
|
|
self.assertEqual(validator.errors, 1)
|
|
|
|
@mock.patch("check_init_priorities.Validator.__init__", return_value=None)
|
|
def test_check_swapped(self, mock_vinit):
|
|
validator = check_init_priorities.Validator("", "", None)
|
|
validator.log = mock.Mock()
|
|
validator.warnings = 0
|
|
validator.errors = 0
|
|
|
|
save_inverted_priorities = check_init_priorities._INVERTED_PRIORITY_COMPATIBLES
|
|
|
|
check_init_priorities._INVERTED_PRIORITY_COMPATIBLES = set([("compat-3", "compat-1")])
|
|
|
|
validator._ord2node = {1: mock.Mock(), 3: mock.Mock()}
|
|
validator._ord2node[1]._binding.compatible = "compat-1"
|
|
validator._ord2node[1].path = "/1"
|
|
validator._ord2node[3]._binding.compatible = "compat-3"
|
|
validator._ord2node[3].path = "/3"
|
|
|
|
validator._dev_priorities = {1: 20, 3: 10}
|
|
|
|
validator._check_dep(3, 1)
|
|
|
|
self.assertListEqual(validator.log.info.call_args_list, [
|
|
mock.call("Swapped priority: compat-3, compat-1"),
|
|
mock.call("/3 20 > /1 10"),
|
|
])
|
|
self.assertEqual(validator.warnings, 0)
|
|
self.assertEqual(validator.errors, 0)
|
|
|
|
check_init_priorities._INVERTED_PRIORITY_COMPATIBLES = save_inverted_priorities
|
|
|
|
@mock.patch("check_init_priorities.Validator.__init__", return_value=None)
|
|
def test_check_ignored(self, mock_vinit):
|
|
validator = check_init_priorities.Validator("", "", None)
|
|
validator.log = mock.Mock()
|
|
validator.warnings = 0
|
|
validator.errors = 0
|
|
|
|
save_ignore_compatibles = check_init_priorities._IGNORE_COMPATIBLES
|
|
|
|
check_init_priorities._IGNORE_COMPATIBLES = set(["compat-3"])
|
|
|
|
validator._ord2node = {1: mock.Mock(), 3: mock.Mock()}
|
|
validator._ord2node[1]._binding.compatible = "compat-1"
|
|
validator._ord2node[1].path = "/1"
|
|
validator._ord2node[3]._binding.compatible = "compat-3"
|
|
validator._ord2node[3].path = "/3"
|
|
|
|
validator._dev_priorities = {1: 20, 3: 10}
|
|
|
|
validator._check_dep(3, 1)
|
|
|
|
self.assertListEqual(validator.log.info.call_args_list, [
|
|
mock.call("Ignoring priority: compat-3"),
|
|
])
|
|
self.assertEqual(validator.warnings, 0)
|
|
self.assertEqual(validator.errors, 0)
|
|
|
|
check_init_priorities._IGNORE_COMPATIBLES = save_ignore_compatibles
|
|
|
|
@mock.patch("check_init_priorities.Validator._check_dep")
|
|
@mock.patch("check_init_priorities.Validator.__init__", return_value=None)
|
|
def test_check_edt_r(self, mock_vinit, mock_cd):
|
|
validator = check_init_priorities.Validator("", "", None)
|
|
|
|
d0 = mock.Mock()
|
|
d0.dep_ordinal = 1
|
|
d1 = mock.Mock()
|
|
d1.dep_ordinal = 2
|
|
|
|
c0 = mock.Mock()
|
|
c0.props = {"compatible": "c"}
|
|
c1 = mock.Mock()
|
|
c1.props = {}
|
|
c1._binding.path = "another-binding-path.yaml"
|
|
c2 = mock.Mock()
|
|
c2.props = {}
|
|
c2._binding.path = "binding-path.yaml"
|
|
c2._binding.child_binding = None
|
|
c2.depends_on = [d1]
|
|
|
|
dev = mock.Mock()
|
|
dev.depends_on = [d0]
|
|
dev._binding.child_binding = "child-binding"
|
|
dev._binding.path = "binding-path.yaml"
|
|
dev.children.values.return_value = [c0, c1, c2]
|
|
|
|
validator._check_edt_r(0, dev)
|
|
|
|
self.assertListEqual(mock_cd.call_args_list, [
|
|
mock.call(0, 1),
|
|
mock.call(0, 2),
|
|
])
|
|
|
|
@mock.patch("check_init_priorities.Validator._check_edt_r")
|
|
@mock.patch("check_init_priorities.Validator.__init__", return_value=None)
|
|
def test_check_edt(self, mock_vinit, mock_cer):
|
|
validator = check_init_priorities.Validator("", "", None)
|
|
validator._ord2node = {1: mock.Mock(), 2: mock.Mock(), 3: mock.Mock()}
|
|
validator._dev_priorities = {1: 10, 2: 10, 3: 20}
|
|
|
|
validator.check_edt()
|
|
|
|
self.assertListEqual(mock_cer.call_args_list, [
|
|
mock.call(1, validator._ord2node[1]),
|
|
mock.call(2, validator._ord2node[2]),
|
|
mock.call(3, validator._ord2node[3]),
|
|
])
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|