1
0
mirror of https://github.com/ThrowTheSwitch/Unity.git synced 2026-01-23 08:25:58 +01:00

Merge branch 'master' into platform_matrix

This commit is contained in:
Mark VanderVoord
2023-11-08 00:16:40 -05:00
27 changed files with 794 additions and 112 deletions

1
.gitignore vendored
View File

@@ -2,6 +2,7 @@ build/
builddir/
test/sandbox
.DS_Store
examples/example_1/subprojects/unity
examples/example_1/test1.exe
examples/example_1/test2.exe
examples/example_2/all_tests.exe

View File

@@ -76,6 +76,7 @@ target_include_directories(${PROJECT_NAME}
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
$<BUILD_INTERFACE:$<$<BOOL:${UNITY_EXTENSION_MEMORY_ENABLED}>:${CMAKE_CURRENT_SOURCE_DIR}/extras/memory/src>>
$<BUILD_INTERFACE:$<$<BOOL:${UNITY_EXTENSION_FIXTURE_ENABLED}>:${CMAKE_CURRENT_SOURCE_DIR}/extras/fixture/src>>
)

View File

@@ -6,7 +6,7 @@ Welcome to the Unity Test Project, one of the main projects of ThrowTheSwitch.or
Unity Test is a unit testing framework built for C, with a focus on working with embedded toolchains.
This project is made to test code targetting microcontrollers big and small.
The core project is a single C file and a pair of headers, allowing it to the added to your existing build setup without too much headache.
The core project is a single C file and a pair of headers, allowing it to be added to your existing build setup without too much headache.
You may use any compiler you wish, and may use most existing build systems including Make, CMake, etc.
If you'd like to leave the hard work to us, you might be interested in Ceedling, a build tool also by ThrowTheSwitch.org.

15
auto/extract_version.py Executable file
View File

@@ -0,0 +1,15 @@
#!/usr/bin/env python3
import re
import sys
ver_re = re.compile(r"^#define\s+UNITY_VERSION_(?:MAJOR|MINOR|BUILD)\s+(\d+)$")
version = []
with open(sys.argv[1], "r") as f:
for line in f:
m = ver_re.match(line)
if m:
version.append(m.group(1))
print(".".join(version))

View File

@@ -132,8 +132,8 @@ class UnityTestRunnerGenerator
lines.each_with_index do |line, _index|
# find tests
next unless line =~ /^((?:\s*(?:TEST_CASE|TEST_RANGE)\s*\(.*?\)\s*)*)\s*void\s+((?:#{@options[:test_prefix]}).*)\s*\(\s*(.*)\s*\)/m
next unless line =~ /^((?:\s*(?:TEST_CASE|TEST_RANGE)\s*\(.*?\)\s*)*)\s*void\s+((?:#{@options[:test_prefix]})\w*)\s*\(\s*(.*)\s*\)/m
next unless line =~ /^((?:\s*(?:TEST_(?:CASE|RANGE|MATRIX))\s*\(.*?\)\s*)*)\s*void\s+((?:#{@options[:test_prefix]}).*)\s*\(\s*(.*)\s*\)/m
next unless line =~ /^((?:\s*(?:TEST_(?:CASE|RANGE|MATRIX))\s*\(.*?\)\s*)*)\s*void\s+((?:#{@options[:test_prefix]})\w*)\s*\(\s*(.*)\s*\)/m
arguments = Regexp.last_match(1)
name = Regexp.last_match(2)
@@ -143,14 +143,13 @@ class UnityTestRunnerGenerator
if @options[:use_param_tests] && !arguments.empty?
args = []
type_and_args = arguments.split(/TEST_(CASE|RANGE)/)
(1...type_and_args.length).step(2).each do |i|
if type_and_args[i] == 'CASE'
type_and_args = arguments.split(/TEST_(CASE|RANGE|MATRIX)/)
for i in (1...type_and_args.length).step(2)
case type_and_args[i]
when "CASE"
args << type_and_args[i + 1].sub(/^\s*\(\s*(.*?)\s*\)\s*$/m, '\1')
next
end
# RANGE
when "RANGE"
args += type_and_args[i + 1].scan(/(\[|<)\s*(-?\d+.?\d*)\s*,\s*(-?\d+.?\d*)\s*,\s*(-?\d+.?\d*)\s*(\]|>)/m).map do |arg_values_str|
exclude_end = arg_values_str[0] == '<' && arg_values_str[-1] == '>'
arg_values_str[1...-1].map do |arg_value_str|
@@ -163,6 +162,20 @@ class UnityTestRunnerGenerator
end.map do |arg_combinations|
arg_combinations.flatten.join(', ')
end
when "MATRIX"
single_arg_regex_string = /(?:(?:"(?:\\"|[^\\])*?")+|(?:'\\?.')+|(?:[^\s\]\["'\,]|\[[\d\S_-]+\])+)/.source
args_regex = /\[((?:\s*#{single_arg_regex_string}\s*,?)*(?:\s*#{single_arg_regex_string})?\s*)\]/m
arg_elements_regex = /\s*(#{single_arg_regex_string})\s*,\s*/m
args += type_and_args[i + 1].scan(args_regex).flatten.map do |arg_values_str|
(arg_values_str + ',').scan(arg_elements_regex)
end.reduce do |result, arg_range_expanded|
result.product(arg_range_expanded)
end.map do |arg_combinations|
arg_combinations.flatten.join(', ')
end
end
end
end
@@ -197,7 +210,7 @@ class UnityTestRunnerGenerator
{
local: source.scan(/^\s*#include\s+"\s*(.+\.#{@options[:include_extensions]})\s*"/).flatten,
system: source.scan(/^\s*#include\s+<\s*(.+)\s*>/).flatten.map { |inc| "<#{inc}>" },
linkonly: source.scan(/^TEST_FILE\(\s*"\s*(.+\.#{@options[:source_extensions]})\s*"/).flatten
linkonly: source.scan(/^TEST_SOURCE_FILE\(\s*\"\s*(.+\.#{@options[:source_extensions]})\s*\"/).flatten
}
end
@@ -388,7 +401,7 @@ class UnityTestRunnerGenerator
output.puts(' {')
output.puts(' if (parse_status < 0)')
output.puts(' {')
output.puts(" UnityPrint(\"#{filename.gsub('.c', '')}.\");")
output.puts(" UnityPrint(\"#{filename.gsub('.c', '').gsub(/\\/, '\\\\\\')}.\");")
output.puts(' UNITY_PRINT_EOL();')
tests.each do |test|
if (!@options[:use_param_tests]) || test[:args].nil? || test[:args].empty?

View File

@@ -10,46 +10,46 @@ Upon boolean False, an assertion stops execution and reports the failure.
and easily execute those assertions.
- The structure of Unity allows you to easily separate test assertions from
source code in, well, test code.
- Unity's assertions:
- Come in many, many flavors to handle different C types and assertion cases.
- Use context to provide detailed and helpful failure messages.
- Document types, expected values, and basic behavior in your source code for
- Unitys assertions:
- Come in many, many flavors to handle different C types and assertion cases.
- Use context to provide detailed and helpful failure messages.
- Document types, expected values, and basic behavior in your source code for
free.
### Unity Is Several Things But Mainly It's Assertions
### Unity Is Several Things But Mainly Its Assertions
One way to think of Unity is simply as a rich collection of assertions you can
use to establish whether your source code behaves the way you think it does.
Unity provides a framework to easily organize and execute those assertions in
test code separate from your source code.
### What's an Assertion?
### Whats an Assertion?
At their core, assertions are an establishment of truth - boolean truth. Was this
thing equal to that thing? Does that code doohickey have such-and-such property
or not? You get the idea. Assertions are executable code (to appreciate the big
picture on this read up on the difference between
[link:Dynamic Verification and Static Analysis]). A failing assertion stops
execution and reports an error through some appropriate I/O channel (e.g.
stdout, GUI, file, blinky light).
or not? You get the idea. Assertions are executable code. Static analysis is a
valuable approach to improving code quality, but it is not executing your code
in the way an assertion can. A failing assertion stops execution and reports an
error through some appropriate I/O channel (e.g. stdout, GUI, output file,
blinky light).
Fundamentally, for dynamic verification all you need is a single assertion
mechanism. In fact, that's what the [assert() macro][] in C's standard library
mechanism. In fact, thats what the [assert() macro][] in Cs standard library
is for. So why not just use it? Well, we can do far better in the reporting
department. C's `assert()` is pretty dumb as-is and is particularly poor for
department. Cs `assert()` is pretty dumb as-is and is particularly poor for
handling common data types like arrays, structs, etc. And, without some other
support, it's far too tempting to litter source code with C's `assert()`'s. It's
support, its far too tempting to litter source code with Cs `assert()`s. Its
generally much cleaner, manageable, and more useful to separate test and source
code in the way Unity facilitates.
### Unity's Assertions: Helpful Messages _and_ Free Source Code Documentation
### Unitys Assertions: Helpful Messages _and_ Free Source Code Documentation
Asserting a simple truth condition is valuable, but using the context of the
assertion is even more valuable. For instance, if you know you're comparing bit
assertion is even more valuable. For instance, if you know youre comparing bit
flags and not just integers, then why not use that context to give explicit,
readable, bit-level feedback when an assertion fails?
That's what Unity's collection of assertions do - capture context to give you
Thats what Unitys collection of assertions do - capture context to give you
helpful, meaningful assertion failure messages. In fact, the assertions
themselves also serve as executable documentation about types and values in your
source code. So long as your tests remain current with your source and all those
@@ -73,12 +73,12 @@ a simple null check).
- `Actual` is the value being tested and unlike the other parameters in an
assertion construction is the only parameter present in all assertion variants.
- `Modifiers` are masks, ranges, bit flag specifiers, floating point deltas.
- `Expected` is your expected value (duh) to compare to an `actual` value; it's
- `Expected` is your expected value (duh) to compare to an `actual` value; its
marked as an optional parameter because some assertions only need a single
`actual` parameter (e.g. null check).
- `Size/count` refers to string lengths, number of array elements, etc.
Many of Unity's assertions are clear duplications in that the same data type
Many of Unitys assertions are clear duplications in that the same data type
is handled by several assertions. The differences among these are in how failure
messages are presented. For instance, a `_HEX` variant of an assertion prints
the expected and actual values of that assertion formatted as hexadecimal.
@@ -99,7 +99,7 @@ _Example:_
TEST_ASSERT_X( {modifiers}, {expected}, actual, {size/count} )
```
becomes messageified like thus...
becomes messageified like thus
```c
TEST_ASSERT_X_MESSAGE( {modifiers}, {expected}, actual, {size/count}, message )
@@ -108,7 +108,7 @@ TEST_ASSERT_X_MESSAGE( {modifiers}, {expected}, actual, {size/count}, message )
Notes:
- The `_MESSAGE` variants intentionally do not support `printf` style formatting
since many embedded projects don't support or avoid `printf` for various reasons.
since many embedded projects dont support or avoid `printf` for various reasons.
It is possible to use `sprintf` before the assertion to assemble a complex fail
message, if necessary.
- If you want to output a counter value within an assertion fail message (e.g. from
@@ -119,7 +119,7 @@ Notes:
Unity provides a collection of assertions for arrays containing a variety of
types. These are documented in the Array section below. These are almost on par
with the `_MESSAGE`variants of Unity's Asserts in that for pretty much any Unity
with the `_MESSAGE`variants of Unitys Asserts in that for pretty much any Unity
type assertion you can tack on `_ARRAY` and run assertions on an entire block of
memory.
@@ -144,7 +144,7 @@ Notes:
Unity provides a collection of assertions for arrays containing a variety of
types which can be compared to a single value as well. These are documented in
the Each Equal section below. these are almost on par with the `_MESSAGE`
variants of Unity's Asserts in that for pretty much any Unity type assertion you
variants of Unitys Asserts in that for pretty much any Unity type assertion you
can inject `_EACH_EQUAL` and run assertions on an entire block of memory.
```c
@@ -203,7 +203,7 @@ code then verifies as a final step.
#### `TEST_PASS_MESSAGE("message")`
This will abort the remainder of the test, but count the test as a pass. Under
normal circumstances, it is not necessary to include this macro in your tests...
normal circumstances, it is not necessary to include this macro in your tests
a lack of failure will automatically be counted as a `PASS`. It is occasionally
useful for tests with `#ifdef`s and such.
@@ -392,7 +392,7 @@ Asserts that the pointers point to the same memory location.
#### `TEST_ASSERT_EQUAL_STRING (expected, actual)`
Asserts that the null terminated (`'\0'`)strings are identical. If strings are
Asserts that the null terminated (`\0`)strings are identical. If strings are
of different lengths or any portion of the strings before their terminators
differ, the assertion fails. Two NULL strings (i.e. zero length) are considered
equivalent.
@@ -561,7 +561,7 @@ Asserts that the `actual` value is NOT within +/- `delta` of the `expected` valu
#### `TEST_ASSERT_EQUAL_FLOAT (expected, actual)`
Asserts that the `actual` value is "close enough to be considered equal" to the
Asserts that the `actual` value is close enough to be considered equal to the
`expected` value. If you are curious about the details, refer to the Advanced
Asserting section for more details on this. Omitting a user-specified delta in a
floating point assertion is both a shorthand convenience and a requirement of
@@ -569,7 +569,7 @@ code generation conventions for CMock.
#### `TEST_ASSERT_NOT_EQUAL_FLOAT (expected, actual)`
Asserts that the `actual` value is NOT "close enough to be considered equal" to the
Asserts that the `actual` value is NOT close enough to be considered equal to the
`expected` value.
#### `TEST_ASSERT_FLOAT_ARRAY_WITHIN (delta, expected, actual, num_elements)`
@@ -662,7 +662,7 @@ Asserts that the `actual` value is NOT within +/- `delta` of the `expected` valu
#### `TEST_ASSERT_EQUAL_DOUBLE (expected, actual)`
Asserts that the `actual` value is "close enough to be considered equal" to the
Asserts that the `actual` value is close enough to be considered equal to the
`expected` value. If you are curious about the details, refer to the Advanced
Asserting section for more details. Omitting a user-specified delta in a
floating point assertion is both a shorthand convenience and a requirement of
@@ -670,7 +670,7 @@ code generation conventions for CMock.
#### `TEST_ASSERT_NOT_EQUAL_DOUBLE (expected, actual)`
Asserts that the `actual` value is NOT "close enough to be considered equal" to the
Asserts that the `actual` value is NOT close enough to be considered equal to the
`expected` value.
#### `TEST_ASSERT_DOUBLE_ARRAY_WITHIN (delta, expected, actual, num_elements)`
@@ -753,7 +753,7 @@ Not A Number floating point representations.
This section helps you understand how to deal with some of the trickier
assertion situations you may run into. It will give you a glimpse into some of
the under-the-hood details of Unity's assertion mechanisms. If you're one of
the under-the-hood details of Unitys assertion mechanisms. If youre one of
those people who likes to know what is going on in the background, read on. If
not, feel free to ignore the rest of this document until you need it.
@@ -768,9 +768,9 @@ mathematical operations might result in a representation of 8 x 2-2
that also evaluates to a value of 2. At some point repeated operations cause
equality checks to fail.
So Unity doesn't do direct floating point comparisons for equality. Instead, it
checks if two floating point values are "really close." If you leave Unity
running with defaults, "really close" means "within a significant bit or two."
So Unity doesnt do direct floating point comparisons for equality. Instead, it
checks if two floating point values are really close. If you leave Unity
running with defaults, really close means within a significant bit or two.
Under the hood, `TEST_ASSERT_EQUAL_FLOAT` is really `TEST_ASSERT_FLOAT_WITHIN`
with the `delta` parameter calculated on the fly. For single precision, delta is
the expected value multiplied by 0.00001, producing a very small proportional
@@ -779,28 +779,27 @@ range around the expected value.
If you are expecting a value of 20,000.0 the delta is calculated to be 0.2. So
any value between 19,999.8 and 20,000.2 will satisfy the equality check. This
works out to be roughly a single bit of range for a single-precision number, and
that's just about as tight a tolerance as you can reasonably get from a floating
thats just about as tight a tolerance as you can reasonably get from a floating
point value.
So what happens when it's zero? Zero - even more than other floating point
values - can be represented many different ways. It doesn't matter if you have
0 x 20 or 0 x 263.It's still zero, right? Luckily, if you
subtract these values from each other, they will always produce a difference of
zero, which will still fall between 0 plus or minus a delta of 0. So it still
works!
So what happens when its zero? Zero - even more than other floating point
values - can be represented many different ways. It doesnt matter if you have
0x20 or 0x263. Its still zero, right? Luckily, if you subtract these
values from each other, they will always produce a difference of zero, which
will still fall between 0 plus or minus a delta of 0. So it still works!
Double precision floating point numbers use a much smaller multiplier, again
approximating a single bit of error.
If you don't like these ranges and you want to make your floating point equality
If you dont like these ranges and you want to make your floating point equality
assertions less strict, you can change these multipliers to whatever you like by
defining UNITY_FLOAT_PRECISION and UNITY_DOUBLE_PRECISION. See Unity
documentation for more.
### How do we deal with targets with non-standard int sizes?
It's "fun" that C is a standard where something as fundamental as an integer
varies by target. According to the C standard, an `int` is to be the target's
Its fun that C is a standard where something as fundamental as an integer
varies by target. According to the C standard, an `int` is to be the targets
natural register size, and it should be at least 16-bits and a multiple of a
byte. It also guarantees an order of sizes:
@@ -814,7 +813,7 @@ and this remains perfectly standard C.
To make things even more interesting, there are compilers and targets out there
that have a hard choice to make. What if their natural register size is 10-bits
or 12-bits? Clearly they can't fulfill _both_ the requirement to be at least
or 12-bits? Clearly they cant fulfill _both_ the requirement to be at least
16-bits AND the requirement to match the natural register size. In these
situations, they often choose the natural register size, leaving us with
something like this:
@@ -823,24 +822,24 @@ something like this:
char (8 bit) <= short (12 bit) <= int (12 bit) <= long (16 bit)
```
Um... yikes. It's obviously breaking a rule or two... but they had to break SOME
Um yikes. Its obviously breaking a rule or two but they had to break SOME
rules, so they made a choice.
When the C99 standard rolled around, it introduced alternate standard-size types.
It also introduced macros for pulling in MIN/MAX values for your integer types.
It's glorious! Unfortunately, many embedded compilers can't be relied upon to
Its glorious! Unfortunately, many embedded compilers cant be relied upon to
use the C99 types (Sometimes because they have weird register sizes as described
above. Sometimes because they don't feel like it?).
above. Sometimes because they dont feel like it?).
A goal of Unity from the beginning was to support every combination of
microcontroller or microprocessor and C compiler. Over time, we've gotten really
microcontroller or microprocessor and C compiler. Over time, weve gotten really
close to this. There are a few tricks that you should be aware of, though, if
you're going to do this effectively on some of these more idiosyncratic targets.
youre going to do this effectively on some of these more idiosyncratic targets.
First, when setting up Unity for a new target, you're going to want to pay
First, when setting up Unity for a new target, youre going to want to pay
special attention to the macros for automatically detecting types
(where available) or manually configuring them yourself. You can get information
on both of these in Unity's documentation.
on both of these in Unitys documentation.
What about the times where you suddenly need to deal with something odd, like a
24-bit `int`? The simplest solution is to use the next size up. If you have a
@@ -848,9 +847,9 @@ What about the times where you suddenly need to deal with something odd, like a
`int`, configure Unity to use 16 bits. There are two ways this is going to
affect you:
1. When Unity displays errors for you, it's going to pad the upper unused bits
1. When Unity displays errors for you, its going to pad the upper unused bits
with zeros.
2. You're going to have to be careful of assertions that perform signed
2. Youre going to have to be careful of assertions that perform signed
operations, particularly `TEST_ASSERT_INT_WITHIN`. Such assertions might wrap
your `int` in the wrong place, and you could experience false failures. You can
always back down to a simple `TEST_ASSERT` and do the operations yourself.

View File

@@ -399,6 +399,68 @@ _Example:_
#define UNITY_EXCLUDE_SETJMP
```
#### `UNITY_TEST_PROTECT`
#### `UNITY_TEST_ABORT`
Unity handles test failures via `setjmp`/`longjmp` pair by default. As mentioned above, you can disable this with `UNITY_EXCLUDE_SETJMP`. You can also customise what happens on every `TEST_PROTECT` and `TEST_ABORT` call. This can be accomplished by providing user-defined `UNITY_TEST_PROTECT` and `UNITY_TEST_ABORT` macros (and these may be defined independently).
`UNITY_TEST_PROTECT` is used as an `if` statement expression, and has to evaluate to `true` on the first call (when saving stack environment with `setjmp`), and to `false` when it returns as a result of a `TEST_ABORT` (when restoring the stack environment with `longjmp`).
Whenever an assert macro fails, `TEST_ABORT` is used to restore the stack environment previously set by `TEST_PROTECT`. This part may be overriden with `UNITY_TEST_ABORT`, e.g. if custom failure handling is needed.
_Example 1:_
Calling `longjmp` on your target is possible, but has a platform-specific (or implementation-specific) set of prerequisites, e.g. privileged access level. You can extend the default behaviour of `TEST_PROTECT` and `TEST_ABORT` as:
`unity_config.h`:
```C
#include "my_custom_test_handlers.h"
#define UNITY_TEST_PROTECT() custom_test_protect()
#define UNITY_TEST_ABORT() custom_test_abort()
```
`my_custom_test_handlers.c`:
```C
int custom_test_protect(void) {
platform_specific_code();
return setjmp(Unity.AbortFrame) == 0;
}
UNITY_NORETURN void custom_test_abort(void) {
more_platform_specific_code();
longjmp(Unity.AbortFrame, 1);
}
```
_Example 2:_
Unity is used to provide the assertion macros only, and an external test harness/runner is used for test orchestration/reporting. In this case you can easily plug your code by overriding `TEST_ABORT` as:
`unity_config.h`:
```C
#include "my_custom_test_handlers.h"
#define UNITY_TEST_PROTECT() 1
#define UNITY_TEST_ABORT() custom_test_abort()
```
`my_custom_test_handlers.c`:
```C
void custom_test_abort(void) {
if (Unity.CurrentTestFailed == 1) {
custom_failed_test_handler();
} else if (Unity.CurrentTestIgnored == 1) {
custom_ignored_test_handler();
}
}
```
#### `UNITY_OUTPUT_COLOR`
If you want to add color using ANSI escape codes you can use this define.
@@ -448,7 +510,7 @@ To enable it, use the following example:
#define UNITY_SUPPORT_TEST_CASES
```
You can manually provide required `TEST_CASE` or `TEST_RANGE` macro definitions
You can manually provide required `TEST_CASE`, `TEST_RANGE` or `TEST_MATRIX` macro definitions
before including `unity.h`, and they won't be redefined.
If you provide one of the following macros, some of default definitions will not be
defined:
@@ -456,8 +518,10 @@ defined:
|---|---|
| `UNITY_EXCLUDE_TEST_CASE` | `TEST_CASE` |
| `UNITY_EXCLUDE_TEST_RANGE` | `TEST_RANGE` |
| `UNITY_EXCLUDE_TEST_MATRIX` | `TEST_MATRIX` |
| `TEST_CASE` | `TEST_CASE` |
| `TEST_RANGE` | `TEST_RANGE` |
| `TEST_MATRIX` | `TEST_MATRIX` |
`UNITY_EXCLUDE_TEST_*` defines is not processed by test runner generator script.
If you exclude one of them from definition, you should provide your own definition

View File

@@ -220,7 +220,7 @@ If we use replace comment before test function with the following code:
```C
TEST_CASE(1, 2, 5)
TEST_CASE(3, 7, 20)
TEST_CASE(10, 7, 20)
```
script will generate 2 test calls:
@@ -296,6 +296,93 @@ TEST_CASE(4, 8, 30)
TEST_CASE(4, 6, 30)
```
##### `TEST_MATRIX`
Test matix is an advanced generator. It single call can be converted to zero,
one or few `TEST_CASE` equivalent commands.
That generator will create tests for all cobinations of the provided list. Each argument has to be given as a list of one or more elements in the format `[<parm1>, <param2>, ..., <paramN-1>, <paramN>]`.
All parameters supported by the `TEST_CASE` is supported as arguments:
- Numbers incl type specifiers e.g. `<1>`, `<1u>`, `<1l>`, `<2.3>`, or `<2.3f>`
- Strings incl string concatianion e.g. `<"string">`, or `<"partial" "string">`
- Chars e.g. `<'c'>`
- Enums e.g. `<ENUM_NAME>`
- Elements of arrays e.g. `<data[0]>`
Let's use our `test_demoParamFunction` test for checking, what ranges
will be generated for our single `TEST_RANGE` row:
```C
TEST_MATRIX([3, 4, 7], [10, 8, 2, 1],[30u, 20.0f])
```
Tests execution output will be similar to that text:
```Log
tests/test_unity_parameterizedDemo.c:18:test_demoParamFunction(3, 10, 30u):PASS
tests/test_unity_parameterizedDemo.c:18:test_demoParamFunction(3, 10, 20.0f):PASS
tests/test_unity_parameterizedDemo.c:18:test_demoParamFunction(3, 8, 30u):PASS
tests/test_unity_parameterizedDemo.c:18:test_demoParamFunction(3, 8, 20.0f):PASS
tests/test_unity_parameterizedDemo.c:18:test_demoParamFunction(3, 2, 30u):PASS
tests/test_unity_parameterizedDemo.c:18:test_demoParamFunction(3, 2, 20.0f):PASS
tests/test_unity_parameterizedDemo.c:18:test_demoParamFunction(3, 1, 30u):PASS
tests/test_unity_parameterizedDemo.c:18:test_demoParamFunction(3, 1, 20.0f):PASS
tests/test_unity_parameterizedDemo.c:18:test_demoParamFunction(4, 10, 30u):PASS
tests/test_unity_parameterizedDemo.c:18:test_demoParamFunction(4, 10, 20.0f):PASS
tests/test_unity_parameterizedDemo.c:18:test_demoParamFunction(4, 8, 30u):PASS
tests/test_unity_parameterizedDemo.c:18:test_demoParamFunction(4, 8, 20.0f):PASS
tests/test_unity_parameterizedDemo.c:18:test_demoParamFunction(4, 2, 30u):PASS
tests/test_unity_parameterizedDemo.c:18:test_demoParamFunction(4, 2, 20.0f):PASS
tests/test_unity_parameterizedDemo.c:18:test_demoParamFunction(4, 1, 30u):PASS
tests/test_unity_parameterizedDemo.c:18:test_demoParamFunction(4, 1, 20.0f):PASS
tests/test_unity_parameterizedDemo.c:18:test_demoParamFunction(7, 10, 30u):PASS
tests/test_unity_parameterizedDemo.c:18:test_demoParamFunction(7, 10, 20.0f):PASS
tests/test_unity_parameterizedDemo.c:18:test_demoParamFunction(7, 8, 30u):PASS
tests/test_unity_parameterizedDemo.c:18:test_demoParamFunction(7, 8, 20.0f):PASS
tests/test_unity_parameterizedDemo.c:18:test_demoParamFunction(7, 2, 30u):PASS
tests/test_unity_parameterizedDemo.c:18:test_demoParamFunction(7, 2, 20.0f):PASS
tests/test_unity_parameterizedDemo.c:18:test_demoParamFunction(7, 1, 30u):PASS
tests/test_unity_parameterizedDemo.c:18:test_demoParamFunction(7, 1, 20.0f):PASS
```
As we can see:
| Parameter | Format | Count of values |
|---|---|---|
| `a` | `[3, 4, 7]` | 2 |
| `b` | `[10, 8, 2, 1]` | 4 |
| `c` | `[30u, 20.0f]` | 2 |
We totally have 2 * 4 * 2 = 16 equal test cases, that can be written as following:
```C
TEST_CASE(3, 10, 30u)
TEST_CASE(3, 10, 20.0f)
TEST_CASE(3, 8, 30u)
TEST_CASE(3, 8, 20.0f)
TEST_CASE(3, 2, 30u)
TEST_CASE(3, 2, 20.0f)
TEST_CASE(3, 1, 30u)
TEST_CASE(3, 1, 20.0f)
TEST_CASE(4, 10, 30u)
TEST_CASE(4, 10, 20.0f)
TEST_CASE(4, 8, 30u)
TEST_CASE(4, 8, 20.0f)
TEST_CASE(4, 2, 30u)
TEST_CASE(4, 2, 20.0f)
TEST_CASE(4, 1, 30u)
TEST_CASE(4, 1, 20.0f)
TEST_CASE(7, 10, 30u)
TEST_CASE(7, 10, 20.0f)
TEST_CASE(7, 8, 30u)
TEST_CASE(7, 8, 20.0f)
TEST_CASE(7, 2, 30u)
TEST_CASE(7, 2, 20.0f)
TEST_CASE(7, 1, 30u)
TEST_CASE(7, 1, 20.0f)
```
### `unity_test_summary.rb`
A Unity test file contains one or more test case functions.

View File

@@ -0,0 +1,48 @@
project('Unity example', 'c',
license: 'MIT',
default_options: [
'c_std=c99',
'warning_level=3',
],
meson_version: '>= 0.49.0'
)
unity_subproject = subproject('unity')
unity_dependency = unity_subproject.get_variable('unity_dep')
unity_gen_runner = unity_subproject.get_variable('gen_test_runner')
src1 = files([
'src' / 'ProductionCode.c',
'test' / 'TestProductionCode.c',
])
src2 = files([
'src' / 'ProductionCode2.c',
'test' / 'TestProductionCode2.c',
])
inc = include_directories('src')
test1 = executable('test1',
sources: [
src1,
unity_gen_runner.process('test' / 'TestProductionCode.c')
],
include_directories: [ inc ],
dependencies: [ unity_dependency ],
)
test('test1', test1,
should_fail: true)
test2 = executable('test2',
sources: [
src2,
unity_gen_runner.process('test' / 'TestProductionCode2.c')
],
include_directories: [ inc ],
dependencies: [ unity_dependency ],
)
test('test2', test2)

View File

@@ -2,4 +2,11 @@ Example 1
=========
Close to the simplest possible example of Unity, using only basic features.
Run make to build & run the example tests.
Build and run with Make
---
Just run `make`.
Build and run with Meson
---
Run `meson setup build` to create the build directory, and then `meson test -C build` to build and run the tests.

View File

@@ -0,0 +1,3 @@
[wrap-git]
url = https://github.com/ThrowTheSwitch/Unity.git
revision = head

40
extras/bdd/readme.md Normal file
View File

@@ -0,0 +1,40 @@
# Unity Project - BDD Feature
Unity's Behavior-Driven Development (BDD) test feature. It allows developers to structure and describe various phases (Given, When, Then) of a test scenario in a BDD-style format.
## Introduction
This project is based on the Unity framework originally created by Mike Karlesky, Mark VanderVoord, and Greg Williams in 2007. The project extends Unity by providing macros to define BDD structures with descriptive elements. Feature added by Michael Gene Brockus (Dreamer).
## License
This project is distributed under the MIT License. See the [license.txt](license.txt) file for more information.
## Usage
### BDD Macros
The provided BDD macros allow you to structure your test scenarios in a descriptive manner. These macros are for descriptive purposes only and do not have functional behavior.
- `GIVEN(description)`: Describes the "Given" phase of a test scenario.
- `WHEN(description)`: Describes the "When" phase of a test scenario.
- `THEN(description)`: Describes the "Then" phase of a test scenario.
Example usage:
```c
GIVEN("a valid input") {
// Test setup and context
// ...
WHEN("the input is processed") {
// Perform the action
// ...
THEN("the expected outcome occurs") {
// Assert the outcome
// ...
}
}
}
```

View File

@@ -0,0 +1,44 @@
/* Copyright (c) 2023 Michael Gene Brockus (Dreamer) and Contributed to Unity Project
* ==========================================
* Unity Project - A Test Framework for C
* Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
* [Released under MIT License. Please refer to license.txt for details]
* ========================================== */
#ifndef UNITY_BDD_TEST_H_
#define UNITY_BDD_TEST_H_
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdio.h>
/**
* @brief Macros for defining a Behavior-Driven Development (BDD) structure with descriptions.
*
* These macros provide a way to structure and describe different phases (Given, When, Then) of a
* test scenario in a BDD-style format. However, they don't have functional behavior by themselves
* and are used for descriptive purposes.
*/
#define GIVEN(description) \
if (0) { \
printf("Given %s\n", description); \
} else
#define WHEN(description) \
if (0) { \
printf("When %s\n", description); \
} else
#define THEN(description) \
if (0) { \
printf("Then %s\n", description); \
} else
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,9 @@
project('BDD Tester', 'c')
# Add Unity as a dependency
unity_dep = dependency('unity')
# Define your source files
sources = files('test_bdd.c')
executable('tester', sources, dependencies : unity_dep)

128
extras/bdd/test/test_bdd.c Normal file
View File

@@ -0,0 +1,128 @@
/* ==========================================
* Unity Project - A Test Framework for C
* Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
* [Released under MIT License. Please refer to license.txt for details]
* ========================================== */
#include "unity.h"
#include "unity_bdd.h"
void test_bdd_logic_test(void) {
GIVEN("a valid statement is passed")
{
// Set up the context
bool givenExecuted = true;
WHEN("a statement is true")
{
// Perform the login action
bool whenExecuted = true;
THEN("we validate everything was worked")
{
// Check the expected outcome
bool thenExecuted = true;
TEST_ASSERT_TRUE(givenExecuted);
TEST_ASSERT_TRUE(whenExecuted);
TEST_ASSERT_TRUE(thenExecuted);
}
}
}
} // end of case
void test_bdd_user_account(void) {
GIVEN("a user's account with sufficient balance")
{
// Set up the context
float accountBalance = 500.0;
float withdrawalAmount = 200.0;
WHEN("the user requests a withdrawal of $200")
{
// Perform the withdrawal action
if (accountBalance >= withdrawalAmount)
{
accountBalance -= withdrawalAmount;
} // end if
THEN("the withdrawal amount should be deducted from the account balance")
{
// Check the expected outcome
// Simulate the scenario
float compareBalance = 500.0;
TEST_ASSERT_LESS_THAN_FLOAT(accountBalance, compareBalance);
}
}
}
} // end of case
void test_bdd_empty_cart(void) {
GIVEN("a user with an empty shopping cart")
{
// Set up the context
int cartItemCount = 0;
WHEN("the user adds a product to the cart")
{
// Perform the action of adding a product
THEN("the cart item count should increase by 1")
{
// Check the expected outcome
cartItemCount++;
TEST_ASSERT_EQUAL_INT(cartItemCount, 1);
}
}
}
} // end of case
void test_bdd_valid_login(void) {
GIVEN("a registered user with valid credentials")
{
// Set up the context
const char* validUsername = "user123";
const char* validPassword = "pass456";
WHEN("the user provides correct username and password")
{
// Perform the action of user login
const char* inputUsername = "user123";
const char* inputPassword = "pass456";
THEN("the login should be successful")
{
// Check the expected outcome
// Simulate login validation
TEST_ASSERT_EQUAL_STRING(inputUsername, validUsername);
TEST_ASSERT_EQUAL_STRING(inputPassword, validPassword);
}
}
WHEN("the user provides incorrect password")
{
// Perform the action of user login
const char* inputUsername = "user123";
const char* inputPassword = "wrongpass";
THEN("the login should fail with an error message")
{
// Check the expected outcome
// Simulate login validation
TEST_ASSERT_EQUAL_STRING(inputUsername, validUsername);
// TEST_ASSERT_NOT_EQUAL_STRING(inputPassword, validPassword);
}
}
}
} // end of case
int main(void)
{
UnityBegin("test_bdd.c");
RUN_TEST(test_bdd_logic_test);
RUN_TEST(test_bdd_user_account);
RUN_TEST(test_bdd_empty_cart);
RUN_TEST(test_bdd_valid_login);
return UnityEnd();
}

View File

@@ -0,0 +1,10 @@
unity_inc += include_directories('.')
unity_src += files('unity_fixture.c')
if not meson.is_subproject()
install_headers(
'unity_fixture.h',
'unity_fixture_internals.h',
subdir: meson.project_name()
)
endif

View File

@@ -0,0 +1,9 @@
unity_inc += include_directories('.')
unity_src += files('unity_memory.c')
if not meson.is_subproject()
install_headers(
'unity_memory.h',
subdir: meson.project_name()
)
endif

View File

@@ -6,20 +6,75 @@
#
project('unity', 'c',
license: 'MIT',
meson_version: '>=0.37.0',
default_options: ['werror=true', 'c_std=c11'])
# Set project version to value extracted from unity.h header
version: run_command(
[
'auto/extract_version.py',
'src/unity.h'
],
check: true
).stdout().strip(),
meson_version: '>=0.47.0',
default_options: [
'werror=true',
'c_std=c11'
]
)
build_fixture = get_option('extension_fixture')
build_memory = get_option('extension_memory')
support_double = get_option('support_double')
unity_args = []
unity_src = []
unity_inc = []
subdir('src')
unity_dep = declare_dependency(link_with: unity_lib, include_directories: unity_dir)
# Get the generate_test_runner script relative to itself or the parent project if it is being used as a subproject
# NOTE: This could be (and probably is) a complete hack - but I haven't yet been able to find a better way....
if meson.is_subproject()
gen_test_runner_path = find_program(meson.source_root() / 'subprojects/unity/auto/generate_test_runner.rb')
else
gen_test_runner_path = find_program('subprojects/unity/auto/generate_test_runner.rb')
if build_fixture
# Building the fixture extension implies building the memory
# extension.
build_memory = true
subdir('extras/fixture/src')
endif
# Create a generator that we can access from the parent project
gen_test_runner = generator(gen_test_runner_path, output: '@BASENAME@_Runner.c', arguments: ['@INPUT@', '@OUTPUT@'] )
if build_memory
subdir('extras/memory/src')
endif
if support_double
unity_args += '-DUNITY_INCLUDE_DOUBLE'
endif
unity_lib = static_library(meson.project_name(),
sources: unity_src,
c_args: unity_args,
include_directories: unity_inc,
install: not meson.is_subproject(),
)
unity_dep = declare_dependency(
link_with: unity_lib,
include_directories: unity_inc
)
# Generate pkg-config file.
if not meson.is_subproject()
pkg = import('pkgconfig')
pkg.generate(
name: meson.project_name(),
version: meson.project_version(),
libraries: [ unity_lib ],
description: 'C Unit testing framework.'
)
endif
# Create a generator that can be used by consumers of our build system to generate
# test runners.
gen_test_runner = generator(
find_program('auto/generate_test_runner.rb'),
output: '@BASENAME@_Runner.c',
arguments: ['@INPUT@', '@OUTPUT@']
)

3
meson_options.txt Normal file
View File

@@ -0,0 +1,3 @@
option('extension_fixture', type: 'boolean', value: 'false', description: 'Whether to enable the fixture extension.')
option('extension_memory', type: 'boolean', value: 'false', description: 'Whether to enable the memory extension.')
option('support_double', type: 'boolean', value: 'false', description: 'Whether to enable double precision floating point assertions.')

View File

@@ -4,10 +4,14 @@
#
# license: MIT
#
unity_dir = include_directories('.')
unity_lib = static_library(meson.project_name(),
'unity.c',
include_directories: unity_dir,
native: true
)
unity_inc += include_directories('.')
unity_src += files('unity.c')
if not meson.is_subproject()
install_headers(
'unity.h',
'unity_internals.h',
subdir: meson.project_name()
)
endif

View File

@@ -1115,6 +1115,7 @@ void UnityAssertFloatSpecial(const UNITY_FLOAT actual,
is_trait = !isinf(actual) && !isnan(actual);
break;
case UNITY_FLOAT_INVALID_TRAIT: /* Supress warning */
default: /* including UNITY_FLOAT_INVALID_TRAIT */
trait_index = 0;
trait_names[0] = UnityStrInvalidFloatTrait;
@@ -1341,6 +1342,7 @@ void UnityAssertDoubleSpecial(const UNITY_DOUBLE actual,
is_trait = !isinf(actual) && !isnan(actual);
break;
case UNITY_FLOAT_INVALID_TRAIT: /* Supress warning */
default: /* including UNITY_FLOAT_INVALID_TRAIT */
trait_index = 0;
trait_names[0] = UnityStrInvalidFloatTrait;
@@ -1607,8 +1609,8 @@ void UnityAssertEqualString(const char* expected,
}
}
else
{ /* handle case of one pointers being null (if both null, test should pass) */
if (expected != actual)
{ /* fail if either null but not if both */
if (expected || actual)
{
Unity.CurrentTestFailed = 1;
}
@@ -1647,8 +1649,8 @@ void UnityAssertEqualStringLen(const char* expected,
}
}
else
{ /* handle case of one pointers being null (if both null, test should pass) */
if (expected != actual)
{ /* fail if either null but not if both */
if (expected || actual)
{
Unity.CurrentTestFailed = 1;
}
@@ -2034,10 +2036,17 @@ static void UnityPrintFVA(const char* format, va_list va)
}
case 'p':
{
const unsigned int number = va_arg(va, unsigned int);
UNITY_UINT number;
char nibbles_to_print = 8;
if (UNITY_POINTER_WIDTH == 64)
{
length_mod = UNITY_LENGTH_MODIFIER_LONG_LONG;
nibbles_to_print = 16;
}
UNITY_EXTRACT_ARG(UNITY_UINT, number, length_mod, va, unsigned int);
UNITY_OUTPUT_CHAR('0');
UNITY_OUTPUT_CHAR('x');
UnityPrintNumberHex((UNITY_UINT)number, UNITY_MAX_NIBBLES);
UnityPrintNumberHex((UNITY_UINT)number, nibbles_to_print);
break;
}
case 'c':

View File

@@ -89,7 +89,7 @@ void verifyTest(void);
* - define UNITY_SUPPORT_TEST_CASES to include the TEST_CASE macro, though really it's mostly about the runner generator script
* Parameterized Tests
* - you'll want to create a define of TEST_CASE(...) and/or TEST_RANGE(...) which basically evaluates to nothing
* - you'll want to create a define of TEST_CASE(...), TEST_RANGE(...) and/or TEST_MATRIX(...) which basically evaluates to nothing
* Tests with Arguments
* - you'll want to define UNITY_USE_COMMAND_LINE_ARGS if you have the test runner passing arguments to Unity
@@ -105,7 +105,7 @@ void verifyTest(void);
#define TEST_MESSAGE(message) UnityMessage((message), __LINE__)
#define TEST_ONLY()
#ifdef UNITY_INCLUDE_PRINT_FORMATTED
#define TEST_PRINTF(message, ...) UnityPrintF(__LINE__, (message), __VA_ARGS__)
#define TEST_PRINTF(message, ...) UnityPrintF(__LINE__, (message), ##__VA_ARGS__)
#endif
/* It is not necessary for you to call PASS. A PASS condition is assumed if nothing fails.
@@ -113,9 +113,19 @@ void verifyTest(void);
#define TEST_PASS() TEST_ABORT()
#define TEST_PASS_MESSAGE(message) do { UnityMessage((message), __LINE__); TEST_ABORT(); } while (0)
/* This macro does nothing, but it is useful for build tools (like Ceedling) to make use of this to figure out
* which files should be linked to in order to perform a test. Use it like TEST_FILE("sandwiches.c") */
#define TEST_FILE(a)
/*-------------------------------------------------------
* Build Directives
*-------------------------------------------------------
* These macros do nothing, but they are useful for additional build context.
* Tools (like Ceedling) can scan for these directives and make use of them for
* per-test-executable #include search paths and linking. */
/* Add source files to a test executable's compilation and linking. Ex: TEST_SOURCE_FILE("sandwiches.c") */
#define TEST_SOURCE_FILE(a)
/* Customize #include search paths for a test executable's compilation. Ex: TEST_INCLUDE_PATH("src/module_a/inc") */
#define TEST_INCLUDE_PATH(a)
/*-------------------------------------------------------
* Test Asserts (simple)

View File

@@ -77,7 +77,7 @@
#endif
#endif
#ifndef UNITY_NORETURN
#define UNITY_NORETURN UNITY_FUNCTION_ATTR(noreturn)
#define UNITY_NORETURN UNITY_FUNCTION_ATTR(__noreturn__)
#endif
/*-------------------------------------------------------
@@ -759,13 +759,25 @@ extern const char UnityStrErrShorthand[];
* Test Running Macros
*-------------------------------------------------------*/
#ifdef UNITY_TEST_PROTECT
#define TEST_PROTECT() UNITY_TEST_PROTECT()
#else
#ifndef UNITY_EXCLUDE_SETJMP_H
#define TEST_PROTECT() (setjmp(Unity.AbortFrame) == 0)
#define TEST_ABORT() longjmp(Unity.AbortFrame, 1)
#else
#define TEST_PROTECT() 1
#endif
#endif
#ifdef UNITY_TEST_ABORT
#define TEST_ABORT() UNITY_TEST_ABORT()
#else
#ifndef UNITY_EXCLUDE_SETJMP_H
#define TEST_ABORT() longjmp(Unity.AbortFrame, 1)
#else
#define TEST_ABORT() return
#endif
#endif
/* Automatically enable variadic macros support, if it not enabled before */
#ifndef UNITY_SUPPORT_VARIADIC_MACROS
@@ -793,6 +805,9 @@ extern const char UnityStrErrShorthand[];
#if !defined(TEST_RANGE) && !defined(UNITY_EXCLUDE_TEST_RANGE)
#define TEST_RANGE(...)
#endif
#if !defined(TEST_MATRIX) && !defined(UNITY_EXCLUDE_TEST_MATRIX)
#define TEST_MATRIX(...)
#endif
#endif
#endif
@@ -953,7 +968,7 @@ int UnityTestMatches(void);
#define UNITY_TEST_ASSERT_INT16_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT16)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16, UNITY_ARRAY_TO_ARRAY)
#define UNITY_TEST_ASSERT_INT32_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT32)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32, UNITY_ARRAY_TO_ARRAY)
#define UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin( (delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT, UNITY_ARRAY_TO_ARRAY)
#define UNITY_TEST_ASSERT_UINT8_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT16)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8, UNITY_ARRAY_TO_ARRAY)
#define UNITY_TEST_ASSERT_UINT8_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT8 )(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8, UNITY_ARRAY_TO_ARRAY)
#define UNITY_TEST_ASSERT_UINT16_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT16)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16, UNITY_ARRAY_TO_ARRAY)
#define UNITY_TEST_ASSERT_UINT32_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT32)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32, UNITY_ARRAY_TO_ARRAY)
#define UNITY_TEST_ASSERT_HEX8_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT8 )(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8, UNITY_ARRAY_TO_ARRAY)

View File

@@ -4,7 +4,7 @@
#include "unity.h"
#include "Defs.h"
TEST_FILE("some_file.c")
TEST_SOURCE_FILE("some_file.c")
/* Notes about prefixes:
test - normal default prefix. these are "always run" tests for this procedure

View File

@@ -7,6 +7,7 @@
#include <setjmp.h>
#include <stdio.h>
#include "unity.h"
#include "types_for_test.h"
/* Include Passthroughs for Linking Tests */
void putcharSpy(int c) { (void)putchar(c);}
@@ -209,6 +210,14 @@ TEST_RANGE([2,
TEST_CASE(
6 , 7)
TEST_MATRIX([7,
8 ,
9, 10],
[
11]
)
void test_SpaceInTestCase(unsigned index, unsigned bigger)
{
TEST_ASSERT_EQUAL_UINT32(NextExpectedSpaceIndex, index);
@@ -216,3 +225,84 @@ void test_SpaceInTestCase(unsigned index, unsigned bigger)
NextExpectedSpaceIndex++;
}
TEST_MATRIX([1, 5, (2*2)+1, 4])
void test_SingleMatix(unsigned value)
{
TEST_ASSERT_LESS_OR_EQUAL(10, value);
}
TEST_MATRIX([2, 5l, 4u+3, 4ul], [-2, 3])
void test_TwoMatrices(unsigned first, signed second)
{
static unsigned idx = 0;
static const unsigned expected[] =
{
// -2 3
-4, 6, // 2
-10, 15, // 5
-14, 21, // 7
-8, 12, // 4
};
TEST_ASSERT_EQUAL_INT(expected[idx++], first * second);
}
TEST_MATRIX(["String1", "String,2", "Stri" "ng3", "String[4]", "String\"5\""], [-5, 12.5f])
void test_StringsAndNumbersMatrices(const char* str, float number)
{
static unsigned idx = 0;
static const char* expected[] =
{
"String1_-05.00",
"String1_+12.50",
"String,2_-05.00",
"String,2_+12.50",
"String3_-05.00",
"String3_+12.50",
"String[4]_-05.00",
"String[4]_+12.50",
"String\"5\"_-05.00",
"String\"5\"_+12.50",
};
char buf[200] = {0};
snprintf(buf, sizeof(buf), "%s_%+06.2f", str, number);
TEST_ASSERT_EQUAL_STRING(expected[idx++], buf);
}
TEST_MATRIX(
[ENUM_A, ENUM_4, ENUM_C],
[test_arr[0], 7.8f, test_arr[2]],
['a', 'f', '[', ']', '\'', '"'],
)
void test_EnumCharAndArrayMatrices(test_enum_t e, float n, char c)
{
static unsigned enum_idx = 0;
static const test_enum_t exp_enum[3] = {
ENUM_A, ENUM_4, ENUM_C,
};
static unsigned float_idx = 0;
float exp_float[3] = {0};
exp_float[0] = test_arr[0];
exp_float[1] = 7.8f;
exp_float[2] = test_arr[2];
static unsigned char_idx = 0;
static const test_enum_t exp_char[] = {
'a', 'f', '[', ']', '\'', '"'
};
TEST_ASSERT_EQUAL_INT(exp_enum[enum_idx], e);
TEST_ASSERT_EQUAL_FLOAT(exp_float[float_idx], n);
TEST_ASSERT_EQUAL_CHAR(exp_char[char_idx], c);
char_idx = (char_idx + 1) % 6;
if (char_idx == 0.0f)
{
float_idx = (float_idx + 1) % 3;
if (float_idx == 0.0f)
{
enum_idx = (enum_idx + 1) % 3;
}
}
}

View File

@@ -7,10 +7,14 @@
#ifndef TEST_RANGE
#define TEST_RANGE(...)
#endif
#ifndef TEST_MATRIX
#define TEST_MATRIX(...)
#endif
TEST_CASE(1, 2, 5)
TEST_CASE(10, 7, 20)
TEST_RANGE([3, 4, 1], [10, 5, -2], <30, 31, 1>)
TEST_MATRIX([3, 4, 7], [10, 8, 2, 1],[30u, 20.0f])
void test_demoParamFunction(int a, int b, int c)
{
TEST_ASSERT_GREATER_THAN_INT(a + b, c);

View File

@@ -0,0 +1,14 @@
#pragma once
typedef enum {
ENUM_A,
ENUM_2,
ENUM_C,
ENUM_4,
} test_enum_t;
static const float test_arr[] = {
1.2f,
2.3f,
3.4f,
};