|
|
#include "../../unity/unity.h" |
|
|
#include <stdio.h> |
|
|
#include <stdlib.h> |
|
|
#include <string.h> |
|
|
#include <stdbool.h> |
|
|
#include <unistd.h> |
|
|
#include <errno.h> |
|
|
|
|
|
|
|
|
void setUp(void) { |
|
|
|
|
|
} |
|
|
void tearDown(void) { |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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"; |
|
|
} |
|
|
|
|
|
|
|
|
bool tabs_saved = tabs; |
|
|
int out_saved = out_column; |
|
|
|
|
|
|
|
|
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; |
|
|
} |
|
|
|
|
|
|
|
|
tabs = tabs_flag; |
|
|
out_column = start_col; |
|
|
|
|
|
|
|
|
put_space(space); |
|
|
|
|
|
int result_col = out_column; |
|
|
|
|
|
|
|
|
fflush(stdout); |
|
|
long pos = ftell(tmp); |
|
|
if (pos < 0) pos = 0; |
|
|
if (fseek(tmp, 0, SEEK_SET) != 0) { |
|
|
|
|
|
dup2(saved_fd, fileno(stdout)); |
|
|
close(saved_fd); |
|
|
fclose(tmp); |
|
|
snprintf(errbuf, sizeof(errbuf), "fseek failed: %s", strerror(errno)); |
|
|
|
|
|
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; |
|
|
|
|
|
|
|
|
if (dup2(saved_fd, fileno(stdout)) < 0) { |
|
|
close(saved_fd); |
|
|
fclose(tmp); |
|
|
snprintf(errbuf, sizeof(errbuf), "restore dup2 failed: %s", strerror(errno)); |
|
|
|
|
|
tabs = tabs_saved; |
|
|
out_column = out_saved; |
|
|
return errbuf; |
|
|
} |
|
|
close(saved_fd); |
|
|
fclose(tmp); |
|
|
|
|
|
|
|
|
tabs = tabs_saved; |
|
|
out_column = out_saved; |
|
|
*final_col = result_col; |
|
|
|
|
|
return NULL; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
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; |
|
|
|
|
|
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); |
|
|
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; |
|
|
|
|
|
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; |
|
|
|
|
|
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; |
|
|
|
|
|
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; |
|
|
|
|
|
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; |
|
|
|
|
|
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; |
|
|
|
|
|
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(); |
|
|
} |