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