|
|
#include "../../unity/unity.h" |
|
|
#include <stdio.h> |
|
|
#include <stdlib.h> |
|
|
#include <string.h> |
|
|
#include <stdint.h> |
|
|
#include <stdbool.h> |
|
|
#include <unistd.h> |
|
|
#include <errno.h> |
|
|
#include <limits.h> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static char* run_and_capture_process_field(const char* input, uintmax_t field, bool* ret_valid) |
|
|
{ |
|
|
char* mutable = strdup(input); |
|
|
if (!mutable) |
|
|
return NULL; |
|
|
|
|
|
|
|
|
fflush(stdout); |
|
|
int saved_fd = dup(fileno(stdout)); |
|
|
if (saved_fd < 0) |
|
|
{ |
|
|
free(mutable); |
|
|
return NULL; |
|
|
} |
|
|
|
|
|
FILE* tmp = tmpfile(); |
|
|
if (!tmp) |
|
|
{ |
|
|
free(mutable); |
|
|
close(saved_fd); |
|
|
return NULL; |
|
|
} |
|
|
|
|
|
int tmp_fd = fileno(tmp); |
|
|
if (dup2(tmp_fd, fileno(stdout)) < 0) |
|
|
{ |
|
|
free(mutable); |
|
|
fclose(tmp); |
|
|
close(saved_fd); |
|
|
return NULL; |
|
|
} |
|
|
|
|
|
|
|
|
bool ok = process_field(mutable, field); |
|
|
|
|
|
|
|
|
fflush(stdout); |
|
|
long size = 0; |
|
|
if (fseek(tmp, 0, SEEK_END) == 0) |
|
|
size = ftell(tmp); |
|
|
if (size < 0) size = 0; |
|
|
(void)fseek(tmp, 0, SEEK_SET); |
|
|
|
|
|
char* out = (char*)malloc((size_t)size + 1); |
|
|
if (!out) |
|
|
{ |
|
|
|
|
|
dup2(saved_fd, fileno(stdout)); |
|
|
close(saved_fd); |
|
|
fclose(tmp); |
|
|
free(mutable); |
|
|
return NULL; |
|
|
} |
|
|
|
|
|
if (size > 0) |
|
|
fread(out, 1, (size_t)size, tmp); |
|
|
out[size] = '\0'; |
|
|
|
|
|
|
|
|
dup2(saved_fd, fileno(stdout)); |
|
|
close(saved_fd); |
|
|
fclose(tmp); |
|
|
free(mutable); |
|
|
|
|
|
if (ret_valid) |
|
|
*ret_valid = ok; |
|
|
|
|
|
return out; |
|
|
} |
|
|
|
|
|
void setUp(void) { |
|
|
|
|
|
|
|
|
|
|
|
decimal_point = "."; |
|
|
decimal_point_length = 1; |
|
|
thousands_sep = ""; |
|
|
thousands_sep_length = 0; |
|
|
|
|
|
|
|
|
scale_from = scale_none; |
|
|
scale_to = scale_none; |
|
|
round_style = round_from_zero; |
|
|
inval_style = inval_ignore; |
|
|
suffix = NULL; |
|
|
unit_separator = NULL; |
|
|
from_unit_size = 1; |
|
|
to_unit_size = 1; |
|
|
grouping = 0; |
|
|
|
|
|
|
|
|
if (padding_buffer) |
|
|
{ |
|
|
free(padding_buffer); |
|
|
padding_buffer = NULL; |
|
|
} |
|
|
padding_buffer_size = 0; |
|
|
padding_width = 0; |
|
|
zero_padding_width = 0; |
|
|
user_precision = -1; |
|
|
format_str = NULL; |
|
|
if (format_str_prefix) |
|
|
{ |
|
|
free(format_str_prefix); |
|
|
format_str_prefix = NULL; |
|
|
} |
|
|
if (format_str_suffix) |
|
|
{ |
|
|
free(format_str_suffix); |
|
|
format_str_suffix = NULL; |
|
|
} |
|
|
auto_padding = 0; |
|
|
delimiter = NULL; |
|
|
line_delim = '\n'; |
|
|
header = 0; |
|
|
debug = false; |
|
|
dev_debug = false; |
|
|
} |
|
|
|
|
|
void tearDown(void) { |
|
|
if (padding_buffer) |
|
|
{ |
|
|
free(padding_buffer); |
|
|
padding_buffer = NULL; |
|
|
} |
|
|
if (format_str_prefix) |
|
|
{ |
|
|
free(format_str_prefix); |
|
|
format_str_prefix = NULL; |
|
|
} |
|
|
if (format_str_suffix) |
|
|
{ |
|
|
free(format_str_suffix); |
|
|
format_str_suffix = NULL; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void test_process_field_not_included_prints_unchanged_and_true(void) |
|
|
{ |
|
|
bool ok = true; |
|
|
const char* input = "abc"; |
|
|
char* out = run_and_capture_process_field(input, 2, &ok); |
|
|
|
|
|
TEST_ASSERT_NOT_NULL(out); |
|
|
TEST_ASSERT_TRUE(ok); |
|
|
TEST_ASSERT_EQUAL_STRING("abc", out); |
|
|
|
|
|
free(out); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void test_process_field_included_valid_integer(void) |
|
|
{ |
|
|
bool ok = false; |
|
|
const char* input = "123"; |
|
|
char* out = run_and_capture_process_field(input, 1, &ok); |
|
|
|
|
|
TEST_ASSERT_NOT_NULL(out); |
|
|
TEST_ASSERT_TRUE(ok); |
|
|
TEST_ASSERT_EQUAL_STRING("123", out); |
|
|
|
|
|
free(out); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void test_process_field_included_invalid_input(void) |
|
|
{ |
|
|
bool ok = true; |
|
|
const char* input = "not-a-number"; |
|
|
char* out = run_and_capture_process_field(input, 1, &ok); |
|
|
|
|
|
TEST_ASSERT_NOT_NULL(out); |
|
|
TEST_ASSERT_FALSE(ok); |
|
|
TEST_ASSERT_EQUAL_STRING("not-a-number", out); |
|
|
|
|
|
free(out); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void test_process_field_suffix_trim_and_add(void) |
|
|
{ |
|
|
suffix = "B"; |
|
|
|
|
|
bool ok = false; |
|
|
const char* input = "10B"; |
|
|
char* out = run_and_capture_process_field(input, 1, &ok); |
|
|
|
|
|
TEST_ASSERT_NOT_NULL(out); |
|
|
TEST_ASSERT_TRUE(ok); |
|
|
TEST_ASSERT_EQUAL_STRING("10B", out); |
|
|
|
|
|
free(out); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void test_process_field_unit_conversion(void) |
|
|
{ |
|
|
from_unit_size = 1024; |
|
|
to_unit_size = 1; |
|
|
|
|
|
bool ok = false; |
|
|
const char* input = "1"; |
|
|
char* out = run_and_capture_process_field(input, 1, &ok); |
|
|
|
|
|
TEST_ASSERT_NOT_NULL(out); |
|
|
TEST_ASSERT_TRUE(ok); |
|
|
TEST_ASSERT_EQUAL_STRING("1024", out); |
|
|
|
|
|
free(out); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void test_process_field_auto_padding_preserves_width(void) |
|
|
{ |
|
|
auto_padding = 1; |
|
|
|
|
|
bool ok = false; |
|
|
const char* input = " 5"; |
|
|
char* out = run_and_capture_process_field(input, 1, &ok); |
|
|
|
|
|
TEST_ASSERT_NOT_NULL(out); |
|
|
TEST_ASSERT_TRUE(ok); |
|
|
TEST_ASSERT_EQUAL_STRING(" 5", out); |
|
|
|
|
|
free(out); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void test_process_field_too_large_precision_returns_false_and_prints_original(void) |
|
|
{ |
|
|
|
|
|
const char* input = "0.1234567890123456789012345"; |
|
|
bool ok = true; |
|
|
char* out = run_and_capture_process_field(input, 1, &ok); |
|
|
|
|
|
TEST_ASSERT_NOT_NULL(out); |
|
|
TEST_ASSERT_FALSE(ok); |
|
|
TEST_ASSERT_EQUAL_STRING(input, out); |
|
|
|
|
|
free(out); |
|
|
} |
|
|
|
|
|
int main(void) |
|
|
{ |
|
|
UNITY_BEGIN(); |
|
|
|
|
|
RUN_TEST(test_process_field_not_included_prints_unchanged_and_true); |
|
|
RUN_TEST(test_process_field_included_valid_integer); |
|
|
RUN_TEST(test_process_field_included_invalid_input); |
|
|
RUN_TEST(test_process_field_suffix_trim_and_add); |
|
|
RUN_TEST(test_process_field_unit_conversion); |
|
|
RUN_TEST(test_process_field_auto_padding_preserves_width); |
|
|
RUN_TEST(test_process_field_too_large_precision_returns_false_and_prints_original); |
|
|
|
|
|
return UNITY_END(); |
|
|
} |