#!/usr/bin/env python # Copyright 2023 The Pigweed Authors # # 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 # # https://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. """Emulator API tests.""" import unittest from typing import Any from pw_emu.core import ( ConfigError, InvalidChannelType, InvalidProperty, InvalidPropertyPath, ) from mock_emu_frontend import _mock_emu from config_helper import ConfigHelperWithEmulator class TestEmulator(ConfigHelperWithEmulator): """Test Emulator APIs.""" _config = { 'emulators': { 'mock-emu': { 'launcher': 'mock_emu_frontend.MockEmuLauncher', 'connector': 'mock_emu_frontend.MockEmuConnector', } }, 'mock-emu': { 'gdb_channel': True, }, 'gdb': _mock_emu + ['--exit', '--'], 'targets': {'test-target': {'mock-emu': {}}}, } def setUp(self) -> None: super().setUp() self._emu.start('test-target') def tearDown(self) -> None: self._emu.stop() super().tearDown() def test_gdb_target_remote(self) -> None: output = self._emu.run_gdb_cmds([]).stdout host, port = self._emu.get_channel_addr('gdb') self.assertTrue(f'{host}:{port}' in output.decode('utf-8')) def test_gdb_commands(self) -> None: output = self._emu.run_gdb_cmds(['test_gdb_cmd']).stdout self.assertTrue( output and '-ex test_gdb_cmd' in output.decode('utf-8'), output ) def test_gdb_executable(self) -> None: output = self._emu.run_gdb_cmds([], 'test_gdb_exec').stdout self.assertTrue('test_gdb_exec' in output.decode('utf-8')) def test_gdb_pause(self) -> None: output = self._emu.run_gdb_cmds([], pause=True).stdout self.assertTrue('-ex disconnect' in output.decode('utf-8')) # Minimal testing for APIs that are straight wrappers over Connector APIs. def test_running(self) -> None: self.assertTrue(self._emu.running()) def test_reset(self) -> None: self._emu.reset() def test_cont(self) -> None: self._emu.cont() def test_list_properties(self) -> None: with self.assertRaises(InvalidPropertyPath): self._emu.list_properties('invalid path') self.assertEqual(self._emu.list_properties('path1'), ['prop1']) def test_get_property(self) -> None: with self.assertRaises(InvalidProperty): self._emu.get_property('path1', 'invalid property') with self.assertRaises(InvalidPropertyPath): self._emu.get_property('invalid path', 'prop1') self.assertEqual(self._emu.get_property('path1', 'prop1'), 'val1') def test_set_property(self) -> None: with self.assertRaises(InvalidPropertyPath): self._emu.set_property('invalid path', 'prop1', 'test') with self.assertRaises(InvalidProperty): self._emu.set_property('path1', 'invalid property', 'test') self._emu.set_property('path1', 'prop1', 'val2') self.assertEqual(self._emu.get_property('path1', 'prop1'), 'val2') def test_get_channel_type(self) -> None: self.assertEqual(self._emu.get_channel_type('gdb'), 'tcp') def test_get_channel_path(self) -> None: with self.assertRaises(InvalidChannelType): self._emu.get_channel_path('gdb') def test_get_channel_addr(self) -> None: self.assertEqual(len(self._emu.get_channel_addr('gdb')), 2) def test_channel_stream(self) -> None: with self._emu.get_channel_stream('gdb') as _: pass class TestGdbEmptyConfig(ConfigHelperWithEmulator): """Check that ConfigError is raised when running gdb with an empty gdb config. """ _config: dict[str, Any] = { 'emulators': { 'mock-emu': { 'launcher': 'mock_emu_frontend.MockEmuLauncher', 'connector': 'mock_emu_frontend.MockEmuConnector', } }, 'targets': {'test-target': {'mock-emu': {}}}, } def setUp(self) -> None: super().setUp() self._emu.start('test-target') def tearDown(self) -> None: self._emu.stop() super().tearDown() def test_gdb_config_error(self) -> None: with self.assertRaises(ConfigError): self._emu.run_gdb_cmds([]) if __name__ == '__main__': unittest.main()