blob: 435fb28ff20955add2ebdd6324453fc7bf9909c6 [file] [log] [blame]
#!/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_")
self.assertEqual(prio1._level_priority, 312)
prio2 = check_init_priorities.Priority("noisenoise_POST_KERNEL99_")
self.assertEqual(prio2._level_priority, 399)
prio3 = check_init_priorities.Priority("_PRE_KERNEL_10_")
self.assertEqual(prio3._level_priority, 100)
prio4 = check_init_priorities.Priority("_PRE_KERNEL_110_")
self.assertEqual(prio4._level_priority, 110)
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_"),
check_init_priorities.Priority(".rel.z_init_EARLY1_"),
check_init_priorities.Priority(".rel.z_init_EARLY11_"),
check_init_priorities.Priority(".rel.z_init_PRE_KERNEL_10_"),
check_init_priorities.Priority(".rel.z_init_PRE_KERNEL_11_"),
check_init_priorities.Priority(".rel.z_init_PRE_KERNEL_111_"),
check_init_priorities.Priority(".rel.z_init_PRE_KERNEL_20_"),
check_init_priorities.Priority(".rel.z_init_PRE_KERNEL_21_"),
check_init_priorities.Priority(".rel.z_init_PRE_KERNEL_211_"),
check_init_priorities.Priority(".rel.z_init_POST_KERNEL0_"),
check_init_priorities.Priority(".rel.z_init_POST_KERNEL1_"),
check_init_priorities.Priority(".rel.z_init_POST_KERNEL11_"),
check_init_priorities.Priority(".rel.z_init_APPLICATION0_"),
check_init_priorities.Priority(".rel.z_init_APPLICATION1_"),
check_init_priorities.Priority(".rel.z_init_APPLICATION11_"),
check_init_priorities.Priority(".rel.z_init_SMP0_"),
check_init_priorities.Priority(".rel.z_init_SMP1_"),
check_init_priorities.Priority(".rel.z_init_SMP11_"),
]
self.assertListEqual(prios, sorted(prios))
def test_priority_strings(self):
prio = check_init_priorities.Priority(".rel.z_init_POST_KERNEL12_")
self.assertEqual(str(prio), "POST_KERNEL 12")
self.assertEqual(repr(prio), "<Priority POST_KERNEL 12>")
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_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", None)
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):
validator = check_init_priorities.Validator("", "", None)
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
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"),
])
@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()