X-Git-Url: http://sigrok.org/gitweb/?a=blobdiff_plain;f=tests%2Fstrutil.c;h=68e6117dfd3c946f0ff3e4cb241b3324217e8c31;hb=HEAD;hp=f4bbe9ec64537987d84290e0d7369ad166561eff;hpb=11cd0ff15948a6c3999f66a6b45ace11049b09ee;p=libsigrok.git diff --git a/tests/strutil.c b/tests/strutil.c index f4bbe9ec..3e43dbdc 100644 --- a/tests/strutil.c +++ b/tests/strutil.c @@ -430,6 +430,184 @@ START_TEST(test_exponent) } END_TEST +START_TEST(test_text_line) +{ + /* + * Covers text line splitting as used in input modules. Accepts + * input with differing end-of-line conventions, accepts leading + * and trailing whitespace. Isolates "the core" of a text line. + * Supports repeated calls which accumulate what later needs to + * get discarded after input data got processed in pieces. + */ +#define EOL "\n" + +#define TEXT_CORE_1 "Need to provide" +#define TEXT_CORE_2 "an input text" +#define TEXT_CORE_3 "" +#define TEXT_CORE_4 "with empty lines and funny spacing perhaps?" + +#define TEXT_LINE_1 TEXT_CORE_1 " \n" +#define TEXT_LINE_2 " " TEXT_CORE_2 "\n" +#define TEXT_LINE_3 TEXT_CORE_3 "\r\n" +#define TEXT_LINE_4 TEXT_CORE_4 "\n" + +#define TEXT_INPUT TEXT_LINE_1 TEXT_LINE_2 TEXT_LINE_3 TEXT_LINE_4 + + char *input_text, *read_pos, *next_pos, *line; + size_t input_len, taken; + + input_text = g_strdup(TEXT_INPUT); + read_pos = input_text; + input_len = strlen(input_text); + + /* Cover first line in tests. */ + taken = 0; + line = sr_text_next_line(read_pos, input_len, &next_pos, &taken); + fail_unless(line, "Text line not found"); + fail_unless(strcmp(line, TEXT_CORE_1) == 0, "Unexpected line content"); + fail_unless(next_pos, "No next line found"); + fail_unless(strncmp(next_pos, TEXT_LINE_2, strlen(TEXT_LINE_2)) == 0, + "Unexpected next line content"); + fail_unless(taken == strlen(TEXT_LINE_1), + "Unexpected consumed count"); + read_pos = next_pos; + input_len -= taken; + taken = 0; + + /* Cover second line in tests. DO NOT void 'taken' yet. */ + line = sr_text_next_line(read_pos, input_len, &next_pos, &taken); + fail_unless(line, "Text line not found"); + fail_unless(strcmp(line, TEXT_CORE_2) == 0, + "Unexpected text line content"); + fail_unless(next_pos, "No next line found"); + fail_unless(strncmp(next_pos, TEXT_LINE_3, strlen(TEXT_LINE_3)) == 0, + "Unexpected next line content"); + fail_unless(taken == strlen(TEXT_LINE_2), + "Unexpected consumed count"); + input_len -= next_pos - read_pos; + read_pos = next_pos; + + /* Cover third line in tests. Accumulates 'taken'. */ + line = sr_text_next_line(read_pos, input_len, &next_pos, &taken); + fail_unless(line, "Text line not found"); + fail_unless(strcmp(line, TEXT_CORE_3) == 0, "Unexpected line content"); + fail_unless(next_pos, "No next line found"); + fail_unless(strncmp(next_pos, TEXT_LINE_4, strlen(TEXT_LINE_4)) == 0, + "Unexpected next line content"); + fail_unless(taken == strlen(TEXT_LINE_2) + strlen(TEXT_LINE_3), + "Unexpected consumed count (totalled)"); + input_len -= next_pos - read_pos; + read_pos = next_pos; + taken = 0; + + /* Cover last line in tests. */ + line = sr_text_next_line(read_pos, input_len, &next_pos, &taken); + fail_unless(line, "Text line not found"); + fail_unless(strcmp(line, TEXT_CORE_4) == 0, + "Unexpected text line content"); + fail_unless(!next_pos, "Next line found, unexpected"); + fail_unless(taken == strlen(TEXT_LINE_4), + "Unexpected consumed count"); + input_len -= taken; + read_pos = next_pos; + + /* All input must have been consumed. */ + fail_unless(!read_pos); + fail_unless(!input_len); + + g_free(input_text); +} +END_TEST + +/* + * TODO Ideally this table of test cases should reside within the + * test_text_word() routine. But compilation fails when it's put there + * (initializers are said to not be constant, cause is yet uncertain). + */ +static const struct { + const char *line; + const char **words; +} word_cases[] = { + { "", (const char *[]){ NULL, }, }, + { " ", (const char *[]){ NULL, }, }, + { "one", (const char *[]){ "one", NULL, }, }, + { "one ", (const char *[]){ "one", NULL, }, }, + { " one ", (const char *[]){ "one", NULL, }, }, + { " one two ", (const char *[]){ "one", "two", NULL, }, }, + { "one two three ", + (const char *[]){ "one", "two", "three", NULL, }, + }, +}; + +START_TEST(test_text_word) +{ + size_t case_idx, word_idx; + char *line; + const char **words, *want; + char *read_pos, *next_pos, *have; + + for (case_idx = 0; case_idx < ARRAY_SIZE(word_cases); case_idx++) { + line = g_strdup(word_cases[case_idx].line); + words = word_cases[case_idx].words; + word_idx = 0; + + read_pos = line; + while (read_pos) { + want = words[word_idx]; + have = sr_text_next_word(read_pos, &next_pos); + if (!want) { + fail_unless(!have, "word found, unexpected"); + fail_unless(!next_pos, "next found after end"); + break; + } + word_idx++; + read_pos = next_pos; + fail_unless(have, "word not found"); + fail_unless(strcmp(have, want) == 0, + "unexpected word found"); + } + fail_unless(!words[word_idx], "missed expected words"); + + g_free(line); + } +} +END_TEST + +static const struct power_case_t { + size_t value; + size_t want_bits; + size_t want_power; +} power_cases[] = { + { 0, 1, 1, }, + { 1, 1, 2, }, + { 2, 2, 4, }, + { 3, 2, 4, }, + { 4, 3, 8, }, + { 5, 3, 8, }, + { 6, 3, 8, }, + { 7, 3, 8, }, + { 8, 4, 16, }, + { 15, 4, 16, }, + { 16, 5, 32, }, + { 31, 5, 32, }, +}; + +START_TEST(test_calc_power_of_two) +{ + size_t case_idx, bits, power; + const struct power_case_t *tcase; + int ret; + + for (case_idx = 0; case_idx < ARRAY_SIZE(power_cases); case_idx++) { + tcase = &power_cases[case_idx]; + ret = sr_next_power_of_two(tcase->value, &bits, &power); + fail_unless(ret == SR_OK, "bits count not found"); + fail_unless(bits == tcase->want_bits, "bits count differs"); + fail_unless(power == tcase->want_power, "power differs"); + } +} +END_TEST + Suite *suite_strutil(void) { Suite *s; @@ -452,5 +630,14 @@ Suite *suite_strutil(void) tcase_add_test(tc, test_exponent); suite_add_tcase(s, tc); + tc = tcase_create("text"); + tcase_add_test(tc, test_text_line); + tcase_add_test(tc, test_text_word); + suite_add_tcase(s, tc); + + tc = tcase_create("calc"); + tcase_add_test(tc, test_calc_power_of_two); + suite_add_tcase(s, tc); + return s; }