diff --git a/tests/build.sh b/tests/build.sh new file mode 100755 index 0000000..72b2e2f --- /dev/null +++ b/tests/build.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +nontapmsg() { + echo $* +} + +for i in *.c +do + f=`echo $i | sed "s/.c$//"` + nontapmsg "compiling $f" + gcc $f.c -Wall -Wextra -Wno-unused-parameter -g -o $f.bin -I../src -L../ -lipc +done diff --git a/tests/func_01_connection_establishment.c b/tests/func_01_connection_establishment.c new file mode 100644 index 0000000..21730e6 --- /dev/null +++ b/tests/func_01_connection_establishment.c @@ -0,0 +1,31 @@ +#include "../src/ipc.h" + +#include +#include +#include + +#define SERVICE_NAME "pong" + +int main(int argc, char * argv[], char **env) +{ + enum ipc_errors ret; + SECURE_DECLARATION(struct ipc_connection_info,service); + SECURE_DECLARATION(struct ipc_event, event); + + ret = ipc_connection (env, &service, SERVICE_NAME); + if (ret != IPC_ERROR_NONE) { + return EXIT_FAILURE; + } + + // ret = ipc_wait_event (services, struct ipc_event *event); + // if (ret != IPC_ERROR_NONE) { + // return EXIT_FAILURE; + // } + + ret = ipc_close (&service); + if (ret != IPC_ERROR_NONE) { + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} diff --git a/tests/func_01_connection_establishmentd.c b/tests/func_01_connection_establishmentd.c new file mode 100644 index 0000000..0968964 --- /dev/null +++ b/tests/func_01_connection_establishmentd.c @@ -0,0 +1,56 @@ +#include "../src/ipc.h" + +#include +#include +#include + +#define SERVICE_NAME "pong" + +int main(int argc, char * argv[], char **env) +{ + enum ipc_errors ret; + SECURE_DECLARATION(struct ipc_connection_info,srv); + + printf ("func 01 - server init...\n"); + ret = ipc_server_init (env, &srv, SERVICE_NAME); + if (ret != IPC_ERROR_NONE) { + return EXIT_FAILURE; + } + printf ("func 01 - server init ok\n"); + + SECURE_DECLARATION(struct ipc_connection_infos, clients); + SECURE_DECLARATION(struct ipc_event,event); + + printf ("func 01 - service polling...\n"); + // listen only for a single client + ret = ipc_wait_event (&clients, &srv, &event); + + switch (event.type) { + case IPC_EVENT_TYPE_CONNECTION : + { + printf ("ok - connection establishment\n"); + break; + } + case IPC_EVENT_TYPE_NOT_SET : + case IPC_EVENT_TYPE_ERROR : + case IPC_EVENT_TYPE_EXTRA_SOCKET : + case IPC_EVENT_TYPE_DISCONNECTION : + case IPC_EVENT_TYPE_MESSAGE : + default : + printf ("not ok - should not happen\n"); + exit (EXIT_FAILURE); + break; + } + + printf ("func 01 - closing clients...\n"); + ipc_connections_free (&clients); + printf ("func 01 - closing server...\n"); + ret = ipc_server_close(&srv); + if (ret != IPC_ERROR_NONE) + { + const char * error_explanation = ipc_errors_get (ret); + printf ("ipc_server_close: %s\n", error_explanation); + } + + return EXIT_SUCCESS; +} diff --git a/tests/func_02_pong.c b/tests/func_02_pong.c new file mode 100644 index 0000000..96c5712 --- /dev/null +++ b/tests/func_02_pong.c @@ -0,0 +1,147 @@ +#include +#include +#include +#include + +#include "../src/ipc.h" + +#define MSG "coucou" +#define SERVICE_NAME "pong" + +#define PRINTERR(ret,msg) {\ + const char * err = ipc_errors_get (ret);\ + fprintf(stderr, "error while %s: %s\n", msg, err);\ +} + +void non_interactive (char *env[]) +{ + enum ipc_errors ret; + struct ipc_message m; + memset (&m, 0, sizeof (struct ipc_message)); + SECURE_DECLARATION(struct ipc_connection_info, srv); + + // init service + ret = ipc_connection (env, &srv, SERVICE_NAME); + if (ret != IPC_ERROR_NONE) { + PRINTERR(ret, "application connection"); + exit (EXIT_FAILURE); + } + + printf ("msg to send (%ld): %.*s\n", (ssize_t) strlen(MSG) +1, (int) strlen(MSG), MSG); + ret = ipc_message_format_data (&m, /* type */ 'a', MSG, (ssize_t) strlen(MSG) +1); + if (ret != IPC_ERROR_NONE) { + PRINTERR(ret, "message format data"); + exit (EXIT_FAILURE); + } + + // printf ("msg to send in the client: "); + // ipc_message_print (&m); + ret = ipc_write (&srv, &m); + if (ret != IPC_ERROR_NONE) { + PRINTERR(ret, "application write"); + exit (EXIT_FAILURE); + } + ipc_message_empty (&m); + + ret = ipc_read (&srv, &m); + if (ret != IPC_ERROR_NONE) { + PRINTERR(ret, "application read"); + exit (EXIT_FAILURE); + } + + printf ("msg recv: %s\n", m.payload); + ipc_message_empty (&m); + + ret = ipc_close (&srv); + if (ret != IPC_ERROR_NONE) { + PRINTERR(ret, "application close"); + exit (EXIT_FAILURE); + } +} + +void interactive (char *env[]) +{ + enum ipc_errors ret; + SECURE_DECLARATION(struct ipc_connection_info, srv); + + // index and version should be filled + srv.index = 0; + srv.version = 0; + + // init service + ret = ipc_connection (env, &srv, SERVICE_NAME); + if (ret != IPC_ERROR_NONE) { + PRINTERR(ret, "application connection"); + exit (EXIT_FAILURE); + } + + SECURE_DECLARATION(struct ipc_event, event); + SECURE_DECLARATION(struct ipc_connection_infos, services); + + ipc_add (&services, &srv); + + while (1) { + printf ("msg to send: "); + fflush (stdout); + ret = ipc_wait_event (&services, NULL, &event); + + if (ret != IPC_ERROR_NONE) { + PRINTERR(ret, "application peek event"); + exit (EXIT_FAILURE); + } + + switch (event.type) { + case IPC_EVENT_TYPE_EXTRA_SOCKET: + { + struct ipc_message *m = event.m; + if ( m->length == 0 || strncmp (m->payload, "exit", 4) == 0) { + + ipc_message_empty (m); + free (m); + + ipc_connections_free (&services); + + ret = ipc_close (&srv); + if (ret != IPC_ERROR_NONE) { + PRINTERR(ret, "application close"); + exit (EXIT_FAILURE); + } + + exit (EXIT_SUCCESS); + } + + ret = ipc_write (&srv, m); + if (ret != IPC_ERROR_NONE) { + PRINTERR(ret, "application write"); + exit (EXIT_FAILURE); + } + } + break; + case IPC_EVENT_TYPE_MESSAGE: + { + struct ipc_message *m = event.m; + printf ("msg recv: %.*s", m->length, m->payload); + }; + break; + case IPC_EVENT_TYPE_DISCONNECTION: + case IPC_EVENT_TYPE_NOT_SET: + case IPC_EVENT_TYPE_CONNECTION: + case IPC_EVENT_TYPE_ERROR: + default : + fprintf (stderr, "should not happen, event type %d\n", event.type); + } + } +} + +int main (int argc, char *argv[], char *env[]) +{ + argc = argc; // warnings + argv = argv; // warnings + + if (argc == 1) + non_interactive (env); + else + interactive (env); + + return EXIT_SUCCESS; +} diff --git a/tests/func_02_pongd.c b/tests/func_02_pongd.c new file mode 100644 index 0000000..9252258 --- /dev/null +++ b/tests/func_02_pongd.c @@ -0,0 +1,163 @@ +#include "../src/ipc.h" +#include + +#include +#include +#include + +#define PONGD_SERVICE_NAME "pong" + +#define PRINTERR(ret,msg) {\ + const char * err = ipc_errors_get (ret);\ + fprintf(stderr, "error while %s: %s\n", msg, err);\ +} + +int cpt = 0; + +struct ipc_connection_info *srv = 0; +struct ipc_connection_infos *clients; + + +void main_loop () +{ + enum ipc_errors ret = 0; + + clients = malloc (sizeof (struct ipc_connection_infos)); + memset(clients, 0, sizeof(struct ipc_connection_infos)); + + SECURE_DECLARATION(struct ipc_event,event); + + while(1) { + // ipc_wait_event provides one event at a time + // warning: event->m is free'ed if not NULL + ret = ipc_wait_event (clients, srv, &event); + if (ret != IPC_ERROR_NONE && ret != IPC_ERROR_CLOSED_RECIPIENT) { + PRINTERR(ret,"service poll event"); + + // the application will shut down, and close the service + ret = ipc_server_close (srv); + if (ret != IPC_ERROR_NONE) { + PRINTERR(ret,"server close"); + } + exit (EXIT_FAILURE); + } + + switch (event.type) { + case IPC_EVENT_TYPE_CONNECTION: + { + cpt++; + printf ("connection: %d clients connected\n", cpt); + printf ("new client has the fd %d\n", ((struct ipc_connection_info*) event.origin)->fd); + }; + break; + case IPC_EVENT_TYPE_DISCONNECTION: + { + cpt--; + printf ("disconnection: %d clients remaining\n", cpt); + + // free the ipc_connection_info structure + free (event.origin); + }; + break; + case IPC_EVENT_TYPE_MESSAGE: + { + struct ipc_message *m = event.m; + if (m->length > 0) { + printf ("message received (type %d): %.*s\n", m->type, m->length, m->payload); + } + + ret = ipc_write (event.origin, m); + if (ret != IPC_ERROR_NONE) { + PRINTERR(ret,"server write"); + } + }; + break; + case IPC_EVENT_TYPE_ERROR: + { + fprintf (stderr, "a problem happened with client %d\n" + , ((struct ipc_connection_info*) event.origin)->fd); + }; + break; + default : + { + fprintf (stderr, "there must be a problem, event not set\n"); + }; + } + } + + // should never go there + exit (1); +} + + +void exit_program(int signal) +{ + printf("Quitting, signal: %d\n", signal); + + // free remaining clients + for (int i = 0; i < clients->size ; i++) { + struct ipc_connection_info *cli = clients->cinfos[i]; + if (cli != NULL) { + free (cli); + } + clients->cinfos[i] = NULL; + } + + ipc_connections_free (clients); + free (clients); + + + // the application will shut down, and close the service + enum ipc_errors ret = ipc_server_close (srv); + if (ret != IPC_ERROR_NONE) { + PRINTERR(ret,"server close"); + } + free (srv); + + exit(EXIT_SUCCESS); +} + +/* + * service ping-pong: send back everything sent by the clients + * stop the program on SIG{TERM,INT,ALRM,USR{1,2},HUP} signals + */ + +int main(int argc, char * argv[], char **env) +{ + argc = argc; // warnings + argv = argv; // warnings + + printf ("pid = %d\n", getpid ()); + + srv = malloc (sizeof (struct ipc_connection_info)); + if (srv == NULL) { + exit (1); + } + memset (srv, 0, sizeof (struct ipc_connection_info)); + srv->index = 0; + srv->version = 0; + + // unlink("/tmp/ipc/pongd-0-0"); + + enum ipc_errors ret = ipc_server_init (env, srv, PONGD_SERVICE_NAME); + if (ret != IPC_ERROR_NONE) { + PRINTERR(ret,"server init"); + return EXIT_FAILURE; + } + printf ("Listening on %s.\n", srv->spath); + + printf("MAIN: server created\n" ); + + signal (SIGHUP, exit_program); + signal (SIGALRM, exit_program); + signal (SIGUSR1, exit_program); + signal (SIGUSR2, exit_program); + signal (SIGTERM, exit_program); + signal (SIGINT, exit_program); + + // the service will loop until the end of time, or a signal + main_loop (); + + // main_loop should not return + return EXIT_FAILURE; +} diff --git a/tests/func_03_multiple-communications-client.c b/tests/func_03_multiple-communications-client.c new file mode 100644 index 0000000..cfbff4e --- /dev/null +++ b/tests/func_03_multiple-communications-client.c @@ -0,0 +1,97 @@ +#include "../src/ipc.h" + +#include +#include +#include + +#define SERVICE_NAME "pong" +#define SECURE_MALLOC(p, s, wat) p = malloc (s); if (p == NULL) { wat; } + +void connection (char **env, struct ipc_connection_info *ci) +{ + enum ipc_errors ret = ipc_connection (env, ci, SERVICE_NAME); + if (ret != IPC_ERROR_NONE) { + fprintf (stderr, "cannot connect to the server\n"); + exit(EXIT_FAILURE); + } +} + +void closing (struct ipc_connection_info *ci) +{ + enum ipc_errors ret = ipc_close (ci); + if (ret != IPC_ERROR_NONE) { + fprintf (stderr, "cannot close server\n"); + exit(EXIT_FAILURE); + } +} + +// test the behavior of the server when the client never read its messages + +void send_message (struct ipc_connection_info *ci) +{ + SECURE_DECLARATION (struct ipc_message, m); + SECURE_MALLOC (m.payload, 5, exit(EXIT_FAILURE)); + memcpy (m.payload, "salut", 5); + m.type = MSG_TYPE_DATA; + m.user_type = 42; + m.length = 5; + + ipc_write (ci, &m); + + ipc_message_empty (&m); +} + + +void read_message (struct ipc_connection_info *ci) +{ +#if 0 + SECURE_DECLARATION(struct ipc_event, event); + SECURE_DECLARATION(struct ipc_connection_infos, clients); + + ipc_add (&clients, ci); + + ipc_wait_event (&clients, NULL, &event); + + switch (event.type) { + case IPC_EVENT_TYPE_MESSAGE : { + printf ("received message: %*.s\n", m.length, ((struct ipc_message*) event.m)->payload); + } + break; + case IPC_EVENT_TYPE_CONNECTION : + case IPC_EVENT_TYPE_DISCONNECTION : + case IPC_EVENT_TYPE_NOT_SET : + case IPC_EVENT_TYPE_ERROR : + case IPC_EVENT_TYPE_EXTRA_SOCKET : + default : + printf ("not ok - should not happen\n"); + exit (EXIT_FAILURE); + break; + } + + ipc_connections_free (&clients); +#else + SECURE_DECLARATION (struct ipc_message, m); + + ipc_read (ci, &m); + printf ("received message: %*.s\n", m.length, m.payload); + free (m.payload); +#endif +} + +int main(int argc, char * argv[], char **env) +{ + SECURE_DECLARATION(struct ipc_connection_info,srv1); + SECURE_DECLARATION(struct ipc_connection_info,srv2); + SECURE_DECLARATION(struct ipc_event, event); + + connection (env, &srv1); + connection (env, &srv2); + send_message (&srv1); + read_message (&srv1); + closing (&srv1); + send_message (&srv2); + read_message (&srv2); + closing (&srv2); + + return EXIT_SUCCESS; +} diff --git a/tests/func_03_multiple-communications-server.c b/tests/func_03_multiple-communications-server.c new file mode 100644 index 0000000..56dabe5 --- /dev/null +++ b/tests/func_03_multiple-communications-server.c @@ -0,0 +1,84 @@ +#include "../src/ipc.h" + +#include +#include +#include +#include + +#define SERVICE_NAME "pong" + +int main_loop(int argc, char * argv[], char **env) +{ + enum ipc_errors ret; + SECURE_DECLARATION (struct ipc_connection_info, srv); + + printf ("func 03 - server init...\n"); + ret = ipc_server_init (env, &srv, SERVICE_NAME); + if (ret != IPC_ERROR_NONE) { + exit(EXIT_FAILURE); + } + printf ("func 03 - server init ok\n"); + + SECURE_DECLARATION (struct ipc_connection_infos, clients); + SECURE_DECLARATION (struct ipc_event, event); + + printf ("func 01 - service polling...\n"); + // listen only for a single client + while (1) { + ret = ipc_wait_event (&clients, &srv, &event); + + switch (event.type) { + case IPC_EVENT_TYPE_CONNECTION : { + printf ("connection establishment: %d \n", event.origin->fd); + } + break; + case IPC_EVENT_TYPE_DISCONNECTION : { + printf ("client %d disconnecting\n", event.origin->fd); + }; + break; + case IPC_EVENT_TYPE_MESSAGE : { + printf ("received message: %s\n", ((struct ipc_message*) event.m)->payload); + ipc_write (event.origin, (struct ipc_message*) event.m); + } + break; + case IPC_EVENT_TYPE_NOT_SET : + case IPC_EVENT_TYPE_ERROR : + case IPC_EVENT_TYPE_EXTRA_SOCKET : + default : + printf ("not ok - should not happen\n"); + exit (EXIT_FAILURE); + break; + } + } + + printf ("func 03 - closing clients...\n"); + ipc_connections_free (&clients); + printf ("func 03 - closing server...\n"); + ret = ipc_server_close(&srv); + if (ret != IPC_ERROR_NONE) + { + const char * error_explanation = ipc_errors_get (ret); + printf ("ipc_server_close: %s\n", error_explanation); + } + + return 0; +} + +void exit_program(int signal) +{ + printf("Quitting, signal: %d\n", signal); + exit(EXIT_SUCCESS); +} + + +int main(int argc, char * argv[], char **env) +{ + signal (SIGHUP, exit_program); + signal (SIGALRM, exit_program); + signal (SIGUSR1, exit_program); + signal (SIGUSR2, exit_program); + signal (SIGTERM, exit_program); + signal (SIGINT, exit_program); + main_loop (argc, argv, env); + return EXIT_SUCCESS; +} diff --git a/tests/func_04_empty_message.c b/tests/func_04_empty_message.c new file mode 100644 index 0000000..cd0d55c --- /dev/null +++ b/tests/func_04_empty_message.c @@ -0,0 +1,72 @@ +#include "../src/ipc.h" + +#include +#include +#include + +#define SERVICE_NAME "pong" +#define SECURE_MALLOC(p, s, wat) p = malloc (s); if (p == NULL) { wat; } + +void connection (char **env, struct ipc_connection_info *ci) +{ + enum ipc_errors ret = ipc_connection (env, ci, SERVICE_NAME); + if (ret != IPC_ERROR_NONE) { + fprintf (stderr, "cannot connect to the server\n"); + exit(EXIT_FAILURE); + } +} + +void closing (struct ipc_connection_info *ci) +{ + enum ipc_errors ret = ipc_close (ci); + if (ret != IPC_ERROR_NONE) { + fprintf (stderr, "cannot close server\n"); + exit(EXIT_FAILURE); + } +} + +// test the behavior of the server when the client never read its messages + +void send_message (struct ipc_connection_info *ci) +{ + SECURE_DECLARATION (struct ipc_message, m); + SECURE_MALLOC (m.payload, 1, exit(EXIT_FAILURE)); + memcpy (m.payload, "", 0); + m.type = MSG_TYPE_DATA; + m.user_type = 42; + m.length = 0; + + ipc_write (ci, &m); + + ipc_message_empty (&m); +} + + +void read_message (struct ipc_connection_info *ci) +{ + SECURE_DECLARATION (struct ipc_message, m); + + ipc_read (ci, &m); + if (m.length > 0) { + printf ("received message: %*.s\n", m.length, m.payload); + } + else { + printf ("received empty message as intended : %d bytes\n", m.length); + if (m.payload == NULL) { + printf ("message payload is NULL\n"); + } + } + free (m.payload); +} + +int main(int argc, char * argv[], char **env) +{ + SECURE_DECLARATION(struct ipc_connection_info,srv1); + + connection (env, &srv1); + send_message (&srv1); + read_message (&srv1); + closing (&srv1); + + return EXIT_SUCCESS; +} diff --git a/tests/unit_01_service-path.c b/tests/unit_01_service-path.c new file mode 100644 index 0000000..cf2d531 --- /dev/null +++ b/tests/unit_01_service-path.c @@ -0,0 +1,34 @@ +#include "../src/ipc.h" + +#include +#include +#include + +#define SERVICE_NAME "example" +#define VERSION 0 +#define INDEX 0 + +int main(int argc, char * argv[]) +{ + char path[PATH_MAX]; + char * sname = SERVICE_NAME; + int32_t index = INDEX; + int32_t version = VERSION; + + if (argc == 4) { + sname = argv[1]; + index = atoi(argv[2]); + version = atoi(argv[3]); + } + else if (argc != 1) { + fprintf (stderr, "usage: %s [service-name index version]\n", argv[0]); + return EXIT_FAILURE; + } + + service_path (path, sname, index, version); + + // printf ("servicename: %s, index: %d, version: %d\n", sname, index, version); + printf ("%s\n", path); + + return EXIT_SUCCESS; +} diff --git a/tests/unit_02_usock-remove.c b/tests/unit_02_usock-remove.c new file mode 100644 index 0000000..168d91f --- /dev/null +++ b/tests/unit_02_usock-remove.c @@ -0,0 +1,26 @@ +#include "../src/ipc.h" +#include "../src/usocket.h" + +#include +#include +#include + +#define FILE_TO_REMOVE "/tmp/FILE_TO_REMOVE" + +int main(int argc, char * argv[]) +{ + char * ftr = FILE_TO_REMOVE; + + if (argc == 2) { + ftr = argv[1]; + } + else if (argc > 2) { + fprintf (stderr, "usage: %s [file-to-remove]\n", argv[0]); + return EXIT_FAILURE; + } + + enum ipc_errors ret = usock_remove (ftr); + if (ret == IPC_ERROR_NONE) + return 0; + return 1; +} diff --git a/tests/unit_03_connection-add-remove.c b/tests/unit_03_connection-add-remove.c new file mode 100644 index 0000000..17968aa --- /dev/null +++ b/tests/unit_03_connection-add-remove.c @@ -0,0 +1,15 @@ +#include "../src/ipc.h" + +#include +#include +#include + +/*** + * TODO + */ + +// int main(int argc, char * argv[]) +int main(void) +{ + return EXIT_SUCCESS; +}