|
|
#include "../../unity/unity.h" |
|
|
#include <stdio.h> |
|
|
#include <string.h> |
|
|
#include <stdlib.h> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static FILE* make_temp_file_with(const char* data) |
|
|
{ |
|
|
FILE* fp = tmpfile(); |
|
|
TEST_ASSERT_NOT_NULL_MESSAGE(fp, "tmpfile failed"); |
|
|
size_t len = strlen(data); |
|
|
if (len) { |
|
|
size_t nw = fwrite(data, 1, len, fp); |
|
|
TEST_ASSERT_EQUAL_size_t(len, nw); |
|
|
} |
|
|
rewind(fp); |
|
|
return fp; |
|
|
} |
|
|
|
|
|
|
|
|
static void cleanup_lines_state(void) |
|
|
{ |
|
|
for (int i = 0; i < 2; ++i) { |
|
|
if (prevline[i]) { |
|
|
freeline(prevline[i]); |
|
|
free(prevline[i]); |
|
|
prevline[i] = NULL; |
|
|
} |
|
|
if (spareline[i]) { |
|
|
freeline(spareline[i]); |
|
|
free(spareline[i]); |
|
|
spareline[i] = NULL; |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
void setUp(void) |
|
|
{ |
|
|
|
|
|
cleanup_lines_state(); |
|
|
line_no[0] = 0; |
|
|
line_no[1] = 0; |
|
|
|
|
|
|
|
|
eolchar = '\n'; |
|
|
|
|
|
|
|
|
check_input_order = CHECK_ORDER_DISABLED; |
|
|
|
|
|
|
|
|
seen_unpairable = false; |
|
|
issued_disorder_warning[0] = false; |
|
|
issued_disorder_warning[1] = false; |
|
|
join_field_1 = -1; |
|
|
join_field_2 = -1; |
|
|
} |
|
|
|
|
|
void tearDown(void) |
|
|
{ |
|
|
cleanup_lines_state(); |
|
|
} |
|
|
|
|
|
static void assert_field_eq(const struct field* f, const char* expect) |
|
|
{ |
|
|
size_t elen = strlen(expect); |
|
|
TEST_ASSERT_EQUAL_size_t(elen, (size_t)f->len); |
|
|
TEST_ASSERT_EQUAL_INT(0, memcmp(f->beg, expect, elen)); |
|
|
} |
|
|
|
|
|
void test_get_line_basic_parsing_file1(void) |
|
|
{ |
|
|
FILE* fp = make_temp_file_with("a b c\n"); |
|
|
|
|
|
struct line* line = NULL; |
|
|
bool ok = get_line(fp, &line, 1); |
|
|
TEST_ASSERT_TRUE(ok); |
|
|
TEST_ASSERT_NOT_NULL(line); |
|
|
TEST_ASSERT_NOT_NULL(line->buf.buffer); |
|
|
TEST_ASSERT_EQUAL_UINT64(1, line_no[0]); |
|
|
TEST_ASSERT_EQUAL_UINT64(0, line_no[1]); |
|
|
TEST_ASSERT_EQUAL_PTR(line, prevline[0]); |
|
|
|
|
|
|
|
|
TEST_ASSERT_EQUAL_INT(3, (int)line->nfields); |
|
|
assert_field_eq(&line->fields[0], "a"); |
|
|
assert_field_eq(&line->fields[1], "b"); |
|
|
assert_field_eq(&line->fields[2], "c"); |
|
|
|
|
|
|
|
|
TEST_ASSERT_TRUE(line->buf.length > 0); |
|
|
TEST_ASSERT_EQUAL_CHAR('\n', line->buf.buffer[line->buf.length - 1]); |
|
|
|
|
|
fclose(fp); |
|
|
} |
|
|
|
|
|
void test_get_line_spareline_swap_prevents_overwrite(void) |
|
|
{ |
|
|
|
|
|
|
|
|
FILE* fp = make_temp_file_with("x y\nxy z\n"); |
|
|
|
|
|
struct line* line = NULL; |
|
|
bool ok1 = get_line(fp, &line, 1); |
|
|
TEST_ASSERT_TRUE(ok1); |
|
|
struct line* first_line = line; |
|
|
|
|
|
|
|
|
bool ok2 = get_line(fp, &line, 1); |
|
|
TEST_ASSERT_TRUE(ok2); |
|
|
|
|
|
|
|
|
TEST_ASSERT_EQUAL_PTR(first_line, spareline[0]); |
|
|
TEST_ASSERT_EQUAL_PTR(line, prevline[0]); |
|
|
TEST_ASSERT_EQUAL_UINT64(2, line_no[0]); |
|
|
|
|
|
|
|
|
TEST_ASSERT_NOT_NULL(line); |
|
|
TEST_ASSERT_EQUAL_INT(2, (int)line->nfields); |
|
|
assert_field_eq(&line->fields[0], "xy"); |
|
|
assert_field_eq(&line->fields[1], "z"); |
|
|
|
|
|
|
|
|
TEST_ASSERT_NOT_NULL(spareline[0]); |
|
|
TEST_ASSERT_TRUE(spareline[0]->nfields >= 2); |
|
|
assert_field_eq(&spareline[0]->fields[0], "x"); |
|
|
assert_field_eq(&spareline[0]->fields[1], "y"); |
|
|
|
|
|
fclose(fp); |
|
|
} |
|
|
|
|
|
void test_get_line_empty_line_zero_fields(void) |
|
|
{ |
|
|
FILE* fp = make_temp_file_with("\n"); |
|
|
|
|
|
struct line* line = NULL; |
|
|
bool ok = get_line(fp, &line, 1); |
|
|
TEST_ASSERT_TRUE(ok); |
|
|
TEST_ASSERT_NOT_NULL(line); |
|
|
TEST_ASSERT_EQUAL_INT(0, (int)line->nfields); |
|
|
|
|
|
fclose(fp); |
|
|
} |
|
|
|
|
|
void test_get_line_eof_returns_false_and_frees_buffers(void) |
|
|
{ |
|
|
FILE* fp = make_temp_file_with("a\n"); |
|
|
|
|
|
struct line* line = NULL; |
|
|
bool ok1 = get_line(fp, &line, 1); |
|
|
TEST_ASSERT_TRUE(ok1); |
|
|
TEST_ASSERT_NOT_NULL(line); |
|
|
|
|
|
struct line* prev = line; |
|
|
|
|
|
|
|
|
bool ok2 = get_line(fp, &line, 1); |
|
|
TEST_ASSERT_FALSE(ok2); |
|
|
|
|
|
|
|
|
TEST_ASSERT_NOT_NULL(line); |
|
|
TEST_ASSERT_NULL(line->buf.buffer); |
|
|
TEST_ASSERT_NULL(line->fields); |
|
|
|
|
|
|
|
|
TEST_ASSERT_EQUAL_PTR(prev, prevline[0]); |
|
|
TEST_ASSERT_EQUAL_PTR(prev, spareline[0]); |
|
|
|
|
|
fclose(fp); |
|
|
} |
|
|
|
|
|
void test_get_line_parsing_with_leading_blanks(void) |
|
|
{ |
|
|
FILE* fp = make_temp_file_with(" hello world \n"); |
|
|
|
|
|
struct line* line = NULL; |
|
|
bool ok = get_line(fp, &line, 1); |
|
|
TEST_ASSERT_TRUE(ok); |
|
|
TEST_ASSERT_NOT_NULL(line); |
|
|
|
|
|
TEST_ASSERT_EQUAL_INT(2, (int)line->nfields); |
|
|
assert_field_eq(&line->fields[0], "hello"); |
|
|
assert_field_eq(&line->fields[1], "world"); |
|
|
|
|
|
fclose(fp); |
|
|
} |
|
|
|
|
|
void test_get_line_file2_independent_state(void) |
|
|
{ |
|
|
FILE* fp1 = make_temp_file_with("a1 b1\n"); |
|
|
FILE* fp2 = make_temp_file_with("a2 b2 c2\n"); |
|
|
|
|
|
struct line* l1 = NULL; |
|
|
struct line* l2 = NULL; |
|
|
|
|
|
bool ok1 = get_line(fp1, &l1, 1); |
|
|
bool ok2 = get_line(fp2, &l2, 2); |
|
|
|
|
|
TEST_ASSERT_TRUE(ok1); |
|
|
TEST_ASSERT_TRUE(ok2); |
|
|
|
|
|
TEST_ASSERT_EQUAL_UINT64(1, line_no[0]); |
|
|
TEST_ASSERT_EQUAL_UINT64(1, line_no[1]); |
|
|
|
|
|
TEST_ASSERT_EQUAL_PTR(l1, prevline[0]); |
|
|
TEST_ASSERT_EQUAL_PTR(l2, prevline[1]); |
|
|
|
|
|
TEST_ASSERT_EQUAL_INT(2, (int)l1->nfields); |
|
|
assert_field_eq(&l1->fields[0], "a1"); |
|
|
assert_field_eq(&l1->fields[1], "b1"); |
|
|
|
|
|
TEST_ASSERT_EQUAL_INT(3, (int)l2->nfields); |
|
|
assert_field_eq(&l2->fields[0], "a2"); |
|
|
assert_field_eq(&l2->fields[1], "b2"); |
|
|
assert_field_eq(&l2->fields[2], "c2"); |
|
|
|
|
|
fclose(fp1); |
|
|
fclose(fp2); |
|
|
} |
|
|
|
|
|
int main(void) |
|
|
{ |
|
|
UNITY_BEGIN(); |
|
|
RUN_TEST(test_get_line_basic_parsing_file1); |
|
|
RUN_TEST(test_get_line_spareline_swap_prevents_overwrite); |
|
|
RUN_TEST(test_get_line_empty_line_zero_fields); |
|
|
RUN_TEST(test_get_line_eof_returns_false_and_frees_buffers); |
|
|
RUN_TEST(test_get_line_parsing_with_leading_blanks); |
|
|
RUN_TEST(test_get_line_file2_independent_state); |
|
|
return UNITY_END(); |
|
|
} |