summaryrefslogtreecommitdiff
path: root/docs/ztest.md
blob: 2cb552e1701bb7d3442c08c77c92dddfa6f8d012 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
# Porting EC unit tests to Ztest

[TOC]

This HOWTO shows the process for porting the EC's `base32` unit test to
Zephyr's Ztest framework. All of the work is done in `src/platform/ec`.

See [Test Framework - Zephyr Project Documentation](https://docs.zephyrproject.org/1.12.0/subsystems/test/ztest.html#quick-start-unit-testing) for details about Zephyr's Ztest framework.

See [chromium:2492527](https://crrev.com/c/2492527) for an example of
porting an EC unit test to the Ztest API.

## Determine source files being tested

Determine which C files the unit test requires by finding the test in
`test/test_config.h`:
```
#ifdef TEST_BASE32
#define CONFIG_BASE32
#endif
```
Locate the `CONFIG` item(s) in `common/build.mk`:
```
common-$(CONFIG_BASE32)+=base32.o
```
So for the `base32` test, we only need to shim `common/base32.c`.

Add the C files to `zephyr/shim/CMakeLists.txt`, in the "Shimmed modules"
section:

```
# Shimmed modules
zephyr_sources_ifdef(CONFIG_PLATFORM_EC "${PLATFORM_EC}/common/base32.c")
```

Refer to [zephyr: shim in base32.c](https://crrev.com/c/2468631).

## Create test directory

Create a new directory for the unit test in `zephyr/test/base32`.

Create `zephyr/test/base32/prj.conf` with these contents:
```
CONFIG_ZTEST=y
CONFIG_PLATFORM_EC=y
```

Create `zephyr/test/base32/CMakeLists.txt` with these contents:
```
cmake_minimum_required(VERSION 3.13.1)
project(base32)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})

target_sources(app PRIVATE ${PLATFORM_EC}/test/base32.c)
```

### Modify test source code

In the unit test, wrap `run_test` in the `#else` portion of an
`#ifdef CONFIG_ZEPHYR`. Create `test_main` in the `#ifdef` portion.

Copy the contents of `run_test` into `test_main`. You will need to keep the
list of test cases in sync between the two functions.

Change `RUN_TEST` to `ztest_unit_test` and add the `ztest_test_suite` wrapper
plus the call to `ztest_run_test_suite`.

```
/*
 * Define the test cases to run. We need to do this twice, once in the format
 * that Ztest uses, and again in the format the the EC test framework uses.
 * If you add a test to one of them, make sure to add it to the other.
 */
#ifdef CONFIG_ZEPHYR
void test_main(void)
{
	ztest_test_suite(test_base32_lib,
			 ztest_unit_test(test_crc5),
			 ztest_unit_test(test_encode),
			 ztest_unit_test(test_decode));
	ztest_run_test_suite(test_base32_lib);
}
#else
void run_test(int argc, char **argv)
{
	test_reset();

	RUN_TEST(test_crc5);
	RUN_TEST(test_encode);
	RUN_TEST(test_decode);

	test_print_result();
}
#endif /* CONFIG_ZEPHYR */
```

Each function that is called by `ztest_unit_test` needs to change its
return type to `EC_TEST_RETURN`. Keep the `return EC_SUCCESS;` at the end
of the test function. If there are any `return` statements that return
something other than `EC_SUCCESS`, you should use `ztest_test_fail` inside
another `ifdef CONFIG_ZEPHYR` block.

Change the `TEST_ASSERT` macros to `zassert` macros. There are plans to
automate this process, but for now, it's a manual process involving some
intelligent find-and-replace.

* `TEST_ASSERT(n)` to `zassert_true(n, NULL)`
* `TEST_EQ(a, b, fmt)` to `zassert_equal(a, b, fmt ## ", " ## fmt, a, b)`
  * e.g. `TEST_EQ(a, b, "%d")` becomes `zassert_equal(a, b, "%d, %d", a, b)`
* `TEST_NE(a, b, fmt)` to `zassert_not_equal(a, b, fmt ## ", " ## fmt, a, b)`
* `TEST_LT(a, b, fmt)` to `zassert_true(a < b, fmt ## ", " ## fmt, a, b)`
* `TEST_LE(a, b, fmt)` to `zassert_true(a <= b, fmt ## ", " ## fmt, a, b)`
* `TEST_GT(a, b, fmt)` to `zassert_true(a > b, fmt ## ", " ## fmt, a, b)`
* `TEST_GE(a, b, fmt)` tp `zassert_true(a >= b, fmt ## ", " ## fmt, a, b)`
* `TEST_BITS_SET(a, bits)` to `zassert_true(a & (int)bits == (int)bits, "%u, %u", a & (int)bits, (int)bits)`
* `TEST_BITS_CLEARED(a, bits)` to `zassert_true(a & (int)bits == 0, "%u, 0", a & (int)bits)`
* `TEST_ASSERT_ARRAY_EQ(s, d, n)` to `zassert_mem_equal(s, d, b, NULL)`
* `TEST_CHECK(n)` to `zassert_true(n, NULL)`
* `TEST_NEAR(a, b, epsilon, fmt)` to `zassert_true(fabs(a-b) < epsilon, "%f, %f, %f", a, b, epsilon)`
  * Currently, every usage of `TEST_NEAR` involves floating point values
* `TEST_ASSERT_ABS_LESS(n, t)` to `zassert_true(abs(n) < t, "%d, %d", n, t)`
  * Currently, every usage of `TEST_ASSERT_ANS_LESS` involves signed integers.

There isn't a good replacement for `TEST_ASSERT_MEMSET(d, c, n)`, but it is
only used in two tests, `printf.c` and `utils.c`. If you need this test,
you'll need to code up a loop over the `n` bytes starting at `d`, and
`zassert_equal` that each byte is equal to `c`.

Also note that some tests use constructs like `TEST_ASSERT(var == const)`,
which would have been better write as `TEST_EQ(var, const)`. These should be
rewritten to use `zassert_equal`.

Refer to
[test: Allow EC unit test to use Ztest API](https://crrev.com/c/2492527) for
the changes to the base32.c source code.

## Build and run

Use `cmake` and `ninja` to build the test:
```
(cr) $ export ZEPHYR_BASE=/mnt/host/source/src/third_party/zephyr/main/v2.4
(cr) $ cd /mnt/host/source/src/platform/ec
(cr) $ cmake -S zephyr/test/base32 -B build/base32 \
 -D ZEPHYR_MODULES=/mnt/host/source/src/platform/ec \
 -D ZEPHYR_TOOLCHAIN_VARIANT=host -D BOARD=native_posix -G Ninja
(cr) $ ninja -C build/base32
(cr) $ build/base32/zephyr/zephyr.exe
UART_0 connected to pseudotty: /dev/pts/1
*** Booting Zephyr OS build zephyr-v2.4.0-1-g63b2330a85cd  ***
Running test suite test_base32_lib
===================================================================
START - test_crc5
 PASS - test_crc5
===================================================================
START - test_encode
 PASS - test_encode
===================================================================
START - test_decode
 PASS - test_decode
===================================================================
Test suite test_base32_lib succeeded
===================================================================
PROJECT EXECUTION SUCCESSFUL
(cr) $
```