Any C language lawyers on the list?

26 views
Skip to first unread message

Steve Byan

unread,
Feb 26, 2010, 1:09:30 PM2/26/10
to cmoc...@googlegroups.com
Consider the following unit-tests for cmockery itself:

/***
* @unit_test assert_in_range with unsigned char.
*/
void test_assert_in_range_unsigned_char(void **state) {
unsigned char value;
unsigned char lower_bound;
unsigned char upper_bound;
value = 0;
lower_bound = 0;
upper_bound = UCHAR_MAX;
fprintf(stderr, " lower bound: %hhu upper bound: %hhu \n",
lower_bound, upper_bound);
assert_in_range(value, lower_bound, upper_bound);
value = UCHAR_MAX;
assert_in_range(value, lower_bound, upper_bound);
value = 128;
assert_in_range(value, lower_bound, upper_bound);
}

/***
* @unit_test assert_in_range with signed char.
*/
void test_assert_in_range_signed_char(void **state) {
signed char value;
signed char lower_bound;
signed char upper_bound;
value = SCHAR_MIN;
lower_bound = SCHAR_MIN;
upper_bound = SCHAR_MAX;
fprintf(stderr, " lower bound: %hhd upper bound: %hhd \n",
lower_bound, upper_bound);
assert_in_range(value, lower_bound, upper_bound);
value = SCHAR_MAX;
assert_in_range(value, lower_bound, upper_bound);
value = 0;
assert_in_range(value, lower_bound, upper_bound);
}

/***
* @unit_test assert_in_range with unsigned short.
*/
void test_assert_in_range_unsigned_short(void **state) {
unsigned short value;
unsigned short lower_bound;
unsigned short upper_bound;
value = 0;
lower_bound = 0;
upper_bound = USHRT_MAX;
fprintf(stderr, " lower bound: %hu upper bound: %hu \n",
lower_bound, upper_bound);
assert_in_range(value, lower_bound, upper_bound);
value = USHRT_MAX;
assert_in_range(value, lower_bound, upper_bound);
value = 32768;
assert_in_range(value, lower_bound, upper_bound);
}

/***
* @unit_test assert_in_range with signed short.
*/
void test_assert_in_range_signed_short(void **state) {
short value;
short lower_bound;
short upper_bound;
value = SHRT_MIN;
lower_bound = SHRT_MIN;
upper_bound = SHRT_MAX;
fprintf(stderr, " lower bound: %hd upper bound: %hd \n",
lower_bound, upper_bound);
assert_in_range(value, lower_bound, upper_bound);
value = SHRT_MAX;
assert_in_range(value, lower_bound, upper_bound);
value = 0;
assert_in_range(value, lower_bound, upper_bound);
}

/***
* @unit_test assert_in_range with unsigned int.
*/
void test_assert_in_range_unsigned_int(void **state) {
unsigned int value;
unsigned int lower_bound;
unsigned int upper_bound;
value = 0;
lower_bound = 0;
upper_bound = UINT_MAX;
fprintf(stderr, " lower bound: %u upper bound: %u \n",
lower_bound, upper_bound);
assert_in_range(value, lower_bound, upper_bound);
value = UINT_MAX;
assert_in_range(value, lower_bound, upper_bound);
value = 65536;
assert_in_range(value, lower_bound, upper_bound);
}

/***
* @unit_test assert_in_range with signed int.
*/
void test_assert_in_range_signed_int(void **state) {
int value;
int lower_bound;
int upper_bound;
value = INT_MIN;
lower_bound = INT_MIN;
upper_bound = INT_MAX;
fprintf(stderr, " lower bound: %d upper bound: %d \n",
lower_bound, upper_bound);
assert_in_range(value, lower_bound, upper_bound);
value = INT_MAX;
assert_in_range(value, lower_bound, upper_bound);
value = 0;
assert_in_range(value, lower_bound, upper_bound);
}

/***
* @unit_test assert_in_range with unsigned long.
*/
void test_assert_in_range_unsigned_long(void **state) {
unsigned long value;
unsigned long lower_bound;
unsigned long upper_bound;
value = 0;
lower_bound = 0;
upper_bound = ULONG_MAX;
fprintf(stderr, " lower bound: %lu upper bound: %lu \n",
lower_bound, upper_bound);
assert_in_range(value, lower_bound, upper_bound);
value = ULONG_MAX;
assert_in_range(value, lower_bound, upper_bound);
value = 2147483648;
assert_in_range(value, lower_bound, upper_bound);
}

/***
* @unit_test assert_in_range with signed long.
*/
void test_assert_in_range_signed_long(void **state) {
long value;
long lower_bound;
long upper_bound;
value = LONG_MIN;
lower_bound = LONG_MIN;
upper_bound = LONG_MAX;
fprintf(stderr, " lower bound: %ld upper bound: %ld \n",
lower_bound, upper_bound);
assert_in_range(value, lower_bound, upper_bound);
value = LONG_MAX;
assert_in_range(value, lower_bound, upper_bound);
value = 0;
assert_in_range(value, lower_bound, upper_bound);
}


Compiling and running these tests on Mac OS X 10.6.2 with gcc 4.2.1 for an x86_64 target gives the following results
(on cmockery-staging tip, but I think the relevant code is essentially the same as for cmockery tip):

[ RUN ] test_assert_in_range_unsigned_char
lower bound: 0 upper bound: 255
[ OK ] test_assert_in_range_unsigned_char
[ RUN ] test_assert_in_range_signed_char
lower bound: -128 upper bound: 127
-128 is not within the range -128-127
ERROR: /Users/smb/src/cmockery-staging/osx/../src/unit_test/unit_test.c:159 Failure!
[ FAILED ] test_assert_in_range_signed_char
[ RUN ] test_assert_in_range_unsigned_short
lower bound: 0 upper bound: 65535
[ OK ] test_assert_in_range_unsigned_short
[ RUN ] test_assert_in_range_signed_short
lower bound: -32768 upper bound: 32767
-32768 is not within the range -32768-32767
ERROR: /Users/smb/src/cmockery-staging/osx/../src/unit_test/unit_test.c:197 Failure!
[ FAILED ] test_assert_in_range_signed_short
[ RUN ] test_assert_in_range_unsigned_int
lower bound: 0 upper bound: 4294967295
[ OK ] test_assert_in_range_unsigned_int
[ RUN ] test_assert_in_range_signed_int
lower bound: -2147483648 upper bound: 2147483647
-2147483648 is not within the range -2147483648-2147483647
ERROR: /Users/smb/src/cmockery-staging/osx/../src/unit_test/unit_test.c:235 Failure!
[ FAILED ] test_assert_in_range_signed_int
[ RUN ] test_assert_in_range_unsigned_long
lower bound: 0 upper bound: 18446744073709551615
[ OK ] test_assert_in_range_unsigned_long
[ RUN ] test_assert_in_range_signed_long
lower bound: -9223372036854775808 upper bound: 9223372036854775807
[ OK ] test_assert_in_range_signed_long

Compiling and running these tests for an i386 target gives these results:

[ RUN ] test_assert_in_range_unsigned_char
lower bound: 0 upper bound: 255
[ OK ] test_assert_in_range_unsigned_char
[ RUN ] test_assert_in_range_signed_char
lower bound: -128 upper bound: 127
-128 is not within the range 0--128
ERROR: /Users/smb/src/cmockery-staging/osx/../src/unit_test/unit_test.c:159 Failure!
[ FAILED ] test_assert_in_range_signed_char
[ RUN ] test_assert_in_range_unsigned_short
lower bound: 0 upper bound: 65535
[ OK ] test_assert_in_range_unsigned_short
[ RUN ] test_assert_in_range_signed_short
lower bound: -32768 upper bound: 32767
-32768 is not within the range 0--32768
ERROR: /Users/smb/src/cmockery-staging/osx/../src/unit_test/unit_test.c:197 Failure!
[ FAILED ] test_assert_in_range_signed_short
[ RUN ] test_assert_in_range_unsigned_int
lower bound: 0 upper bound: 4294967295
[ OK ] test_assert_in_range_unsigned_int
[ RUN ] test_assert_in_range_signed_int
lower bound: -2147483648 upper bound: 2147483647
-2147483648 is not within the range 0--2147483648
ERROR: /Users/smb/src/cmockery-staging/osx/../src/unit_test/unit_test.c:235 Failure!
[ FAILED ] test_assert_in_range_signed_int
[ RUN ] test_assert_in_range_unsigned_long
lower bound: 0 upper bound: 4294967295
[ OK ] test_assert_in_range_unsigned_long
[ RUN ] test_assert_in_range_signed_long
lower bound: -2147483648 upper bound: 2147483647
-2147483648 is not within the range 0--2147483648
ERROR: /Users/smb/src/cmockery-staging/osx/../src/unit_test/unit_test.c:273 Failure!
[ FAILED ] test_assert_in_range_signed_long

So something in cmockery's assert_in_range logic has tripped into C-language-undefined-behavior-land. The cmockery range assertions are clearly buggy. The cause isn't clear to me.

Any ideas?

Best regards,
-Steve

--
Steve Byan <stev...@me.com>
Littleton, MA 01460

Steve Byan

unread,
Feb 26, 2010, 3:03:35 PM2/26/10
to cmoc...@googlegroups.com

On Feb 26, 2010, at 10:09 AM, Steve Byan wrote:

> So something in cmockery's assert_in_range logic has tripped into C-language-undefined-behavior-land. The cmockery range assertions are clearly buggy. The cause isn't clear to me.
>
> Any ideas?

Fixing the printf format specification string in integer_in_range_display_error() to reflect the actual size and type of the arguments (unsigned long longs) gives a better diagnosis of the problem. Changing the print_error() call to:

print_error("%llu is not within the range %llu-%llu\n", value, range_min,
range_max);

gives us this on i386:

[ RUN ] test_assert_in_range_signed_char
lower bound: -128 upper bound: 127

4294967168 is not within the range 4294967168-127


ERROR: /Users/smb/src/cmockery-staging/osx/../src/unit_test/unit_test.c:159 Failure!
[ FAILED ] test_assert_in_range_signed_char

[ RUN ] test_assert_in_range_signed_short
lower bound: -32768 upper bound: 32767

4294934528 is not within the range 4294934528-32767


ERROR: /Users/smb/src/cmockery-staging/osx/../src/unit_test/unit_test.c:197 Failure!
[ FAILED ] test_assert_in_range_signed_short

[ RUN ] test_assert_in_range_signed_int
lower bound: -2147483648 upper bound: 2147483647

2147483648 is not within the range 2147483648-2147483647


ERROR: /Users/smb/src/cmockery-staging/osx/../src/unit_test/unit_test.c:235 Failure!
[ FAILED ] test_assert_in_range_signed_int

[ RUN ] test_assert_in_range_signed_long
lower bound: -2147483648 upper bound: 2147483647

2147483648 is not within the range 2147483648-2147483647


ERROR: /Users/smb/src/cmockery-staging/osx/../src/unit_test/unit_test.c:273 Failure!
[ FAILED ] test_assert_in_range_signed_long


On x86_64:

[ RUN ] test_assert_in_range_signed_char
lower bound: -128 upper bound: 127

4294967168 is not within the range 4294967168-127


ERROR: /Users/smb/src/cmockery-staging/osx/../src/unit_test/unit_test.c:159 Failure!
[ FAILED ] test_assert_in_range_signed_char

[ RUN ] test_assert_in_range_signed_short
lower bound: -32768 upper bound: 32767

4294934528 is not within the range 4294934528-32767


ERROR: /Users/smb/src/cmockery-staging/osx/../src/unit_test/unit_test.c:197 Failure!
[ FAILED ] test_assert_in_range_signed_short

[ RUN ] test_assert_in_range_signed_int
lower bound: -2147483648 upper bound: 2147483647

2147483648 is not within the range 2147483648-2147483647


ERROR: /Users/smb/src/cmockery-staging/osx/../src/unit_test/unit_test.c:235 Failure!
[ FAILED ] test_assert_in_range_signed_int

Now the problem is clear: the use of an unsigned LargestIntegralType as the type of the arguments to assert_in_range. It appears cmockery needs assert_in_unsigned_range() and assert_in_signed_range() instead of assert_in_range.

Comments?

Reply all
Reply to author
Forward
0 new messages