UnityConfigurationGuide.md 16.4 KB
Newer Older
T
toby 已提交
1 2 3
# Unity Configuration Guide

## C Standards, Compilers and Microcontrollers
4

T
toby 已提交
5
The embedded software world contains its challenges. Compilers support different
6 7 8
revisions of the C Standard. They ignore requirements in places, sometimes to
make the language more usable in some special regard. Sometimes it's to simplify
their support. Sometimes it's due to specific quirks of the microcontroller they
T
toby 已提交
9 10
are targeting. Simulators add another dimension to this menagerie.

11 12 13 14
Unity is designed to run on almost anything that is targeted by a C compiler. It
would be awesome if this could be done with zero configuration. While there are
some targets that come close to this dream, it is sadly not universal. It is
likely that you are going to need at least a couple of the configuration options
T
toby 已提交
15 16
described in this document.

17 18 19 20 21 22
All of Unity's configuration options are `#defines`. Most of these are simple
definitions. A couple are macros with arguments. They live inside the
unity_internals.h header file. We don't necessarily recommend opening that file
unless you really need to. That file is proof that a cross-platform library is
challenging to build. From a more positive perspective, it is also proof that a
great deal of complexity can be centralized primarily to one place in order to
T
toby 已提交
23 24
provide a more consistent and simple experience elsewhere.

25 26 27 28 29

### Using These Options

It doesn't matter if you're using a target-specific compiler and a simulator or
a native compiler. In either case, you've got a couple choices for configuring
T
toby 已提交
30 31
these options:

32 33 34 35 36 37 38 39
1. Because these options are specified via C defines, you can pass most of these
options to your compiler through command line compiler flags. Even if you're
using an embedded target that forces you to use their overbearing IDE for all
configuration, there will be a place somewhere in your project to configure
defines for your compiler.
2. You can create a custom `unity_config.h` configuration file (present in your
toolchain's search paths). In this file, you will list definitions and macros
specific to your target. All you must do is define `UNITY_INCLUDE_CONFIG_H` and
T
toby 已提交
40 41
Unity will rely on `unity_config.h` for any further definitions it may need.

42

T
toby 已提交
43 44 45
## The Options

### Integer Types
46 47 48 49 50 51 52 53 54

If you've been a C developer for long, you probably already know that C's
concept of an integer varies from target to target. The C Standard has rules
about the `int` matching the register size of the target microprocessor. It has
rules about the `int` and how its size relates to other integer types. An `int`
on one target might be 16 bits while on another target it might be 64. There are
more specific types in compilers compliant with C99 or later, but that's
certainly not every compiler you are likely to encounter. Therefore, Unity has a
number of features for helping to adjust itself to match your required integer
T
toby 已提交
55 56
sizes. It starts off by trying to do it automatically.

57

T
toby 已提交
58
##### `UNITY_EXCLUDE_STDINT_H`
59 60 61 62 63 64 65

The first thing that Unity does to guess your types is check `stdint.h`.
This file includes defines like `UINT_MAX` that Unity can make use of to
learn a lot about your system. It's possible you don't want it to do this
(um. why not?) or (more likely) it's possible that your system doesn't
support `stdint.h`. If that's the case, you're going to want to define this.
That way, Unity will know to skip the inclusion of this file and you won't
T
toby 已提交
66 67 68 69 70
be left with a compiler error.

_Example:_
        #define UNITY_EXCLUDE_STDINT_H

71

T
toby 已提交
72
##### `UNITY_EXCLUDE_LIMITS_H`
73 74 75

The second attempt to guess your types is to check `limits.h`. Some compilers
that don't support `stdint.h` could include `limits.h` instead. If you don't
T
toby 已提交
76 77 78 79 80
want Unity to check this file either, define this to make it skip the inclusion.

_Example:_
        #define UNITY_EXCLUDE_LIMITS_H

81

T
toby 已提交
82
##### `UNITY_EXCLUDE_SIZEOF`
83 84

The third and final attempt to guess your types is to use the `sizeof()`
T
toby 已提交
85
operator. Even if the first two options don't work, this one covers most cases.
86 87
There _is_ a rare compiler or two out there that doesn't support sizeof() in the
preprocessing stage, though. For these, you have the ability to disable this
T
toby 已提交
88 89 90 91 92
feature as well.

_Example:_
        #define UNITY_EXCLUDE_SIZEOF

93 94 95
If you've disabled all of the automatic options above, you're going to have to
do the configuration yourself. Don't worry. Even this isn't too bad... there are
just a handful of defines that you are going to specify if you don't like the
T
toby 已提交
96 97
defaults.

98

T
toby 已提交
99
##### `UNITY_INT_WIDTH`
100 101

Define this to be the number of bits an `int` takes up on your system. The
T
toby 已提交
102 103 104 105 106
default, if not autodetected, is 32 bits.

_Example:_
        #define UNITY_INT_WIDTH 16

107

T
toby 已提交
108
##### `UNITY_LONG_WIDTH`
109 110 111 112 113

Define this to be the number of bits a `long` takes up on your system. The
default, if not autodetected, is 32 bits. This is used to figure out what kind
of 64-bit support your system can handle. Does it need to specify a `long` or a
`long long` to get a 64-bit value. On 16-bit systems, this option is going to be
T
toby 已提交
114 115 116 117 118
ignored.

_Example:_
        #define UNITY_LONG_WIDTH 16

119

T
toby 已提交
120
##### `UNITY_POINTER_WIDTH`
121 122 123

Define this to be the number of bits a pointer takes up on your system. The
default, if not autodetected, is 32-bits. If you're getting ugly compiler
T
toby 已提交
124 125 126 127 128
warnings about casting from pointers, this is the one to look at.

_Example:_
        #define UNITY_POINTER_WIDTH 64

129

T
toby 已提交
130
##### `UNITY_INCLUDE_64`
131 132 133 134 135

Unity will automatically include 64-bit support if it auto-detects it, or if
your `int`, `long`, or pointer widths are greater than 32-bits. Define this to
enable 64-bit support if none of the other options already did it for you. There
can be a significant size and speed impact to enabling 64-bit support on small
T
toby 已提交
136 137 138 139 140
targets, so don't define it if you don't need it.

_Example:_
        #define UNITY_INCLUDE_64

141 142 143 144 145 146 147 148

### Floating Point Types

In the embedded world, it's not uncommon for targets to have no support for
floating point operations at all or to have support that is limited to only
single precision. We are able to guess integer sizes on the fly because integers
are always available in at least one size. Floating point, on the other hand, is
sometimes not available at all. Trying to include `float.h` on these platforms
T
toby 已提交
149 150
would result in an error. This leaves manual configuration as the only option.

151

T
toby 已提交
152
##### `UNITY_INCLUDE_FLOAT`
153

T
toby 已提交
154
##### `UNITY_EXCLUDE_FLOAT`
155

T
toby 已提交
156
##### `UNITY_INCLUDE_DOUBLE`
157

T
toby 已提交
158
##### `UNITY_EXCLUDE_DOUBLE`
159 160 161 162 163

By default, Unity guesses that you will want single precision floating point
support, but not double precision. It's easy to change either of these using the
include and exclude options here. You may include neither, either, or both, as
suits your needs. For features that are enabled, the following floating point
T
toby 已提交
164 165 166 167 168 169 170 171
options also become available.

_Example:_

        //what manner of strange processor is this?
        #define UNITY_EXCLUDE_FLOAT
        #define UNITY_INCLUDE_DOUBLE

172

T
toby 已提交
173
##### `UNITY_FLOAT_VERBOSE`
174

T
toby 已提交
175
##### `UNITY_DOUBLE_VERBOSE`
176 177 178 179 180 181 182 183 184 185 186

Unity aims for as small of a footprint as possible and avoids most standard
library calls (some embedded platforms don't have a standard library!). Because
of this, its routines for printing integer values are minimalist and hand-coded.
To keep Unity universal, though, we chose to _not_ develop our own floating
point print routines. Instead, the display of floating point values during a
failure are optional. By default, Unity will not print the actual results of
floating point assertion failure. So a failed assertion will produce a message
like `"Values Not Within Delta"`. If you would like verbose failure messages for
floating point assertions, use these options to give more explicit failure
messages (e.g. `"Expected 4.56 Was 4.68"`). Note that this feature requires the
T
toby 已提交
187 188 189 190 191
use of `sprintf` so might not be desirable in all cases.

_Example:_
        #define UNITY_DOUBLE_VERBOSE

192

T
toby 已提交
193
##### `UNITY_FLOAT_TYPE`
194 195 196

If enabled, Unity assumes you want your `FLOAT` asserts to compare standard C
floats. If your compiler supports a specialty floating point type, you can
T
toby 已提交
197 198 199 200 201
always override this behavior by using this definition.

_Example:_
        #define UNITY_FLOAT_TYPE float16_t

202

T
toby 已提交
203
##### `UNITY_DOUBLE_TYPE`
204 205 206 207 208

If enabled, Unity assumes you want your `DOUBLE` asserts to compare standard C
doubles. If you would like to change this, you can specify something else by
using this option. For example, defining `UNITY_DOUBLE_TYPE` to `long double`
could enable gargantuan floating point types on your 64-bit processor instead of
T
toby 已提交
209 210 211 212 213
the standard `double`.

_Example:_
        #define UNITY_DOUBLE_TYPE long double

214

T
toby 已提交
215
##### `UNITY_FLOAT_PRECISION`
216

T
toby 已提交
217
##### `UNITY_DOUBLE_PRECISION`
218 219 220 221 222 223 224 225 226 227

If you look up `UNITY_ASSERT_EQUAL_FLOAT` and `UNITY_ASSERT_EQUAL_DOUBLE` as
documented in the big daddy Unity Assertion Guide, you will learn that they are
not really asserting that two values are equal but rather that two values are
"close enough" to equal. "Close enough" is controlled by these precision
configuration options. If you are working with 32-bit floats and/or 64-bit
doubles (the normal on most processors), you should have no need to change these
options. They are both set to give you approximately 1 significant bit in either
direction. The float precision is 0.00001 while the double is 10-12.
For further details on how this works, see the appendix of the Unity Assertion
T
toby 已提交
228 229 230 231 232
Guide.

_Example:_
        #define UNITY_FLOAT_PRECISION 0.001f

233

T
toby 已提交
234
### Toolset Customization
235 236 237 238 239 240

In addition to the options listed above, there are a number of other options
which will come in handy to customize Unity's behavior for your specific
toolchain. It is possible that you may not need to touch any of these... but
certain platforms, particularly those running in simulators, may need to jump
through extra hoops to operate properly. These macros will help in those
T
toby 已提交
241 242
situations.

243

T
toby 已提交
244
##### `UNITY_OUTPUT_CHAR(a)`
245

T
toby 已提交
246
##### `UNITY_OUTPUT_FLUSH()`
247

T
toby 已提交
248
##### `UNITY_OUTPUT_START()`
249

T
toby 已提交
250
##### `UNITY_OUTPUT_COMPLETE()`
251 252 253 254 255 256 257 258 259

By default, Unity prints its results to `stdout` as it runs. This works
perfectly fine in most situations where you are using a native compiler for
testing. It works on some simulators as well so long as they have `stdout`
routed back to the command line. There are times, however, where the simulator
will lack support for dumping results or you will want to route results
elsewhere for other reasons. In these cases, you should define the
`UNITY_OUTPUT_CHAR` macro. This macro accepts a single character at a time (as
an `int`, since this is the parameter type of the standard C `putchar` function
T
toby 已提交
260 261 262
most commonly used). You may replace this with whatever function call you like.

_Example:_
263 264
Say you are forced to run your test suite on an embedded processor with no
`stdout` option. You decide to route your test result output to a custom serial
T
toby 已提交
265 266 267 268 269 270 271 272
`RS232_putc()` function you wrote like thus:

        #define UNITY_OUTPUT_CHAR(a) RS232_putc(a)
        #define UNITY_OUTPUT_START() RS232_config(115200,1,8,0)
        #define UNITY_OUTPUT_FLUSH() RS232_flush()
        #define UNITY_OUTPUT_COMPLETE() RS232_close()

_Note:_
273 274 275 276
`UNITY_OUTPUT_FLUSH()` can be set to the standard out flush function simply by
specifying `UNITY_USE_FLUSH_STDOUT`. No other defines are required. If you
specify a custom flush function instead with `UNITY_OUTPUT_FLUSH` directly, it
will declare an instance of your function by default. If you want to disable
T
toby 已提交
277 278
this behavior, add `UNITY_OMIT_OUTPUT_FLUSH_HEADER_DECLARATION`.

279

T
toby 已提交
280
##### `UNITY_SUPPORT_WEAK`
281 282 283 284 285 286 287 288 289 290 291 292 293

For some targets, Unity can make the otherwise required `setUp()` and
`tearDown()` functions optional. This is a nice convenience for test writers
since `setUp` and `tearDown` don't often actually _do_ anything. If you're using
gcc or clang, this option is automatically defined for you. Other compilers can
also support this behavior, if they support a C feature called weak functions. A
weak function is a function that is compiled into your executable _unless_ a
non-weak version of the same function is defined elsewhere. If a non-weak
version is found, the weak version is ignored as if it never existed. If your
compiler supports this feature, you can let Unity know by defining
`UNITY_SUPPORT_WEAK` as the function attributes that would need to be applied to
identify a function as weak. If your compiler lacks support for weak functions,
you will always need to define `setUp` and `tearDown` functions (though they can
T
toby 已提交
294 295 296 297 298 299
be and often will be just empty). The most common options for this feature are:

_Example:_
        #define UNITY_SUPPORT_WEAK weak
        #define UNITY_SUPPORT_WEAK __attribute__((weak))

300

T
toby 已提交
301
##### `UNITY_PTR_ATTRIBUTE`
302 303 304

Some compilers require a custom attribute to be assigned to pointers, like
`near` or `far`. In these cases, you can give Unity a safe default for these by
T
toby 已提交
305 306 307 308 309 310
defining this option with the attribute you would like.

_Example:_
        #define UNITY_PTR_ATTRIBUTE __attribute__((far))
        #define UNITY_PTR_ATTRIBUTE near

311

T
toby 已提交
312
## Getting Into The Guts
313 314 315 316 317 318 319 320 321

There will be cases where the options above aren't quite going to get everything
perfect. They are likely sufficient for any situation where you are compiling
and executing your tests with a native toolchain (e.g. clang on Mac). These
options may even get you through the majority of cases encountered in working
with a target simulator run from your local command line. But especially if you
must run your test suite on your target hardware, your Unity configuration will
require special help. This special help will usually reside in one of two
places: the `main()` function or the `RUN_TEST` macro. Let's look at how these
T
toby 已提交
322 323
work.

324

T
toby 已提交
325
##### `main()`
326 327 328 329 330 331

Each test module is compiled and run on its own, separate from the other test
files in your project. Each test file, therefore, has a `main` function. This
`main` function will need to contain whatever code is necessary to initialize
your system to a workable state. This is particularly true for situations where
you must set up a memory map or initialize a communication channel for the
T
toby 已提交
332 333 334 335
output of your test results.

A simple main function looks something like this:

336 337 338 339 340 341
        int main(void) {
            UNITY_BEGIN();
            RUN_TEST(test_TheFirst);
            RUN_TEST(test_TheSecond);
            RUN_TEST(test_TheThird);
            return UNITY_END();
T
toby 已提交
342 343
        }

344 345 346 347
You can see that our main function doesn't bother taking any arguments. For our
most barebones case, we'll never have arguments because we just run all the
tests each time. Instead, we start by calling `UNITY_BEGIN`. We run each test
(in whatever order we wish). Finally, we call `UNITY_END`, returning its return
T
toby 已提交
348 349
value (which is the total number of failures).

350 351 352
It should be easy to see that you can add code before any test cases are run or
after all the test cases have completed. This allows you to do any needed
system-wide setup or teardown that might be required for your special
T
toby 已提交
353 354
circumstances.

355

T
toby 已提交
356
##### `RUN_TEST`
357 358 359 360 361 362

The `RUN_TEST` macro is called with each test case function. Its job is to
perform whatever setup and teardown is necessary for executing a single test
case function. This includes catching failures, calling the test module's
`setUp()` and `tearDown()` functions, and calling `UnityConcludeTest()`. If
using CMock or test coverage, there will be additional stubs in use here. A
T
toby 已提交
363 364 365 366 367 368 369 370 371 372 373 374
simple minimalist RUN_TEST macro looks something like this:

        #define RUN_TEST(testfunc) \
            UNITY_NEW_TEST(#testfunc) \
            if (TEST_PROTECT()) { \
                setUp(); \
                testfunc(); \
            } \
            if (TEST_PROTECT() && (!TEST_IS_IGNORED)) \
                tearDown(); \
            UnityConcludeTest();

375 376 377 378 379 380
So that's quite a macro, huh? It gives you a glimpse of what kind of stuff Unity
has to deal with for every single test case. For each test case, we declare that
it is a new test. Then we run `setUp` and our test function. These are run
within a `TEST_PROTECT` block, the function of which is to handle failures that
occur during the test. Then, assuming our test is still running and hasn't been
ignored, we run `tearDown`. No matter what, our last step is to conclude this
T
toby 已提交
381 382
test before moving on to the next.

383 384 385 386 387
Let's say you need to add a call to `fsync` to force all of your output data to
flush to a file after each test. You could easily insert this after your
`UnityConcludeTest` call. Maybe you want to write an xml tag before and after
each result set. Again, you could do this by adding lines to this macro. Updates
to this macro are for the occasions when you need an action before or after
T
toby 已提交
388 389
every single test case throughout your entire suite of tests.

390

T
toby 已提交
391
## Happy Porting
392 393 394

The defines and macros in this guide should help you port Unity to just about
any C target we can imagine. If you run into a snag or two, don't be afraid of
T
toby 已提交
395
asking for help on the forums. We love a good challenge!