|
|
#include "../../unity/unity.h" |
|
|
#include <stdio.h> |
|
|
#include <stdlib.h> |
|
|
#include <string.h> |
|
|
#include <unistd.h> |
|
|
#include <errno.h> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void set_prefix (char *p); |
|
|
static int copy_rest (FILE *f, int c); |
|
|
|
|
|
|
|
|
extern bool tabs; |
|
|
extern int in_column; |
|
|
extern int next_prefix_indent; |
|
|
|
|
|
|
|
|
static FILE* make_input_stream(const char* content) |
|
|
{ |
|
|
FILE* f = tmpfile(); |
|
|
if (!f) |
|
|
return NULL; |
|
|
size_t len = content ? strlen(content) : 0; |
|
|
if (len > 0) |
|
|
{ |
|
|
if (fwrite(content, 1, len, f) != len) |
|
|
{ |
|
|
fclose(f); |
|
|
return NULL; |
|
|
} |
|
|
} |
|
|
rewind(f); |
|
|
return f; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static char* capture_copy_rest_output(FILE* fin, int c, int* ret_c) |
|
|
{ |
|
|
if (!ret_c) |
|
|
return NULL; |
|
|
|
|
|
fflush(stdout); |
|
|
int saved_fd = dup(fileno(stdout)); |
|
|
if (saved_fd == -1) |
|
|
return NULL; |
|
|
|
|
|
FILE* cap = tmpfile(); |
|
|
if (!cap) |
|
|
{ |
|
|
close(saved_fd); |
|
|
return NULL; |
|
|
} |
|
|
int cap_fd = fileno(cap); |
|
|
if (dup2(cap_fd, fileno(stdout)) == -1) |
|
|
{ |
|
|
fclose(cap); |
|
|
close(saved_fd); |
|
|
return NULL; |
|
|
} |
|
|
|
|
|
int r = copy_rest(fin, c); |
|
|
|
|
|
fflush(stdout); |
|
|
fflush(cap); |
|
|
|
|
|
|
|
|
if (dup2(saved_fd, fileno(stdout)) == -1) |
|
|
{ |
|
|
fclose(cap); |
|
|
close(saved_fd); |
|
|
return NULL; |
|
|
} |
|
|
close(saved_fd); |
|
|
|
|
|
|
|
|
if (fseek(cap, 0, SEEK_END) != 0) |
|
|
{ |
|
|
fclose(cap); |
|
|
return NULL; |
|
|
} |
|
|
long sz = ftell(cap); |
|
|
if (sz < 0) |
|
|
{ |
|
|
fclose(cap); |
|
|
return NULL; |
|
|
} |
|
|
if (fseek(cap, 0, SEEK_SET) != 0) |
|
|
{ |
|
|
fclose(cap); |
|
|
return NULL; |
|
|
} |
|
|
|
|
|
char* buf = (char*)malloc((size_t)sz + 1); |
|
|
if (!buf) |
|
|
{ |
|
|
fclose(cap); |
|
|
return NULL; |
|
|
} |
|
|
size_t nread = fread(buf, 1, (size_t)sz, cap); |
|
|
buf[nread] = '\0'; |
|
|
fclose(cap); |
|
|
|
|
|
*ret_c = r; |
|
|
return buf; |
|
|
} |
|
|
|
|
|
void setUp(void) |
|
|
{ |
|
|
|
|
|
tabs = false; |
|
|
} |
|
|
|
|
|
void tearDown(void) |
|
|
{ |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
static void test_copy_rest_blank_line_no_output(void) |
|
|
{ |
|
|
char pfx[] = ""; |
|
|
set_prefix(pfx); |
|
|
next_prefix_indent = 0; |
|
|
in_column = 0; |
|
|
|
|
|
FILE* fin = make_input_stream(""); |
|
|
TEST_ASSERT_NOT_NULL(fin); |
|
|
|
|
|
int retc = 0; |
|
|
char* out = capture_copy_rest_output(fin, '\n', &retc); |
|
|
fclose(fin); |
|
|
|
|
|
TEST_ASSERT_NOT_NULL(out); |
|
|
TEST_ASSERT_EQUAL_INT('\n', retc); |
|
|
TEST_ASSERT_EQUAL_UINT(0, strlen(out)); |
|
|
free(out); |
|
|
} |
|
|
|
|
|
|
|
|
static void test_copy_rest_newline_with_partial_prefix(void) |
|
|
{ |
|
|
char pfx[] = "ABC"; |
|
|
set_prefix(pfx); |
|
|
next_prefix_indent = 2; |
|
|
in_column = 3; |
|
|
|
|
|
FILE* fin = make_input_stream(""); |
|
|
TEST_ASSERT_NOT_NULL(fin); |
|
|
|
|
|
int retc = 0; |
|
|
char* out = capture_copy_rest_output(fin, '\n', &retc); |
|
|
fclose(fin); |
|
|
|
|
|
TEST_ASSERT_NOT_NULL(out); |
|
|
TEST_ASSERT_EQUAL_INT('\n', retc); |
|
|
|
|
|
TEST_ASSERT_EQUAL_STRING(" A", out); |
|
|
free(out); |
|
|
} |
|
|
|
|
|
|
|
|
static void test_copy_rest_mismatch_no_padding(void) |
|
|
{ |
|
|
char pfx[] = "ABC"; |
|
|
set_prefix(pfx); |
|
|
next_prefix_indent = 2; |
|
|
in_column = 3; |
|
|
|
|
|
|
|
|
FILE* fin = make_input_stream("YZ\n"); |
|
|
TEST_ASSERT_NOT_NULL(fin); |
|
|
|
|
|
int retc = 0; |
|
|
char* out = capture_copy_rest_output(fin, 'X', &retc); |
|
|
fclose(fin); |
|
|
|
|
|
TEST_ASSERT_NOT_NULL(out); |
|
|
TEST_ASSERT_EQUAL_INT('\n', retc); |
|
|
|
|
|
TEST_ASSERT_EQUAL_STRING(" AXYZ", out); |
|
|
free(out); |
|
|
} |
|
|
|
|
|
|
|
|
static void test_copy_rest_mismatch_with_padding_beyond_trimmed_prefix(void) |
|
|
{ |
|
|
char pfx[] = "AB "; |
|
|
set_prefix(pfx); |
|
|
next_prefix_indent = 1; |
|
|
in_column = next_prefix_indent + 4; |
|
|
|
|
|
|
|
|
FILE* fin = make_input_stream("T\n"); |
|
|
TEST_ASSERT_NOT_NULL(fin); |
|
|
|
|
|
int retc = 0; |
|
|
char* out = capture_copy_rest_output(fin, 'X', &retc); |
|
|
fclose(fin); |
|
|
|
|
|
TEST_ASSERT_NOT_NULL(out); |
|
|
TEST_ASSERT_EQUAL_INT('\n', retc); |
|
|
|
|
|
TEST_ASSERT_EQUAL_STRING(" AB XT", out); |
|
|
free(out); |
|
|
} |
|
|
|
|
|
|
|
|
static void test_copy_rest_eof_emits_newline_after_full_prefix(void) |
|
|
{ |
|
|
char pfx[] = "HELLO"; |
|
|
set_prefix(pfx); |
|
|
next_prefix_indent = 3; |
|
|
in_column = next_prefix_indent + (int)strlen("HELLO"); |
|
|
|
|
|
FILE* fin = make_input_stream(""); |
|
|
TEST_ASSERT_NOT_NULL(fin); |
|
|
|
|
|
int retc = 0; |
|
|
char* out = capture_copy_rest_output(fin, EOF, &retc); |
|
|
fclose(fin); |
|
|
|
|
|
TEST_ASSERT_NOT_NULL(out); |
|
|
TEST_ASSERT_EQUAL_INT(EOF, retc); |
|
|
|
|
|
TEST_ASSERT_EQUAL_STRING(" HELLO\n", out); |
|
|
free(out); |
|
|
} |
|
|
|
|
|
|
|
|
static void test_copy_rest_eof_no_output_when_no_progress(void) |
|
|
{ |
|
|
char pfx[] = "HELLO"; |
|
|
set_prefix(pfx); |
|
|
next_prefix_indent = 2; |
|
|
in_column = 2; |
|
|
|
|
|
FILE* fin = make_input_stream(""); |
|
|
TEST_ASSERT_NOT_NULL(fin); |
|
|
|
|
|
int retc = 0; |
|
|
char* out = capture_copy_rest_output(fin, EOF, &retc); |
|
|
fclose(fin); |
|
|
|
|
|
TEST_ASSERT_NOT_NULL(out); |
|
|
TEST_ASSERT_EQUAL_INT(EOF, retc); |
|
|
TEST_ASSERT_EQUAL_UINT(0, strlen(out)); |
|
|
free(out); |
|
|
} |
|
|
|
|
|
|
|
|
static void test_copy_rest_no_prefix_context_non_newline(void) |
|
|
{ |
|
|
char pfx[] = ""; |
|
|
set_prefix(pfx); |
|
|
next_prefix_indent = 0; |
|
|
in_column = 0; |
|
|
|
|
|
FILE* fin = make_input_stream("RS\n"); |
|
|
TEST_ASSERT_NOT_NULL(fin); |
|
|
|
|
|
int retc = 0; |
|
|
char* out = capture_copy_rest_output(fin, 'Q', &retc); |
|
|
fclose(fin); |
|
|
|
|
|
TEST_ASSERT_NOT_NULL(out); |
|
|
TEST_ASSERT_EQUAL_INT('\n', retc); |
|
|
|
|
|
TEST_ASSERT_EQUAL_STRING("QRS", out); |
|
|
free(out); |
|
|
} |
|
|
|
|
|
int main(void) |
|
|
{ |
|
|
UNITY_BEGIN(); |
|
|
RUN_TEST(test_copy_rest_blank_line_no_output); |
|
|
RUN_TEST(test_copy_rest_newline_with_partial_prefix); |
|
|
RUN_TEST(test_copy_rest_mismatch_no_padding); |
|
|
RUN_TEST(test_copy_rest_mismatch_with_padding_beyond_trimmed_prefix); |
|
|
RUN_TEST(test_copy_rest_eof_emits_newline_after_full_prefix); |
|
|
RUN_TEST(test_copy_rest_eof_no_output_when_no_progress); |
|
|
RUN_TEST(test_copy_rest_no_prefix_context_non_newline); |
|
|
return UNITY_END(); |
|
|
} |