diff options
Diffstat (limited to 'tests/lib/utilunix__mc_pstream_get_string.c')
-rw-r--r-- | tests/lib/utilunix__mc_pstream_get_string.c | 396 |
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); +} + +/* --------------------------------------------------------------------------------------------- */ |