xref: /illumos-gate/usr/src/test/header-tests/tests/common/README.md (revision e1e6b944360d951edf36ef4198261818ed2d9b2f)
1# tests/common - C and C++ symbol visibility test program
2
3## Overview
4
5This directory contains the source for the symbol visibility test program:
6
7- `symbol_test.py` - test driver for C and C++ (supports parallel compilation)
8- `test_parse_env_cfg.py` - unit test for environment config parser
9- `test_parse_sym_cfg.py` - unit test for symbols config parser
10- `test_gen_probe.py` - unit test for test/probe program generation
11
12The `symbol_test.py` program:
13- reads an `environment config` file
14- reads a `symbols config` file
15- runs short compiler jobs for each combination of environement and symbol,
16  verifying that it exists or does not exist as indicated by the data from
17  the `symbols config` file.
18- generates include-only tests where needed to ensure the primary header has
19  at least one expected-success compilation in each environment selected for
20  positive coverage.
21
22The first header named by a symbols configuration is its primary header.  The
23first header of later entries is expected to be the same.  Additional headers
24after the first one in an entry are supporting headers and do not affect
25positive coverage.  Multiple symbols configuration files may be supplied;
26they are effectively concatenated and must have the same primary header.
27
28The config file format is documented in `../cfg/README`,
29`../cfg/c-symbols/README`, and `../cfg/cxx-symbols/README`.
30
31## Program Operation
32
33- Compiler discovery: tries `g++` then `clang++`, or accepts `-c compiler`.
34- C++ include path setup: queries the compiler for its internal include
35  directory and constructs the `-isystem` paths needed to find C++ standard
36  headers without picking up GCC's fixincludes copies of system headers.
37
38## Probe program generation
39
40For each test entry, the program generates a minimal C or C++ program.
41For notes on "probe" program generation, see `test_gen_probe.py`
42
43#### `func` - function call test
44
45Config line:
46```
47func | log | double | double | math.h | C99+
48```
49Generated program (C):
50```c
51#include <math.h>
52double
53test_func(double a0)
54{
55	return log(a0);
56}
57```
58
59In the C++ program, the return value uses a `RESULT()` macro that selects
60brace-initialisation (C++11 and later) or plain assignment (C++98):
61```cpp
62#if __cplusplus >= 201103L
63#define RESULT(v) result{v}
64#else
65#define RESULT(v) result = (v)
66#endif
67double
68test_func(double a0)
69{
70	double RESULT(log(a0));
71	return result;
72}
73```
74Brace-initialisation prohibits narrowing conversions, so a missing `float`
75or `long double` overload that would silently promote through `double` is
76caught as a compile error rather than a silent pass.  C++98 uses plain
77assignment since brace-init is a C++11 extension.
78Function pointer return types use plain `return` in the program since
79brace-init does not compose with declarator syntax.
80
81#### `type` - type existence test
82
83Config line:
84```
85type | size_t | stddef.h | C11+
86```
87Generated program:
88```c
89#include <stddef.h>
90size_t test_type;
91```
92
93#### `value` - constant/variable access test
94
95Config line:
96```
97value | M_PI | double | math.h | C99+
98```
99Generated program:
100```c
101#include <math.h>
102double test_value;
103void
104test_func(void)
105{
106	test_value = M_PI;
107}
108```
109
110#### `define` - preprocessor macro test
111
112Config line:
113```
114define | INFINITY | | math.h | C99+
115```
116Generated program:
117```c
118#include <math.h>
119#if !defined(INFINITY)
120#error INFINITY is not defined or has the wrong value
121#endif
122```
123An optional value field checks strict equality:
124```
125define | FLT_RADIX | 2 | float.h | C99+
126```
127```c
128#include <float.h>
129#if !defined(FLT_RADIX) || FLT_RADIX != 2
130#error FLT_RADIX is not defined or has the wrong value
131#endif
132```
133
134## Command-line options
135
136### Usage
137
138    python3 symbol_test.py --lang c|c++ -m64|-m32 [options] env_cfg sym_cfg...
139
140Required arguments:
141
142    --lang c|c++   Language to test
143    -m64 | -m32    Target ABI
144
145Options:
146
147    -C          Check compiler only, do not run tests
148    -f          Force: continue after failures
149    -d          Debug: print probe and compiler output on failures
150    -D          Extra debug: also print the compiler command and probe
151                program for every test, not just failures (implies -d)
152    -c compiler Use the specified compiler instead of auto-detecting
153    -s sym      Run only the test for the named symbol
154    -e ENV      Run only tests for the named environment
155    -j N        Number of parallel compile jobs (default: 4 or
156                the environment variable SYMBOL_TEST_JOBS)
157    --positive-coverage=NAME
158                Ensure that at least one expected-success test compiles the
159                primary header in every environment named by NAME. Additional
160                include-only tests are generated where needed. By default,
161                all declared environments require positive coverage.
162    -R ROOT     Alternate root directory (e.g. a proto area) whose
163                ROOT/usr/include is tested instead of the default
164                (default: $HEADER_TEST_ROOT/usr/include if that
165                environment variable is set, else /usr/include)
166
167When running tests by hand (not via the `setup` script), you may
168pass `-f` to see all failures instead of stopping on errors.
169
170## Extending the tests
171
172To add tests for a new header:
173
1741. Add a new `.cfg` file in `../cfg/c-symbols/` or `../cfg/cxx-symbols/`.
1752. Add a wrapper script (hardlink or copy of `setup`) in the corresponding
176   `../c-symbols/` or `../cxx-symbols/` subdirectory, named after the cfg file
177   without `.cfg`.
1783. Add the new files to the `../cfg/Makefile` and the IPS manifest.
179
180To add a new compilation environment or group, edit
181`../cfg/c-symbols-env.cfg` or `../cfg/cxx-symbols-env.cfg`.
182
183## Developer Notes
184
185Unit tests for the Python components (`symbol_test.py`) live alongside the
186source in this directory.  They use canned string input and require no
187external files or build products.
188
189Run individual test modules from `tests/common/`:
190
191```
192python3 test_parse_env_cfg.py -v
193python3 test_parse_sym_cfg.py -v
194python3 test_gen_probe.py -v
195```
196
197Or run all unit tests at once from the repository root:
198
199```
200python3 -m unittest discover -s usr/src/test/header-tests/tests/common -p 'test_*.py' -v
201```
202