diff options
-rw-r--r-- | build_and_test.sh | 20 | ||||
-rw-r--r-- | source/tests/test_interprocess.c | 124 |
2 files changed, 143 insertions, 1 deletions
diff --git a/build_and_test.sh b/build_and_test.sh index 157f88a..bd347f2 100644 --- a/build_and_test.sh +++ b/build_and_test.sh @@ -172,6 +172,15 @@ if [ $? -ne 0 ]; then exit 1 fi +$COMPILEPP ${FLAGS} \ + ${FLAG_EXE}"build/test_interprocess${EXE_POSTFIX}" \ + "build/kit${OBJ_POSTFIX}" \ + "source/tests/test_interprocess.c" \ + ${LINK_FLAGS} +if [ $? -ne 0 ]; then + exit 1 +fi + echo "Run tests" echo "" @@ -206,7 +215,7 @@ else STATUS=1 fi -./build/test_signals +./build/test_signals --quiet if [ $? -eq 0 ]; then echo "signals - OK" else @@ -214,4 +223,13 @@ else STATUS=1 fi +./build/test_interprocess writer & +./build/test_interprocess reader +if [ $? -eq 0 ]; then + echo "interprocess - OK" +else + echo "interprocess - FAILED (code $?)" + STATUS=1 +fi + exit $STATUS diff --git a/source/tests/test_interprocess.c b/source/tests/test_interprocess.c new file mode 100644 index 0000000..df2a375 --- /dev/null +++ b/source/tests/test_interprocess.c @@ -0,0 +1,124 @@ +#ifdef _WIN32 +int main() { + return 0; +} +#else +# include "../kit/threads.h" + +# include <stdio.h> +# include <string.h> +# include <sys/mman.h> +# include <sys/stat.h> +# include <fcntl.h> +# include <unistd.h> + +# define NAME "/kit_test_interprocess" + +enum { STATE_INIT, STATE_READY, STATE_DONE }; + +enum { SIZE = 64 }; + +int run_writer() { + int f = shm_open(NAME, O_RDWR | O_CREAT, 0660); + + if (f == -1) { + printf("%s: shm_open failed.\n", __FUNCTION__); + return 1; + } + + if (ftruncate(f, SIZE) == -1) { + printf("%s: ftruncate failed.\n", __FUNCTION__); + fflush(stdout); + return 1; + } + + void *p = mmap(NULL, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, f, + 0); + + if (p == MAP_FAILED) { + printf("%s: mmap failed.\n", __FUNCTION__); + fflush(stdout); + return 1; + } + + unsigned char *bytes = (unsigned char *) p; + + bytes[0] = STATE_INIT; + for (int i = 1; i < SIZE; i++) bytes[i] = i; + bytes[0] = STATE_READY; + + while (bytes[0] != STATE_DONE) thrd_yield(); + + shm_unlink(NAME); + + return 0; +} + +int run_reader() { + int f = -1; + + while (f == -1) { + f = shm_open(NAME, O_RDWR, 0); + thrd_yield(); + } + + void *p = mmap(NULL, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, f, + 0); + + if (p == MAP_FAILED) { + printf("%s: mmap failed.\n", __FUNCTION__); + fflush(stdout); + return 1; + } + + unsigned char *bytes = (unsigned char *) p; + + while (bytes[0] != STATE_READY) thrd_yield(); + + int status = 0; + + for (int i = 1; i < SIZE; i++) + if (bytes[i] != i) { + printf("%s: wrong byte %d\n", __FUNCTION__, i); + fflush(stdout); + status = 1; + } + + bytes[0] = STATE_DONE; + + return status; +} + +int main(int argc, char **argv) { + if (argc != 2) { + printf("Wrong number of command line arguments %d\n", argc); + return 1; + } + + int status = 0; + + struct timespec t0; + timespec_get(&t0, TIME_UTC); + + if (strcmp(argv[1], "writer") == 0) + status = run_writer(); + else if (strcmp(argv[1], "reader") == 0) + status = run_reader(); + else { + printf("Invalid command line argument \"%s\"\n", argv[1]); + return 1; + } + + struct timespec t1; + timespec_get(&t1, TIME_UTC); + + long long sec = t1.tv_sec - t0.tv_sec; + long long nsec = t1.tv_nsec - t0.tv_nsec; + + printf("%s: done in %.2lf msec\n", argv[1], + (sec * 1000000000 + nsec) * 0.000001); + fflush(stdout); + + return status; +} +#endif |