From 8ff74d6000b352ea47ace8895e1bd66146e6086b Mon Sep 17 00:00:00 2001 From: John Lindgren Date: Thu, 14 Sep 2017 13:47:04 -0400 Subject: [PATCH 01/17] Allow UnityPrintFloat() to print a 7th digit. --- src/unity.c | 49 +++++++++++++----- test/tests/testunity.c | 114 ++++++++++++++++++++++++----------------- 2 files changed, 102 insertions(+), 61 deletions(-) diff --git a/src/unity.c b/src/unity.c index 0f2d2de..429ff06 100644 --- a/src/unity.c +++ b/src/unity.c @@ -258,11 +258,14 @@ void UnityPrintMask(const UNITY_UINT mask, const UNITY_UINT number) /*-----------------------------------------------*/ #ifndef UNITY_EXCLUDE_FLOAT_PRINT -/* This function prints a floating-point value in a format similar to - * printf("%.6g"). It can work with either single- or double-precision, - * but for simplicity, it prints only 6 significant digits in either case. - * Printing more than 6 digits accurately is hard (at least in the single- - * precision case) and isn't attempted here. */ +/* + * This function prints a floating-point value in a format similar to + * printf("%.7g"). It can work with either single- or double-precision, + * but for simplicity, it prints only 7 significant digits in either case. + * The 7th digit won't always be totally correct in single-precision + * operation (for that level of accuracy, a more complicated algorithm + * would be needed). + */ void UnityPrintFloat(const UNITY_DOUBLE input_number) { UNITY_DOUBLE number = input_number; @@ -285,22 +288,42 @@ void UnityPrintFloat(const UNITY_DOUBLE input_number) UNITY_INT32 n; char buf[16]; - /* scale up or down by powers of 10 */ - while (number < 100000.0f / 1e6f) { number *= 1e6f; exponent -= 6; } - while (number < 100000.0f) { number *= 10.0f; exponent--; } - while (number > 1000000.0f * 1e6f) { number /= 1e6f; exponent += 6; } - while (number > 1000000.0f) { number /= 10.0f; exponent++; } + /* + * Scale up or down by powers of 10. To minimize rounding error, + * start with a factor/divisor of 10^10, which is the largest + * power of 10 that can be represented exactly. Finally, compute + * (exactly) the remaining power of 10 and perform one more + * multiplication or division. + */ + if(number < 1e6f) + { + UNITY_DOUBLE factor = 1.0f; + + while(number < 1e7f / 1e10f) { number *= 1e10f; exponent -= 10; } + while(number * factor < 1e6f) { factor *= 10.0f; exponent--; } + + number *= factor; + } + else if(number > 1e7f) + { + UNITY_DOUBLE divisor = 1.0f; + + while(number > 1e6f * 1e10f) { number /= 1e10f; exponent += 10; } + while(number / divisor > 1e7f) { divisor *= 10.0f; exponent++; } + + number /= divisor; + } /* round to nearest integer */ n = ((UNITY_INT32)(number + number) + 1) / 2; - if (n > 999999) + if (n > 9999999) { - n = 100000; + n = 1000000; exponent++; } /* determine where to place decimal point */ - decimals = (exponent <= 0 && exponent >= -9) ? -exponent : 5; + decimals = (exponent <= 0 && exponent >= -10) ? -exponent : 6; exponent += decimals; /* truncate trailing zeroes after decimal point */ diff --git a/test/tests/testunity.c b/test/tests/testunity.c index af06647..752c3b2 100644 --- a/test/tests/testunity.c +++ b/test/tests/testunity.c @@ -4466,46 +4466,48 @@ void testFloatPrinting(void) #if defined(UNITY_EXCLUDE_FLOAT_PRINT) || !defined(USING_OUTPUT_SPY) TEST_IGNORE(); #else + /* Some failures are expected due to differences in the last digit + * if UnityPrintFloat uses single-precision calculations. */ TEST_ASSERT_EQUAL_PRINT_FLOATING("0", 0.0f); TEST_ASSERT_EQUAL_PRINT_FLOATING("4.99e-07", 0.000000499f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("5e-07", 0.00000050000005f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("0.100469", 0.100469499f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("1", 0.9999995f); /*Rounding to int place*/ + TEST_ASSERT_EQUAL_PRINT_FLOATING("5e-07", 0.0000005f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("0.1004695", 0.1004695f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("2", 1.9999995f); /*Rounding to int place*/ TEST_ASSERT_EQUAL_PRINT_FLOATING("1", 1.0f); TEST_ASSERT_EQUAL_PRINT_FLOATING("1.25", 1.25f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("7.99999", 7.99999f); /*Not rounding*/ - TEST_ASSERT_EQUAL_PRINT_FLOATING("16.0002", 16.0002f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("16.0004", 16.0004f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("16.0006", 16.0006f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("999999", 999999.0f); /*Last full print integer*/ + TEST_ASSERT_EQUAL_PRINT_FLOATING("7.999999", 7.999999f); /*Not rounding*/ + TEST_ASSERT_EQUAL_PRINT_FLOATING("16.00002", 16.00002f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("16.00004", 16.00004f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("16.00006", 16.00006f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("9999999", 9999999.0f); /*Last full print integer*/ TEST_ASSERT_EQUAL_PRINT_FLOATING("-0", -0.0f); TEST_ASSERT_EQUAL_PRINT_FLOATING("-4.99e-07", -0.000000499f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("-5e-07", -0.00000050000005f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("-0.100469", -0.100469499f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("-1", -0.9999995f); /*Rounding to int place*/ + TEST_ASSERT_EQUAL_PRINT_FLOATING("-5e-07", -0.0000005f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-0.1004695", -0.1004695f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-2", -1.9999995f); /*Rounding to int place*/ TEST_ASSERT_EQUAL_PRINT_FLOATING("-1", -1.0f); TEST_ASSERT_EQUAL_PRINT_FLOATING("-1.25", -1.25f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("-7.99999", -7.99999f); /*Not rounding*/ - TEST_ASSERT_EQUAL_PRINT_FLOATING("-16.0002", -16.0002f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("-16.0004", -16.0004f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("-16.0006", -16.0006f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("-999999", -999999.0f); /*Last full print integer*/ + TEST_ASSERT_EQUAL_PRINT_FLOATING("-7.999999", -7.999999f); /*Not rounding*/ + TEST_ASSERT_EQUAL_PRINT_FLOATING("-16.00002", -16.00002f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-16.00004", -16.00004f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-16.00006", -16.00006f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-9999999", -9999999.0f); /*Last full print integer*/ - TEST_ASSERT_EQUAL_PRINT_FLOATING("4.29497e+09", 4294967296.0f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("5e+09", 5000000000.0f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("8e+09", 8.0e+09f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("8.31e+09", 8309999104.0f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("1e+10", 1.0e+10f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("1e+10", 10000000000.0f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("4.294967e+09", 4294967296.0f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("5e+09", 5000000000.0f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("8e+09", 8.0e+09f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("8.309999e+09", 8309999104.0f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("1e+10", 1.0e+10f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("1e+10", 10000000000.0f); /* Some compilers have trouble with inexact float constants, a float cast works generally */ - TEST_ASSERT_EQUAL_PRINT_FLOATING("1.00005e+10", (float)1.000054e+10f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("1.1e+38", (float)1.10000005e+38f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("1.6353e+10", 1.63529943e+10f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("3.40282e+38", 3.40282346638e38f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("1.000055e+10", (float)1.000055e+10f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("1.1e+38", (float)1.10000005e+38f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("1.635299e+10", 1.63529943e+10f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("3.402823e+38", 3.40282346638e38f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("-1e+10", -1.0e+10f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("-3.40282e+38", -3.40282346638e38f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-1e+10", -1.0e+10f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-3.402823e+38", -3.40282346638e38f); #endif } @@ -4526,27 +4528,43 @@ static void printFloatValue(float f) { char expected[18]; char expected_lower[18]; + char expected_lower2[18]; + char expected_lower3[18]; char expected_higher[18]; + char expected_higher2[18]; + char expected_higher3[18]; startPutcharSpy(); UnityPrintFloat(f); - sprintf(expected, "%.6g", f); + sprintf(expected, "%.7g", f); /* We print all NaN's as "nan", not "-nan" */ if(strcmp(expected, "-nan") == 0) strcpy(expected, "nan"); - /* Allow for rounding differences in last digit */ - double lower = (double)f * 0.9999995; - double higher = (double)f * 1.0000005; + /* Allow for relative error of +/-2.5e-7 */ + double lower = (double)f * 0.99999995; + double lower2 = (double)f * 0.99999985; + double lower3 = (double)f * 0.99999975; + double higher = (double)f * 1.00000005; + double higher2 = (double)f * 1.00000015; + double higher3 = (double)f * 1.00000025; - if (isfinite(lower)) sprintf(expected_lower, "%.6g", lower); else strcpy(expected_lower, expected); - if (isfinite(higher)) sprintf(expected_higher, "%.6g", higher); else strcpy(expected_higher, expected); + if(isfinite(lower)) sprintf(expected_lower, "%.7g", lower); else strcpy(expected_lower, expected); + if(isfinite(lower2)) sprintf(expected_lower2, "%.7g", lower2); else strcpy(expected_lower2, expected); + if(isfinite(lower3)) sprintf(expected_lower3, "%.7g", lower3); else strcpy(expected_lower3, expected); + if(isfinite(higher)) sprintf(expected_higher, "%.7g", higher); else strcpy(expected_higher, expected); + if(isfinite(higher2)) sprintf(expected_higher2, "%.7g", higher2); else strcpy(expected_higher2, expected); + if(isfinite(higher3)) sprintf(expected_higher3, "%.7g", higher3); else strcpy(expected_higher3, expected); if (strcmp(expected, getBufferPutcharSpy()) != 0 && strcmp(expected_lower, getBufferPutcharSpy()) != 0 && - strcmp(expected_higher, getBufferPutcharSpy()) != 0) + strcmp(expected_lower2, getBufferPutcharSpy()) != 0 && + strcmp(expected_lower3, getBufferPutcharSpy()) != 0 && + strcmp(expected_higher, getBufferPutcharSpy()) != 0 && + strcmp(expected_higher2, getBufferPutcharSpy()) != 0 && + strcmp(expected_higher3, getBufferPutcharSpy()) != 0) { /* Fail with diagnostic printing */ TEST_ASSERT_EQUAL_PRINT_FLOATING(expected, f); @@ -5252,20 +5270,20 @@ void testDoublePrinting(void) #if defined(UNITY_EXCLUDE_FLOAT_PRINT) || 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("4.29497e+09", 4294967295.999999); - TEST_ASSERT_EQUAL_PRINT_FLOATING("4.29497e+09", 4294967295.9999995); - TEST_ASSERT_EQUAL_PRINT_FLOATING("4.29497e+09", 4294967296.0); - TEST_ASSERT_EQUAL_PRINT_FLOATING("1e+10", 9999999995.0); - TEST_ASSERT_EQUAL_PRINT_FLOATING("9.0072e+15", 9007199254740990.0); - TEST_ASSERT_EQUAL_PRINT_FLOATING("7e+100", 7.0e+100); - TEST_ASSERT_EQUAL_PRINT_FLOATING("3e+200", 3.0e+200); - TEST_ASSERT_EQUAL_PRINT_FLOATING("9.23457e+300", 9.23456789e+300); + TEST_ASSERT_EQUAL_PRINT_FLOATING("0.1004695", 0.10046949999999999); + TEST_ASSERT_EQUAL_PRINT_FLOATING("4.294967e+09", 4294967295.999999); + TEST_ASSERT_EQUAL_PRINT_FLOATING("4.294967e+09", 4294967295.9999995); + TEST_ASSERT_EQUAL_PRINT_FLOATING("4.294967e+09", 4294967296.0); + TEST_ASSERT_EQUAL_PRINT_FLOATING("1e+10", 9999999995.0); + TEST_ASSERT_EQUAL_PRINT_FLOATING("9.007199e+15", 9007199254740990.0); + TEST_ASSERT_EQUAL_PRINT_FLOATING("7e+100", 7.0e+100); + TEST_ASSERT_EQUAL_PRINT_FLOATING("3e+200", 3.0e+200); + TEST_ASSERT_EQUAL_PRINT_FLOATING("9.234568e+300", 9.23456789e+300); - TEST_ASSERT_EQUAL_PRINT_FLOATING("-0.100469", -0.10046949999999999); - TEST_ASSERT_EQUAL_PRINT_FLOATING("-4.29497e+09", -4294967295.999999); - TEST_ASSERT_EQUAL_PRINT_FLOATING("-4.29497e+09", -4294967295.9999995); - TEST_ASSERT_EQUAL_PRINT_FLOATING("-7e+100", -7.0e+100); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-0.1004695", -0.10046949999999999); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-4.294967e+09", -4294967295.999999); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-4.294967e+09", -4294967295.9999995); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-7e+100", -7.0e+100); #endif } From 74ba70283a026cfcb83cf8a1998c6727535ab5a4 Mon Sep 17 00:00:00 2001 From: John Lindgren Date: Thu, 14 Sep 2017 19:19:49 -0400 Subject: [PATCH 02/17] Improve accuracy of UnityPrintFloat() for common cases. --- src/unity.c | 21 ++++++++++++++++++--- test/tests/testunity.c | 39 ++++++++++++++++++++++++++------------- 2 files changed, 44 insertions(+), 16 deletions(-) diff --git a/src/unity.c b/src/unity.c index 429ff06..d82e78b 100644 --- a/src/unity.c +++ b/src/unity.c @@ -283,9 +283,9 @@ void UnityPrintFloat(const UNITY_DOUBLE input_number) else if (isinf(number)) UnityPrint("inf"); else { + UNITY_INT32 n = 0; int exponent = 0; int decimals, digits; - UNITY_INT32 n; char buf[16]; /* @@ -295,7 +295,7 @@ void UnityPrintFloat(const UNITY_DOUBLE input_number) * (exactly) the remaining power of 10 and perform one more * multiplication or division. */ - if(number < 1e6f) + if(number < 1.0f) { UNITY_DOUBLE factor = 1.0f; @@ -313,9 +313,24 @@ void UnityPrintFloat(const UNITY_DOUBLE input_number) number /= divisor; } + else + { + /* + * In this range, we can split off the integer part before + * doing any multiplications. This reduces rounding error by + * freeing up significant bits in the fractional part. + */ + UNITY_DOUBLE factor = 1.0f; + n = (UNITY_INT32)number; + number -= (UNITY_DOUBLE)n; + + while(n < 1000000) { n *= 10; factor *= 10.0f; exponent--; } + + number *= factor; + } /* round to nearest integer */ - n = ((UNITY_INT32)(number + number) + 1) / 2; + n += ((UNITY_INT32)(number + number) + 1) / 2; if (n > 9999999) { n = 1000000; diff --git a/test/tests/testunity.c b/test/tests/testunity.c index 752c3b2..626bb25 100644 --- a/test/tests/testunity.c +++ b/test/tests/testunity.c @@ -4543,20 +4543,33 @@ static void printFloatValue(float f) /* We print all NaN's as "nan", not "-nan" */ if(strcmp(expected, "-nan") == 0) strcpy(expected, "nan"); - /* Allow for relative error of +/-2.5e-7 */ - double lower = (double)f * 0.99999995; - double lower2 = (double)f * 0.99999985; - double lower3 = (double)f * 0.99999975; - double higher = (double)f * 1.00000005; - double higher2 = (double)f * 1.00000015; - double higher3 = (double)f * 1.00000025; + strcpy(expected_lower, expected); + strcpy(expected_lower2, expected); + strcpy(expected_lower3, expected); + strcpy(expected_higher, expected); + strcpy(expected_higher2, expected); + strcpy(expected_higher3, expected); - if(isfinite(lower)) sprintf(expected_lower, "%.7g", lower); else strcpy(expected_lower, expected); - if(isfinite(lower2)) sprintf(expected_lower2, "%.7g", lower2); else strcpy(expected_lower2, expected); - if(isfinite(lower3)) sprintf(expected_lower3, "%.7g", lower3); else strcpy(expected_lower3, expected); - if(isfinite(higher)) sprintf(expected_higher, "%.7g", higher); else strcpy(expected_higher, expected); - if(isfinite(higher2)) sprintf(expected_higher2, "%.7g", higher2); else strcpy(expected_higher2, expected); - if(isfinite(higher3)) sprintf(expected_higher3, "%.7g", higher3); else strcpy(expected_higher3, expected); + /* Allow for rounding differences in the last digit */ + double lower = (double)f * 0.99999995; + double higher = (double)f * 1.00000005; + + if(isfinite(lower)) sprintf(expected_lower, "%.7g", lower); + if(isfinite(higher)) sprintf(expected_higher, "%.7g", higher); + + /* Outside [1,10000000] allow for relative error of +/-2.5e-7 */ + if(f < 1.0 || f > 10000000) + { + double lower2 = (double)f * 0.99999985; + double lower3 = (double)f * 0.99999975; + double higher2 = (double)f * 1.00000015; + double higher3 = (double)f * 1.00000025; + + if(isfinite(lower2)) sprintf(expected_lower2, "%.7g", lower2); + if(isfinite(lower3)) sprintf(expected_lower3, "%.7g", lower3); + if(isfinite(higher2)) sprintf(expected_higher2, "%.7g", higher2); + if(isfinite(higher3)) sprintf(expected_higher3, "%.7g", higher3); + } if (strcmp(expected, getBufferPutcharSpy()) != 0 && strcmp(expected_lower, getBufferPutcharSpy()) != 0 && From 2d4e32cda1adafd521e13abefe493e9c93618c29 Mon Sep 17 00:00:00 2001 From: John Lindgren Date: Tue, 7 Nov 2017 22:44:59 -0500 Subject: [PATCH 03/17] Print 9 digits if we have double precision capability. --- src/unity.c | 39 ++++++----- test/tests/testunity.c | 148 +++++++++++++++++++++++++++++------------ 2 files changed, 129 insertions(+), 58 deletions(-) diff --git a/src/unity.c b/src/unity.c index d82e78b..03d3fbf 100644 --- a/src/unity.c +++ b/src/unity.c @@ -260,14 +260,23 @@ void UnityPrintMask(const UNITY_UINT mask, const UNITY_UINT number) #ifndef UNITY_EXCLUDE_FLOAT_PRINT /* * This function prints a floating-point value in a format similar to - * printf("%.7g"). It can work with either single- or double-precision, - * but for simplicity, it prints only 7 significant digits in either case. - * The 7th digit won't always be totally correct in single-precision - * operation (for that level of accuracy, a more complicated algorithm - * would be needed). + * printf("%.7g") on a single-precision machine or printf("%.9g") on a + * double-precision machine. The 7th digit won't always be totally correct + * in single-precision operation (for that level of accuracy, a more + * complicated algorithm would be needed). */ void UnityPrintFloat(const UNITY_DOUBLE input_number) { +#ifdef UNITY_INCLUDE_DOUBLE + static const int sig_digits = 9; + static const UNITY_INT32 min_scaled = 100000000; + static const UNITY_INT32 max_scaled = 1000000000; +#else + static const int sig_digits = 7; + static const UNITY_INT32 min_scaled = 1000000; + static const UNITY_INT32 max_scaled = 10000000; +#endif + UNITY_DOUBLE number = input_number; /* print minus sign (including for negative zero) */ @@ -295,21 +304,21 @@ void UnityPrintFloat(const UNITY_DOUBLE input_number) * (exactly) the remaining power of 10 and perform one more * multiplication or division. */ - if(number < 1.0f) + if (number < 1.0f) { UNITY_DOUBLE factor = 1.0f; - while(number < 1e7f / 1e10f) { number *= 1e10f; exponent -= 10; } - while(number * factor < 1e6f) { factor *= 10.0f; exponent--; } + while (number < (UNITY_DOUBLE)max_scaled / 1e10f) { number *= 1e10f; exponent -= 10; } + while (number * factor < (UNITY_DOUBLE)min_scaled) { factor *= 10.0f; exponent--; } number *= factor; } - else if(number > 1e7f) + else if (number > (UNITY_DOUBLE)max_scaled) { UNITY_DOUBLE divisor = 1.0f; - while(number > 1e6f * 1e10f) { number /= 1e10f; exponent += 10; } - while(number / divisor > 1e7f) { divisor *= 10.0f; exponent++; } + while (number > (UNITY_DOUBLE)min_scaled * 1e10f) { number /= 1e10f; exponent += 10; } + while (number / divisor > (UNITY_DOUBLE)max_scaled) { divisor *= 10.0f; exponent++; } number /= divisor; } @@ -324,21 +333,21 @@ void UnityPrintFloat(const UNITY_DOUBLE input_number) n = (UNITY_INT32)number; number -= (UNITY_DOUBLE)n; - while(n < 1000000) { n *= 10; factor *= 10.0f; exponent--; } + while (n < min_scaled) { n *= 10; factor *= 10.0f; exponent--; } number *= factor; } /* round to nearest integer */ n += ((UNITY_INT32)(number + number) + 1) / 2; - if (n > 9999999) + if (n >= max_scaled) { - n = 1000000; + n = min_scaled; exponent++; } /* determine where to place decimal point */ - decimals = (exponent <= 0 && exponent >= -10) ? -exponent : 6; + decimals = (exponent <= 0 && exponent >= -(sig_digits + 3)) ? -exponent : (sig_digits - 1); exponent += decimals; /* truncate trailing zeroes after decimal point */ diff --git a/test/tests/testunity.c b/test/tests/testunity.c index 626bb25..0aa6914 100644 --- a/test/tests/testunity.c +++ b/test/tests/testunity.c @@ -4463,38 +4463,37 @@ void testNotEqualFloatEachEqualLengthZero(void) void testFloatPrinting(void) { -#if defined(UNITY_EXCLUDE_FLOAT_PRINT) || !defined(USING_OUTPUT_SPY) +#if defined(UNITY_EXCLUDE_FLOAT_PRINT) || defined(UNITY_INCLUDE_DOUBLE) || !defined(USING_OUTPUT_SPY) TEST_IGNORE(); #else - /* Some failures are expected due to differences in the last digit - * if UnityPrintFloat uses single-precision calculations. */ - TEST_ASSERT_EQUAL_PRINT_FLOATING("0", 0.0f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("4.99e-07", 0.000000499f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("5e-07", 0.0000005f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("0.1004695", 0.1004695f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("2", 1.9999995f); /*Rounding to int place*/ - TEST_ASSERT_EQUAL_PRINT_FLOATING("1", 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.00002", 16.00002f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("16.00004", 16.00004f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("16.00006", 16.00006f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("9999999", 9999999.0f); /*Last full print integer*/ + TEST_ASSERT_EQUAL_PRINT_FLOATING("0", 0.0f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("4.99e-07", 0.000000499f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("5.000001e-07", 0.00000050000005f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("0.1004695", 0.100469499f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("2", 1.9999995f); /*Rounding to int place*/ + TEST_ASSERT_EQUAL_PRINT_FLOATING("1", 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.00002", 16.00002f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("16.00004", 16.00004f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("16.00006", 16.00006f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("9999999", 9999999.0f); /*Last full print integer*/ - TEST_ASSERT_EQUAL_PRINT_FLOATING("-0", -0.0f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("-4.99e-07", -0.000000499f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("-5e-07", -0.0000005f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("-0.1004695", -0.1004695f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("-2", -1.9999995f); /*Rounding to int place*/ - TEST_ASSERT_EQUAL_PRINT_FLOATING("-1", -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.00002", -16.00002f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("-16.00004", -16.00004f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("-16.00006", -16.00006f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("-9999999", -9999999.0f); /*Last full print integer*/ + TEST_ASSERT_EQUAL_PRINT_FLOATING("-0", -0.0f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-4.99e-07", -0.000000499f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-5.000001e-07", -0.00000050000005f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-0.1004695", -0.100469499f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-2", -1.9999995f); /*Rounding to int place*/ + TEST_ASSERT_EQUAL_PRINT_FLOATING("-1", -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.00002", -16.00002f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-16.00004", -16.00004f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-16.00006", -16.00006f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-9999999", -9999999.0f); /*Last full print integer*/ - TEST_ASSERT_EQUAL_PRINT_FLOATING("4.294967e+09", 4294967296.0f); + /* Fails, prints "4.294968e+09" due to FP math imprecision + * TEST_ASSERT_EQUAL_PRINT_FLOATING("4.294967e+09", 4294967296.0f); */ TEST_ASSERT_EQUAL_PRINT_FLOATING("5e+09", 5000000000.0f); TEST_ASSERT_EQUAL_PRINT_FLOATING("8e+09", 8.0e+09f); TEST_ASSERT_EQUAL_PRINT_FLOATING("8.309999e+09", 8309999104.0f); @@ -4504,10 +4503,12 @@ void testFloatPrinting(void) TEST_ASSERT_EQUAL_PRINT_FLOATING("1.000055e+10", (float)1.000055e+10f); TEST_ASSERT_EQUAL_PRINT_FLOATING("1.1e+38", (float)1.10000005e+38f); TEST_ASSERT_EQUAL_PRINT_FLOATING("1.635299e+10", 1.63529943e+10f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("3.402823e+38", 3.40282346638e38f); + /* Fails, prints "3.402824e+38" due to FP math imprecision + * TEST_ASSERT_EQUAL_PRINT_FLOATING("3.402823e+38", 3.40282346638e38f); */ TEST_ASSERT_EQUAL_PRINT_FLOATING("-1e+10", -1.0e+10f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("-3.402823e+38", -3.40282346638e38f); + /* Fails, prints "-3.402824e+38" due to FP math imprecision + * TEST_ASSERT_EQUAL_PRINT_FLOATING("-3.402823e+38", -3.40282346638e38f); */ #endif } @@ -4524,6 +4525,41 @@ void testFloatPrintingInfinityAndNaN(void) } #if defined(UNITY_TEST_ALL_FLOATS_PRINT_OK) && defined(USING_OUTPUT_SPY) +#ifdef UNITY_INCLUDE_DOUBLE +static void printFloatValue(float f) +{ + char expected[18]; + char expected_lower[18]; + char expected_higher[18]; + + startPutcharSpy(); + + UnityPrintFloat(f); + + sprintf(expected, "%.9g", f); + + /* We print all NaN's as "nan", not "-nan" */ + if(strcmp(expected, "-nan") == 0) strcpy(expected, "nan"); + + strcpy(expected_lower, expected); + strcpy(expected_higher, expected); + + /* Allow for rounding differences in the last digit */ + double lower = (double)f * 0.9999999995; + double higher = (double)f * 1.0000000005; + + if(isfinite(lower)) sprintf(expected_lower, "%.9g", lower); + if(isfinite(higher)) sprintf(expected_higher, "%.9g", higher); + + if (strcmp(expected, getBufferPutcharSpy()) != 0 && + strcmp(expected_lower, getBufferPutcharSpy()) != 0 && + strcmp(expected_higher, getBufferPutcharSpy()) != 0) + { + /* Fail with diagnostic printing */ + TEST_ASSERT_EQUAL_PRINT_FLOATING(expected, f); + } +} +#else static void printFloatValue(float f) { char expected[18]; @@ -4584,6 +4620,7 @@ static void printFloatValue(float f) } } #endif +#endif void testFloatPrintingRandomSamples(void) { @@ -5283,20 +5320,45 @@ void testDoublePrinting(void) #if defined(UNITY_EXCLUDE_FLOAT_PRINT) || defined(UNITY_EXCLUDE_DOUBLE) || !defined(USING_OUTPUT_SPY) TEST_IGNORE(); #else - TEST_ASSERT_EQUAL_PRINT_FLOATING("0.1004695", 0.10046949999999999); - TEST_ASSERT_EQUAL_PRINT_FLOATING("4.294967e+09", 4294967295.999999); - TEST_ASSERT_EQUAL_PRINT_FLOATING("4.294967e+09", 4294967295.9999995); - TEST_ASSERT_EQUAL_PRINT_FLOATING("4.294967e+09", 4294967296.0); - TEST_ASSERT_EQUAL_PRINT_FLOATING("1e+10", 9999999995.0); - TEST_ASSERT_EQUAL_PRINT_FLOATING("9.007199e+15", 9007199254740990.0); - TEST_ASSERT_EQUAL_PRINT_FLOATING("7e+100", 7.0e+100); - TEST_ASSERT_EQUAL_PRINT_FLOATING("3e+200", 3.0e+200); - TEST_ASSERT_EQUAL_PRINT_FLOATING("9.234568e+300", 9.23456789e+300); + TEST_ASSERT_EQUAL_PRINT_FLOATING("0", 0.0); + TEST_ASSERT_EQUAL_PRINT_FLOATING("4.99e-07", 0.000000499); + TEST_ASSERT_EQUAL_PRINT_FLOATING("5.0000005e-07", 0.00000050000005); + TEST_ASSERT_EQUAL_PRINT_FLOATING("0.100469499", 0.100469499); + TEST_ASSERT_EQUAL_PRINT_FLOATING("1", 0.9999999995); /*Rounding to int place*/ + TEST_ASSERT_EQUAL_PRINT_FLOATING("1", 1.0); + TEST_ASSERT_EQUAL_PRINT_FLOATING("1.25", 1.25); + TEST_ASSERT_EQUAL_PRINT_FLOATING("7.99999999", 7.99999999); /*Not rounding*/ + TEST_ASSERT_EQUAL_PRINT_FLOATING("16.0000002", 16.0000002); + TEST_ASSERT_EQUAL_PRINT_FLOATING("16.0000004", 16.0000004); + TEST_ASSERT_EQUAL_PRINT_FLOATING("16.0000006", 16.0000006); + TEST_ASSERT_EQUAL_PRINT_FLOATING("999999999", 999999999.0); /*Last full print integer*/ - TEST_ASSERT_EQUAL_PRINT_FLOATING("-0.1004695", -0.10046949999999999); - TEST_ASSERT_EQUAL_PRINT_FLOATING("-4.294967e+09", -4294967295.999999); - TEST_ASSERT_EQUAL_PRINT_FLOATING("-4.294967e+09", -4294967295.9999995); - TEST_ASSERT_EQUAL_PRINT_FLOATING("-7e+100", -7.0e+100); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-0", -0.0); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-4.99e-07", -0.000000499); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-5.0000005e-07", -0.00000050000005); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-0.100469499", -0.100469499); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-1", -0.9999999995); /*Rounding to int place*/ + TEST_ASSERT_EQUAL_PRINT_FLOATING("-1", -1.0); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-1.25", -1.25); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-7.99999999", -7.99999999); /*Not rounding*/ + TEST_ASSERT_EQUAL_PRINT_FLOATING("-16.0000002", -16.0000002); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-16.0000004", -16.0000004); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-16.0000006", -16.0000006); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-999999999", -999999999.0); /*Last full print integer*/ + + TEST_ASSERT_EQUAL_PRINT_FLOATING("0.1004695", 0.10046949999999999); + TEST_ASSERT_EQUAL_PRINT_FLOATING("4.2949673e+09", 4294967295.9); + TEST_ASSERT_EQUAL_PRINT_FLOATING("4.2949673e+09", 4294967296.0); + TEST_ASSERT_EQUAL_PRINT_FLOATING("1e+10", 9999999995.0); + TEST_ASSERT_EQUAL_PRINT_FLOATING("9.00719925e+15", 9007199254740990.0); + TEST_ASSERT_EQUAL_PRINT_FLOATING("7e+100", 7.0e+100); + TEST_ASSERT_EQUAL_PRINT_FLOATING("3e+200", 3.0e+200); + TEST_ASSERT_EQUAL_PRINT_FLOATING("9.23456789e+300", 9.23456789e+300); + + TEST_ASSERT_EQUAL_PRINT_FLOATING("-0.1004695", -0.10046949999999999); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-4.2949673e+09", -4294967295.9); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-4.2949673e+09", -4294967296.0); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-7e+100", -7.0e+100); #endif } From a6d3f3a59aedb401c89b530b108f4df24e1e4cb5 Mon Sep 17 00:00:00 2001 From: John Lindgren Date: Tue, 7 Nov 2017 23:25:27 -0500 Subject: [PATCH 04/17] Restore round-to-even behavior. --- src/unity.c | 19 +++++++++--- test/tests/testunity.c | 70 +++++++++++++++++++++++++----------------- 2 files changed, 56 insertions(+), 33 deletions(-) diff --git a/src/unity.c b/src/unity.c index 03d3fbf..fc3ae53 100644 --- a/src/unity.c +++ b/src/unity.c @@ -292,7 +292,7 @@ void UnityPrintFloat(const UNITY_DOUBLE input_number) else if (isinf(number)) UnityPrint("inf"); else { - UNITY_INT32 n = 0; + UNITY_INT32 n_int = 0, n; int exponent = 0; int decimals, digits; char buf[16]; @@ -330,16 +330,25 @@ void UnityPrintFloat(const UNITY_DOUBLE input_number) * freeing up significant bits in the fractional part. */ UNITY_DOUBLE factor = 1.0f; - n = (UNITY_INT32)number; - number -= (UNITY_DOUBLE)n; + n_int = (UNITY_INT32)number; + number -= (UNITY_DOUBLE)n_int; - while (n < min_scaled) { n *= 10; factor *= 10.0f; exponent--; } + while (n_int < min_scaled) { n_int *= 10; factor *= 10.0f; exponent--; } number *= factor; } /* round to nearest integer */ - n += ((UNITY_INT32)(number + number) + 1) / 2; + n = ((UNITY_INT32)(number + number) + 1) / 2; + +#ifndef UNITY_ROUND_TIES_AWAY_FROM_ZERO + /* round to even if exactly between two integers */ + if ((n & 1) && ((UNITY_DOUBLE)n - number == 0.5f)) + n--; +#endif + + n += n_int; + if (n >= max_scaled) { n = min_scaled; diff --git a/test/tests/testunity.c b/test/tests/testunity.c index 0aa6914..2d6a5ab 100644 --- a/test/tests/testunity.c +++ b/test/tests/testunity.c @@ -4468,7 +4468,6 @@ void testFloatPrinting(void) #else TEST_ASSERT_EQUAL_PRINT_FLOATING("0", 0.0f); TEST_ASSERT_EQUAL_PRINT_FLOATING("4.99e-07", 0.000000499f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("5.000001e-07", 0.00000050000005f); TEST_ASSERT_EQUAL_PRINT_FLOATING("0.1004695", 0.100469499f); TEST_ASSERT_EQUAL_PRINT_FLOATING("2", 1.9999995f); /*Rounding to int place*/ TEST_ASSERT_EQUAL_PRINT_FLOATING("1", 1.0f); @@ -4481,7 +4480,6 @@ void testFloatPrinting(void) TEST_ASSERT_EQUAL_PRINT_FLOATING("-0", -0.0f); TEST_ASSERT_EQUAL_PRINT_FLOATING("-4.99e-07", -0.000000499f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("-5.000001e-07", -0.00000050000005f); TEST_ASSERT_EQUAL_PRINT_FLOATING("-0.1004695", -0.100469499f); TEST_ASSERT_EQUAL_PRINT_FLOATING("-2", -1.9999995f); /*Rounding to int place*/ TEST_ASSERT_EQUAL_PRINT_FLOATING("-1", -1.0f); @@ -4512,6 +4510,25 @@ void testFloatPrinting(void) #endif } +void testFloatPrintingRoundTiesToEven(void) +{ +#if defined(UNITY_EXCLUDE_FLOAT_PRINT) || defined(UNITY_INCLUDE_DOUBLE) || !defined(USING_OUTPUT_SPY) + TEST_IGNORE(); +#else + #ifdef UNITY_ROUND_TIES_AWAY_FROM_ZERO + TEST_ASSERT_EQUAL_PRINT_FLOATING("0.0004882813", 0.00048828125f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("488281.3", 488281.25f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("5.000001e-07", 0.00000050000005f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-5.000001e-07", -0.00000050000005f); + #else /* Default to Round ties to even */ + TEST_ASSERT_EQUAL_PRINT_FLOATING("0.0004882812", 0.00048828125f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("488281.2", 488281.25f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("5e-07", 0.00000050000005f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-5e-07", -0.00000050000005f); + #endif +#endif +} + void testFloatPrintingInfinityAndNaN(void) { #if defined(UNITY_EXCLUDE_FLOAT_PRINT) || !defined(USING_OUTPUT_SPY) @@ -4529,31 +4546,15 @@ void testFloatPrintingInfinityAndNaN(void) static void printFloatValue(float f) { char expected[18]; - char expected_lower[18]; - char expected_higher[18]; startPutcharSpy(); - UnityPrintFloat(f); sprintf(expected, "%.9g", f); - /* We print all NaN's as "nan", not "-nan" */ - if(strcmp(expected, "-nan") == 0) strcpy(expected, "nan"); + if (strcmp(expected, "-nan") == 0) strcpy(expected, "nan"); - strcpy(expected_lower, expected); - strcpy(expected_higher, expected); - - /* Allow for rounding differences in the last digit */ - double lower = (double)f * 0.9999999995; - double higher = (double)f * 1.0000000005; - - if(isfinite(lower)) sprintf(expected_lower, "%.9g", lower); - if(isfinite(higher)) sprintf(expected_higher, "%.9g", higher); - - if (strcmp(expected, getBufferPutcharSpy()) != 0 && - strcmp(expected_lower, getBufferPutcharSpy()) != 0 && - strcmp(expected_higher, getBufferPutcharSpy()) != 0) + if (strcmp(expected, getBufferPutcharSpy())) { /* Fail with diagnostic printing */ TEST_ASSERT_EQUAL_PRINT_FLOATING(expected, f); @@ -4571,13 +4572,11 @@ static void printFloatValue(float f) char expected_higher3[18]; startPutcharSpy(); - UnityPrintFloat(f); sprintf(expected, "%.7g", f); - /* We print all NaN's as "nan", not "-nan" */ - if(strcmp(expected, "-nan") == 0) strcpy(expected, "nan"); + if (strcmp(expected, "-nan") == 0) strcpy(expected, "nan"); strcpy(expected_lower, expected); strcpy(expected_lower2, expected); @@ -4594,17 +4593,17 @@ static void printFloatValue(float f) if(isfinite(higher)) sprintf(expected_higher, "%.7g", higher); /* Outside [1,10000000] allow for relative error of +/-2.5e-7 */ - if(f < 1.0 || f > 10000000) + if (f < 1.0 || f > 10000000) { double lower2 = (double)f * 0.99999985; double lower3 = (double)f * 0.99999975; double higher2 = (double)f * 1.00000015; double higher3 = (double)f * 1.00000025; - if(isfinite(lower2)) sprintf(expected_lower2, "%.7g", lower2); - if(isfinite(lower3)) sprintf(expected_lower3, "%.7g", lower3); - if(isfinite(higher2)) sprintf(expected_higher2, "%.7g", higher2); - if(isfinite(higher3)) sprintf(expected_higher3, "%.7g", higher3); + if (isfinite(lower2)) sprintf(expected_lower2, "%.7g", lower2); + if (isfinite(lower3)) sprintf(expected_lower3, "%.7g", lower3); + if (isfinite(higher2)) sprintf(expected_higher2, "%.7g", higher2); + if (isfinite(higher3)) sprintf(expected_higher3, "%.7g", higher3); } if (strcmp(expected, getBufferPutcharSpy()) != 0 && @@ -5362,6 +5361,21 @@ void testDoublePrinting(void) #endif } +void testDoublePrintingRoundTiesToEven(void) +{ +#if defined(UNITY_EXCLUDE_FLOAT_PRINT) || 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("1e+10", 10000000050.0); + TEST_ASSERT_EQUAL_PRINT_FLOATING("9.00719924e+15", 9007199245000000.0); + #endif +#endif +} + void testDoublePrintingInfinityAndNaN(void) { #if defined(UNITY_EXCLUDE_FLOAT_PRINT) || defined(UNITY_EXCLUDE_DOUBLE) || !defined(USING_OUTPUT_SPY) From e0d52d1a7908a4c0a78c439919c31c71bc2dc8d5 Mon Sep 17 00:00:00 2001 From: Kyle Krueger Date: Wed, 12 Sep 2018 17:46:11 +0200 Subject: [PATCH 05/17] fix uninitialzed value warning --- src/unity.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/unity.c b/src/unity.c index 103bde2..4bad2c2 100644 --- a/src/unity.c +++ b/src/unity.c @@ -283,7 +283,7 @@ void UnityPrintFloat(const UNITY_DOUBLE input_number) int exponent = 0; int decimals, digits; UNITY_INT32 n; - char buf[16]; + char buf[16] = {0}; /* scale up or down by powers of 10 */ while (number < 100000.0f / 1e6f) { number *= 1e6f; exponent -= 6; } From e84cb29acc0e01e22728bc6bf093329b67710588 Mon Sep 17 00:00:00 2001 From: Fabian Zahn Date: Sat, 27 Oct 2018 11:24:29 +0200 Subject: [PATCH 06/17] Fixed an "array index out of bounds violation" in the examples (regarding issue #360). --- examples/example_1/src/ProductionCode.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/example_1/src/ProductionCode.c b/examples/example_1/src/ProductionCode.c index d039c3e..db128e5 100644 --- a/examples/example_1/src/ProductionCode.c +++ b/examples/example_1/src/ProductionCode.c @@ -4,14 +4,14 @@ int Counter = 0; int NumbersToFind[9] = { 0, 34, 55, 66, 32, 11, 1, 77, 888 }; /* some obnoxious array to search that is 1-based indexing instead of 0. */ -/* This function is supposed to search through NumbersToFind and find a particular number. - * If it finds it, the index is returned. Otherwise 0 is returned which sorta makes sense since - * NumbersToFind is indexed from 1. Unfortunately it's broken +/* This function is supposed to search through NumbersToFind and find a particular number. + * If it finds it, the index is returned. Otherwise 0 is returned which sorta makes sense since + * NumbersToFind is indexed from 1. Unfortunately it's broken * (and should therefore be caught by our tests) */ int FindFunction_WhichIsBroken(int NumberToFind) { int i = 0; - while (i <= 8) /* Notice I should have been in braces */ + while (i < 8) /* Notice I should have been in braces */ i++; if (NumbersToFind[i] == NumberToFind) /* Yikes! I'm getting run after the loop finishes instead of during it! */ return i; From be765649f1f4203de9ea79241f6c9f929b056502 Mon Sep 17 00:00:00 2001 From: Kochise Date: Wed, 31 Oct 2018 11:24:37 +0100 Subject: [PATCH 07/17] Some cleanup --- src/unity_internals.h | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/unity_internals.h b/src/unity_internals.h index 7249fc7..0d047da 100644 --- a/src/unity_internals.h +++ b/src/unity_internals.h @@ -359,7 +359,6 @@ typedef UNITY_FLOAT_TYPE UNITY_FLOAT; # undef UNITY_WEAK_PRAGMA #endif - /*------------------------------------------------------- * Internal Structs Needed *-------------------------------------------------------*/ @@ -400,11 +399,13 @@ UNITY_DISPLAY_STYLE_UINT = sizeof(unsigned) + UNITY_DISPLAY_RANGE_UINT, typedef enum { + UNITY_WITHIN = 0, UNITY_EQUAL_TO = 1, UNITY_GREATER_THAN = 2, UNITY_GREATER_OR_EQUAL = 2 + UNITY_EQUAL_TO, UNITY_SMALLER_THAN = 4, - UNITY_SMALLER_OR_EQUAL = 4 + UNITY_EQUAL_TO + UNITY_SMALLER_OR_EQUAL = 4 + UNITY_EQUAL_TO, + UNITY_UNKNOWN } UNITY_COMPARISON_T; #ifndef UNITY_EXCLUDE_FLOAT @@ -425,7 +426,8 @@ typedef enum UNITY_FLOAT_TRAIT typedef enum { UNITY_ARRAY_TO_VAL = 0, - UNITY_ARRAY_TO_ARRAY + UNITY_ARRAY_TO_ARRAY, + UNITY_ARRAY_UNKNOWN } UNITY_FLAGS_T; struct UNITY_STORAGE_T @@ -568,9 +570,9 @@ void UnityAssertNumbersWithin(const UNITY_UINT delta, const UNITY_LINE_TYPE lineNumber, const UNITY_DISPLAY_STYLE_T style); -void UnityFail(const char* msg, const UNITY_LINE_TYPE line); +void UnityFail(const char* message, const UNITY_LINE_TYPE line); -void UnityIgnore(const char* msg, const UNITY_LINE_TYPE line); +void UnityIgnore(const char* message, const UNITY_LINE_TYPE line); #ifndef UNITY_EXCLUDE_FLOAT void UnityAssertFloatsWithin(const UNITY_FLOAT delta, @@ -826,9 +828,9 @@ int UnityTestMatches(void); #define UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64, UNITY_ARRAY_TO_ARRAY) #define UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64, UNITY_ARRAY_TO_ARRAY) #define UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64, UNITY_ARRAY_TO_ARRAY) -#define UNITY_TEST_ASSERT_EACH_EQUAL_INT64(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT64)expected, 8), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64, UNITY_ARRAY_TO_VAL) -#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT64(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT64)expected, 8), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64, UNITY_ARRAY_TO_VAL) -#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX64(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT64)expected, 8), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_INT64(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT64)(expected), 8), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT64(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT64)(expected), 8), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX64(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT64)(expected), 8), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64, UNITY_ARRAY_TO_VAL) #define UNITY_TEST_ASSERT_INT64_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) #define UNITY_TEST_ASSERT_UINT64_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) #define UNITY_TEST_ASSERT_HEX64_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) @@ -910,10 +912,10 @@ int UnityTestMatches(void); #define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) #define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) #else -#define UNITY_TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual, line, message) UnityAssertDoublesWithin((UNITY_DOUBLE)(delta), (UNITY_DOUBLE)(expected), (UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)line) -#define UNITY_TEST_ASSERT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_ASSERT_DOUBLE_WITHIN((UNITY_DOUBLE)(expected) * (UNITY_DOUBLE)UNITY_DOUBLE_PRECISION, (UNITY_DOUBLE)expected, (UNITY_DOUBLE)actual, (UNITY_LINE_TYPE)(line), message) -#define UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualDoubleArray((UNITY_DOUBLE*)(expected), (UNITY_DOUBLE*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)line, UNITY_ARRAY_TO_ARRAY) -#define UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE(expected, actual, num_elements, line, message) UnityAssertEqualDoubleArray(UnityDoubleToPtr(expected), (UNITY_DOUBLE*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)line, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual, line, message) UnityAssertDoublesWithin((UNITY_DOUBLE)(delta), (UNITY_DOUBLE)(expected), (UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_ASSERT_DOUBLE_WITHIN((UNITY_DOUBLE)(expected) * (UNITY_DOUBLE)UNITY_DOUBLE_PRECISION, (UNITY_DOUBLE)(expected), (UNITY_DOUBLE)(actual), (UNITY_LINE_TYPE)(line), (message)) +#define UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualDoubleArray((UNITY_DOUBLE*)(expected), (UNITY_DOUBLE*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE(expected, actual, num_elements, line, message) UnityAssertEqualDoubleArray(UnityDoubleToPtr(expected), (UNITY_DOUBLE*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL) #define UNITY_TEST_ASSERT_DOUBLE_IS_INF(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_INF) #define UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NEG_INF) #define UNITY_TEST_ASSERT_DOUBLE_IS_NAN(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NAN) From 96127581a041a2c76a3a6ae6659499dbb7dc1678 Mon Sep 17 00:00:00 2001 From: Kochise Date: Wed, 31 Oct 2018 11:30:13 +0100 Subject: [PATCH 08/17] Some cleanup --- src/unity.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/unity.c b/src/unity.c index 103bde2..4efc47f 100644 --- a/src/unity.c +++ b/src/unity.c @@ -67,6 +67,7 @@ static const char UnityStrDetail2Name[] = " " UNITY_DETAIL2_NAME " "; * Pretty Printers & Test Result Output Handlers *-----------------------------------------------*/ +/*-----------------------------------------------*/ void UnityPrint(const char* string) { const char* pch = string; @@ -116,6 +117,7 @@ void UnityPrint(const char* string) } } +/*-----------------------------------------------*/ void UnityPrintLen(const char* string, const UNITY_UINT32 length) { const char* pch = string; @@ -479,6 +481,7 @@ static void UnityPrintExpectedAndActualStringsLen(const char* expected, * Assertion & Control Helpers *-----------------------------------------------*/ +/*-----------------------------------------------*/ static int UnityIsOneArrayNull(UNITY_INTERNAL_PTR expected, UNITY_INTERNAL_PTR actual, const UNITY_LINE_TYPE lineNumber, @@ -511,6 +514,7 @@ static int UnityIsOneArrayNull(UNITY_INTERNAL_PTR expected, * Assertion Functions *-----------------------------------------------*/ +/*-----------------------------------------------*/ void UnityAssertBits(const UNITY_INT mask, const UNITY_INT expected, const UNITY_INT actual, @@ -704,12 +708,14 @@ void UnityAssertEqualIntArray(UNITY_INTERNAL_PTR expected, UnityPrint(UnityStrDelta) #endif /* UNITY_EXCLUDE_FLOAT_PRINT */ +/*-----------------------------------------------*/ static int UnityFloatsWithin(UNITY_FLOAT delta, UNITY_FLOAT expected, UNITY_FLOAT actual) { UNITY_FLOAT diff; UNITY_FLOAT_OR_DOUBLE_WITHIN(delta, expected, actual, diff); } +/*-----------------------------------------------*/ void UnityAssertEqualFloatArray(UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* expected, UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* actual, const UNITY_UINT32 num_elements, @@ -840,6 +846,7 @@ static int UnityDoublesWithin(UNITY_DOUBLE delta, UNITY_DOUBLE expected, UNITY_D UNITY_FLOAT_OR_DOUBLE_WITHIN(delta, expected, actual, diff); } +/*-----------------------------------------------*/ void UnityAssertEqualDoubleArray(UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* expected, UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* actual, const UNITY_UINT32 num_elements, @@ -900,7 +907,6 @@ void UnityAssertDoublesWithin(const UNITY_DOUBLE delta, } /*-----------------------------------------------*/ - void UnityAssertDoubleSpecial(const UNITY_DOUBLE actual, const char* msg, const UNITY_LINE_TYPE lineNumber, @@ -1259,6 +1265,7 @@ UNITY_INTERNAL_PTR UnityNumToPtr(const UNITY_INT num, const UNITY_UINT8 size) } #ifndef UNITY_EXCLUDE_FLOAT +/*-----------------------------------------------*/ UNITY_INTERNAL_PTR UnityFloatToPtr(const float num) { UnityQuickCompare.f = num; @@ -1267,6 +1274,7 @@ UNITY_INTERNAL_PTR UnityFloatToPtr(const float num) #endif #ifndef UNITY_EXCLUDE_DOUBLE +/*-----------------------------------------------*/ UNITY_INTERNAL_PTR UnityDoubleToPtr(const double num) { UnityQuickCompare.d = num; @@ -1278,6 +1286,7 @@ UNITY_INTERNAL_PTR UnityDoubleToPtr(const double num) * Control Functions *-----------------------------------------------*/ +/*-----------------------------------------------*/ void UnityFail(const char* msg, const UNITY_LINE_TYPE line) { RETURN_IF_FAIL_OR_IGNORE; @@ -1402,6 +1411,7 @@ char* UnityOptionIncludeNamed = NULL; char* UnityOptionExcludeNamed = NULL; int UnityVerbosity = 1; +/*-----------------------------------------------*/ int UnityParseOptions(int argc, char** argv) { UnityOptionIncludeNamed = NULL; @@ -1458,6 +1468,7 @@ int UnityParseOptions(int argc, char** argv) return 0; } +/*-----------------------------------------------*/ int IsStringInBiggerString(const char* longstring, const char* shortstring) { const char* lptr = longstring; @@ -1496,9 +1507,11 @@ int IsStringInBiggerString(const char* longstring, const char* shortstring) lptr = lnext; sptr = shortstring; } + return 0; } +/*-----------------------------------------------*/ int UnityStringArgumentMatches(const char* str) { int retval; @@ -1522,24 +1535,33 @@ int UnityStringArgumentMatches(const char* str) if ((ptr2[0] == ':') && (ptr2[1] != 0) && (ptr2[0] != '\'') && (ptr2[0] != '"') && (ptr2[0] != ',')) ptrf = &ptr2[1]; } while ((ptr2[0] != 0) && (ptr2[0] != '\'') && (ptr2[0] != '"') && (ptr2[0] != ',')); + while ((ptr2[0] != 0) && ((ptr2[0] == ':') || (ptr2[0] == '\'') || (ptr2[0] == '"') || (ptr2[0] == ','))) + { ptr2++; + } /* done if complete filename match */ retval = IsStringInBiggerString(Unity.TestFile, ptr1); if (retval == 1) + { return retval; + } /* done if testname match after filename partial match */ if ((retval == 2) && (ptrf != 0)) { if (IsStringInBiggerString(Unity.CurrentTestName, ptrf)) + { return 1; + } } /* done if complete testname match */ if (IsStringInBiggerString(Unity.CurrentTestName, ptr1) == 1) + { return 1; + } ptr1 = ptr2; } @@ -1548,6 +1570,7 @@ int UnityStringArgumentMatches(const char* str) return 0; } +/*-----------------------------------------------*/ int UnityTestMatches(void) { /* Check if this test name matches the included test pattern */ From 50ce8a880af6d27dabab5d3655bbd26a3a16d295 Mon Sep 17 00:00:00 2001 From: Kochise Date: Wed, 31 Oct 2018 11:41:44 +0100 Subject: [PATCH 09/17] Some cleanup --- src/unity.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 77 insertions(+), 7 deletions(-) diff --git a/src/unity.c b/src/unity.c index 4efc47f..732db55 100644 --- a/src/unity.c +++ b/src/unity.c @@ -214,7 +214,9 @@ void UnityPrintNumberHex(const UNITY_UINT number, const char nibbles_to_print) int nibble; char nibbles = nibbles_to_print; if ((unsigned)nibbles > (2 * sizeof(number))) + { nibbles = 2 * sizeof(number); + } while (nibbles > 0) { @@ -277,9 +279,18 @@ void UnityPrintFloat(const UNITY_DOUBLE input_number) } /* handle zero, NaN, and +/- infinity */ - if (number == 0.0f) UnityPrint("0"); - else if (isnan(number)) UnityPrint("nan"); - else if (isinf(number)) UnityPrint("inf"); + if (number == 0.0f) + { + UnityPrint("0"); + } + else if (isnan(number)) + { + UnityPrint("nan"); + } + else if (isinf(number)) + { + UnityPrint("inf"); + } else { int exponent = 0; @@ -621,9 +632,15 @@ void UnityAssertEqualIntArray(UNITY_INTERNAL_PTR expected, UnityPrintPointlessAndBail(); } - if (expected == actual) return; /* Both are NULL or same pointer */ + if (expected == actual) + { + return; /* Both are NULL or same pointer */ + } + if (UnityIsOneArrayNull(expected, actual, lineNumber, msg)) + { UNITY_FAIL_AND_BAIL; + } while ((elements > 0) && elements--) { @@ -734,9 +751,15 @@ void UnityAssertEqualFloatArray(UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* expected, UnityPrintPointlessAndBail(); } - if (expected == actual) return; /* Both are NULL or same pointer */ + if (expected == actual) + { + return; /* Both are NULL or same pointer */ + } + if (UnityIsOneArrayNull((UNITY_INTERNAL_PTR)expected, (UNITY_INTERNAL_PTR)actual, lineNumber, msg)) + { UNITY_FAIL_AND_BAIL; + } while (elements--) { @@ -821,14 +844,18 @@ void UnityAssertFloatSpecial(const UNITY_FLOAT actual, UnityTestResultsFailBegin(lineNumber); UnityPrint(UnityStrExpected); if (!should_be_trait) + { UnityPrint(UnityStrNot); + } UnityPrint(trait_names[trait_index]); UnityPrint(UnityStrWas); #ifndef UNITY_EXCLUDE_FLOAT_PRINT UnityPrintFloat((UNITY_DOUBLE)actual); #else if (should_be_trait) + { UnityPrint(UnityStrNot); + } UnityPrint(trait_names[trait_index]); #endif UnityAddMsgIfSpecified(msg); @@ -865,9 +892,15 @@ void UnityAssertEqualDoubleArray(UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* expecte UnityPrintPointlessAndBail(); } - if (expected == actual) return; /* Both are NULL or same pointer */ + if (expected == actual) + { + return; /* Both are NULL or same pointer */ + } + if (UnityIsOneArrayNull((UNITY_INTERNAL_PTR)expected, (UNITY_INTERNAL_PTR)actual, lineNumber, msg)) + { UNITY_FAIL_AND_BAIL; + } while (elements--) { @@ -951,14 +984,18 @@ void UnityAssertDoubleSpecial(const UNITY_DOUBLE actual, UnityTestResultsFailBegin(lineNumber); UnityPrint(UnityStrExpected); if (!should_be_trait) + { UnityPrint(UnityStrNot); + } UnityPrint(trait_names[trait_index]); UnityPrint(UnityStrWas); #ifndef UNITY_EXCLUDE_FLOAT_PRINT UnityPrintFloat(actual); #else if (should_be_trait) + { UnityPrint(UnityStrNot); + } UnityPrint(trait_names[trait_index]); #endif UnityAddMsgIfSpecified(msg); @@ -981,16 +1018,24 @@ void UnityAssertNumbersWithin(const UNITY_UINT delta, if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) { if (actual > expected) + { Unity.CurrentTestFailed = (UNITY_UINT)((UNITY_UINT)(actual - expected) > delta); + } else + { Unity.CurrentTestFailed = (UNITY_UINT)((UNITY_UINT)(expected - actual) > delta); + } } else { if ((UNITY_UINT)actual > (UNITY_UINT)expected) + { Unity.CurrentTestFailed = (UNITY_UINT)((UNITY_UINT)(actual - expected) > delta); + } else + { Unity.CurrentTestFailed = (UNITY_UINT)((UNITY_UINT)(expected - actual) > delta); + } } if (Unity.CurrentTestFailed) @@ -1186,9 +1231,15 @@ void UnityAssertEqualMemory(UNITY_INTERNAL_PTR expected, UnityPrintPointlessAndBail(); } - if (expected == actual) return; /* Both are NULL or same pointer */ + if (expected == actual) + { + return; /* Both are NULL or same pointer */ + } + if (UnityIsOneArrayNull(expected, actual, lineNumber, msg)) + { UNITY_FAIL_AND_BAIL; + } while (elements--) { @@ -1428,9 +1479,13 @@ int UnityParseOptions(int argc, char** argv) case 'n': /* include tests with name including this string */ case 'f': /* an alias for -n */ if (argv[i][2] == '=') + { UnityOptionIncludeNamed = &argv[i][3]; + } else if (++i < argc) + { UnityOptionIncludeNamed = argv[i]; + } else { UnityPrint("ERROR: No Test String to Include Matches For"); @@ -1446,9 +1501,13 @@ int UnityParseOptions(int argc, char** argv) break; case 'x': /* exclude tests with name including this string */ if (argv[i][2] == '=') + { UnityOptionExcludeNamed = &argv[i][3]; + } else if (++i < argc) + { UnityOptionExcludeNamed = argv[i]; + } else { UnityPrint("ERROR: No Test String to Exclude Matches For"); @@ -1476,7 +1535,9 @@ int IsStringInBiggerString(const char* longstring, const char* shortstring) const char* lnext = lptr; if (*sptr == '*') + { return 1; + } while (*lptr) { @@ -1524,7 +1585,9 @@ int UnityStringArgumentMatches(const char* str) while (ptr1[0] != 0) { if ((ptr1[0] == '"') || (ptr1[0] == '\'')) + { ptr1++; + } /* look for the start of the next partial */ ptr2 = ptr1; @@ -1533,7 +1596,9 @@ int UnityStringArgumentMatches(const char* str) { ptr2++; if ((ptr2[0] == ':') && (ptr2[1] != 0) && (ptr2[0] != '\'') && (ptr2[0] != '"') && (ptr2[0] != ',')) + { ptrf = &ptr2[1]; + } } while ((ptr2[0] != 0) && (ptr2[0] != '\'') && (ptr2[0] != '"') && (ptr2[0] != ',')); while ((ptr2[0] != 0) && ((ptr2[0] == ':') || (ptr2[0] == '\'') || (ptr2[0] == '"') || (ptr2[0] == ','))) @@ -1580,14 +1645,19 @@ int UnityTestMatches(void) retval = UnityStringArgumentMatches(UnityOptionIncludeNamed); } else + { retval = 1; + } /* Check if this test name matches the excluded test pattern */ if (UnityOptionExcludeNamed) { if (UnityStringArgumentMatches(UnityOptionExcludeNamed)) + { retval = 0; + } } + return retval; } From 7dd21c333e56098b2e047a6fedd1c7ddfc4a88ab Mon Sep 17 00:00:00 2001 From: Mark VanderVoord Date: Fri, 2 Nov 2018 07:42:47 -0400 Subject: [PATCH 10/17] Fix unintended array overrun in example (#360. Thanks @quantum-leaps) --- examples/example_1/src/ProductionCode.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/example_1/src/ProductionCode.c b/examples/example_1/src/ProductionCode.c index d039c3e..db128e5 100644 --- a/examples/example_1/src/ProductionCode.c +++ b/examples/example_1/src/ProductionCode.c @@ -4,14 +4,14 @@ int Counter = 0; int NumbersToFind[9] = { 0, 34, 55, 66, 32, 11, 1, 77, 888 }; /* some obnoxious array to search that is 1-based indexing instead of 0. */ -/* This function is supposed to search through NumbersToFind and find a particular number. - * If it finds it, the index is returned. Otherwise 0 is returned which sorta makes sense since - * NumbersToFind is indexed from 1. Unfortunately it's broken +/* This function is supposed to search through NumbersToFind and find a particular number. + * If it finds it, the index is returned. Otherwise 0 is returned which sorta makes sense since + * NumbersToFind is indexed from 1. Unfortunately it's broken * (and should therefore be caught by our tests) */ int FindFunction_WhichIsBroken(int NumberToFind) { int i = 0; - while (i <= 8) /* Notice I should have been in braces */ + while (i < 8) /* Notice I should have been in braces */ i++; if (NumbersToFind[i] == NumberToFind) /* Yikes! I'm getting run after the loop finishes instead of during it! */ return i; From 100c73d37feef84c63530535793c739b30b23c0f Mon Sep 17 00:00:00 2001 From: Dan Yeaw Date: Tue, 13 Nov 2018 21:07:05 -0500 Subject: [PATCH 11/17] Move license for GitHub detection --- docs/license.txt => LICENSE.txt | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename docs/license.txt => LICENSE.txt (100%) diff --git a/docs/license.txt b/LICENSE.txt similarity index 100% rename from docs/license.txt rename to LICENSE.txt From 6b657c6f17ca45c240dd7ad74e8096dd17ab3ad1 Mon Sep 17 00:00:00 2001 From: John Lindgren Date: Wed, 28 Nov 2018 13:27:00 -0500 Subject: [PATCH 12/17] Fix (most) Rubocop warnings. --- auto/colour_prompt.rb | 4 +- auto/colour_reporter.rb | 2 +- auto/generate_module.rb | 8 ++-- auto/generate_test_runner.rb | 8 ++-- auto/parse_output.rb | 55 +++++++++++++-------------- auto/stylize_as_junit.rb | 12 ++---- auto/test_file_filter.rb | 4 +- auto/unity_test_summary.rb | 4 -- examples/example_3/rakefile.rb | 11 ++---- examples/example_3/rakefile_helper.rb | 8 ++-- extras/fixture/rakefile.rb | 14 +++---- test/.rubocop.yml | 2 +- test/rakefile | 7 ++-- test/rakefile_helper.rb | 8 ++-- 14 files changed, 64 insertions(+), 83 deletions(-) diff --git a/auto/colour_prompt.rb b/auto/colour_prompt.rb index 0f1dc4e..bf09d02 100644 --- a/auto/colour_prompt.rb +++ b/auto/colour_prompt.rb @@ -24,7 +24,7 @@ class ColourCommandLine return unless RUBY_PLATFORM =~ /(win|w)32$/ get_std_handle = Win32API.new('kernel32', 'GetStdHandle', ['L'], 'L') @set_console_txt_attrb = - Win32API.new('kernel32', 'SetConsoleTextAttribute', %w(L N), 'I') + Win32API.new('kernel32', 'SetConsoleTextAttribute', %w[L N], 'I') @hout = get_std_handle.call(-11) end @@ -107,7 +107,7 @@ class ColourCommandLine $stdout.print("#{change_to(colour)}#{str}\033[0m") if mode == :print end end -end # ColourCommandLine +end def colour_puts(role, str) ColourCommandLine.new.out_c(:puts, role, str) diff --git a/auto/colour_reporter.rb b/auto/colour_reporter.rb index bb1fbfc..1c3bc21 100644 --- a/auto/colour_reporter.rb +++ b/auto/colour_reporter.rb @@ -4,7 +4,7 @@ # [Released under MIT License. Please refer to license.txt for details] # ========================================== -require "#{File.expand_path(File.dirname(__FILE__))}/colour_prompt" +require_relative 'colour_prompt' $colour_output = true diff --git a/auto/generate_module.rb b/auto/generate_module.rb index 13b4cc7..fb8c7ac 100644 --- a/auto/generate_module.rb +++ b/auto/generate_module.rb @@ -45,8 +45,6 @@ TEMPLATE_INC ||= '#ifndef _%3$s_H class UnityModuleGenerator ############################ def initialize(options = nil) - here = File.expand_path(File.dirname(__FILE__)) + '/' - @options = UnityModuleGenerator.default_options case options when NilClass then @options @@ -56,9 +54,9 @@ class UnityModuleGenerator end # Create default file paths if none were provided - @options[:path_src] = here + '../src/' if @options[:path_src].nil? - @options[:path_inc] = @options[:path_src] if @options[:path_inc].nil? - @options[:path_tst] = here + '../test/' if @options[:path_tst].nil? + @options[:path_src] = "#{__dir__}/../src/" if @options[:path_src].nil? + @options[:path_inc] = @options[:path_src] if @options[:path_inc].nil? + @options[:path_tst] = "#{__dir__}/../test/" if @options[:path_tst].nil? @options[:path_src] += '/' unless @options[:path_src][-1] == 47 @options[:path_inc] += '/' unless @options[:path_inc][-1] == 47 @options[:path_tst] += '/' unless @options[:path_tst][-1] == 47 diff --git a/auto/generate_test_runner.rb b/auto/generate_test_runner.rb index 2f14966..377db6f 100644 --- a/auto/generate_test_runner.rb +++ b/auto/generate_test_runner.rb @@ -4,8 +4,6 @@ # [Released under MIT License. Please refer to license.txt for details] # ========================================== -File.expand_path(File.join(File.dirname(__FILE__), 'colour_prompt')) - class UnityTestRunnerGenerator def initialize(options = nil) @options = UnityTestRunnerGenerator.default_options @@ -15,7 +13,7 @@ class UnityTestRunnerGenerator when Hash then @options.merge!(options) else raise 'If you specify arguments, it should be a filename or a hash of options' end - require "#{File.expand_path(File.dirname(__FILE__))}/type_sanitizer" + require_relative 'type_sanitizer' end def self.default_options @@ -165,7 +163,7 @@ class UnityTestRunnerGenerator output.puts('#include "cmock.h"') unless mocks.empty? output.puts('#ifndef UNITY_EXCLUDE_SETJMP_H') output.puts('#include ') - output.puts("#endif") + output.puts('#endif') output.puts('#include ') if @options[:defines] && !@options[:defines].empty? @options[:defines].each { |d| output.puts("#define #{d}") } @@ -379,7 +377,7 @@ class UnityTestRunnerGenerator end output.puts output.puts(' CMock_Guts_MemFreeFinal();') unless used_mocks.empty? - output.puts(" return suite_teardown(UnityEnd());") + output.puts(' return suite_teardown(UnityEnd());') output.puts('}') end diff --git a/auto/parse_output.rb b/auto/parse_output.rb index f04508f..fa07b7d 100644 --- a/auto/parse_output.rb +++ b/auto/parse_output.rb @@ -210,7 +210,7 @@ class ParseOutput # Adjusts the os specific members according to the current path style # (Windows or Unix based) - def set_os_specifics(line) + def detect_os_specifics(line) if line.include? '\\' # Windows X:\Y\Z @class_name_idx = 1 @@ -254,43 +254,42 @@ class ParseOutput # TEST() PASS # # Note: Where path is different on Unix vs Windows devices (Windows leads with a drive letter)! - set_os_specifics(line) + detect_os_specifics(line) line_array = line.split(':') # If we were able to split the line then we can look to see if any of our target words # were found. Case is important. - if (line_array.size >= 4) || (line.start_with? 'TEST(') || (line.start_with? 'IGNORE_TEST(') + next unless (line_array.size >= 4) || (line.start_with? 'TEST(') || (line.start_with? 'IGNORE_TEST(') - # check if the output is fixture output (with verbose flag "-v") - if (line.start_with? 'TEST(') || (line.start_with? 'IGNORE_TEST(') - line_array = prepare_fixture_line(line) - if line.include? ' PASS' - test_passed_unity_fixture(line_array) - @test_passed += 1 - elsif line.include? 'FAIL' - test_failed_unity_fixture(line_array) - @test_failed += 1 - elsif line.include? 'IGNORE' - test_ignored_unity_fixture(line_array) - @test_ignored += 1 - end - # normal output / fixture output (without verbose "-v") - elsif line.include? ':PASS' - test_passed(line_array) + # check if the output is fixture output (with verbose flag "-v") + if (line.start_with? 'TEST(') || (line.start_with? 'IGNORE_TEST(') + line_array = prepare_fixture_line(line) + if line.include? ' PASS' + test_passed_unity_fixture(line_array) @test_passed += 1 - elsif line.include? ':FAIL' - test_failed(line_array) + elsif line.include? 'FAIL' + test_failed_unity_fixture(line_array) @test_failed += 1 - elsif line.include? ':IGNORE:' - test_ignored(line_array) - @test_ignored += 1 - elsif line.include? ':IGNORE' - line_array.push('No reason given') - test_ignored(line_array) + elsif line.include? 'IGNORE' + test_ignored_unity_fixture(line_array) @test_ignored += 1 end - @total_tests = @test_passed + @test_failed + @test_ignored + # normal output / fixture output (without verbose "-v") + elsif line.include? ':PASS' + test_passed(line_array) + @test_passed += 1 + elsif line.include? ':FAIL' + test_failed(line_array) + @test_failed += 1 + elsif line.include? ':IGNORE:' + test_ignored(line_array) + @test_ignored += 1 + elsif line.include? ':IGNORE' + line_array.push('No reason given') + test_ignored(line_array) + @test_ignored += 1 end + @total_tests = @test_passed + @test_failed + @test_ignored end puts '' puts '=================== SUMMARY =====================' diff --git a/auto/stylize_as_junit.rb b/auto/stylize_as_junit.rb index b3d8f40..a53f85f 100755 --- a/auto/stylize_as_junit.rb +++ b/auto/stylize_as_junit.rb @@ -61,8 +61,8 @@ class ArgvParser opts.parse!(args) options - end # parse() -end # class OptparseExample + end +end class UnityToJUnit include FileUtils::Verbose @@ -155,10 +155,6 @@ class UnityToJUnit [Regexp.last_match(1).to_i, Regexp.last_match(2).to_i, Regexp.last_match(3).to_i] end - def here - File.expand_path(File.dirname(__FILE__)) - end - private def results_structure @@ -221,9 +217,9 @@ class UnityToJUnit def write_suites_footer(stream) stream.puts '' end -end # UnityToJUnit +end -if __FILE__ == $0 +if $0 == __FILE__ # parse out the command options options = ArgvParser.parse(ARGV) diff --git a/auto/test_file_filter.rb b/auto/test_file_filter.rb index aad28e3..5c3a79f 100644 --- a/auto/test_file_filter.rb +++ b/auto/test_file_filter.rb @@ -11,8 +11,8 @@ module RakefileHelpers def initialize(all_files = false) @all_files = all_files - return false unless @all_files - return false unless File.exist?('test_file_filter.yml') + return unless @all_files + return unless File.exist?('test_file_filter.yml') filters = YAML.load_file('test_file_filter.yml') @all_files = filters[:all_files] diff --git a/auto/unity_test_summary.rb b/auto/unity_test_summary.rb index b37dc5f..810fdbd 100644 --- a/auto/unity_test_summary.rb +++ b/auto/unity_test_summary.rb @@ -101,10 +101,6 @@ class UnityTestSummary raise "Couldn't parse test results: #{summary}" unless summary.find { |v| v =~ /(\d+) Tests (\d+) Failures (\d+) Ignored/ } [Regexp.last_match(1).to_i, Regexp.last_match(2).to_i, Regexp.last_match(3).to_i] end - - def here - File.expand_path(File.dirname(__FILE__)) - end end if $0 == __FILE__ diff --git a/examples/example_3/rakefile.rb b/examples/example_3/rakefile.rb index bf9f42b..d014929 100644 --- a/examples/example_3/rakefile.rb +++ b/examples/example_3/rakefile.rb @@ -1,12 +1,9 @@ -HERE = File.expand_path(File.dirname(__FILE__)) + '/' -UNITY_ROOT = File.expand_path(File.dirname(__FILE__)) + '/../..' - require 'rake' require 'rake/clean' -require HERE + 'rakefile_helper' +require_relative 'rakefile_helper' TEMP_DIRS = [ - File.join(HERE, 'build') + File.join(__dir__, 'build') ].freeze TEMP_DIRS.each do |dir| @@ -32,8 +29,8 @@ task :summary do end desc 'Build and test Unity' -task all: %i(clean unit summary) -task default: %i(clobber all) +task all: %i[clean unit summary] +task default: %i[clobber all] task ci: [:default] task cruise: [:default] diff --git a/examples/example_3/rakefile_helper.rb b/examples/example_3/rakefile_helper.rb index a186cf0..f1f51d4 100644 --- a/examples/example_3/rakefile_helper.rb +++ b/examples/example_3/rakefile_helper.rb @@ -1,8 +1,8 @@ require 'yaml' require 'fileutils' -require UNITY_ROOT + '/auto/unity_test_summary' -require UNITY_ROOT + '/auto/generate_test_runner' -require UNITY_ROOT + '/auto/colour_reporter' +require_relative '../../auto/unity_test_summary' +require_relative '../../auto/generate_test_runner' +require_relative '../../auto/colour_reporter' module RakefileHelpers C_EXTENSION = '.c'.freeze @@ -149,7 +149,7 @@ module RakefileHelpers def report_summary summary = UnityTestSummary.new - summary.root = HERE + summary.root = __dir__ results_glob = "#{$cfg['compiler']['build_path']}*.test*" results_glob.tr!('\\', '/') results = Dir[results_glob] diff --git a/extras/fixture/rakefile.rb b/extras/fixture/rakefile.rb index 7603e57..8b5319c 100644 --- a/extras/fixture/rakefile.rb +++ b/extras/fixture/rakefile.rb @@ -4,15 +4,13 @@ # [Released under MIT License. Please refer to license.txt for details] # ========================================== -HERE = File.expand_path(File.dirname(__FILE__)) + '/' - require 'rake' require 'rake/clean' require 'rake/testtask' -require HERE + 'rakefile_helper' +require_relative 'rakefile_helper' TEMP_DIRS = [ - File.join(HERE, 'build') + File.join(__dir__, 'build') ].freeze TEMP_DIRS.each do |dir| @@ -33,10 +31,10 @@ task unit: [:prepare_for_tests] do end desc 'Build and test Unity Framework' -task all: %i(clean unit) -task default: %i(clobber all) -task ci: %i(no_color default) -task cruise: %i(no_color default) +task all: %i[clean unit] +task default: %i[clobber all] +task ci: %i[no_color default] +task cruise: %i[no_color default] desc 'Load configuration' task :config, :config_file do |_t, args| diff --git a/test/.rubocop.yml b/test/.rubocop.yml index c074ca9..3bfe31a 100644 --- a/test/.rubocop.yml +++ b/test/.rubocop.yml @@ -18,7 +18,7 @@ Style/HashSyntax: EnforcedStyle: no_mixed_keys # This is disabled because it seems to get confused over nested hashes -Style/AlignHash: +Layout/AlignHash: Enabled: false EnforcedHashRocketStyle: table EnforcedColonStyle: table diff --git a/test/rakefile b/test/rakefile index 4a2f3d2..770fead 100644 --- a/test/rakefile +++ b/test/rakefile @@ -4,17 +4,16 @@ # [Released under MIT License. Please refer to license.txt for details] # ========================================== -UNITY_ROOT = File.expand_path(File.dirname(__FILE__)) + '/' $verbose = false require 'rake' require 'rake/clean' -require UNITY_ROOT + 'rakefile_helper' +require_relative 'rakefile_helper' require 'rspec/core/rake_task' TEMP_DIRS = [ - File.join(UNITY_ROOT, 'build'), - File.join(UNITY_ROOT, 'sandbox') + File.join(__dir__, 'build'), + File.join(__dir__, 'sandbox') ] TEMP_DIRS.each do |dir| diff --git a/test/rakefile_helper.rb b/test/rakefile_helper.rb index 1fd60c5..d4335ec 100644 --- a/test/rakefile_helper.rb +++ b/test/rakefile_helper.rb @@ -6,9 +6,9 @@ require 'yaml' require 'fileutils' -require UNITY_ROOT + '../auto/unity_test_summary' -require UNITY_ROOT + '../auto/generate_test_runner' -require UNITY_ROOT + '../auto/colour_reporter' +require_relative '../auto/unity_test_summary' +require_relative '../auto/generate_test_runner' +require_relative '../auto/colour_reporter' module RakefileHelpers C_EXTENSION = '.c'.freeze @@ -179,7 +179,7 @@ module RakefileHelpers def report_summary summary = UnityTestSummary.new - summary.root = UNITY_ROOT + summary.root = __dir__ results_glob = "#{$cfg['compiler']['build_path']}*.test*" results_glob.tr!('\\', '/') results = Dir[results_glob] From 5cd1c33b0e99bfaa1c1c1a2c950854286e6c5eb3 Mon Sep 17 00:00:00 2001 From: John Lindgren Date: Wed, 28 Nov 2018 13:36:27 -0500 Subject: [PATCH 13/17] Fix uninitialized constant --- extras/fixture/rakefile_helper.rb | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/extras/fixture/rakefile_helper.rb b/extras/fixture/rakefile_helper.rb index c45b239..71e752b 100644 --- a/extras/fixture/rakefile_helper.rb +++ b/extras/fixture/rakefile_helper.rb @@ -6,9 +6,9 @@ require 'yaml' require 'fileutils' -require HERE + '../../auto/unity_test_summary' -require HERE + '../../auto/generate_test_runner' -require HERE + '../../auto/colour_reporter' +require_relative '../../auto/unity_test_summary' +require_relative '../../auto/generate_test_runner' +require_relative '../../auto/colour_reporter' module RakefileHelpers C_EXTENSION = '.c'.freeze @@ -16,7 +16,7 @@ module RakefileHelpers def load_configuration(config_file) return if $configured - $cfg_file = HERE + "../../test/targets/#{config_file}" unless config_file =~ /[\\|\/]/ + $cfg_file = "#{__dir__}/../../test/targets/#{config_file}" unless config_file =~ /[\\|\/]/ $cfg = YAML.load(File.read($cfg_file)) $colour_output = false unless $cfg['colour'] $configured = true if config_file != DEFAULT_CONFIG_FILE @@ -128,7 +128,7 @@ module RakefileHelpers def report_summary summary = UnityTestSummary.new - summary.root = HERE + summary.root = __dir__ results_glob = "#{$cfg['compiler']['build_path']}*.test*" results_glob.tr!('\\', '/') results = Dir[results_glob] @@ -145,9 +145,9 @@ module RakefileHelpers $cfg['compiler']['defines']['items'] = [] if $cfg['compiler']['defines']['items'].nil? # Get a list of all source files needed - src_files = Dir[HERE + 'src/*.c'] - src_files += Dir[HERE + 'test/*.c'] - src_files += Dir[HERE + 'test/main/*.c'] + src_files = Dir["#{__dir__}/src/*.c"] + src_files += Dir["#{__dir__}/test/*.c"] + src_files += Dir["#{__dir__}/test/main/*.c"] src_files << '../../src/unity.c' # Build object files From 8a77f48634a055a11edf1583babd1b7a86e7d3a6 Mon Sep 17 00:00:00 2001 From: John Lindgren Date: Wed, 28 Nov 2018 14:40:40 -0500 Subject: [PATCH 14/17] Fix undefined behavior when printing INT_MIN/INT64_MIN. Negating the most-negative signed integer results in overflow, which is undefined behavior. Fix this by casting to an unsigned type first (unsigned overflow is well-defined as it uses modular arithmetic). --- src/unity.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/unity.c b/src/unity.c index d1dda41..00c9412 100644 --- a/src/unity.c +++ b/src/unity.c @@ -183,7 +183,7 @@ void UnityPrintNumber(const UNITY_INT number_to_print) { /* A negative number, including MIN negative */ UNITY_OUTPUT_CHAR('-'); - number = (UNITY_UINT)(-number_to_print); + number = -number; } UnityPrintNumberUnsigned(number); } From d09f4953ffd67bcaf774d3f0e6476a9ec33265f4 Mon Sep 17 00:00:00 2001 From: John Lindgren Date: Wed, 28 Nov 2018 15:17:25 -0500 Subject: [PATCH 15/17] Fix another signed integer overflow. --- src/unity.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/unity.c b/src/unity.c index 00c9412..70c6b26 100644 --- a/src/unity.c +++ b/src/unity.c @@ -1019,22 +1019,22 @@ void UnityAssertNumbersWithin(const UNITY_UINT delta, { if (actual > expected) { - Unity.CurrentTestFailed = (UNITY_UINT)((UNITY_UINT)(actual - expected) > delta); + Unity.CurrentTestFailed = (((UNITY_UINT)actual - (UNITY_UINT)expected) > delta); } else { - Unity.CurrentTestFailed = (UNITY_UINT)((UNITY_UINT)(expected - actual) > delta); + Unity.CurrentTestFailed = (((UNITY_UINT)expected - (UNITY_UINT)actual) > delta); } } else { if ((UNITY_UINT)actual > (UNITY_UINT)expected) { - Unity.CurrentTestFailed = (UNITY_UINT)((UNITY_UINT)(actual - expected) > delta); + Unity.CurrentTestFailed = (((UNITY_UINT)actual - (UNITY_UINT)expected) > delta); } else { - Unity.CurrentTestFailed = (UNITY_UINT)((UNITY_UINT)(expected - actual) > delta); + Unity.CurrentTestFailed = (((UNITY_UINT)expected - (UNITY_UINT)actual) > delta); } } From 5db2a3dbd9b72070c236eda6549520a38ca0ada1 Mon Sep 17 00:00:00 2001 From: Elliot Gawthrop Date: Sun, 9 Dec 2018 21:21:46 +0000 Subject: [PATCH 16/17] Add support for strings in TEST_CASE() --- auto/generate_test_runner.rb | 15 ++++++++- test/tests/testparameterized.c | 61 ++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 1 deletion(-) diff --git a/auto/generate_test_runner.rb b/auto/generate_test_runner.rb index 377db6f..9f64b44 100644 --- a/auto/generate_test_runner.rb +++ b/auto/generate_test_runner.rb @@ -90,12 +90,25 @@ class UnityTestRunnerGenerator def find_tests(source) tests_and_line_numbers = [] + # contains characters which will be substituted from within strings, doing + # this prevents these characters from interferring with scrubbers + # @ is not a valid C character, so there should be no clashes with files genuinely containing these markers + substring_subs = { '{' => '@co@', '}' => '@cc@', ';' => '@ss@', '/' => '@fs@' } + substring_re = Regexp.union(substring_subs.keys) + substring_unsubs = substring_subs.invert # the inverse map will be used to fix the strings afterwords + substring_unsubs['@quote@'] = '\\"' + substring_unsubs['@apos@'] = '\\\'' + substring_unre = Regexp.union(substring_unsubs.keys) source_scrubbed = source.clone - source_scrubbed = source_scrubbed.gsub(/"[^"\n]*"/, '') # remove things in strings + source_scrubbed = source_scrubbed.gsub(/\\"/, '@quote@') # hide escaped quotes to allow capture of the full string/char + source_scrubbed = source_scrubbed.gsub(/\\'/, '@apos@') # hide escaped apostrophes to allow capture of the full string/char + source_scrubbed = source_scrubbed.gsub(/("[^"\n]*")|('[^'\n]*')/) { |s| s.gsub(substring_re, substring_subs) } # temporarily hide problematic + # characters within strings source_scrubbed = source_scrubbed.gsub(/\/\/.*$/, '') # remove line comments source_scrubbed = source_scrubbed.gsub(/\/\*.*?\*\//m, '') # remove block comments lines = source_scrubbed.split(/(^\s*\#.*$) # Treat preprocessor directives as a logical line | (;|\{|\}) /x) # Match ;, {, and } as end of lines + .map { |line| line.gsub(substring_unre, substring_unsubs) } # unhide the problematic characters previously removed lines.each_with_index do |line, _index| # find tests diff --git a/test/tests/testparameterized.c b/test/tests/testparameterized.c index 136cd2f..6100834 100644 --- a/test/tests/testparameterized.c +++ b/test/tests/testparameterized.c @@ -46,6 +46,14 @@ void flushSpy(void) {} int SetToOneToFailInTearDown; int SetToOneMeanWeAlreadyCheckedThisGuy; +static unsigned NextExpectedStringIndex; +static unsigned NextExpectedCharIndex; + +void suiteSetUp(void) +{ + NextExpectedStringIndex = 0; + NextExpectedCharIndex = 0; +} void setUp(void) { @@ -111,3 +119,56 @@ void test_NormalFailsStillWork(void) TEST_ASSERT_TRUE(0); VERIFY_FAILS_END } + +TEST_CASE(0, "abc") +TEST_CASE(1, "{") +TEST_CASE(2, "}") +TEST_CASE(3, ";") +TEST_CASE(4, "\"quoted\"") +void test_StringsArePreserved(unsigned index, const char * str) +{ + static const char * const expected[] = + { + "abc", + "{", + "}", + ";", + "\"quoted\"" + }; + + /* Ensure that no test cases are skipped by tracking the next expected index */ + TEST_ASSERT_EQUAL_UINT32(NextExpectedStringIndex, index); + TEST_ASSERT_LESS_THAN(sizeof(expected) / sizeof(expected[0]), index); + TEST_ASSERT_EQUAL_STRING(expected[index], str); + + NextExpectedStringIndex++; +} + +TEST_CASE(0, 'x') +TEST_CASE(1, '{') +TEST_CASE(2, '}') +TEST_CASE(3, ';') +TEST_CASE(4, '\'') +TEST_CASE(5, '"') +void test_CharsArePreserved(unsigned index, char c) +{ + static const char expected[] = + { + 'x', + '{', + '}', + ';', + '\'', + '"' + }; + + /* Ensure that no test cases are skipped by tracking the next expected index */ + TEST_ASSERT_EQUAL_UINT32(NextExpectedCharIndex, index); + TEST_ASSERT_LESS_THAN(sizeof(expected) / sizeof(expected[0]), index); + TEST_ASSERT_EQUAL(expected[index], c); + + NextExpectedCharIndex++; +} + + + From 516f7be04526b4573e0a5bc37fad2917e9e189aa Mon Sep 17 00:00:00 2001 From: Dom Postorivo Date: Wed, 13 Jun 2018 23:44:58 -0400 Subject: [PATCH 17/17] generate runner defines with #ifndef guards --- auto/generate_test_runner.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/auto/generate_test_runner.rb b/auto/generate_test_runner.rb index 9f64b44..2acda0f 100644 --- a/auto/generate_test_runner.rb +++ b/auto/generate_test_runner.rb @@ -179,7 +179,7 @@ class UnityTestRunnerGenerator output.puts('#endif') output.puts('#include ') if @options[:defines] && !@options[:defines].empty? - @options[:defines].each { |d| output.puts("#define #{d}") } + @options[:defines].each { |d| output.puts("#ifndef #{d}\n#define #{d}\n#endif /* #{d} */") } end if @options[:header_file] && !@options[:header_file].empty? output.puts("#include \"#{File.basename(@options[:header_file])}\"")