xref: /aosp_15_r20/external/pigweed/pw_emu/py/tests/frontend_test.py (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1#!/usr/bin/env python
2# Copyright 2023 The Pigweed Authors
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may not
5# use this file except in compliance with the License. You may obtain a copy of
6# the License at
7#
8#     https://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations under
14# the License.
15"""Emulator API tests."""
16
17import unittest
18
19from typing import Any
20
21from pw_emu.core import (
22    ConfigError,
23    InvalidChannelType,
24    InvalidProperty,
25    InvalidPropertyPath,
26)
27from mock_emu_frontend import _mock_emu
28from config_helper import ConfigHelperWithEmulator
29
30
31class TestEmulator(ConfigHelperWithEmulator):
32    """Test Emulator APIs."""
33
34    _config = {
35        'emulators': {
36            'mock-emu': {
37                'launcher': 'mock_emu_frontend.MockEmuLauncher',
38                'connector': 'mock_emu_frontend.MockEmuConnector',
39            }
40        },
41        'mock-emu': {
42            'gdb_channel': True,
43        },
44        'gdb': _mock_emu + ['--exit', '--'],
45        'targets': {'test-target': {'mock-emu': {}}},
46    }
47
48    def setUp(self) -> None:
49        super().setUp()
50        self._emu.start('test-target')
51
52    def tearDown(self) -> None:
53        self._emu.stop()
54        super().tearDown()
55
56    def test_gdb_target_remote(self) -> None:
57        output = self._emu.run_gdb_cmds([]).stdout
58        host, port = self._emu.get_channel_addr('gdb')
59        self.assertTrue(f'{host}:{port}' in output.decode('utf-8'))
60
61    def test_gdb_commands(self) -> None:
62        output = self._emu.run_gdb_cmds(['test_gdb_cmd']).stdout
63        self.assertTrue(
64            output and '-ex test_gdb_cmd' in output.decode('utf-8'), output
65        )
66
67    def test_gdb_executable(self) -> None:
68        output = self._emu.run_gdb_cmds([], 'test_gdb_exec').stdout
69        self.assertTrue('test_gdb_exec' in output.decode('utf-8'))
70
71    def test_gdb_pause(self) -> None:
72        output = self._emu.run_gdb_cmds([], pause=True).stdout
73        self.assertTrue('-ex disconnect' in output.decode('utf-8'))
74
75    # Minimal testing for APIs that are straight wrappers over Connector APIs.
76    def test_running(self) -> None:
77        self.assertTrue(self._emu.running())
78
79    def test_reset(self) -> None:
80        self._emu.reset()
81
82    def test_cont(self) -> None:
83        self._emu.cont()
84
85    def test_list_properties(self) -> None:
86        with self.assertRaises(InvalidPropertyPath):
87            self._emu.list_properties('invalid path')
88        self.assertEqual(self._emu.list_properties('path1'), ['prop1'])
89
90    def test_get_property(self) -> None:
91        with self.assertRaises(InvalidProperty):
92            self._emu.get_property('path1', 'invalid property')
93        with self.assertRaises(InvalidPropertyPath):
94            self._emu.get_property('invalid path', 'prop1')
95        self.assertEqual(self._emu.get_property('path1', 'prop1'), 'val1')
96
97    def test_set_property(self) -> None:
98        with self.assertRaises(InvalidPropertyPath):
99            self._emu.set_property('invalid path', 'prop1', 'test')
100        with self.assertRaises(InvalidProperty):
101            self._emu.set_property('path1', 'invalid property', 'test')
102        self._emu.set_property('path1', 'prop1', 'val2')
103        self.assertEqual(self._emu.get_property('path1', 'prop1'), 'val2')
104
105    def test_get_channel_type(self) -> None:
106        self.assertEqual(self._emu.get_channel_type('gdb'), 'tcp')
107
108    def test_get_channel_path(self) -> None:
109        with self.assertRaises(InvalidChannelType):
110            self._emu.get_channel_path('gdb')
111
112    def test_get_channel_addr(self) -> None:
113        self.assertEqual(len(self._emu.get_channel_addr('gdb')), 2)
114
115    def test_channel_stream(self) -> None:
116        with self._emu.get_channel_stream('gdb') as _:
117            pass
118
119
120class TestGdbEmptyConfig(ConfigHelperWithEmulator):
121    """Check that ConfigError is raised when running gdb with an empty
122    gdb config.
123
124    """
125
126    _config: dict[str, Any] = {
127        'emulators': {
128            'mock-emu': {
129                'launcher': 'mock_emu_frontend.MockEmuLauncher',
130                'connector': 'mock_emu_frontend.MockEmuConnector',
131            }
132        },
133        'targets': {'test-target': {'mock-emu': {}}},
134    }
135
136    def setUp(self) -> None:
137        super().setUp()
138        self._emu.start('test-target')
139
140    def tearDown(self) -> None:
141        self._emu.stop()
142        super().tearDown()
143
144    def test_gdb_config_error(self) -> None:
145        with self.assertRaises(ConfigError):
146            self._emu.run_gdb_cmds([])
147
148
149if __name__ == '__main__':
150    unittest.main()
151