
--- test/zdtm/Makefile | 2 +- test/zdtm/customization/Makefile | 53 ++++++++ test/zdtm/customization/ipc.c | 202 +++++++++++++++++++++++++++++++ test/zdtm/customization/ipc.desc | 1 + 4 files changed, 257 insertions(+), 1 deletion(-) create mode 100644 test/zdtm/customization/Makefile create mode 100644 test/zdtm/customization/ipc.c create mode 100644 test/zdtm/customization/ipc.desc diff --git a/test/zdtm/Makefile b/test/zdtm/Makefile index 24a33f2..8f9857b 100644 --- a/test/zdtm/Makefile +++ b/test/zdtm/Makefile @@ -1,4 +1,4 @@ -SUBDIRS := lib static transition +SUBDIRS := lib static transition customization all: $(SUBDIRS) .PHONY: all $(SUBDIRS) diff --git a/test/zdtm/customization/Makefile b/test/zdtm/customization/Makefile new file mode 100644 index 0000000..563b7b1 --- /dev/null +++ b/test/zdtm/customization/Makefile @@ -0,0 +1,53 @@ +LIBDIR := ../lib +LIB := $(LIBDIR)/libzdtmtst.a +LDLIBS += $(LIB) +CPPFLAGS += -I$(LIBDIR) + +TST = \ + ipc + +SRC = $(TST:%=%.c) +OBJ = $(SRC:%.c=%.o) +DEP = $(SRC:%.c=%.d) +PID = $(TST:%=%.pid) +OUT = $(TST:%=%.out) + +include ../Makefile.inc + +all: $(TST) +install: all +.PHONY: all install + +$(TST:%=%.pid): %.pid: % + $(<D)/$(<F) --pidfile=$@ --outfile=$<.out + +%.out: %.pid % + -kill -TERM `cat $<` + +start: $(PID) + +%.is_running: %.pid + kill -0 `cat $<` + +check_start: $(PID:%.pid=%.is_running) + +stop: + -kill -TERM `awk '{print}' *.pid` + +WAIT_TIME=10 +wait_stop: + -for i in `seq 1 $(WAIT_TIME)`; do \ + kill -0 `awk '{print}' *.pid 2>/dev/null` 2>/dev/null || break; \ + sleep 1; \ + done + +$(TST): | $(LIB) + +%: %.sh + cp $< $@ + chmod +x $@ + +$(LIB): force + $(Q) $(MAKE) -C $(LIBDIR) + +.PHONY: force start check_start stop wait_stop diff --git a/test/zdtm/customization/ipc.c b/test/zdtm/customization/ipc.c new file mode 100644 index 0000000..2b3c2b1 --- /dev/null +++ b/test/zdtm/customization/ipc.c @@ -0,0 +1,202 @@ +#include <sched.h> + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <sys/sem.h> +#include <sys/ipc.h> +#include <sys/shm.h> +#include <signal.h> +#include <errno.h> + +#include "zdtmtst.h" + +const char *test_doc="Tests ipc sems and shmems migrate fine"; +const char *test_author="Pavel Emelianov <xemul@parallels.com>"; + +static struct sembuf unlock = { + .sem_op = 1, + .sem_num = 0, + .sem_flg = 0, +}; + +static struct sembuf lock = { + .sem_op = -1, + .sem_num = 0, + .sem_flg = 0, +}; + +#define DEF_MEM_SIZE (40960) +unsigned int shmem_size = DEF_MEM_SIZE; +TEST_OPTION(shmem_size, uint, "Size of shared memory segment", 0); + +#define INIT_CRC (~0) + +#define POISON 0xac +static inline void poison_area(int *mem) +{ + memset(mem, POISON, shmem_size); +} + +static int child(key_t key) +{ + int sem, shm, ret, res = 0; + uint8_t *mem; + uint32_t crc; + + sem = semget(key, 1, 0777); + if (sem == -1) + return -1; + shm = shmget(key, shmem_size, 0777); + if (shm == -1) + return -2; + mem = shmat(shm, NULL, 0); + if (mem == (uint8_t *)-1) + return -3; + + while (test_go()) { + ret = semop(sem, &lock, 1); + if (ret) { + if (errno == EINTR) + continue; + fail("Error in semop lock"); + res = errno; + break; + } + crc = INIT_CRC; + datagen(mem, shmem_size, &crc); + while ((ret = semop(sem, &unlock, 1)) && (errno == EINTR)); + if (ret) { + fail("Error in semop unlock"); + res = errno; + break; + } + } + shmdt(mem); + return res; +} + +int main(int argc, char **argv) +{ + key_t key; + int sem, shm, pid1, pid2; + int fail_count = 0; + uint8_t *mem; + uint32_t crc; + int ret; + + test_init(argc, argv); + + /* using the large number to fill string length */ + key = ftok(argv[0], 1822155650); + if (key == -1) { + pr_perror("Can't make key"); + goto out; + } + + sem = semget(key, 1, 0777 | IPC_CREAT | IPC_EXCL); + if (sem == -1) { + pr_perror("Can't get sem"); + goto out; + } + + if (semctl(sem, 0, SETVAL, 1) == -1) { + pr_perror("Can't init sem"); + fail_count++; + goto out_sem; + } + + shm = shmget(key, shmem_size, 0777 | IPC_CREAT | IPC_EXCL); + if (shm == -1) { + pr_perror("Can't get shm"); + fail_count++; + goto out_sem; + } + + mem = shmat(shm, NULL, 0); + if (mem == (void *)-1) { + pr_perror("Can't attach shm"); + fail_count++; + goto out_shm; + } + + poison_area((int *)mem); + + pid1 = test_fork(); + if (pid1 == -1) { + pr_perror("Can't fork 1st time"); + goto out_shdt; + } else if (pid1 == 0) + exit(child(key)); + + pid2 = test_fork(); + if (pid2 == -1) { + pr_perror("Can't fork 2nd time"); + fail_count++; + goto out_child; + } else if (pid2 == 0) + exit(child(key)); + + test_daemon(); + while (test_go()) { + ret = semop(sem, &lock, 1); + if (ret) { + if (errno == EINTR) + continue; + fail_count++; + fail("Error in semop lock"); + break; + } + if (mem[0] != POISON) { + crc = INIT_CRC; + if (datachk(mem, shmem_size, &crc)) { + fail_count++; + fail("Semaphore protection is broken or " + "shmem pages are messed"); + semop(sem, &unlock, 1); + break; + } + poison_area((int *)mem); + } + while ((ret = semop(sem, &unlock, 1)) && (errno == EINTR)); + if (ret) { + fail_count++; + fail("Error in semop unlock"); + break; + } + } + test_waitsig(); + + kill(pid2, SIGTERM); + waitpid(pid2, &ret, 0); + if (!WIFEXITED(ret)) { + fail_count++; + pr_perror("Child 2 was killed"); + } else if (WEXITSTATUS(ret)) { + fail_count++; + pr_perror("Child 2 couldn't inititalise"); + } +out_child: + kill(pid1, SIGTERM); + waitpid(pid1, &ret, 0); + if (!WIFEXITED(ret)) { + fail_count++; + pr_perror("Child 1 was killed"); + } else if (WEXITSTATUS(ret)) { + fail_count++; + pr_perror("Child 1 couldn't inititalise"); + } +out_shdt: + shmdt(mem); +out_shm: + shmctl(shm, IPC_RMID, NULL); +out_sem: + semctl(sem, 1, IPC_RMID); + if (fail_count == 0) + pass(); +out: + return 0; +} diff --git a/test/zdtm/customization/ipc.desc b/test/zdtm/customization/ipc.desc new file mode 100644 index 0000000..63df42a --- /dev/null +++ b/test/zdtm/customization/ipc.desc @@ -0,0 +1 @@ +{'flavor': 'h'} -- 2.27.0