|
|
#include "../../unity/unity.h" |
|
|
#include <stdio.h> |
|
|
#include <stdlib.h> |
|
|
#include <string.h> |
|
|
|
|
|
|
|
|
void setUp(void) { |
|
|
|
|
|
|
|
|
check_input_order = CHECK_ORDER_DISABLED; |
|
|
|
|
|
seen_unpairable = false; |
|
|
} |
|
|
|
|
|
void tearDown(void) { |
|
|
|
|
|
free_spareline(); |
|
|
} |
|
|
|
|
|
|
|
|
static FILE* make_tempfile_with(const char* content) { |
|
|
FILE *fp = tmpfile(); |
|
|
TEST_ASSERT_NOT_NULL_MESSAGE(fp, "tmpfile() failed"); |
|
|
if (content && *content) { |
|
|
size_t len = strlen(content); |
|
|
TEST_ASSERT_EQUAL_MESSAGE(len, fwrite(content, 1, len, fp), |
|
|
"Failed to write content to tmp file"); |
|
|
} |
|
|
fflush(fp); |
|
|
rewind(fp); |
|
|
return fp; |
|
|
} |
|
|
|
|
|
|
|
|
static void assert_field_equals(const struct field *f, const char *s) { |
|
|
size_t slen = strlen(s); |
|
|
TEST_ASSERT_EQUAL_size_t(slen, (size_t)f->len); |
|
|
if (slen > 0) { |
|
|
TEST_ASSERT_NOT_NULL(f->beg); |
|
|
TEST_ASSERT_EQUAL_INT(0, memcmp(f->beg, s, slen)); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void test_getseq_reads_single_line_and_fields(void) { |
|
|
FILE *fp = make_tempfile_with("a b c\n"); |
|
|
|
|
|
struct seq s; |
|
|
initseq(&s); |
|
|
|
|
|
bool ok = getseq(fp, &s, 1); |
|
|
TEST_ASSERT_TRUE(ok); |
|
|
TEST_ASSERT_TRUE(s.count == 1); |
|
|
TEST_ASSERT_NOT_NULL(s.lines); |
|
|
TEST_ASSERT_TRUE(s.alloc >= 1); |
|
|
TEST_ASSERT_NOT_NULL(s.lines[0]); |
|
|
|
|
|
struct line *l = s.lines[0]; |
|
|
TEST_ASSERT_NOT_NULL(l); |
|
|
TEST_ASSERT_TRUE(l->nfields == 3); |
|
|
|
|
|
TEST_ASSERT_NOT_NULL(l->fields); |
|
|
assert_field_equals(&l->fields[0], "a"); |
|
|
assert_field_equals(&l->fields[1], "b"); |
|
|
assert_field_equals(&l->fields[2], "c"); |
|
|
|
|
|
delseq(&s); |
|
|
fclose(fp); |
|
|
} |
|
|
|
|
|
|
|
|
void test_getseq_returns_false_on_empty_file(void) { |
|
|
FILE *fp = make_tempfile_with(""); |
|
|
|
|
|
struct seq s; |
|
|
initseq(&s); |
|
|
|
|
|
bool ok = getseq(fp, &s, 1); |
|
|
TEST_ASSERT_FALSE(ok); |
|
|
TEST_ASSERT_TRUE(s.count == 0); |
|
|
|
|
|
TEST_ASSERT_NOT_NULL(s.lines); |
|
|
TEST_ASSERT_TRUE(s.alloc >= 1); |
|
|
TEST_ASSERT_NULL(s.lines[0]); |
|
|
|
|
|
delseq(&s); |
|
|
fclose(fp); |
|
|
} |
|
|
|
|
|
|
|
|
void test_getseq_reads_multiple_lines(void) { |
|
|
FILE *fp = make_tempfile_with("x\ny\nz\n"); |
|
|
|
|
|
struct seq s; |
|
|
initseq(&s); |
|
|
|
|
|
bool ok1 = getseq(fp, &s, 1); |
|
|
TEST_ASSERT_TRUE(ok1); |
|
|
TEST_ASSERT_TRUE(s.count == 1); |
|
|
TEST_ASSERT_NOT_NULL(s.lines[0]); |
|
|
TEST_ASSERT_TRUE(s.lines[0]->nfields == 1); |
|
|
assert_field_equals(&s.lines[0]->fields[0], "x"); |
|
|
|
|
|
bool ok2 = getseq(fp, &s, 1); |
|
|
TEST_ASSERT_TRUE(ok2); |
|
|
TEST_ASSERT_TRUE(s.count == 2); |
|
|
TEST_ASSERT_NOT_NULL(s.lines[1]); |
|
|
TEST_ASSERT_TRUE(s.lines[1]->nfields == 1); |
|
|
assert_field_equals(&s.lines[1]->fields[0], "y"); |
|
|
|
|
|
bool ok3 = getseq(fp, &s, 1); |
|
|
TEST_ASSERT_TRUE(ok3); |
|
|
TEST_ASSERT_TRUE(s.count == 3); |
|
|
TEST_ASSERT_NOT_NULL(s.lines[2]); |
|
|
TEST_ASSERT_TRUE(s.lines[2]->nfields == 1); |
|
|
assert_field_equals(&s.lines[2]->fields[0], "z"); |
|
|
|
|
|
|
|
|
bool ok4 = getseq(fp, &s, 1); |
|
|
TEST_ASSERT_FALSE(ok4); |
|
|
TEST_ASSERT_TRUE(s.count == 3); |
|
|
|
|
|
delseq(&s); |
|
|
fclose(fp); |
|
|
} |
|
|
|
|
|
|
|
|
void test_getseq_works_for_both_files(void) { |
|
|
FILE *fp1 = make_tempfile_with("a\nb\n"); |
|
|
FILE *fp2 = make_tempfile_with("c\nd\n"); |
|
|
|
|
|
struct seq s1, s2; |
|
|
initseq(&s1); |
|
|
initseq(&s2); |
|
|
|
|
|
|
|
|
TEST_ASSERT_TRUE(getseq(fp1, &s1, 1)); |
|
|
TEST_ASSERT_TRUE(s1.count == 1); |
|
|
TEST_ASSERT_TRUE(s1.lines[0]->nfields == 1); |
|
|
assert_field_equals(&s1.lines[0]->fields[0], "a"); |
|
|
|
|
|
|
|
|
TEST_ASSERT_TRUE(getseq(fp2, &s2, 2)); |
|
|
TEST_ASSERT_TRUE(s2.count == 1); |
|
|
TEST_ASSERT_TRUE(s2.lines[0]->nfields == 1); |
|
|
assert_field_equals(&s2.lines[0]->fields[0], "c"); |
|
|
|
|
|
|
|
|
TEST_ASSERT_TRUE(getseq(fp1, &s1, 1)); |
|
|
TEST_ASSERT_TRUE(s1.count == 2); |
|
|
assert_field_equals(&s1.lines[1]->fields[0], "b"); |
|
|
|
|
|
TEST_ASSERT_TRUE(getseq(fp2, &s2, 2)); |
|
|
TEST_ASSERT_TRUE(s2.count == 2); |
|
|
assert_field_equals(&s2.lines[1]->fields[0], "d"); |
|
|
|
|
|
|
|
|
TEST_ASSERT_FALSE(getseq(fp1, &s1, 1)); |
|
|
TEST_ASSERT_FALSE(getseq(fp2, &s2, 2)); |
|
|
|
|
|
delseq(&s1); |
|
|
delseq(&s2); |
|
|
fclose(fp1); |
|
|
fclose(fp2); |
|
|
} |
|
|
|
|
|
|
|
|
void test_getseq_handles_line_without_trailing_newline(void) { |
|
|
FILE *fp = make_tempfile_with("no-trailing-newline"); |
|
|
|
|
|
struct seq s; |
|
|
initseq(&s); |
|
|
|
|
|
TEST_ASSERT_TRUE(getseq(fp, &s, 1)); |
|
|
TEST_ASSERT_TRUE(s.count == 1); |
|
|
TEST_ASSERT_NOT_NULL(s.lines[0]); |
|
|
TEST_ASSERT_TRUE(s.lines[0]->nfields == 1); |
|
|
assert_field_equals(&s.lines[0]->fields[0], "no-trailing-newline"); |
|
|
|
|
|
|
|
|
TEST_ASSERT_FALSE(getseq(fp, &s, 1)); |
|
|
|
|
|
delseq(&s); |
|
|
fclose(fp); |
|
|
} |
|
|
|
|
|
int main(void) { |
|
|
UNITY_BEGIN(); |
|
|
RUN_TEST(test_getseq_reads_single_line_and_fields); |
|
|
RUN_TEST(test_getseq_returns_false_on_empty_file); |
|
|
RUN_TEST(test_getseq_reads_multiple_lines); |
|
|
RUN_TEST(test_getseq_works_for_both_files); |
|
|
RUN_TEST(test_getseq_handles_line_without_trailing_newline); |
|
|
return UNITY_END(); |
|
|
} |