coreutils / tests /fmt /tests_for_put_space.c
AryaWu's picture
Upload folder using huggingface_hub
78d2150 verified
#include "../../unity/unity.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <unistd.h>
#include <errno.h>
/* Unity hooks */
void setUp(void) {
/* No global setup needed */
}
void tearDown(void) {
/* No global teardown needed */
}
/* Helper to capture output of put_space while respecting the redirection rule.
It sets tabs and out_column as requested, calls put_space(space),
captures the emitted bytes into 'out' (NUL-terminated), returns the final
out_column via final_col, and the captured byte count via out_len.
Returns NULL on success, or a static error message string on failure. */
static char* capture_put_space_call(int start_col, bool tabs_flag, int space,
char* out, size_t out_cap,
int* final_col, size_t* out_len)
{
static char errbuf[128];
if (!out || out_cap == 0 || !final_col || !out_len) {
return "invalid arguments";
}
/* Save original globals */
bool tabs_saved = tabs;
int out_saved = out_column;
/* Prepare redirection */
fflush(stdout);
int saved_fd = dup(fileno(stdout));
if (saved_fd < 0) {
snprintf(errbuf, sizeof(errbuf), "dup failed: %s", strerror(errno));
return errbuf;
}
FILE* tmp = tmpfile();
if (!tmp) {
close(saved_fd);
snprintf(errbuf, sizeof(errbuf), "tmpfile failed: %s", strerror(errno));
return errbuf;
}
int tmpfd = fileno(tmp);
if (dup2(tmpfd, fileno(stdout)) < 0) {
fclose(tmp);
close(saved_fd);
snprintf(errbuf, sizeof(errbuf), "dup2 failed: %s", strerror(errno));
return errbuf;
}
/* Set globals for this call */
tabs = tabs_flag;
out_column = start_col;
/* Call the function under test (do not assert while redirected) */
put_space(space);
int result_col = out_column;
/* Flush and read back from tmp */
fflush(stdout);
long pos = ftell(tmp);
if (pos < 0) pos = 0;
if (fseek(tmp, 0, SEEK_SET) != 0) {
/* Attempt to restore stdout before returning error */
dup2(saved_fd, fileno(stdout));
close(saved_fd);
fclose(tmp);
snprintf(errbuf, sizeof(errbuf), "fseek failed: %s", strerror(errno));
/* Restore globals */
tabs = tabs_saved;
out_column = out_saved;
return errbuf;
}
size_t toread = (size_t)pos;
if (toread >= out_cap) toread = out_cap - 1;
size_t nread = fread(out, 1, toread, tmp);
out[nread] = '\0';
*out_len = nread;
/* Restore stdout */
if (dup2(saved_fd, fileno(stdout)) < 0) {
close(saved_fd);
fclose(tmp);
snprintf(errbuf, sizeof(errbuf), "restore dup2 failed: %s", strerror(errno));
/* Restore globals */
tabs = tabs_saved;
out_column = out_saved;
return errbuf;
}
close(saved_fd);
fclose(tmp);
/* Restore globals except report the result of the call */
tabs = tabs_saved;
out_column = out_saved;
*final_col = result_col;
return NULL;
}
/* Tests */
void test_put_space_zero_no_tabs(void) {
char buf[16];
size_t n = 0;
int final_col = -1;
char* err = capture_put_space_call(0, false, 0, buf, sizeof(buf), &final_col, &n);
TEST_ASSERT_MESSAGE(err == NULL, err ? err : "");
TEST_ASSERT_EQUAL_INT(0, (int)n);
TEST_ASSERT_EQUAL_INT(0, final_col);
TEST_ASSERT_EQUAL_STRING("", buf);
}
void test_put_space_only_spaces_simple(void) {
char buf[32];
size_t n = 0;
int final_col = -1;
char* err = capture_put_space_call(0, false, 5, buf, sizeof(buf), &final_col, &n);
TEST_ASSERT_MESSAGE(err == NULL, err ? err : "");
TEST_ASSERT_EQUAL_INT(5, (int)n);
TEST_ASSERT_EQUAL_INT(5, final_col);
TEST_ASSERT_EQUAL_STRING(" ", buf);
}
void test_put_space_preserves_starting_column_no_tabs(void) {
char buf[32];
size_t n = 0;
int final_col = -1;
/* Start not at column 0; still must print exactly 'space' spaces */
char* err = capture_put_space_call(7, false, 3, buf, sizeof(buf), &final_col, &n);
TEST_ASSERT_MESSAGE(err == NULL, err ? err : "");
TEST_ASSERT_EQUAL_INT(3, (int)n);
TEST_ASSERT_EQUAL_INT(10, final_col); /* 7 + 3 */
TEST_ASSERT_EQUAL_STRING(" ", buf);
}
void test_put_space_tabs_exact_tabstop_from_zero(void) {
char buf[32];
size_t n = 0;
int final_col = -1;
/* From col 0 to exactly 8: expect one tab, final col 8 */
char* err = capture_put_space_call(0, true, 8, buf, sizeof(buf), &final_col, &n);
TEST_ASSERT_MESSAGE(err == NULL, err ? err : "");
TEST_ASSERT_EQUAL_INT(1, (int)n);
TEST_ASSERT_EQUAL_INT(8, final_col);
TEST_ASSERT_EQUAL_STRING("\t", buf);
}
void test_put_space_tabs_to_non_tabstop_from_zero(void) {
char buf[32];
size_t n = 0;
int final_col = -1;
/* From col 0 to 10: expect tab (to 8) + two spaces, final col 10 */
char* err = capture_put_space_call(0, true, 10, buf, sizeof(buf), &final_col, &n);
TEST_ASSERT_MESSAGE(err == NULL, err ? err : "");
TEST_ASSERT_EQUAL_INT(3, (int)n);
TEST_ASSERT_EQUAL_INT(10, final_col);
TEST_ASSERT_EQUAL_STRING("\t ", buf);
}
void test_put_space_tabs_one_before_tabstop_no_tab_used(void) {
char buf[32];
size_t n = 0;
int final_col = -1;
/* out_column=7, space=1 -> target=8; condition prevents tab; expect one space */
char* err = capture_put_space_call(7, true, 1, buf, sizeof(buf), &final_col, &n);
TEST_ASSERT_MESSAGE(err == NULL, err ? err : "");
TEST_ASSERT_EQUAL_INT(1, (int)n);
TEST_ASSERT_EQUAL_INT(8, final_col);
TEST_ASSERT_EQUAL_STRING(" ", buf);
}
void test_put_space_tabs_multiple_tabs_then_spaces(void) {
char buf[32];
size_t n = 0;
int final_col = -1;
/* From 0 to 20: two tabs to 16, then 4 spaces */
char* err = capture_put_space_call(0, true, 20, buf, sizeof(buf), &final_col, &n);
TEST_ASSERT_MESSAGE(err == NULL, err ? err : "");
TEST_ASSERT_EQUAL_INT(6, (int)n);
TEST_ASSERT_EQUAL_INT(20, final_col);
TEST_ASSERT_EQUAL_STRING("\t\t ", buf);
}
void test_put_space_negative_space_no_output(void) {
char buf[16];
size_t n = 0;
int final_col = -1;
/* Negative space should result in no output and no backward move */
char* err = capture_put_space_call(5, false, -3, buf, sizeof(buf), &final_col, &n);
TEST_ASSERT_MESSAGE(err == NULL, err ? err : "");
TEST_ASSERT_EQUAL_INT(0, (int)n);
TEST_ASSERT_EQUAL_INT(5, final_col);
TEST_ASSERT_EQUAL_STRING("", buf);
}
void test_put_space_tabs_from_nonzero_cross_one_tab(void) {
char buf[32];
size_t n = 0;
int final_col = -1;
/* Start at col 3, target 13: tab to 8, then 5 spaces */
char* err = capture_put_space_call(3, true, 10, buf, sizeof(buf), &final_col, &n);
TEST_ASSERT_MESSAGE(err == NULL, err ? err : "");
TEST_ASSERT_EQUAL_INT(6, (int)n);
TEST_ASSERT_EQUAL_INT(13, final_col);
TEST_ASSERT_EQUAL_STRING("\t ", buf);
}
int main(void) {
UNITY_BEGIN();
RUN_TEST(test_put_space_zero_no_tabs);
RUN_TEST(test_put_space_only_spaces_simple);
RUN_TEST(test_put_space_preserves_starting_column_no_tabs);
RUN_TEST(test_put_space_tabs_exact_tabstop_from_zero);
RUN_TEST(test_put_space_tabs_to_non_tabstop_from_zero);
RUN_TEST(test_put_space_tabs_one_before_tabstop_no_tab_used);
RUN_TEST(test_put_space_tabs_multiple_tabs_then_spaces);
RUN_TEST(test_put_space_negative_space_no_output);
RUN_TEST(test_put_space_tabs_from_nonzero_cross_one_tab);
return UNITY_END();
}