/* * test-simple-ipc.c: verify that the Inter-Process Communication works. */ #include "test-tool.h" #include "gettext.h" #include "simple-ipc.h" #include "parse-options.h" #include "thread-utils.h" #include "strvec.h" #include "run-command.h" #include "trace2.h" #ifndef SUPPORTS_SIMPLE_IPC int cmd__simple_ipc(int argc, const char **argv) { die("simple IPC not available on this platform"); } #else /* * The test daemon defines an "application callback" that supports a * series of commands (see `test_app_cb()`). * * Unknown commands are caught here and we send an error message back * to the client process. */ static int app__unhandled_command(const char *command, ipc_server_reply_cb *reply_cb, struct ipc_server_reply_data *reply_data) { … } /* * Reply with a single very large buffer. This is to ensure that * long response are properly handled -- whether the chunking occurs * in the kernel or in the (probably pkt-line) layer. */ #define BIG_ROWS … static int app__big_command(ipc_server_reply_cb *reply_cb, struct ipc_server_reply_data *reply_data) { … } /* * Reply with a series of lines. This is to ensure that we can incrementally * compute the response and chunk it to the client. */ #define CHUNK_ROWS … static int app__chunk_command(ipc_server_reply_cb *reply_cb, struct ipc_server_reply_data *reply_data) { … } /* * Slowly reply with a series of lines. This is to model an expensive to * compute chunked response (which might happen if this callback is running * in a thread and is fighting for a lock with other threads). */ #define SLOW_ROWS … #define SLOW_DELAY_MS … static int app__slow_command(ipc_server_reply_cb *reply_cb, struct ipc_server_reply_data *reply_data) { … } /* * The client sent a command followed by a (possibly very) large buffer. */ static int app__sendbytes_command(const char *received, size_t received_len, ipc_server_reply_cb *reply_cb, struct ipc_server_reply_data *reply_data) { … } /* * An arbitrary fixed address to verify that the application instance * data is handled properly. */ static int my_app_data = …; static ipc_server_application_cb test_app_cb; /* * This is the "application callback" that sits on top of the * "ipc-server". It completely defines the set of commands supported * by this application. */ static int test_app_cb(void *application_data, const char *command, size_t command_len, ipc_server_reply_cb *reply_cb, struct ipc_server_reply_data *reply_data) { … } struct cl_args { … }; static struct cl_args cl_args = …; /* * This process will run as a simple-ipc server and listen for IPC commands * from client processes. */ static int daemon__run_server(void) { … } static start_bg_wait_cb bg_wait_cb; static int bg_wait_cb(const struct child_process *cp UNUSED, void *cb_data UNUSED) { … } static int daemon__start_server(void) { … } /* * This process will run a quick probe to see if a simple-ipc server * is active on this path. * * Returns 0 if the server is alive. */ static int client__probe_server(void) { … } /* * Send an IPC command token to an already-running server daemon and * print the response. * * This is a simple 1 word command/token that `test_app_cb()` (in the * daemon process) will understand. */ static int client__send_ipc(void) { … } /* * Send an IPC command to an already-running server and ask it to * shutdown. "send quit" is an async request and queues a shutdown * event in the server, so we spin and wait here for it to actually * shutdown to make the unit tests a little easier to write. */ static int client__stop_server(void) { … } /* * Send an IPC command followed by ballast to confirm that a large * message can be sent and that the kernel or pkt-line layers will * properly chunk it and that the daemon receives the entire message. */ static int do_sendbytes(int bytecount, char byte, const char *path, const struct ipc_client_connect_options *options) { … } /* * Send an IPC command with ballast to an already-running server daemon. */ static int client__sendbytes(void) { … } struct multiple_thread_data { … }; static void *multiple_thread_proc(void *_multiple_thread_data) { … } /* * Start a client-side thread pool. Each thread sends a series of * IPC requests. Each request is on a new connection to the server. */ static int client__multiple(void) { … } int cmd__simple_ipc(int argc, const char **argv) { … } #endif