tests: add tests for ipc syscalls decoding

* tests/ipc_msg.c: New file.
* tests/ipc_sem.c: Likewise.
* tests/ipc_shm.c: Likewise.
* tests/ipc_msg.test: New test.
* tests/ipc_sem.test: Likewise.
* tests/ipc_shm.test: Likewise.
* tests/Makefile.am (check_PROGRAMS): Add ipc_msg, ipc_sem, and ipc_shm.
(TESTS): Add ipc_msg.test, ipc_sem.test, and ipc_shm.test.
* tests/.gitignore: Add ipc_msg, ipc_sem, and ipc_shm.
diff --git a/tests/.gitignore b/tests/.gitignore
index ce3e210..3941f6e 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -1,6 +1,9 @@
 caps
 fanotify_mark
 inet-accept-connect-send-recv
+ipc_msg
+ipc_sem
+ipc_shm
 mmsg
 net-accept-connect
 netlink_inet_diag
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 7c8f7b1..e4d3be4 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -4,6 +4,9 @@
 
 check_PROGRAMS = \
 	inet-accept-connect-send-recv \
+	ipc_msg \
+	ipc_shm \
+	ipc_sem \
 	caps \
 	fanotify_mark \
 	mmsg \
@@ -35,6 +38,9 @@
 	caps.test \
 	fanotify_mark.test \
 	getdents.test \
+	ipc_msg.test \
+	ipc_shm.test \
+	ipc_sem.test \
 	scm_rights-fd.test \
 	sigaction.test \
 	stat.test \
diff --git a/tests/ipc_msg.c b/tests/ipc_msg.c
new file mode 100644
index 0000000..4888d3a
--- /dev/null
+++ b/tests/ipc_msg.c
@@ -0,0 +1,31 @@
+#include <stdio.h>
+#include <sys/msg.h>
+
+int
+main(void)
+{
+	int id = msgget(IPC_PRIVATE, 0600);
+	if (id < 0)
+		return 77;
+	printf("msgget\\(IPC_PRIVATE, 0600\\) += %d\n", id);
+
+	int rc = 1;
+
+	struct msqid_ds ds;
+	int max = msgctl(0, MSG_INFO, &ds);
+	if (max < 0)
+		goto fail;
+	printf("msgctl\\(0, MSG_INFO, %p\\) += %d\n", &ds, max);
+
+	if (msgctl(id, MSG_STAT, &ds) != id)
+		goto fail;
+	printf("msgctl\\(%d, MSG_STAT, %p\\) += %d\n", id, &ds, id);
+
+	rc = 0;
+
+fail:
+	if (msgctl(id, IPC_RMID, 0) < 0)
+		return 1;
+	printf("msgctl\\(%d, IPC_RMID, 0\\) += 0\n", id);
+	return rc;
+}
diff --git a/tests/ipc_msg.test b/tests/ipc_msg.test
new file mode 100755
index 0000000..b1ebe6d
--- /dev/null
+++ b/tests/ipc_msg.test
@@ -0,0 +1,28 @@
+#!/bin/sh
+
+# Check decoding of ipc msgget/msgctl syscalls
+
+. "${srcdir=.}/init.sh"
+
+check_prog grep
+
+OUT="$LOG.out"
+
+./ipc_msg > /dev/null || {
+	if [ $? -eq 77 ]; then
+		framework_skip_ 'ipc msgget/msgctl syscalls do not behave as expected'
+	else
+		fail_ 'ipc_msg failed'
+	fi
+}
+
+args="-eipc ./ipc_msg $f"
+$STRACE -o "$LOG" $args > "$OUT" &&
+LC_ALL=C grep -E -x -f "$OUT" "$LOG" > /dev/null || {
+	cat "$OUT" "$LOG"
+	fail_ "$STRACE $args output mismatch"
+}
+
+rm -f "$OUT"
+
+exit 0
diff --git a/tests/ipc_sem.c b/tests/ipc_sem.c
new file mode 100644
index 0000000..78d9682
--- /dev/null
+++ b/tests/ipc_sem.c
@@ -0,0 +1,33 @@
+#include <stdio.h>
+#include <sys/sem.h>
+
+int
+main(void)
+{
+	int id = semget(IPC_PRIVATE, 1, 0600);
+	if (id < 0)
+		return 77;
+	printf("semget\\(IPC_PRIVATE, 1, 0600\\) += %d\n", id);
+
+	int rc = 1;
+
+	struct seminfo info;
+	int max = semctl(0, 0, SEM_INFO, &info);
+	if (max < 0)
+		goto fail;
+	printf("semctl\\(0, 0, SEM_INFO, %p\\) += %d\n", &info, max);
+
+	struct semid_ds ds;
+	if (semctl(id, 0, SEM_STAT, &ds) != id)
+		goto fail;
+	printf("semctl\\(%d, 0, SEM_STAT, %p\\) += %d\n", id, &ds, id);
+
+	rc = 0;
+
+fail:
+	if (semctl(id, 0, IPC_RMID, 0) < 0)
+		return 1;
+	printf("semctl\\(%d, 0, IPC_RMID, 0\\) += 0\n", id);
+
+	return rc;
+}
diff --git a/tests/ipc_sem.test b/tests/ipc_sem.test
new file mode 100755
index 0000000..df9a9bb
--- /dev/null
+++ b/tests/ipc_sem.test
@@ -0,0 +1,28 @@
+#!/bin/sh
+
+# Check decoding of ipc semget/semctl syscalls
+
+. "${srcdir=.}/init.sh"
+
+check_prog grep
+
+OUT="$LOG.out"
+
+./ipc_sem > /dev/null || {
+	if [ $? -eq 77 ]; then
+		framework_skip_ 'ipc semget/semctl syscalls do not behave as expected'
+	else
+		fail_ 'ipc_sem failed'
+	fi
+}
+
+args="-eipc ./ipc_sem $f"
+$STRACE -o "$LOG" $args > "$OUT" &&
+LC_ALL=C grep -E -x -f "$OUT" "$LOG" > /dev/null || {
+	cat "$OUT" "$LOG"
+	fail_ "$STRACE $args output mismatch"
+}
+
+rm -f "$OUT"
+
+exit 0
diff --git a/tests/ipc_shm.c b/tests/ipc_shm.c
new file mode 100644
index 0000000..5b3c9fa
--- /dev/null
+++ b/tests/ipc_shm.c
@@ -0,0 +1,31 @@
+#include <stdio.h>
+#include <sys/shm.h>
+
+int
+main(void)
+{
+	int id = shmget(IPC_PRIVATE, 1, 0600);
+	if (id < 0)
+		return 77;
+	printf("shmget\\(IPC_PRIVATE, 1, 0600\\) += %d\n", id);
+
+	int rc = 1;
+
+	struct shmid_ds ds;
+	int max = shmctl(0, SHM_INFO, &ds);
+	if (max < 0)
+		goto fail;
+	printf("shmctl\\(0, SHM_INFO, %p\\) += %d\n", &ds, max);
+
+	if (shmctl(id, SHM_STAT, &ds) != id)
+		goto fail;
+	printf("shmctl\\(%d, SHM_STAT, %p\\) += %d\n", id, &ds, id);
+
+	rc = 0;
+
+fail:
+	if (shmctl(id, IPC_RMID, 0) < 0)
+		return 1;
+	printf("shmctl\\(%d, IPC_RMID, 0\\) += 0\n", id);
+	return rc;
+}
diff --git a/tests/ipc_shm.test b/tests/ipc_shm.test
new file mode 100755
index 0000000..b09dc2b
--- /dev/null
+++ b/tests/ipc_shm.test
@@ -0,0 +1,28 @@
+#!/bin/sh
+
+# Check decoding of ipc shmget/shmctl syscalls
+
+. "${srcdir=.}/init.sh"
+
+check_prog grep
+
+OUT="$LOG.out"
+
+./ipc_shm > /dev/null || {
+	if [ $? -eq 77 ]; then
+		framework_skip_ 'ipc shmget/shmctl syscalls do not behave as expected'
+	else
+		fail_ 'ipc_shm failed'
+	fi
+}
+
+args="-eipc ./ipc_shm $f"
+$STRACE -o "$LOG" $args > "$OUT" &&
+LC_ALL=C grep -E -x -f "$OUT" "$LOG" > /dev/null || {
+	cat "$OUT" "$LOG"
+	fail_ "$STRACE $args output mismatch"
+}
+
+rm -f "$OUT"
+
+exit 0