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 19The config file format is documented in `../cfg/README`, 20`../cfg/c-symbols/README`, and `../cfg/cxx-symbols/README`. 21 22## Program Operation 23 24- Compiler discovery: tries `g++` then `clang++`, or accepts `-c compiler`. 25- C++ include path setup: queries the compiler for its internal include 26 directory and constructs the `-isystem` paths needed to find C++ standard 27 headers without picking up GCC's fixincludes copies of system headers. 28 29## Probe program generation 30 31For each test entry, the program generates a minimal C or C++ program. 32For notes on "probe" program generation, see `test_gen_probe.py` 33 34#### `func` - function call test 35 36Config line: 37``` 38func | log | double | double | math.h | C99+ 39``` 40Generated program (C): 41```c 42#include <math.h> 43double 44test_func(double a0) 45{ 46 return log(a0); 47} 48``` 49 50In the C++ program, the return value uses a `RESULT()` macro that selects 51brace-initialisation (C++11 and later) or plain assignment (C++98): 52```cpp 53#if __cplusplus >= 201103L 54#define RESULT(v) result{v} 55#else 56#define RESULT(v) result = (v) 57#endif 58double 59test_func(double a0) 60{ 61 double RESULT(log(a0)); 62 return result; 63} 64``` 65Brace-initialisation prohibits narrowing conversions, so a missing `float` 66or `long double` overload that would silently promote through `double` is 67caught as a compile error rather than a silent pass. C++98 uses plain 68assignment since brace-init is a C++11 extension. 69Function pointer return types use plain `return` in the program since 70brace-init does not compose with declarator syntax. 71 72#### `type` - type existence test 73 74Config line: 75``` 76type | size_t | stddef.h | C11+ 77``` 78Generated program: 79```c 80#include <stddef.h> 81size_t test_type; 82``` 83 84#### `value` - constant/variable access test 85 86Config line: 87``` 88value | M_PI | double | math.h | C99+ 89``` 90Generated program: 91```c 92#include <math.h> 93double test_value; 94void 95test_func(void) 96{ 97 test_value = M_PI; 98} 99``` 100 101#### `define` - preprocessor macro test 102 103Config line: 104``` 105define | INFINITY | | math.h | C99+ 106``` 107Generated program: 108```c 109#include <math.h> 110#if !defined(INFINITY) 111#error INFINITY is not defined or has the wrong value 112#endif 113``` 114An optional value field checks strict equality: 115``` 116define | FLT_RADIX | 2 | float.h | C99+ 117``` 118```c 119#include <float.h> 120#if !defined(FLT_RADIX) || FLT_RADIX != 2 121#error FLT_RADIX is not defined or has the wrong value 122#endif 123``` 124 125## Command-line options 126 127### Usage 128 129 python3 symbol_test.py --lang c|c++ -m64|-m32 [options] env_cfg sym_cfg... 130 131Required arguments: 132 133 --lang c|c++ Language to test 134 -m64 | -m32 Target ABI 135 136Options: 137 138 -C Check compiler only, do not run tests 139 -f Force: continue after failures 140 -d Debug: print probe and compiler output on failures 141 -D Extra debug: also print the compiler command (implies -d) 142 -c compiler Use the specified compiler instead of auto-detecting 143 -s sym Run only the test for the named symbol 144 -e ENV Run only tests for the named environment 145 -j N Number of parallel compile jobs (default: 4 or 146 the environment variable SYMBOL_TEST_JOBS) 147 148When running tests by hand (not via the `setup` script), you may 149pass `-f` to see all failures instead of stopping on errors. 150 151## Extending the tests 152 153To add tests for a new header: 154 1551. Add a new `.cfg` file in `../cfg/c-symbols/` or `../cfg/cxx-symbols/`. 1562. Add a wrapper script (hardlink or copy of `setup`) in the corresponding 157 `../c-symbols/` or `../cxx-symbols/` subdirectory, named after the cfg file 158 without `.cfg`. 1593. Add the new files to the `../cfg/Makefile` and the IPS manifest. 160 161To add a new compilation environment or group, edit 162`../cfg/c-symbols-env.cfg` or `../cfg/cxx-symbols-env.cfg`. 163 164## Developer Notes 165 166Unit tests for the Python components (`symbol_test.py`) live alongside the 167source in this directory. They use canned string input and require no 168external files or build products. 169 170Run individual test modules from `tests/common/`: 171 172``` 173python3 test_parse_env_cfg.py -v 174python3 test_parse_sym_cfg.py -v 175python3 test_gen_probe.py -v 176``` 177 178Or run all unit tests at once from the repository root: 179 180``` 181python3 -m unittest discover -s usr/src/test/header-tests/tests/common -p 'test_*.py' -v 182``` 183