mirror of
https://github.com/ThrowTheSwitch/Unity.git
synced 2025-08-06 13:50:49 +08:00
Merge branch 'feature/print-floats'
Fix new type name conflicts Conflicts: src/unity.c src/unity_internals.h
This commit is contained in:
149
src/unity.c
149
src/unity.c
@ -250,24 +250,94 @@ void UnityPrintMask(const UNITY_UINT mask, const UNITY_UINT number)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*-----------------------------------------------*/
|
/*-----------------------------------------------*/
|
||||||
#ifdef UNITY_FLOAT_VERBOSE
|
#ifndef UNITY_EXCLUDE_FLOAT_PRINT
|
||||||
#include <stdio.h>
|
static void UnityPrintDecimalAndNumberWithLeadingZeros(UNITY_INT32 fraction_part, UNITY_INT32 divisor)
|
||||||
|
{
|
||||||
#ifndef UNITY_VERBOSE_NUMBER_MAX_LENGTH
|
UNITY_OUTPUT_CHAR('.');
|
||||||
# ifdef UNITY_DOUBLE_VERBOSE
|
while (divisor > 0)
|
||||||
# define UNITY_VERBOSE_NUMBER_MAX_LENGTH 317
|
{
|
||||||
# else
|
UNITY_OUTPUT_CHAR('0' + fraction_part / divisor);
|
||||||
# define UNITY_VERBOSE_NUMBER_MAX_LENGTH 47
|
fraction_part %= divisor;
|
||||||
# endif
|
divisor /= 10;
|
||||||
|
if (fraction_part == 0) break; /* Truncate trailing 0's */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#ifndef UNITY_ROUND_TIES_AWAY_FROM_ZERO
|
||||||
|
/* If rounds up && remainder 0.5 && result odd && below cutoff for double precision issues */
|
||||||
|
#define ROUND_TIES_TO_EVEN(orig, num_int, num) \
|
||||||
|
if (num_int > (num) && (num) - (num_int-1) <= 0.5 && (num_int & 1) == 1 && orig < 1e22) \
|
||||||
|
num_int -= 1 /* => a tie to round down to even */
|
||||||
|
#else
|
||||||
|
#define ROUND_TIES_TO_EVEN(orig, num_int, num) /* Remove macro */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Printing floating point numbers is hard. Some goals of this implementation: works for embedded
|
||||||
|
* systems, floats or doubles, and has a reasonable format. The key paper in this area,
|
||||||
|
* 'How to Print Floating-Point Numbers Accurately' by Steele & White, shows an approximation by
|
||||||
|
* scaling called Dragon 2. This code uses a similar idea. The other core algorithm uses casts and
|
||||||
|
* floating subtraction to give exact remainders after the decimal, to be scaled into an integer.
|
||||||
|
* Extra trailing 0's are excluded. The output defaults to rounding to nearest, ties to even. You
|
||||||
|
* can enable rounding ties away from zero. Note: UNITY_DOUBLE param can typedef to float or double
|
||||||
|
|
||||||
|
* The old version required compiling in snprintf. For reference, with a similar format as now:
|
||||||
|
* char buf[19];
|
||||||
|
* if (number > 4294967296.0 || -number > 4294967296.0) snprintf(buf, sizeof buf, "%.8e", number);
|
||||||
|
* else snprintf(buf, sizeof buf, "%.6f", number);
|
||||||
|
* UnityPrint(buf);
|
||||||
|
*/
|
||||||
void UnityPrintFloat(UNITY_DOUBLE number)
|
void UnityPrintFloat(UNITY_DOUBLE number)
|
||||||
{
|
{
|
||||||
char TempBuffer[UNITY_VERBOSE_NUMBER_MAX_LENGTH + 1];
|
if (number < 0)
|
||||||
snprintf(TempBuffer, sizeof(TempBuffer), "%.6f", number);
|
{
|
||||||
UnityPrint(TempBuffer);
|
UNITY_OUTPUT_CHAR('-');
|
||||||
|
number = -number;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isnan(number)) UnityPrint(UnityStrNaN);
|
||||||
|
else if (isinf(number)) UnityPrintLen(UnityStrInf, 3);
|
||||||
|
else if (number <= 0.0000005 && number > 0) UnityPrint("0.000000..."); /* Small number */
|
||||||
|
else if (number < 4294967295.9999995) /* Rounded result fits in 32 bits, "%.6f" format */
|
||||||
|
{
|
||||||
|
const UNITY_INT32 divisor = 1000000/10;
|
||||||
|
UNITY_UINT32 integer_part = (UNITY_UINT32)number;
|
||||||
|
UNITY_INT32 fraction_part = (UNITY_INT32)((number - (UNITY_DOUBLE)integer_part)*1000000.0 + 0.5);
|
||||||
|
/* Double precision calculation gives best performance for six rounded decimal places */
|
||||||
|
ROUND_TIES_TO_EVEN(number, fraction_part, (number - (UNITY_DOUBLE)integer_part)*1000000.0);
|
||||||
|
|
||||||
|
if (fraction_part == 1000000) /* Carry across the decimal point */
|
||||||
|
{
|
||||||
|
fraction_part = 0;
|
||||||
|
integer_part += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
UnityPrintNumberUnsigned(integer_part);
|
||||||
|
UnityPrintDecimalAndNumberWithLeadingZeros(fraction_part, divisor);
|
||||||
|
}
|
||||||
|
else /* Number is larger, use exponential format of 9 digits, "%.8e" */
|
||||||
|
{
|
||||||
|
const UNITY_INT32 divisor = 1000000000/10;
|
||||||
|
UNITY_INT32 integer_part;
|
||||||
|
UNITY_DOUBLE_TYPE divide = 10.0;
|
||||||
|
int exponent = 9;
|
||||||
|
|
||||||
|
while (number / divide >= 1000000000.0 - 0.5)
|
||||||
|
{
|
||||||
|
divide *= 10;
|
||||||
|
exponent++;
|
||||||
|
}
|
||||||
|
integer_part = (UNITY_INT32)(number / divide + 0.5);
|
||||||
|
/* Double precision calculation required for float, to produce 9 rounded digits */
|
||||||
|
ROUND_TIES_TO_EVEN(number, integer_part, number / divide);
|
||||||
|
|
||||||
|
UNITY_OUTPUT_CHAR('0' + integer_part / divisor);
|
||||||
|
UnityPrintDecimalAndNumberWithLeadingZeros(integer_part % divisor, divisor / 10);
|
||||||
|
UNITY_OUTPUT_CHAR('e');
|
||||||
|
UNITY_OUTPUT_CHAR('+');
|
||||||
|
if (exponent < 10) UNITY_OUTPUT_CHAR('0');
|
||||||
|
UnityPrintNumber(exponent);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif /* ! UNITY_EXCLUDE_FLOAT_PRINT */
|
||||||
|
|
||||||
/*-----------------------------------------------*/
|
/*-----------------------------------------------*/
|
||||||
|
|
||||||
@ -631,6 +701,19 @@ void UnityAssertEqualIntArray(UNITY_INTERNAL_PTR expected,
|
|||||||
#define UNITY_NAN_CHECK 0
|
#define UNITY_NAN_CHECK 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef UNITY_EXCLUDE_FLOAT_PRINT
|
||||||
|
#define UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(expected, actual) \
|
||||||
|
do { \
|
||||||
|
UnityPrint(UnityStrExpected); \
|
||||||
|
UnityPrintFloat(expected); \
|
||||||
|
UnityPrint(UnityStrWas); \
|
||||||
|
UnityPrintFloat(actual); \
|
||||||
|
} while(0)
|
||||||
|
#else
|
||||||
|
#define UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(expected, actual) \
|
||||||
|
UnityPrint(UnityStrDelta)
|
||||||
|
#endif /* UNITY_EXCLUDE_FLOAT_PRINT */
|
||||||
|
|
||||||
#ifndef UNITY_EXCLUDE_FLOAT
|
#ifndef UNITY_EXCLUDE_FLOAT
|
||||||
static int UnityFloatsWithin(UNITY_FLOAT delta, UNITY_FLOAT expected, UNITY_FLOAT actual)
|
static int UnityFloatsWithin(UNITY_FLOAT delta, UNITY_FLOAT expected, UNITY_FLOAT actual)
|
||||||
{
|
{
|
||||||
@ -665,14 +748,7 @@ void UnityAssertEqualFloatArray(UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* expected,
|
|||||||
UnityTestResultsFailBegin(lineNumber);
|
UnityTestResultsFailBegin(lineNumber);
|
||||||
UnityPrint(UnityStrElement);
|
UnityPrint(UnityStrElement);
|
||||||
UnityPrintNumberUnsigned(num_elements - elements - 1);
|
UnityPrintNumberUnsigned(num_elements - elements - 1);
|
||||||
#ifdef UNITY_FLOAT_VERBOSE
|
UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(*ptr_expected, *ptr_actual);
|
||||||
UnityPrint(UnityStrExpected);
|
|
||||||
UnityPrintFloat(*ptr_expected);
|
|
||||||
UnityPrint(UnityStrWas);
|
|
||||||
UnityPrintFloat(*ptr_actual);
|
|
||||||
#else
|
|
||||||
UnityPrint(UnityStrDelta);
|
|
||||||
#endif
|
|
||||||
UnityAddMsgIfSpecified(msg);
|
UnityAddMsgIfSpecified(msg);
|
||||||
UNITY_FAIL_AND_BAIL;
|
UNITY_FAIL_AND_BAIL;
|
||||||
}
|
}
|
||||||
@ -694,14 +770,7 @@ void UnityAssertFloatsWithin(const UNITY_FLOAT delta,
|
|||||||
if (!UnityFloatsWithin(delta, expected, actual))
|
if (!UnityFloatsWithin(delta, expected, actual))
|
||||||
{
|
{
|
||||||
UnityTestResultsFailBegin(lineNumber);
|
UnityTestResultsFailBegin(lineNumber);
|
||||||
#ifdef UNITY_FLOAT_VERBOSE
|
UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(expected, actual);
|
||||||
UnityPrint(UnityStrExpected);
|
|
||||||
UnityPrintFloat(expected);
|
|
||||||
UnityPrint(UnityStrWas);
|
|
||||||
UnityPrintFloat(actual);
|
|
||||||
#else
|
|
||||||
UnityPrint(UnityStrDelta);
|
|
||||||
#endif
|
|
||||||
UnityAddMsgIfSpecified(msg);
|
UnityAddMsgIfSpecified(msg);
|
||||||
UNITY_FAIL_AND_BAIL;
|
UNITY_FAIL_AND_BAIL;
|
||||||
}
|
}
|
||||||
@ -759,7 +828,7 @@ void UnityAssertFloatSpecial(const UNITY_FLOAT actual,
|
|||||||
UnityPrint(UnityStrNot);
|
UnityPrint(UnityStrNot);
|
||||||
UnityPrint(trait_names[trait_index]);
|
UnityPrint(trait_names[trait_index]);
|
||||||
UnityPrint(UnityStrWas);
|
UnityPrint(UnityStrWas);
|
||||||
#ifdef UNITY_FLOAT_VERBOSE
|
#ifndef UNITY_EXCLUDE_FLOAT_PRINT
|
||||||
UnityPrintFloat(actual);
|
UnityPrintFloat(actual);
|
||||||
#else
|
#else
|
||||||
if (should_be_trait)
|
if (should_be_trait)
|
||||||
@ -808,14 +877,7 @@ void UnityAssertEqualDoubleArray(UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* expecte
|
|||||||
UnityTestResultsFailBegin(lineNumber);
|
UnityTestResultsFailBegin(lineNumber);
|
||||||
UnityPrint(UnityStrElement);
|
UnityPrint(UnityStrElement);
|
||||||
UnityPrintNumberUnsigned(num_elements - elements - 1);
|
UnityPrintNumberUnsigned(num_elements - elements - 1);
|
||||||
#ifdef UNITY_DOUBLE_VERBOSE
|
UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(*ptr_expected, *ptr_actual);
|
||||||
UnityPrint(UnityStrExpected);
|
|
||||||
UnityPrintFloat((float)(*ptr_expected));
|
|
||||||
UnityPrint(UnityStrWas);
|
|
||||||
UnityPrintFloat((float)(*ptr_actual));
|
|
||||||
#else
|
|
||||||
UnityPrint(UnityStrDelta);
|
|
||||||
#endif
|
|
||||||
UnityAddMsgIfSpecified(msg);
|
UnityAddMsgIfSpecified(msg);
|
||||||
UNITY_FAIL_AND_BAIL;
|
UNITY_FAIL_AND_BAIL;
|
||||||
}
|
}
|
||||||
@ -836,14 +898,7 @@ void UnityAssertDoublesWithin(const UNITY_DOUBLE delta,
|
|||||||
if (!UnityDoublesWithin(delta, expected, actual))
|
if (!UnityDoublesWithin(delta, expected, actual))
|
||||||
{
|
{
|
||||||
UnityTestResultsFailBegin(lineNumber);
|
UnityTestResultsFailBegin(lineNumber);
|
||||||
#ifdef UNITY_DOUBLE_VERBOSE
|
UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(expected, actual);
|
||||||
UnityPrint(UnityStrExpected);
|
|
||||||
UnityPrintFloat((float)expected);
|
|
||||||
UnityPrint(UnityStrWas);
|
|
||||||
UnityPrintFloat((float)actual);
|
|
||||||
#else
|
|
||||||
UnityPrint(UnityStrDelta);
|
|
||||||
#endif
|
|
||||||
UnityAddMsgIfSpecified(msg);
|
UnityAddMsgIfSpecified(msg);
|
||||||
UNITY_FAIL_AND_BAIL;
|
UNITY_FAIL_AND_BAIL;
|
||||||
}
|
}
|
||||||
@ -902,7 +957,7 @@ void UnityAssertDoubleSpecial(const UNITY_DOUBLE actual,
|
|||||||
UnityPrint(UnityStrNot);
|
UnityPrint(UnityStrNot);
|
||||||
UnityPrint(trait_names[trait_index]);
|
UnityPrint(trait_names[trait_index]);
|
||||||
UnityPrint(UnityStrWas);
|
UnityPrint(UnityStrWas);
|
||||||
#ifdef UNITY_DOUBLE_VERBOSE
|
#ifndef UNITY_EXCLUDE_FLOAT_PRINT
|
||||||
UnityPrintFloat(actual);
|
UnityPrintFloat(actual);
|
||||||
#else
|
#else
|
||||||
if (should_be_trait)
|
if (should_be_trait)
|
||||||
|
@ -37,13 +37,11 @@ void tearDown(void);
|
|||||||
* - define UNITY_EXCLUDE_FLOAT to disallow floating point comparisons
|
* - define UNITY_EXCLUDE_FLOAT to disallow floating point comparisons
|
||||||
* - define UNITY_FLOAT_PRECISION to specify the precision to use when doing TEST_ASSERT_EQUAL_FLOAT
|
* - define UNITY_FLOAT_PRECISION to specify the precision to use when doing TEST_ASSERT_EQUAL_FLOAT
|
||||||
* - define UNITY_FLOAT_TYPE to specify doubles instead of single precision floats
|
* - define UNITY_FLOAT_TYPE to specify doubles instead of single precision floats
|
||||||
* - define UNITY_FLOAT_VERBOSE to print floating point values in errors (uses sprintf)
|
|
||||||
* - define UNITY_INCLUDE_DOUBLE to allow double floating point comparisons
|
* - define UNITY_INCLUDE_DOUBLE to allow double floating point comparisons
|
||||||
* - define UNITY_EXCLUDE_DOUBLE to disallow double floating point comparisons (default)
|
* - define UNITY_EXCLUDE_DOUBLE to disallow double floating point comparisons (default)
|
||||||
* - define UNITY_DOUBLE_PRECISION to specify the precision to use when doing TEST_ASSERT_EQUAL_DOUBLE
|
* - define UNITY_DOUBLE_PRECISION to specify the precision to use when doing TEST_ASSERT_EQUAL_DOUBLE
|
||||||
* - define UNITY_DOUBLE_TYPE to specify something other than double
|
* - define UNITY_DOUBLE_TYPE to specify something other than double
|
||||||
* - define UNITY_DOUBLE_VERBOSE to print floating point values in errors (uses sprintf)
|
* - define UNITY_EXCLUDE_FLOAT_PRINT to trim binary size, won't print floating point values in errors
|
||||||
* - define UNITY_VERBOSE_NUMBER_MAX_LENGTH to change maximum length of printed numbers (used by sprintf)
|
|
||||||
|
|
||||||
* Output
|
* Output
|
||||||
* - by default, Unity prints to standard out with putchar. define UNITY_OUTPUT_CHAR(a) with a different function if desired
|
* - by default, Unity prints to standard out with putchar. define UNITY_OUTPUT_CHAR(a) with a different function if desired
|
||||||
|
@ -171,7 +171,6 @@
|
|||||||
#undef UNITY_INCLUDE_FLOAT
|
#undef UNITY_INCLUDE_FLOAT
|
||||||
#undef UNITY_FLOAT_PRECISION
|
#undef UNITY_FLOAT_PRECISION
|
||||||
#undef UNITY_FLOAT_TYPE
|
#undef UNITY_FLOAT_TYPE
|
||||||
#undef UNITY_FLOAT_VERBOSE
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
@ -225,15 +224,19 @@ typedef UNITY_FLOAT_TYPE UNITY_FLOAT;
|
|||||||
/* No Floating Point Support */
|
/* No Floating Point Support */
|
||||||
#undef UNITY_DOUBLE_PRECISION
|
#undef UNITY_DOUBLE_PRECISION
|
||||||
#undef UNITY_DOUBLE_TYPE
|
#undef UNITY_DOUBLE_TYPE
|
||||||
#undef UNITY_DOUBLE_VERBOSE
|
|
||||||
|
|
||||||
#ifdef UNITY_INCLUDE_DOUBLE
|
#ifdef UNITY_INCLUDE_DOUBLE
|
||||||
#undef UNITY_INCLUDE_DOUBLE
|
#undef UNITY_INCLUDE_DOUBLE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef UNITY_FLOAT_VERBOSE
|
#ifdef UNITY_EXCLUDE_FLOAT
|
||||||
typedef UNITY_FLOAT UNITY_DOUBLE;
|
#define UNITY_EXCLUDE_FLOAT_PRINT
|
||||||
/* For parameter in UnityPrintFloat, double promotion required */
|
#else
|
||||||
|
#ifndef UNITY_DOUBLE_TYPE
|
||||||
|
#define UNITY_DOUBLE_TYPE double
|
||||||
|
#endif
|
||||||
|
typedef UNITY_FLOAT UNITY_DOUBLE;
|
||||||
|
/* For parameter in UnityPrintFloat(UNITY_DOUBLE), which aliases to double or float */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#else
|
#else
|
||||||
@ -250,12 +253,6 @@ typedef UNITY_FLOAT_TYPE UNITY_FLOAT;
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef UNITY_DOUBLE_VERBOSE
|
|
||||||
#ifndef UNITY_FLOAT_VERBOSE
|
|
||||||
#define UNITY_FLOAT_VERBOSE
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*-------------------------------------------------------
|
/*-------------------------------------------------------
|
||||||
* Output Method: stdout (DEFAULT)
|
* Output Method: stdout (DEFAULT)
|
||||||
*-------------------------------------------------------*/
|
*-------------------------------------------------------*/
|
||||||
@ -443,7 +440,7 @@ void UnityPrintNumber(const UNITY_INT number);
|
|||||||
void UnityPrintNumberUnsigned(const UNITY_UINT number);
|
void UnityPrintNumberUnsigned(const UNITY_UINT number);
|
||||||
void UnityPrintNumberHex(const UNITY_UINT number, const char nibbles);
|
void UnityPrintNumberHex(const UNITY_UINT number, const char nibbles);
|
||||||
|
|
||||||
#ifdef UNITY_FLOAT_VERBOSE
|
#ifndef UNITY_EXCLUDE_FLOAT_PRINT
|
||||||
void UnityPrintFloat(const UNITY_DOUBLE number);
|
void UnityPrintFloat(const UNITY_DOUBLE number);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -5,8 +5,8 @@
|
|||||||
========================================== */
|
========================================== */
|
||||||
|
|
||||||
#include "unity.h"
|
#include "unity.h"
|
||||||
#include <setjmp.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
// Dividing by these constants produces +/- infinity.
|
// Dividing by these constants produces +/- infinity.
|
||||||
// The rationale is given in UnityAssertFloatIsInf's body.
|
// The rationale is given in UnityAssertFloatIsInf's body.
|
||||||
@ -59,19 +59,20 @@ static int SetToOneMeanWeAlreadyCheckedThisGuy;
|
|||||||
|
|
||||||
void setUp(void)
|
void setUp(void)
|
||||||
{
|
{
|
||||||
SetToOneToFailInTearDown = 0;
|
SetToOneToFailInTearDown = 0;
|
||||||
SetToOneMeanWeAlreadyCheckedThisGuy = 0;
|
SetToOneMeanWeAlreadyCheckedThisGuy = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void tearDown(void)
|
void tearDown(void)
|
||||||
{
|
{
|
||||||
if (SetToOneToFailInTearDown == 1)
|
endPutcharSpy(); /* Stop suppressing test output */
|
||||||
TEST_FAIL_MESSAGE("<= Failed in tearDown");
|
if (SetToOneToFailInTearDown == 1)
|
||||||
if ((SetToOneMeanWeAlreadyCheckedThisGuy == 0) && (Unity.CurrentTestFailed > 0))
|
TEST_FAIL_MESSAGE("<= Failed in tearDown");
|
||||||
{
|
if ((SetToOneMeanWeAlreadyCheckedThisGuy == 0) && (Unity.CurrentTestFailed > 0))
|
||||||
UnityPrint(": [[[[ Test Should Have Passed But Did Not ]]]]");
|
{
|
||||||
UNITY_OUTPUT_CHAR('\n');
|
UnityPrint(": [[[[ Test Should Have Passed But Did Not ]]]]");
|
||||||
}
|
UNITY_OUTPUT_CHAR('\n');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void testUnitySizeInitializationReminder(void)
|
void testUnitySizeInitializationReminder(void)
|
||||||
@ -2265,7 +2266,7 @@ void putcharSpy(int c)
|
|||||||
if (indexSpyBuffer < SPY_BUFFER_MAX - 1)
|
if (indexSpyBuffer < SPY_BUFFER_MAX - 1)
|
||||||
putcharSpyBuffer[indexSpyBuffer++] = (char)c;
|
putcharSpyBuffer[indexSpyBuffer++] = (char)c;
|
||||||
} else
|
} else
|
||||||
c = putchar(c);
|
putchar((char)c);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2284,10 +2285,14 @@ void testFailureCountIncrementsAndIsReturnedAtEnd(void)
|
|||||||
|
|
||||||
void testCstringsEscapeSequence(void)
|
void testCstringsEscapeSequence(void)
|
||||||
{
|
{
|
||||||
|
#ifndef USING_OUTPUT_SPY
|
||||||
|
TEST_IGNORE();
|
||||||
|
#else
|
||||||
startPutcharSpy();
|
startPutcharSpy();
|
||||||
UnityPrint("\x16\x10");
|
UnityPrint("\x16\x10");
|
||||||
endPutcharSpy();
|
endPutcharSpy();
|
||||||
TEST_ASSERT_EQUAL_STRING("\\x16\\x10", getBufferPutcharSpy());
|
TEST_ASSERT_EQUAL_STRING("\\x16\\x10", getBufferPutcharSpy());
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#define TEST_ASSERT_EQUAL_PRINT_NUMBERS(expected, actual) { \
|
#define TEST_ASSERT_EQUAL_PRINT_NUMBERS(expected, actual) { \
|
||||||
@ -3227,6 +3232,180 @@ void testNotEqualFloatArraysLengthZero(void)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define TEST_ASSERT_EQUAL_PRINT_FLOATING(expected, actual) { \
|
||||||
|
startPutcharSpy(); UnityPrintFloat((actual)); endPutcharSpy(); \
|
||||||
|
TEST_ASSERT_EQUAL_STRING((expected), getBufferPutcharSpy()); \
|
||||||
|
}
|
||||||
|
|
||||||
|
void testFloatPrinting(void)
|
||||||
|
{
|
||||||
|
#if defined(UNITY_EXCLUDE_FLOAT_PRINT) || !defined(USING_OUTPUT_SPY)
|
||||||
|
TEST_IGNORE();
|
||||||
|
#else
|
||||||
|
TEST_ASSERT_EQUAL_PRINT_FLOATING("0.0", 0.0f);
|
||||||
|
TEST_ASSERT_EQUAL_PRINT_FLOATING("0.000000...", 0.000000499f);
|
||||||
|
TEST_ASSERT_EQUAL_PRINT_FLOATING("0.000001", 0.00000050000005f);
|
||||||
|
TEST_ASSERT_EQUAL_PRINT_FLOATING("0.100469", 0.100469499f);
|
||||||
|
TEST_ASSERT_EQUAL_PRINT_FLOATING("1.0", 0.9999995f); /*Rounding to int place*/
|
||||||
|
TEST_ASSERT_EQUAL_PRINT_FLOATING("1.0", 1.0f);
|
||||||
|
TEST_ASSERT_EQUAL_PRINT_FLOATING("1.25", 1.25f);
|
||||||
|
TEST_ASSERT_EQUAL_PRINT_FLOATING("7.999999", 7.999999f); /*Not rounding*/
|
||||||
|
TEST_ASSERT_EQUAL_PRINT_FLOATING("16.000002", 16.000002f);
|
||||||
|
TEST_ASSERT_EQUAL_PRINT_FLOATING("16.000004", 16.000004f);
|
||||||
|
TEST_ASSERT_EQUAL_PRINT_FLOATING("16.000006", 16.000006f);
|
||||||
|
TEST_ASSERT_EQUAL_PRINT_FLOATING("4294967040.0", 4294967040.0f); /*Last full print integer*/
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL_PRINT_FLOATING("0.0", -0.0f);
|
||||||
|
TEST_ASSERT_EQUAL_PRINT_FLOATING("-0.000000...",-0.000000499f);
|
||||||
|
TEST_ASSERT_EQUAL_PRINT_FLOATING("-0.000001", -0.00000050000005f);
|
||||||
|
TEST_ASSERT_EQUAL_PRINT_FLOATING("-0.100469", -0.100469499f);
|
||||||
|
TEST_ASSERT_EQUAL_PRINT_FLOATING("-1.0", -0.9999995f); /*Rounding to int place*/
|
||||||
|
TEST_ASSERT_EQUAL_PRINT_FLOATING("-1.0", -1.0f);
|
||||||
|
TEST_ASSERT_EQUAL_PRINT_FLOATING("-1.25", -1.25f);
|
||||||
|
TEST_ASSERT_EQUAL_PRINT_FLOATING("-7.999999", -7.999999f); /*Not rounding*/
|
||||||
|
TEST_ASSERT_EQUAL_PRINT_FLOATING("-16.000002", -16.000002f);
|
||||||
|
TEST_ASSERT_EQUAL_PRINT_FLOATING("-16.000004", -16.000004f);
|
||||||
|
TEST_ASSERT_EQUAL_PRINT_FLOATING("-16.000006", -16.000006f);
|
||||||
|
TEST_ASSERT_EQUAL_PRINT_FLOATING("-4294967040.0",-4294967040.0f); /*Last full print integer*/
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL_PRINT_FLOATING("4.2949673e+09", 4294967296.0f);
|
||||||
|
TEST_ASSERT_EQUAL_PRINT_FLOATING("5.0e+09", 5000000000.0f);
|
||||||
|
TEST_ASSERT_EQUAL_PRINT_FLOATING("8.0e+09", 8.0e+09f);
|
||||||
|
TEST_ASSERT_EQUAL_PRINT_FLOATING("8.3099991e+09", 8309999104.0f);
|
||||||
|
TEST_ASSERT_EQUAL_PRINT_FLOATING("1.0e+10", 1.0e+10f);
|
||||||
|
TEST_ASSERT_EQUAL_PRINT_FLOATING("1.0e+10", 10000000000.0f);
|
||||||
|
TEST_ASSERT_EQUAL_PRINT_FLOATING("1.00005499e+10", 1.000055e+10f);
|
||||||
|
TEST_ASSERT_EQUAL_PRINT_FLOATING("1.10000006e+38", 1.10000005e+38f);
|
||||||
|
TEST_ASSERT_EQUAL_PRINT_FLOATING("1.63529943e+10", 1.63529943e+10f);
|
||||||
|
TEST_ASSERT_EQUAL_PRINT_FLOATING("3.40282347e+38", 3.40282346638e38f);
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL_PRINT_FLOATING("-1.0e+10", -1.0e+10f);
|
||||||
|
TEST_ASSERT_EQUAL_PRINT_FLOATING("-3.40282347e+38",-3.40282346638e38f);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void testFloatPrintingRoundTiesToEven(void)
|
||||||
|
{
|
||||||
|
#if defined(UNITY_EXCLUDE_FLOAT) || !defined(USING_OUTPUT_SPY)
|
||||||
|
TEST_IGNORE();
|
||||||
|
#else
|
||||||
|
#ifdef UNITY_ROUND_TIES_AWAY_FROM_ZERO
|
||||||
|
TEST_ASSERT_EQUAL_PRINT_FLOATING("0.007813", 0.0078125f);
|
||||||
|
TEST_ASSERT_EQUAL_PRINT_FLOATING("0.976563", 0.9765625f);
|
||||||
|
#else /* Default to Round ties to even */
|
||||||
|
TEST_ASSERT_EQUAL_PRINT_FLOATING("0.007182", 0.0071825f);
|
||||||
|
TEST_ASSERT_EQUAL_PRINT_FLOATING("0.976562", 0.9765625f);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void testFloatPrintingInfinityAndNaN(void)
|
||||||
|
{
|
||||||
|
#if defined(UNITY_EXCLUDE_FLOAT) || !defined(USING_OUTPUT_SPY)
|
||||||
|
TEST_IGNORE();
|
||||||
|
#else
|
||||||
|
TEST_ASSERT_EQUAL_PRINT_FLOATING("Inf", 1.0f / f_zero);
|
||||||
|
TEST_ASSERT_EQUAL_PRINT_FLOATING("-Inf", -1.0f / f_zero);
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL_PRINT_FLOATING("NaN", 0.0f / f_zero);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(UNITY_TEST_ALL_FLOATS_PRINT_OK) && defined(USING_OUTPUT_SPY)
|
||||||
|
static void AllFloatPrinting_LessThan32Bits(void)
|
||||||
|
{
|
||||||
|
char expected[18];
|
||||||
|
union { float f_value; int32_t int_value; } u;
|
||||||
|
/* Float representations are laid out in integer order, walk up the list */
|
||||||
|
for (u.f_value = 0.00000050000005f; u.f_value <= 4294967040.0f; u.int_value += 1)
|
||||||
|
{
|
||||||
|
startPutcharSpy();
|
||||||
|
|
||||||
|
UnityPrintFloat(u.f_value); /*1.5x as fast as sprintf 5e-7f - 0.01f, 20s vs 30s*/
|
||||||
|
int len = sprintf(expected, "%.6f", u.f_value);
|
||||||
|
|
||||||
|
while (expected[len - 1] == '0' && expected[len - 2] != '.') { len--; }
|
||||||
|
expected[len] = '\0'; /* delete trailing 0's */
|
||||||
|
|
||||||
|
if (strcmp(expected, getBufferPutcharSpy()) != 0)
|
||||||
|
{
|
||||||
|
double six_digits = ((double)u.f_value - (uint32_t)u.f_value)*1000000.0;
|
||||||
|
/* Not a tie (remainder != 0.5) => Can't explain the different strings */
|
||||||
|
if (six_digits - (uint32_t)six_digits != 0.5)
|
||||||
|
{
|
||||||
|
/* Fail with diagnostic printing */
|
||||||
|
TEST_ASSERT_EQUAL_PRINT_FLOATING(expected, u.f_value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Compared to perfect, floats are occasionally rounded wrong. It doesn't affect
|
||||||
|
* correctness, though. Two examples (of 13 total found during testing):
|
||||||
|
* Printed: 6.19256349e+20, Exact: 619256348499999981568.0f <= Eliminated by ROUND_TIES_TO_EVEN
|
||||||
|
* Printed: 2.19012272e+35, Exact: 219012271499999993621766990196637696.0f */
|
||||||
|
static void AllFloatPrinting_Larger(const float start, const float end)
|
||||||
|
{
|
||||||
|
unsigned int wrong = 0;
|
||||||
|
char expected[18];
|
||||||
|
union { float f_value; int32_t int_value; } u;
|
||||||
|
for (u.f_value = start; u.f_value <= end; u.int_value += 1)
|
||||||
|
{
|
||||||
|
startPutcharSpy();
|
||||||
|
|
||||||
|
UnityPrintFloat(u.f_value); /*Twice as fast as sprintf 2**32-1e12, 10s vs 21s*/
|
||||||
|
sprintf(expected, "%.8e", u.f_value);
|
||||||
|
|
||||||
|
int len = 11 - 1; /* 11th char is 'e' in exponential format */
|
||||||
|
while (expected[len - 1] == '0' && expected[len - 2] != '.') { len --; }
|
||||||
|
if (expected[14] != '\0') memmove(&expected[12], &expected[13], 3); /* Two char exponent */
|
||||||
|
memmove(&expected[len], &expected[11 - 1], sizeof "e+09"); /* 5 char length */
|
||||||
|
|
||||||
|
if (strcmp(expected, getBufferPutcharSpy()) != 0)
|
||||||
|
{
|
||||||
|
wrong++;
|
||||||
|
/* endPutcharSpy(); UnityPrint("Expected "); UnityPrint(expected);
|
||||||
|
UnityPrint(" Was "); UnityPrint(getBufferPutcharSpy()); UNITY_OUTPUT_CHAR('\n'); */
|
||||||
|
|
||||||
|
if (wrong > 10 || (wrong > 3 && end <= 1e25f))
|
||||||
|
TEST_ASSERT_EQUAL_PRINT_FLOATING(expected, u.f_value);
|
||||||
|
/* Empirical values from the current routine, don't be worse when making changes */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Exhaustive testing of all float values we differentiate when printing. Doubles
|
||||||
|
* are not explored here -- too many. These tests confirm that the routine works
|
||||||
|
* for all floats > 5e-7, positives only. Off by default due to test time.
|
||||||
|
* Compares Unity's routine to your sprintf() C lib, tested to pass on 3 platforms.
|
||||||
|
* Part1 takes a long time, around 3 minutes compiled with -O2
|
||||||
|
* Runs through all floats from 0.000001 - 2**32, ~300 million values */
|
||||||
|
void testAllFloatPrintingPart1_LessThan32Bits(void)
|
||||||
|
{
|
||||||
|
#if defined(UNITY_TEST_ALL_FLOATS_PRINT_OK) && defined(USING_OUTPUT_SPY)
|
||||||
|
AllFloatPrinting_LessThan32Bits();
|
||||||
|
#else
|
||||||
|
TEST_IGNORE(); /* Ignore one of three */
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Test takes a long time, around 3.5 minutes compiled with -O2, try ~500 million values */
|
||||||
|
void testAllFloatPrintingPart2_Larger(void)
|
||||||
|
{
|
||||||
|
#if defined(UNITY_TEST_ALL_FLOATS_PRINT_OK) && defined(USING_OUTPUT_SPY)
|
||||||
|
AllFloatPrinting_Larger(4294967296.0f, 1e25f);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Test takes a long time, around 3.5 minutes compiled with -O2, try ~500 million values */
|
||||||
|
void testAllFloatPrintingPart3_LargerStill(void)
|
||||||
|
{
|
||||||
|
#if defined(UNITY_TEST_ALL_FLOATS_PRINT_OK) && defined(USING_OUTPUT_SPY)
|
||||||
|
AllFloatPrinting_Larger(1e25f, 3.40282347e+38f);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
// ===================== THESE TEST WILL RUN IF YOUR CONFIG INCLUDES DOUBLE SUPPORT ==================
|
// ===================== THESE TEST WILL RUN IF YOUR CONFIG INCLUDES DOUBLE SUPPORT ==================
|
||||||
|
|
||||||
void testDoublesWithinDelta(void)
|
void testDoublesWithinDelta(void)
|
||||||
@ -3750,6 +3929,55 @@ void testNotEqualDoubleArraysLengthZero(void)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void testDoublePrinting(void)
|
||||||
|
{
|
||||||
|
#if defined(UNITY_EXCLUDE_DOUBLE) || !defined(USING_OUTPUT_SPY)
|
||||||
|
TEST_IGNORE();
|
||||||
|
#else
|
||||||
|
TEST_ASSERT_EQUAL_PRINT_FLOATING("0.100469", 0.10046949999999999);
|
||||||
|
TEST_ASSERT_EQUAL_PRINT_FLOATING("4294967295.999999", 4294967295.999999);
|
||||||
|
TEST_ASSERT_EQUAL_PRINT_FLOATING("4.2949673e+09", 4294967295.9999995);
|
||||||
|
TEST_ASSERT_EQUAL_PRINT_FLOATING("4.2949673e+09", 4294967296.0);
|
||||||
|
TEST_ASSERT_EQUAL_PRINT_FLOATING("1.0e+10", 9999999995.0);
|
||||||
|
TEST_ASSERT_EQUAL_PRINT_FLOATING("9.00719925e+15", 9007199254740990.0);
|
||||||
|
TEST_ASSERT_EQUAL_PRINT_FLOATING("7.0e+100", 7.0e+100);
|
||||||
|
TEST_ASSERT_EQUAL_PRINT_FLOATING("3.0e+200", 3.0e+200);
|
||||||
|
TEST_ASSERT_EQUAL_PRINT_FLOATING("9.23456789e+300", 9.23456789e+300);
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL_PRINT_FLOATING("-0.100469", -0.10046949999999999);
|
||||||
|
TEST_ASSERT_EQUAL_PRINT_FLOATING("-4294967295.999999", -4294967295.999999);
|
||||||
|
TEST_ASSERT_EQUAL_PRINT_FLOATING("-4.2949673e+09", -4294967295.9999995);
|
||||||
|
TEST_ASSERT_EQUAL_PRINT_FLOATING("-7.0e+100", -7.0e+100);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void testDoublePrintingRoundTiesToEven(void)
|
||||||
|
{
|
||||||
|
#if defined(UNITY_EXCLUDE_DOUBLE) || !defined(USING_OUTPUT_SPY)
|
||||||
|
TEST_IGNORE();
|
||||||
|
#else
|
||||||
|
#ifdef UNITY_ROUND_TIES_AWAY_FROM_ZERO
|
||||||
|
TEST_ASSERT_EQUAL_PRINT_FLOATING("1.00000001e+10", 10000000050.0);
|
||||||
|
TEST_ASSERT_EQUAL_PRINT_FLOATING("9.00719925e+15", 9007199245000000.0);
|
||||||
|
#else /* Default to Round ties to even */
|
||||||
|
TEST_ASSERT_EQUAL_PRINT_FLOATING("1.0e+10", 10000000050.0);
|
||||||
|
TEST_ASSERT_EQUAL_PRINT_FLOATING("9.00719924e+15", 9007199245000000.0);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void testDoublePrintingInfinityAndNaN(void)
|
||||||
|
{
|
||||||
|
#if defined(UNITY_EXCLUDE_DOUBLE) || !defined(USING_OUTPUT_SPY)
|
||||||
|
TEST_IGNORE();
|
||||||
|
#else
|
||||||
|
TEST_ASSERT_EQUAL_PRINT_FLOATING("Inf", 1.0 / d_zero);
|
||||||
|
TEST_ASSERT_EQUAL_PRINT_FLOATING("-Inf", -1.0 / d_zero);
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL_PRINT_FLOATING("NaN", 0.0 / d_zero);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
// ===================== THESE TEST WILL RUN IF YOUR CONFIG INCLUDES DETAIL SUPPORT ==================
|
// ===================== THESE TEST WILL RUN IF YOUR CONFIG INCLUDES DETAIL SUPPORT ==================
|
||||||
|
|
||||||
void testThatDetailsCanBeHandleOneDetail(void)
|
void testThatDetailsCanBeHandleOneDetail(void)
|
||||||
|
Reference in New Issue
Block a user