| #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(); |
| } |