xref: /xnu-11215/doc/debugging/macro_testing.md (revision 8d741a5d)
1# LLDB macro testing
2
3How to work with bundled unit test framework.
4
5Be careful when touching common framework code. For larger changes, ask the Platform Triage team to
6validate that the changes work in their environment before integration.
7
8Unit-test architecture supports two kinds of tests:
9
10- Standalone unit test \
11  `tools/lldbmacros/tests/standalone_tests`
12- LLDB based unit test \
13  `tools/lldbmacros/tests/lldb_tests`
14
15**Standalone** unit tests replace _lldb_ and _lldbwrap_ modules with _MagicMock_
16instances. All tests in this location must not depend on LLDB.
17
18**LLDB** unit tests are run from LLDB's python interpreter. It is possible to
19access debugger/process/target from such test or invoke LLDB commands. This
20way a test can exercise full stack including SBAPI and expression handlers.
21
22## How to run tests
23
24Standalone tests do not need LLDB and can be run with:
25```sh
26PYTHON=tools/lldbmacros python3 tools/lldbmacros/tests/runtest.py <kernel>
27```
28
29To run all tests (including LLDB based ones) a developer has to install
30XCode and configure properly Python's path:
31
32```sh
33PYTHONPATH="tools/lldbmacros:`xcrun --toolchain ios lldb -P`"xcrun --toolchain ios python3 tools/lldbmacros/tests/runtest.py <kernel>
34```
35
36Default runner supports few options:
37
38  * `-v` enables verbose output from unit test framework
39  * `-d` enables debug logging and more detailed exception reports
40  * `-c <path>` outputus HTML coverage if `coverage` module is installed
41
42## Mocking framework
43
44The goal of the mocking framework is to enhance existing mocking solutions
45rather than building completely new framework. A test should still rely on
46`unittest.mock` and cover specific needs with additional mocks provided by
47this framework.
48
49A test developer has three options how to handle mocking in a test:
50
51* `unittest.mock` that covers general purpose Python mocking.
52* `lldbmock.valuemock` designed to mock away `value` class instances.
53* `lldbmock.memorymock` designed to provide real object in target's memory.
54
55Examples of usage can be found in: \
56    `tools/lldbmacros/tests/lldb_tests/test_examples.py`
57
58### lldbmock.valuemock
59
60A very simple mocking designed for replacing a `value` class instance or
61some similar construct in the code.
62
63The `ValueMock` class parses given `SBType` and recreates recursively whole
64hierarchy of `MagicMock` instances. Final result looks like a value class but
65it does not implement any value class logic or methods.
66
67It does not perform any extra logic to handle special types like `union`.
68A developer has to correctly populate all members that overlap because this
69mock treats all such members as unique.
70
71Auto generating mock specification from kernel under test allows checking that
72all referenced members do exist in the final binary. Broken reference will
73result either in test or tested code failure.
74
75### lldbmock.memorymock
76
77The goal of memory mock is to provide easy to use interface for a test developer
78to describe object in target's memory. From technical perspective this is a data
79serializer that reflects memory location and representation of given SBType's
80members.
81
82The framework provides two kinds of mocks:
83
84  * `RawMock` that is suitable to place unstructured data into target's memory.
85  * `MemoryMock` that mirrors given `SBType` and serializes data into target's
86    memory.
87
88