]> sigrok.org Git - libsigrok.git/blobdiff - tests/strutil.c
output/csv: use intermediate time_t var, silence compiler warning
[libsigrok.git] / tests / strutil.c
index f4bbe9ec64537987d84290e0d7369ad166561eff..3e43dbdca2c2ba2a278c6e72b6306656da33be88 100644 (file)
@@ -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;
 }