summaryrefslogtreecommitdiffstats
path: root/src/lib-program-client/test-program-client-local.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 09:51:24 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 09:51:24 +0000
commitf7548d6d28c313cf80e6f3ef89aed16a19815df1 (patch)
treea3f6f2a3f247293bee59ecd28e8cd8ceb6ca064a /src/lib-program-client/test-program-client-local.c
parentInitial commit. (diff)
downloaddovecot-f7548d6d28c313cf80e6f3ef89aed16a19815df1.tar.xz
dovecot-f7548d6d28c313cf80e6f3ef89aed16a19815df1.zip
Adding upstream version 1:2.3.19.1+dfsg1.upstream/1%2.3.19.1+dfsg1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/lib-program-client/test-program-client-local.c')
-rw-r--r--src/lib-program-client/test-program-client-local.c289
1 files changed, 289 insertions, 0 deletions
diff --git a/src/lib-program-client/test-program-client-local.c b/src/lib-program-client/test-program-client-local.c
new file mode 100644
index 0000000..2040b15
--- /dev/null
+++ b/src/lib-program-client/test-program-client-local.c
@@ -0,0 +1,289 @@
+/* Copyright (c) 2002-2018 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "test-lib.h"
+#include "buffer.h"
+#include "str.h"
+#include "istream.h"
+#include "istream-concat.h"
+#include "ostream.h"
+#include "lib-signals.h"
+#include "program-client.h"
+
+#include <unistd.h>
+
+static const char *pclient_test_io_string =
+ "Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n"
+ "Praesent vehicula ac leo vel placerat. Nullam placerat \n"
+ "volutpat leo, sed ultricies felis pulvinar quis. Nam \n"
+ "tempus, augue ut tempor cursus, neque felis commodo lacus, \n"
+ "sit amet tincidunt arcu justo vel augue. Proin dapibus \n"
+ "vulputate maximus. Mauris congue lacus felis, sed varius \n"
+ "leo finibus sagittis. Cum sociis natoque penatibus et magnis \n"
+ "dis parturient montes, nascetur ridiculus mus. Aliquam \n"
+ "laoreet arcu a hendrerit consequat. Duis vitae erat tellus.";
+
+static struct program_client_settings pc_set = {
+ .client_connect_timeout_msecs = 10000,
+ .input_idle_timeout_msecs = 5000,
+ .debug = FALSE,
+ .restrict_set = {
+ .uid = (uid_t)-1,
+ .gid = (gid_t)-1,
+ },
+ /* we need to permit root when running make check as root */
+ .allow_root = TRUE,
+};
+
+static void test_program_success(void)
+{
+ struct program_client *pc;
+
+ const char *const args[] = {
+ "hello", "world", NULL
+ };
+
+ test_begin("test_program_success");
+
+ pc = program_client_local_create("/bin/echo", args, &pc_set);
+
+ buffer_t *output = buffer_create_dynamic(default_pool, 16);
+ struct ostream *os = test_ostream_create(output);
+ program_client_set_output(pc, os);
+
+ test_assert(program_client_run(pc) == 1);
+ test_assert(strcmp(str_c(output), "hello world\n") == 0);
+
+ program_client_destroy(&pc);
+
+ o_stream_unref(&os);
+ buffer_free(&output);
+
+ test_end();
+}
+
+static void test_program_io_sync(void)
+{
+ struct program_client *pc;
+
+ const char *const args[] = {
+ NULL
+ };
+
+ test_begin("test_program_io (sync)");
+
+ pc = program_client_local_create("/bin/cat", args, &pc_set);
+
+ struct istream *is = test_istream_create(pclient_test_io_string);
+ program_client_set_input(pc, is);
+
+ buffer_t *output = buffer_create_dynamic(default_pool, 16);
+ struct ostream *os = test_ostream_create(output);
+ program_client_set_output(pc, os);
+
+ test_assert(program_client_run(pc) == 1);
+ test_assert(strcmp(str_c(output), pclient_test_io_string) == 0);
+
+ program_client_destroy(&pc);
+
+ i_stream_unref(&is);
+ o_stream_unref(&os);
+ buffer_free(&output);
+
+ test_end();
+}
+
+static void test_program_io_async_callback(int result, int *ret)
+{
+ *ret = result;
+ test_assert(result == 1);
+ io_loop_stop(current_ioloop);
+}
+
+static void test_program_io_async(void)
+{
+ struct ioloop *prev_ioloop, *ioloop;
+ struct program_client *pc;
+ int ret = -2;
+
+ const char *const args[] = {
+ NULL
+ };
+
+ test_begin("test_program_io (async)");
+
+ prev_ioloop = current_ioloop;
+ ioloop = io_loop_create();
+
+ pc = program_client_local_create("/bin/cat", args, &pc_set);
+
+ struct istream *is = test_istream_create(pclient_test_io_string);
+ program_client_set_input(pc, is);
+
+ buffer_t *output = buffer_create_dynamic(default_pool, 16);
+ struct ostream *os = test_ostream_create(output);
+ program_client_set_output(pc, os);
+
+ program_client_run_async(pc, test_program_io_async_callback, &ret);
+
+ if (ret == -2)
+ io_loop_run(ioloop);
+
+ test_assert(strcmp(str_c(output), pclient_test_io_string) == 0);
+
+ program_client_destroy(&pc);
+
+ i_stream_unref(&is);
+ o_stream_unref(&os);
+ buffer_free(&output);
+ io_loop_set_current(prev_ioloop);
+ io_loop_set_current(ioloop);
+ io_loop_destroy(&ioloop);
+
+ test_end();
+}
+
+static void test_program_failure(void)
+{
+ struct program_client *pc;
+
+ const char *const args[] = {
+ NULL
+ };
+
+ test_begin("test_program_failure");
+
+ pc = program_client_local_create("/bin/false", args, &pc_set);
+
+ buffer_t *output = buffer_create_dynamic(default_pool, 16);
+ struct ostream *os = test_ostream_create(output);
+ program_client_set_output(pc, os);
+
+ test_assert(program_client_run(pc) == 0);
+ test_assert(strcmp(str_c(output), "") == 0);
+
+ program_client_destroy(&pc);
+
+ o_stream_unref(&os);
+ buffer_free(&output);
+
+ test_end();
+}
+
+static void test_program_io_big(void)
+{
+ struct program_client *pc;
+
+ /* nasty program that reads data in bits with intermittent delays
+ and then finally reads the rest in one go. */
+ const char *const args[] = {
+ "-c",
+ "(dd bs=10240 count=1; sleep 0.1; "
+ "dd bs=10240 count=1; sleep 0.1; "
+ "dd bs=10240 count=1; sleep 0.1; "
+ "dd bs=10240 count=1; sleep 0.1; "
+ "dd bs=10240 count=1; sleep 0.1; "
+ "dd bs=10240 count=1; sleep 0.1; cat) 2>/dev/null",
+ NULL
+ };
+
+ test_begin("test_program_io (big)");
+
+ pc = program_client_local_create("/bin/sh", args, &pc_set);
+
+ /* make big input with only a small reference string */
+ struct istream *is1 = test_istream_create(pclient_test_io_string);
+ struct istream *in1[11] = {is1, is1, is1, is1, is1,
+ is1, is1, is1, is1, is1, NULL};
+ struct istream *is2 = i_stream_create_concat(in1);
+ struct istream *in2[11] = {is2, is2, is2, is2, is2,
+ is2, is2, is2, is2, is2, NULL};
+ struct istream *is3 = i_stream_create_concat(in2);
+ struct istream *in3[11] = {is3, is3, is3, is3, is3,
+ is3, is3, is3, is3, is3, NULL};
+ struct istream *is = i_stream_create_concat(in3);
+
+ i_stream_unref(&is1);
+ i_stream_unref(&is2);
+ i_stream_unref(&is3);
+
+ program_client_set_input(pc, is);
+
+ buffer_t *output = buffer_create_dynamic(default_pool, 16);
+ struct ostream *os = test_ostream_create(output);
+ program_client_set_output(pc, os);
+
+ test_assert(program_client_run(pc) == 1);
+
+ test_assert(str_len(output) == strlen(pclient_test_io_string)*10*10*10);
+
+ program_client_destroy(&pc);
+
+ i_stream_unref(&is);
+ o_stream_unref(&os);
+ buffer_free(&output);
+
+ test_end();
+}
+
+static void test_program_wait_no_io(void)
+{
+ struct program_client_settings set = pc_set;
+ struct program_client *pc;
+
+ /* nasty program that reads data in bits with intermittent delays
+ and then finally reads the rest in one go. */
+ const char *const args[] = {
+ "-c", "sleep 1",
+ NULL
+ };
+
+ test_begin("test_program_wait (no timeout, no I/O)");
+
+ set.client_connect_timeout_msecs = 0;
+ set.input_idle_timeout_msecs = 0;
+ pc = program_client_local_create("/bin/sh", args, &set);
+
+ test_assert(program_client_run(pc) == 1);
+
+ program_client_destroy(&pc);
+
+ test_end();
+}
+
+int main(int argc, char *argv[])
+{
+ struct ioloop *ioloop;
+ int ret, c;
+
+ void (*tests[])(void) = {
+ test_program_success,
+ test_program_io_sync,
+ test_program_io_async,
+ test_program_io_big,
+ test_program_failure,
+ test_program_wait_no_io,
+ NULL
+ };
+
+ lib_init();
+
+ while ((c = getopt(argc, argv, "D")) > 0) {
+ switch (c) {
+ case 'D':
+ pc_set.debug = TRUE;
+ break;
+ default:
+ i_fatal("Usage: %s [-D]", argv[0]);
+ }
+ }
+
+ ioloop = io_loop_create();
+ lib_signals_init();
+ ret = test_run(tests);
+ lib_signals_deinit();
+ io_loop_destroy(&ioloop);
+
+ lib_deinit();
+ return ret;
+}