summaryrefslogtreecommitdiffstats
path: root/tests/lib/utilunix__mc_pstream_get_string.c
diff options
context:
space:
mode:
Diffstat (limited to 'tests/lib/utilunix__mc_pstream_get_string.c')
-rw-r--r--tests/lib/utilunix__mc_pstream_get_string.c396
1 files changed, 396 insertions, 0 deletions
diff --git a/tests/lib/utilunix__mc_pstream_get_string.c b/tests/lib/utilunix__mc_pstream_get_string.c
new file mode 100644
index 0000000..db5233e
--- /dev/null
+++ b/tests/lib/utilunix__mc_pstream_get_string.c
@@ -0,0 +1,396 @@
+/*
+ lib - Read string from mc_pipe_stream
+
+ Copyright (C) 2021-2023
+ Free Software Foundation, Inc.
+
+ Written by:
+ Andrew Borodin <aborodin@vmail.ru>, 2021
+
+ This file is part of the Midnight Commander.
+
+ The Midnight Commander is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation, either version 3 of the License,
+ or (at your option) any later version.
+
+ The Midnight Commander is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define TEST_SUITE_NAME "/lib/util"
+
+#include "tests/mctest.h"
+
+#include "lib/util.h"
+
+/* --------------------------------------------------------------------------------------------- */
+
+#define MAX_CHUNKS 8
+
+/* --------------------------------------------------------------------------------------------- */
+
+static mc_pipe_stream_t stream;
+
+static char etalon_long_file_list[BUF_1K];
+static size_t etalon_long_file_list_pos;
+
+/* --------------------------------------------------------------------------------------------- */
+
+/* @Before */
+static void
+setup (void)
+{
+}
+
+/* @After */
+static void
+teardown (void)
+{
+}
+
+/* --------------------------------------------------------------------------------------------- */
+
+/* @DataSource("data_source") */
+/* *INDENT-OFF* */
+static const struct data_source
+{
+ /* input */
+ const char *buf; /* string to read */
+
+ /* output */
+ int pos[MAX_CHUNKS]; /* ps.pos values */
+ const char *str[MAX_CHUNKS]; /* chunks */
+ size_t len[MAX_CHUNKS]; /* chunk lengths */
+}
+data_source[] =
+{
+ /* 0 */
+ {
+ .buf = "",
+ .pos = { 0 },
+ .str = { "" },
+ .len = { 0 }
+ },
+ /* 1 */
+ {
+ .buf = "\n",
+ .pos = { 0, 1 },
+ .str = { "\n" },
+ .len = { 1, 0 }
+ },
+ /* 2 */
+ {
+ .buf = "\\\n",
+ .pos = { 0, 2 },
+ .str = { "\\\n" },
+ .len = { 2, 0 }
+ },
+ /* 3 */
+ {
+ .buf = "\\\\\n",
+ .pos = { 0, 3 },
+ .str = { "\\\\\n" },
+ .len = { 3, 0 }
+ },
+ /* 4 */
+ {
+ .buf = "\\\\\\\n",
+ .pos = { 0, 4 },
+ .str = { "\\\\\\\n" },
+ .len = { 4, 0 }
+ },
+ /* 5 */
+ {
+ .buf = "\\\\\\\\\n",
+ .pos = { 0, 5 },
+ .str = { "\\\\\\\\\n" },
+ .len = { 5, 0 }
+ },
+ /* 6 */
+ {
+ .buf = "12345",
+ .pos = { 0, 5 },
+ .str = { "12345" },
+ .len = { 5, 0 }
+ },
+ /* 7 */
+ {
+ .buf = "12345\n",
+ .pos = { 0, 6 },
+ .str = { "12345\n" },
+ .len = { 6, 0 }
+ },
+ /* 8 */
+ {
+ .buf = "12345\\\n",
+ .pos = { 0, 7 },
+ .str = { "12345\\\n" },
+ .len = { 7, 0 }
+ },
+ /* 9 */
+ {
+ .buf = "12345\\\\\n",
+ .pos = { 0, 8 },
+ .str = { "12345\\\\\n" },
+ .len = { 8, 0 }
+ },
+ /* 10 */
+ {
+ .buf = "12345\nabcd",
+ .pos = { 0, 6, 10 },
+ .str = { "12345\n", "abcd" },
+ .len = { 6, 4, 0 }
+ },
+ /* 11 */
+ {
+ .buf = "12345\\\nabcd",
+ .pos = { 0, 11 },
+ .str = { "12345\\\nabcd" },
+ .len = { 11, 0 }
+ },
+ /* 12 */
+ {
+ .buf = "12345\\\\\nabcd",
+ .pos = { 0, 8, 12 },
+ .str = { "12345\\\\\n", "abcd" },
+ .len = { 8, 4, 0 }
+ },
+ /* 13 */
+ {
+ .buf = "12345\\\\\\\nabcd",
+ .pos = { 0, 13 },
+ .str = { "12345\\\\\\\nabcd" },
+ .len = { 13, 0 }
+ },
+ /* 14 */
+ {
+ .buf = "12345\\\\\\\\\nabcd",
+ .pos = { 0, 10, 14 },
+ .str = { "12345\\\\\\\\\n", "abcd" },
+ .len = { 10, 4, 0 }
+ },
+ /* 15 */
+ {
+ .buf = "12345\nabcd\n",
+ .pos = { 0, 6, 11 },
+ .str = { "12345\n", "abcd\n" },
+ .len = { 6, 5, 0 }
+ },
+ /* 16 */
+ {
+ .buf = "12345\nabcd\n~!@#$%^",
+ .pos = { 0, 6, 11, 18 },
+ .str = { "12345\n", "abcd\n", "~!@#$%^" },
+ .len = { 6, 5, 7, 0 }
+ },
+ /* 17 */
+ {
+ .buf = "12345\nabcd\n~!@#$%^\n",
+ .pos = { 0, 6, 11, 19 },
+ .str = { "12345\n", "abcd\n", "~!@#$%^\n" },
+ .len = { 6, 5, 8, 0 }
+ }
+};
+/* *INDENT-ON* */
+
+/* @Test(dataSource = "data_source") */
+/* *INDENT-OFF* */
+START_PARAMETRIZED_TEST (mc_pstream_get_string_test, data_source)
+/* *INDENT-ON* */
+{
+ /* given */
+ int j = 0;
+
+ /* when */
+ memset (&stream, 0, sizeof (stream));
+ stream.len = strlen (data->buf);
+ memmove (&stream.buf, data->buf, stream.len);
+
+ /* then */
+ do
+ {
+ GString *ret;
+
+ ck_assert_int_eq (stream.pos, data->pos[j]);
+
+ ret = mc_pstream_get_string (&stream);
+ if (ret == NULL)
+ break;
+
+ ck_assert_int_eq (ret->len, data->len[j]);
+ mctest_assert_str_eq (ret->str, data->str[j]);
+
+ g_string_free (ret, TRUE);
+
+ j++;
+ }
+ while (TRUE);
+}
+/* *INDENT-OFF* */
+END_PARAMETRIZED_TEST
+/* *INDENT-ON* */
+
+/* --------------------------------------------------------------------------------------------- */
+
+static mc_pipe_t *
+test_mc_popen (void)
+{
+ mc_pipe_t *p;
+
+ p = g_try_new0 (mc_pipe_t, 1);
+ /* make less than sizeof (etalon_long_file_list) */
+ p->out.len = 128;
+
+ etalon_long_file_list_pos = 0;
+
+ return p;
+}
+
+static void
+test_mc_pread (mc_pipe_t * p)
+{
+ size_t len;
+
+ p->out.pos = 0;
+
+ if (etalon_long_file_list_pos >= sizeof (etalon_long_file_list))
+ {
+ etalon_long_file_list_pos = sizeof (etalon_long_file_list);
+ p->out.len = MC_PIPE_STREAM_EOF;
+ return;
+ }
+
+ len = sizeof (etalon_long_file_list) - etalon_long_file_list_pos;
+ len = MIN (len, (size_t) p->out.len);
+ memmove (p->out.buf, etalon_long_file_list + etalon_long_file_list_pos, len);
+ p->out.len = (ssize_t) len;
+
+ etalon_long_file_list_pos += len;
+}
+
+/* *INDENT-OFF* */
+START_TEST (mc_pstream_get_long_file_list_test)
+/* *INDENT-ON* */
+
+{
+ /* given */
+ GString *result_long_file_list = NULL;
+ mc_pipe_t *pip;
+ GString *remain_file_name = NULL;
+
+ /* when */
+ /* fill the list */
+ memset (etalon_long_file_list, 'a', sizeof (etalon_long_file_list) - 1);
+ /* create an \n-separated list */
+ etalon_long_file_list[5] = '\n';
+ etalon_long_file_list[25] = '\n';
+ etalon_long_file_list[50] = '\n';
+ etalon_long_file_list[75] = '\n';
+ etalon_long_file_list[127] = '\n';
+ etalon_long_file_list[200] = '\n';
+ etalon_long_file_list[310] = '\n';
+ etalon_long_file_list[325] = '\n';
+ etalon_long_file_list[360] = '\n';
+ etalon_long_file_list[512] = '\n';
+ etalon_long_file_list[701] = '\n';
+ etalon_long_file_list[725] = '\n';
+ etalon_long_file_list[800] = '\n';
+ etalon_long_file_list[sizeof (etalon_long_file_list) - 2] = '\n';
+ etalon_long_file_list[sizeof (etalon_long_file_list) - 1] = '\0';
+
+ /* then */
+ /* read file list */
+ pip = test_mc_popen ();
+
+ while (TRUE)
+ {
+ GString *line;
+
+ test_mc_pread (pip);
+
+ if (pip->out.len == MC_PIPE_STREAM_EOF)
+ break;
+
+ while ((line = mc_pstream_get_string (&pip->out)) != NULL)
+ {
+ /* handle an \n-separated file list */
+
+ if (line->str[line->len - 1] == '\n')
+ {
+ /* entire file name or last chunk */
+
+ g_string_truncate (line, line->len - 1);
+
+ /* join filename chunks */
+ if (remain_file_name != NULL)
+ {
+ g_string_append_len (remain_file_name, line->str, line->len);
+ g_string_free (line, TRUE);
+ line = remain_file_name;
+ remain_file_name = NULL;
+ }
+ }
+ else
+ {
+ /* first or middle chunk of file name */
+ if (remain_file_name == NULL)
+ remain_file_name = line;
+ else
+ {
+ g_string_append_len (remain_file_name, line->str, line->len);
+ g_string_free (line, TRUE);
+ }
+
+ line = NULL;
+ }
+
+ /* collect file names to assemble the result string */
+ if (line == NULL)
+ continue;
+
+ if (result_long_file_list == NULL)
+ result_long_file_list = line;
+ else
+ {
+ g_string_append_len (result_long_file_list, line->str, line->len);
+ g_string_free (line, TRUE);
+ }
+
+ g_string_append_c (result_long_file_list, '\n');
+ }
+ }
+
+ mctest_assert_str_eq (etalon_long_file_list, result_long_file_list->str);
+ g_string_free (result_long_file_list, TRUE);
+
+}
+/* *INDENT-OFF* */
+END_TEST
+/* *INDENT-ON* */
+
+/* --------------------------------------------------------------------------------------------- */
+
+int
+main (void)
+{
+ TCase *tc_core;
+
+ tc_core = tcase_create ("Core");
+
+ tcase_add_checked_fixture (tc_core, setup, teardown);
+
+ /* Add new tests here: *************** */
+ mctest_add_parameterized_test (tc_core, mc_pstream_get_string_test, data_source);
+ tcase_add_test (tc_core, mc_pstream_get_long_file_list_test);
+ /* *********************************** */
+
+ return mctest_run_all (tc_core);
+}
+
+/* --------------------------------------------------------------------------------------------- */