coreutils / tests /od /tests_for_ATTRIBUTE_NONNULL.c
AryaWu's picture
Upload folder using huggingface_hub
78d2150 verified
#include "../../unity/unity.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
#include <limits.h>
#include <stdint.h>
/* The test file is included into the same translation unit as od.c,
so we can use internal types, enums, arrays, and functions directly:
- struct tspec, enum output_format, enum size_spec
- width_bytes, integral_type_size, fp_type_size
- ispec_to_format, print_* functions
*/
static print_function_type expected_print_fn_integral(enum size_spec size_spec,
enum output_format fmt)
{
/* Mirror the selection logic in decode_one_format for integer formats. */
if (size_spec == INT)
return print_int;
else if (SHORT < INT && size_spec == SHORT)
return (fmt == SIGNED_DECIMAL ? print_s_short : print_short);
else if (CHAR < SHORT && size_spec == CHAR)
return (fmt == SIGNED_DECIMAL ? print_s_char : print_char);
else if (INT < LONG && size_spec == LONG)
return print_long;
else if (LONG < INTMAX && size_spec == INTMAX)
return print_intmax;
else if (LONG < LONG_LONG && LONG_LONG < INTMAX && size_spec == LONG_LONG)
return print_long_long;
/* Should not reach here for valid inputs. */
return (print_function_type)0;
}
static int fp_size_supported(size_t sz)
{
/* Match the acceptance check used by decode_one_format. */
if (sz >= countof(fp_type_size))
return 0;
if (fp_type_size[sz] == NO_SIZE)
return 0;
#if !FLOAT16_SUPPORTED && BF16_SUPPORTED
/* Special-case rejection per decode_one_format. */
if (sz == sizeof(bfloat16))
return 0;
#endif
return 1;
}
void setUp(void) {
/* No global state set up is required. */
}
void tearDown(void) {
/* No teardown required. */
}
static void init_tspec_pattern(struct tspec *t, unsigned char pat)
{
memset(t, pat, sizeof(*t));
}
static void assert_tspec_unchanged(struct tspec const *orig, struct tspec const *now)
{
TEST_ASSERT_EQUAL_UINT8_ARRAY(orig, now, sizeof(*orig));
}
void test_decode_one_format_invalid_character(void)
{
const char *s = "q"; /* invalid leading specifier */
const char *next = (const char*)0xDEADBEEF; /* sentinel */
struct tspec t, before;
init_tspec_pattern(&t, 0xA5);
before = t;
bool ok = decode_one_format(s, s, &next, &t);
TEST_ASSERT_FALSE(ok);
TEST_ASSERT_EQUAL_PTR((const char*)0xDEADBEEF, next);
assert_tspec_unchanged(&before, &t);
}
void test_decode_one_format_signed_decimal_default_int(void)
{
const char *s = "d";
const char *next = NULL;
struct tspec t;
memset(&t, 0, sizeof t);
bool ok = decode_one_format(s, s, &next, &t);
TEST_ASSERT_TRUE(ok);
TEST_ASSERT_EQUAL_PTR(s + 1, next);
TEST_ASSERT_EQUAL_INT(SIGNED_DECIMAL, t.fmt);
int sz = (int)sizeof(unsigned int);
TEST_ASSERT_TRUE(sz < (int)countof(integral_type_size));
enum size_spec ss = integral_type_size[sz];
TEST_ASSERT_EQUAL_INT(ss, t.size);
/* Expected print function per selection logic. */
TEST_ASSERT_EQUAL_PTR(expected_print_fn_integral(ss, SIGNED_DECIMAL), t.print_function);
int expected_width = INT_BITS_STRLEN_BOUND(CHAR_BIT * sz - 1) + 1;
TEST_ASSERT_EQUAL_INT(expected_width, t.field_width);
char expected_fmt[FMT_BYTES_ALLOCATED];
sprintf(expected_fmt, "%%*%s",
ispec_to_format(ss, "d", "ld", "lld", "jd"));
TEST_ASSERT_EQUAL_STRING(expected_fmt, t.fmt_string);
TEST_ASSERT_FALSE(t.hexl_mode_trailer);
}
void test_decode_one_format_octal_size_2(void)
{
const char *s = "o2";
const char *next = NULL;
struct tspec t;
memset(&t, 0, sizeof t);
bool ok = decode_one_format(s, s, &next, &t);
TEST_ASSERT_TRUE(ok);
TEST_ASSERT_EQUAL_PTR(s + 2, next);
TEST_ASSERT_EQUAL_INT(OCTAL, t.fmt);
int sz = 2;
TEST_ASSERT_TRUE(sz < (int)countof(integral_type_size));
enum size_spec ss = integral_type_size[sz];
TEST_ASSERT_NOT_EQUAL(NO_SIZE, ss);
TEST_ASSERT_EQUAL_INT(ss, t.size);
TEST_ASSERT_EQUAL_PTR(expected_print_fn_integral(ss, OCTAL), t.print_function);
int expected_width = (CHAR_BIT * sz + 2) / 3;
TEST_ASSERT_EQUAL_INT(expected_width, t.field_width);
char expected_fmt[FMT_BYTES_ALLOCATED];
sprintf(expected_fmt, "%%*.%d%s", expected_width,
ispec_to_format(ss, "o", "lo", "llo", "jo"));
TEST_ASSERT_EQUAL_STRING(expected_fmt, t.fmt_string);
TEST_ASSERT_FALSE(t.hexl_mode_trailer);
}
void test_decode_one_format_hex_with_trailer_z(void)
{
const char *s = "x1zREST";
const char *next = NULL;
struct tspec t;
memset(&t, 0, sizeof t);
bool ok = decode_one_format(s, s, &next, &t);
TEST_ASSERT_TRUE(ok);
/* Parsed: 'x' + size 1 + 'z' => next should point at 'R' */
TEST_ASSERT_EQUAL_PTR(s + 3, next);
TEST_ASSERT_EQUAL_INT(HEXADECIMAL, t.fmt);
TEST_ASSERT_TRUE(t.hexl_mode_trailer);
}
void test_decode_one_format_named_character_a(void)
{
const char *s = "a";
const char *next = NULL;
struct tspec t;
memset(&t, 0, sizeof t);
bool ok = decode_one_format(s, s, &next, &t);
TEST_ASSERT_TRUE(ok);
TEST_ASSERT_EQUAL_PTR(s + 1, next);
TEST_ASSERT_EQUAL_INT(NAMED_CHARACTER, t.fmt);
TEST_ASSERT_EQUAL_INT(CHAR, t.size);
TEST_ASSERT_EQUAL_PTR(print_named_ascii, t.print_function);
TEST_ASSERT_EQUAL_INT(3, t.field_width);
TEST_ASSERT_FALSE(t.hexl_mode_trailer);
}
void test_decode_one_format_ascii_c(void)
{
const char *s = "c";
const char *next = NULL;
struct tspec t;
memset(&t, 0, sizeof t);
bool ok = decode_one_format(s, s, &next, &t);
TEST_ASSERT_TRUE(ok);
TEST_ASSERT_EQUAL_PTR(s + 1, next);
TEST_ASSERT_EQUAL_INT(CHARACTER, t.fmt);
TEST_ASSERT_EQUAL_INT(CHAR, t.size);
TEST_ASSERT_EQUAL_PTR(print_ascii, t.print_function);
TEST_ASSERT_EQUAL_INT(3, t.field_width);
TEST_ASSERT_FALSE(t.hexl_mode_trailer);
}
void test_decode_one_format_float_default_double(void)
{
const char *s = "f";
const char *next = NULL;
struct tspec t;
memset(&t, 0, sizeof t);
bool ok = decode_one_format(s, s, &next, &t);
TEST_ASSERT_TRUE(ok);
TEST_ASSERT_EQUAL_PTR(s + 1, next);
TEST_ASSERT_EQUAL_INT(FLOATING_POINT, t.fmt);
size_t sz = sizeof(double);
TEST_ASSERT_TRUE(fp_size_supported(sz));
enum size_spec ss = fp_type_size[sz];
TEST_ASSERT_EQUAL_INT(ss, t.size);
TEST_ASSERT_EQUAL_PTR(print_double, t.print_function);
struct lconv const *lc = localeconv();
size_t dp_len = (lc->decimal_point[0] ? strlen(lc->decimal_point) : 1);
int expected_width = DBL_STRLEN_BOUND_L(dp_len);
TEST_ASSERT_EQUAL_INT(expected_width, t.field_width);
}
void test_decode_one_format_float_F_handling(void)
{
const char *s = "fF";
const char *next = NULL;
struct tspec t, before;
init_tspec_pattern(&t, 0xCC);
before = t;
size_t sz = sizeof(float);
int supported = fp_size_supported(sz);
bool ok = decode_one_format(s, s, &next, &t);
if (supported) {
TEST_ASSERT_TRUE(ok);
TEST_ASSERT_EQUAL_PTR(s + 2, next);
TEST_ASSERT_EQUAL_INT(FLOATING_POINT, t.fmt);
TEST_ASSERT_EQUAL_INT(fp_type_size[sz], t.size);
TEST_ASSERT_EQUAL_PTR(print_float, t.print_function);
struct lconv const *lc = localeconv();
size_t dp_len = (lc->decimal_point[0] ? strlen(lc->decimal_point) : 1);
int expected_width = FLT_STRLEN_BOUND_L(dp_len);
TEST_ASSERT_EQUAL_INT(expected_width, t.field_width);
} else {
TEST_ASSERT_FALSE(ok);
TEST_ASSERT_EQUAL_PTR(NULL, next); /* decode_one_format does not set on failure */
assert_tspec_unchanged(&before, &t);
}
}
void test_decode_one_format_float_L_handling(void)
{
const char *s = "fL";
const char *next = NULL;
struct tspec t, before;
init_tspec_pattern(&t, 0xDD);
before = t;
size_t sz = sizeof(long double);
int supported = fp_size_supported(sz);
bool ok = decode_one_format(s, s, &next, &t);
if (supported) {
TEST_ASSERT_TRUE(ok);
TEST_ASSERT_EQUAL_PTR(s + 2, next);
TEST_ASSERT_EQUAL_INT(FLOATING_POINT, t.fmt);
TEST_ASSERT_EQUAL_INT(fp_type_size[sz], t.size);
TEST_ASSERT_EQUAL_PTR(print_long_double, t.print_function);
struct lconv const *lc = localeconv();
size_t dp_len = (lc->decimal_point[0] ? strlen(lc->decimal_point) : 1);
int expected_width = LDBL_STRLEN_BOUND_L(dp_len);
TEST_ASSERT_EQUAL_INT(expected_width, t.field_width);
} else {
TEST_ASSERT_FALSE(ok);
TEST_ASSERT_EQUAL_PTR(NULL, next);
assert_tspec_unchanged(&before, &t);
}
}
void test_decode_one_format_invalid_integral_size_3(void)
{
const char *s = "d3"; /* no standard 3-byte integral type */
const char *next = (const char*)0xABCD;
struct tspec t, before;
init_tspec_pattern(&t, 0xEE);
before = t;
bool ok = decode_one_format(s, s, &next, &t);
TEST_ASSERT_FALSE(ok);
TEST_ASSERT_EQUAL_PTR((const char*)0xABCD, next);
assert_tspec_unchanged(&before, &t);
}
void test_decode_one_format_integer_size_overflow_digits(void)
{
/* A number too large to fit into int should be rejected by simple_strtoi. */
const char *s = "d999999999999999999999"; /* many 9s -> overflow */
const char *next = (const char*)0xFEED;
struct tspec t, before;
init_tspec_pattern(&t, 0x77);
before = t;
bool ok = decode_one_format(s, s, &next, &t);
TEST_ASSERT_FALSE(ok);
TEST_ASSERT_EQUAL_PTR((const char*)0xFEED, next);
assert_tspec_unchanged(&before, &t);
}
void test_decode_one_format_integral_letter_sizes(void)
{
/* Verify C,S,I,L mapping and outputs for several formats. */
struct { const char *spec; enum output_format fmt; char typech; size_t bytes; } cases[] = {
{ "uC", UNSIGNED_DECIMAL, 'C', sizeof(unsigned char) },
{ "xS", HEXADECIMAL, 'S', sizeof(unsigned short) },
{ "dI", SIGNED_DECIMAL, 'I', sizeof(unsigned int) },
{ "oL", OCTAL, 'L', sizeof(unsigned long) },
};
for (size_t i = 0; i < sizeof(cases)/sizeof(cases[0]); ++i) {
const char *s = cases[i].spec;
const char *next = NULL;
struct tspec t;
memset(&t, 0, sizeof t);
bool ok = decode_one_format(s, s, &next, &t);
TEST_ASSERT_TRUE(ok);
TEST_ASSERT_EQUAL_PTR(s + 2, next);
TEST_ASSERT_EQUAL_INT(cases[i].fmt, t.fmt);
size_t sz = cases[i].bytes;
TEST_ASSERT_TRUE(sz < countof(integral_type_size));
enum size_spec ss = integral_type_size[sz];
TEST_ASSERT_NOT_EQUAL(NO_SIZE, ss);
TEST_ASSERT_EQUAL_INT(ss, t.size);
TEST_ASSERT_EQUAL_PTR(expected_print_fn_integral(ss, cases[i].fmt), t.print_function);
int expected_width = 0;
char expected_fmt[FMT_BYTES_ALLOCATED];
if (cases[i].fmt == SIGNED_DECIMAL) {
expected_width = INT_BITS_STRLEN_BOUND(CHAR_BIT * sz - 1) + 1;
sprintf(expected_fmt, "%%*%s",
ispec_to_format(ss, "d", "ld", "lld", "jd"));
} else if (cases[i].fmt == UNSIGNED_DECIMAL) {
expected_width = INT_BITS_STRLEN_BOUND(CHAR_BIT * sz);
sprintf(expected_fmt, "%%*%s",
ispec_to_format(ss, "u", "lu", "llu", "ju"));
} else if (cases[i].fmt == OCTAL) {
expected_width = (CHAR_BIT * sz + 2) / 3;
sprintf(expected_fmt, "%%*.%d%s", expected_width,
ispec_to_format(ss, "o", "lo", "llo", "jo"));
} else if (cases[i].fmt == HEXADECIMAL) {
expected_width = (CHAR_BIT * sz + 3) / 4;
sprintf(expected_fmt, "%%*.%d%s", expected_width,
ispec_to_format(ss, "x", "lx", "llx", "jx"));
}
TEST_ASSERT_EQUAL_INT(expected_width, t.field_width);
TEST_ASSERT_EQUAL_STRING(expected_fmt, t.fmt_string);
TEST_ASSERT_FALSE(t.hexl_mode_trailer);
}
}
int main(void)
{
UNITY_BEGIN();
RUN_TEST(test_decode_one_format_invalid_character);
RUN_TEST(test_decode_one_format_signed_decimal_default_int);
RUN_TEST(test_decode_one_format_octal_size_2);
RUN_TEST(test_decode_one_format_hex_with_trailer_z);
RUN_TEST(test_decode_one_format_named_character_a);
RUN_TEST(test_decode_one_format_ascii_c);
RUN_TEST(test_decode_one_format_float_default_double);
RUN_TEST(test_decode_one_format_float_F_handling);
RUN_TEST(test_decode_one_format_float_L_handling);
RUN_TEST(test_decode_one_format_invalid_integral_size_3);
RUN_TEST(test_decode_one_format_integer_size_overflow_digits);
RUN_TEST(test_decode_one_format_integral_letter_sizes);
return UNITY_END();
}