| #include "../../unity/unity.h" |
|
|
| #include <stdlib.h> |
| #include <string.h> |
| #include <stdio.h> |
| #include <stdint.h> |
|
|
| |
| |
| |
| |
| |
| |
| |
|
|
| static void reset_tab_default(void) |
| { |
| |
| tab.len = 0; |
| tab.ch = 0; |
| tab.err = 0; |
| } |
|
|
| static void set_tab_char(char c) |
| { |
| char s[2] = { c, 0 }; |
| tab = mcel_scanz(s); |
| } |
|
|
| static void prepare_line(struct line *ln, const char *content_with_newline) |
| { |
| memset(ln, 0, sizeof *ln); |
| ln->buf.buffer = strdup(content_with_newline); |
| TEST_ASSERT_NOT_NULL(ln->buf.buffer); |
| ln->buf.length = (idx_t)strlen(content_with_newline); |
| ln->nfields = 0; |
| ln->nfields_allocated = 0; |
| ln->fields = NULL; |
| } |
|
|
| static void cleanup_line(struct line *ln) |
| { |
| freeline(ln); |
| } |
|
|
| static void assert_nfields(struct line *ln, unsigned expected) |
| { |
| TEST_ASSERT_EQUAL_UINT_MESSAGE(expected, (unsigned)ln->nfields, "Unexpected number of fields"); |
| } |
|
|
| static void assert_field_eq(struct line *ln, unsigned index, const char *expected) |
| { |
| char msg[128]; |
| snprintf(msg, sizeof msg, "Field index %u out of range", index); |
| TEST_ASSERT_TRUE_MESSAGE(index < (unsigned)ln->nfields, msg); |
| idx_t len = ln->fields[index].len; |
| TEST_ASSERT_EQUAL_UINT((unsigned)strlen(expected), (unsigned)len); |
| TEST_ASSERT_EQUAL_INT(0, memcmp(ln->fields[index].beg, expected, (size_t)len)); |
| } |
|
|
| void setUp(void) |
| { |
| reset_tab_default(); |
| } |
|
|
| void tearDown(void) |
| { |
| |
| } |
|
|
| |
| void test_xfields_blank_mode_basic(void) |
| { |
| struct line ln; |
| prepare_line(&ln, "alpha beta gamma\n"); |
|
|
| |
| xfields(&ln); |
|
|
| assert_nfields(&ln, 3); |
| assert_field_eq(&ln, 0, "alpha"); |
| assert_field_eq(&ln, 1, "beta"); |
| assert_field_eq(&ln, 2, "gamma"); |
|
|
| cleanup_line(&ln); |
| } |
|
|
| |
| void test_xfields_blank_mode_leading_trailing_and_multiple_blanks(void) |
| { |
| struct line ln; |
| prepare_line(&ln, " alpha \t beta gamma \n"); |
|
|
| xfields(&ln); |
|
|
| assert_nfields(&ln, 3); |
| assert_field_eq(&ln, 0, "alpha"); |
| assert_field_eq(&ln, 1, "beta"); |
| assert_field_eq(&ln, 2, "gamma"); |
|
|
| cleanup_line(&ln); |
| } |
|
|
| |
| void test_xfields_blank_mode_tabs_as_blanks(void) |
| { |
| struct line ln; |
| prepare_line(&ln, "\tfoo\tbar\tbaz\t\n"); |
|
|
| xfields(&ln); |
|
|
| assert_nfields(&ln, 3); |
| assert_field_eq(&ln, 0, "foo"); |
| assert_field_eq(&ln, 1, "bar"); |
| assert_field_eq(&ln, 2, "baz"); |
|
|
| cleanup_line(&ln); |
| } |
|
|
| |
| void test_xfields_blank_mode_empty_line(void) |
| { |
| struct line ln; |
| prepare_line(&ln, "\n"); |
|
|
| xfields(&ln); |
|
|
| assert_nfields(&ln, 0); |
|
|
| cleanup_line(&ln); |
| } |
|
|
| |
| void test_xfields_char_sep_comma_basic(void) |
| { |
| struct line ln; |
| prepare_line(&ln, "x,y,z\n"); |
|
|
| set_tab_char(','); |
| xfields(&ln); |
|
|
| assert_nfields(&ln, 3); |
| assert_field_eq(&ln, 0, "x"); |
| assert_field_eq(&ln, 1, "y"); |
| assert_field_eq(&ln, 2, "z"); |
|
|
| cleanup_line(&ln); |
| } |
|
|
| |
| void test_xfields_char_sep_comma_allows_empty_fields(void) |
| { |
| struct line ln; |
| prepare_line(&ln, "a,,b,c,\n"); |
|
|
| set_tab_char(','); |
| xfields(&ln); |
|
|
| assert_nfields(&ln, 5); |
| assert_field_eq(&ln, 0, "a"); |
| assert_field_eq(&ln, 1, ""); |
| assert_field_eq(&ln, 2, "b"); |
| assert_field_eq(&ln, 3, "c"); |
| assert_field_eq(&ln, 4, ""); |
|
|
| cleanup_line(&ln); |
| } |
|
|
| |
| void test_xfields_char_sep_space_consecutive_spaces(void) |
| { |
| struct line ln; |
| prepare_line(&ln, "a b\n"); |
|
|
| set_tab_char(' '); |
| xfields(&ln); |
|
|
| assert_nfields(&ln, 3); |
| assert_field_eq(&ln, 0, "a"); |
| assert_field_eq(&ln, 1, ""); |
| assert_field_eq(&ln, 2, "b"); |
|
|
| cleanup_line(&ln); |
| } |
|
|
| |
| void test_xfields_delim_newline_single_field(void) |
| { |
| struct line ln; |
| prepare_line(&ln, "hello world\n"); |
|
|
| set_tab_char('\n'); |
| xfields(&ln); |
|
|
| assert_nfields(&ln, 1); |
| assert_field_eq(&ln, 0, "hello world"); |
|
|
| cleanup_line(&ln); |
| } |
|
|
| |
| void test_xfields_many_fields_reallocation(void) |
| { |
| |
| unsigned n = 100; |
| size_t cap = 1024; |
| char *buf = (char *)malloc(cap); |
| TEST_ASSERT_NOT_NULL(buf); |
| size_t pos = 0; |
| for (unsigned i = 0; i < n; i++) |
| { |
| char tmp[32]; |
| int k = snprintf(tmp, sizeof tmp, "%u", i); |
| TEST_ASSERT_TRUE(k > 0); |
| if (pos + (size_t)k + 2 >= cap) |
| { |
| cap *= 2; |
| char *nb = (char *)realloc(buf, cap); |
| TEST_ASSERT_NOT_NULL(nb); |
| buf = nb; |
| } |
| memcpy(buf + pos, tmp, (size_t)k); |
| pos += (size_t)k; |
| if (i + 1 < n) |
| buf[pos++] = ','; |
| } |
| buf[pos++] = '\n'; |
| buf[pos] = '\0'; |
|
|
| struct line ln; |
| memset(&ln, 0, sizeof ln); |
| ln.buf.buffer = buf; |
| ln.buf.length = (idx_t)pos; |
|
|
| set_tab_char(','); |
| xfields(&ln); |
|
|
| assert_nfields(&ln, n); |
| |
| assert_field_eq(&ln, 0, "0"); |
| assert_field_eq(&ln, 1, "1"); |
| assert_field_eq(&ln, 50, "50"); |
| assert_field_eq(&ln, 99, "99"); |
|
|
| cleanup_line(&ln); |
| |
| } |
|
|
| int main(void) |
| { |
| UNITY_BEGIN(); |
| RUN_TEST(test_xfields_blank_mode_basic); |
| RUN_TEST(test_xfields_blank_mode_leading_trailing_and_multiple_blanks); |
| RUN_TEST(test_xfields_blank_mode_tabs_as_blanks); |
| RUN_TEST(test_xfields_blank_mode_empty_line); |
| RUN_TEST(test_xfields_char_sep_comma_basic); |
| RUN_TEST(test_xfields_char_sep_comma_allows_empty_fields); |
| RUN_TEST(test_xfields_char_sep_space_consecutive_spaces); |
| RUN_TEST(test_xfields_delim_newline_single_field); |
| RUN_TEST(test_xfields_many_fields_reallocation); |
| return UNITY_END(); |
| } |