[GSOC 2014][PATCH 4/4] JSON: Add basic test for JSON output

Zhu YangMin zym0017d at gmail.com
Wed Jun 18 16:29:50 UTC 2014


We will do 3 compare to check the output:
1) Compare the Unmodified strace output to the Normal outputs;
2) Compare the JSON parsed results to the Normal outputs(ignore space);
3) Compare the JSON parsed results to the Unmodified strace outputs(ignore space);

The 1st comparison should be identical to make sure we didn't break
the output content of strace.

The 2nd,3rd comparison may be different which remind us our implementation
need to be checked to see why we got this different.

Note: All the comparison may be different in some cases that the traced
results are random depending the runtime.

* test/json_io.c: New file. Test for syscalls in io.c .
* test/Makefile: Add json_io.c .
* test/.gitignore: Add json_io.
* test/json_parse.py: New file. Translate the JSON output to Normal
format using Python's json module.
* test/json_test.sh: New file. Generate the trace results, translate the
JSON output using json_parse.py and then make the comparison using diff.
---
 test/.gitignore    |   1 +
 test/Makefile      |   2 +-
 test/json_io.c     | 151 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 test/json_parse.py |  33 ++++++++++++
 test/json_test.sh  |  48 +++++++++++++++++
 5 files changed, 234 insertions(+), 1 deletion(-)
 create mode 100644 test/json_io.c
 create mode 100755 test/json_parse.py
 create mode 100755 test/json_test.sh

diff --git a/test/.gitignore b/test/.gitignore
index c73b64a..f488409 100644
--- a/test/.gitignore
+++ b/test/.gitignore
@@ -1,3 +1,4 @@
+json_io
 vfork
 fork
 sig
diff --git a/test/Makefile b/test/Makefile
index cc7d47a..d19b187 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -3,7 +3,7 @@ CFLAGS += -Wall
 PROGS = \
     vfork fork sig skodic clone leaderkill childthread \
     sigkill_rain wait_must_be_interruptible threaded_execve \
-    mtd ubi select sigreturn
+    mtd ubi select sigreturn json_io
 
 all: $(PROGS)
 
diff --git a/test/json_io.c b/test/json_io.c
new file mode 100644
index 0000000..fded8a0
--- /dev/null
+++ b/test/json_io.c
@@ -0,0 +1,151 @@
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/uio.h>
+#include <sys/sendfile.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <limits.h>
+#define BUFSIZE (1000)
+
+static int fd_to = 0, fd_from = 0;
+
+static int prepare_fd(char* my_name)
+{
+	fd_to = fileno( tmpfile() );
+	fd_from = fileno( tmpfile() );
+
+	if (fd_to < 0 || fd_from < 0)
+		return -1;
+
+	int tmpfd = open(my_name, O_RDONLY);
+	int n = sendfile(fd_from, tmpfd, NULL, 5432);
+	close(tmpfd);
+
+	return n<=0 ? -1 : 0;
+}
+
+static void do_some_rw(void)
+{
+	int n;
+    char buf[BUFSIZE];
+
+    while ((n = read(fd_from, buf, BUFSIZE))) {
+		if (n == -1)
+			break;
+		write(fd_to, buf, n);
+    }
+	return;
+}
+
+void do_some_rwv(void)
+{
+	int i;
+	struct iovec vbuf[5];
+	for (i=0; i<5; i++) {
+		vbuf[i].iov_base = malloc(101+i);
+		vbuf[i].iov_len = 101+i;
+	}
+
+	int n;
+    while ((n = readv(fd_from, vbuf, 5))) {
+        if (n == -1) {
+            fprintf(stderr, "failed to readv()\n");
+            return;
+        }
+        n = writev(fd_to, vbuf, 5);
+        if (n == -1) {
+            fprintf(stderr, "failed to writev()\n");
+            return;
+        }
+    }
+
+    return;
+}
+
+void do_some_prw(void)
+{
+	int n = 0;
+	int rn = 0;
+	int wn = 0;
+	char buf[BUFSIZE];
+    while ((n = pread(fd_from, buf, BUFSIZE, rn))) {
+		if (n == -1)
+			break;
+		rn += n;
+		wn += pwrite(fd_to, buf, n, wn);
+    }
+	return;
+}
+
+void do_some_prwv(void)
+{
+	int i;
+#define IOVEC_CNT (5)
+	struct iovec vbuf[IOVEC_CNT];
+	for (i=0; i<IOVEC_CNT; i++) {
+		vbuf[i].iov_base = malloc(101+i);
+		vbuf[i].iov_len = 101+i;
+	}
+
+	int n = 0;
+	int rn = 0;
+	int wn = 0;
+    while ((n = preadv(fd_from, vbuf, IOVEC_CNT, rn))) {
+        if (n == -1) {
+            fprintf(stderr, "failed to preadv()\n");
+            return;
+        }
+		for (i=0; i<IOVEC_CNT; i++)
+			rn += vbuf[i].iov_len;
+
+        n = pwritev(fd_to, vbuf, IOVEC_CNT, wn);
+        if (n == -1) {
+            fprintf(stderr, "failed to pwritev()\n");
+            return;
+        }
+		for (i=0; i<IOVEC_CNT; i++)
+			wn += vbuf[i].iov_len;
+    }
+
+    return;
+}
+
+void do_sendfile(void)
+{
+	int n = 0;
+	off_t off = 0;
+	size_t cnt = 1000;
+	while ((n = sendfile(fd_to, fd_from, &off, cnt))) {
+		if (n < 0) {
+            fprintf(stderr, "sendfile() returned <0\n");
+            return;
+		}
+	}
+
+	return;
+}
+
+void do_tee(void)
+{
+	tee(fd_from, fd_to, 2345, SPLICE_F_MORE | SPLICE_F_MOVE | SPLICE_F_GIFT);
+	tee(fd_from, fd_to, 2345, SPLICE_F_NONBLOCK | SPLICE_F_MOVE);
+	tee(STDIN_FILENO, STDOUT_FILENO, 99999, SPLICE_F_NONBLOCK);
+	return;
+}
+
+int main(int argc, char *argv[])
+{
+	prepare_fd(argv[0]);
+
+	do_some_rw();
+	do_some_rwv();
+	do_some_prw();
+	do_some_prwv();
+	do_sendfile();
+	do_tee();
+
+    return 0;
+}
\ No newline at end of file
diff --git a/test/json_parse.py b/test/json_parse.py
new file mode 100755
index 0000000..a1affa5
--- /dev/null
+++ b/test/json_parse.py
@@ -0,0 +1,33 @@
+#!/usr/bin/python
+import json
+from sys import argv
+from sys import stdout
+from sys import stderr
+
+def main(infile):
+	with open(infile) as f:
+		for i, line in enumerate(f):
+			try:
+				entry = json.loads(line)
+			except ValueError as e:
+				stderr.write("<Error> JSON format invalid!\n")
+				stderr.write("  File:" + infile + ", line:" + str(i+1) + "\n")
+				stderr.write("  " + line + "\n")
+				raise ValueError
+
+			if (entry["type"] == "syscall"):
+				stdout.write(entry["name"])
+				stdout.write("(" + ", ".join(entry["args"]) + ")")
+				stdout.write(" = " + entry["ret"])
+				if ("desc" in entry):
+					stdout.write(" " + entry["desc"])
+				if ("desc_long" in entry):
+					stdout.write(" (" + entry["desc_long"] + ")")
+				if ("auxstr" in entry):
+					stdout.write(" (" + entry["auxstr"] + ")")
+				stdout.write("\n")
+			elif (entry["type"] == "+++"):
+				print "+++ " + entry["desc"] + " with " + entry["sigcode"] + " +++"
+
+if __name__ == "__main__":
+	main(argv[1])
diff --git a/test/json_test.sh b/test/json_test.sh
new file mode 100755
index 0000000..991f473
--- /dev/null
+++ b/test/json_test.sh
@@ -0,0 +1,48 @@
+#!/bin/bash
+set -u
+
+Unmodified_Strace="strace"
+Normal_Strace="../strace"
+JSON_Strace="../strace -j"
+
+TEMPDIR=${TEMPDIR:-"./temp_results"}
+SYSCALLS=${SYSCALLS:-""}
+FLAGS=${FLAGS:-""}
+TARGETS=${TARGETS:-""}
+
+JSON_PARSER="./json_parse.py"
+
+mkdir -p $TEMPDIR
+
+function start_test() {
+	for i in $TARGETS; do
+		echo "--- --- --- ---"
+		echo "generating trace results for $i"
+		$Unmodified_Strace -o "$TEMPDIR/Unmodified_Strace.out.$i" $SYSCALLS $FLAGS ./$i
+		$Normal_Strace -o "$TEMPDIR/Normal_Strace.out.$i" $SYSCALLS $FLAGS ./$i
+		$JSON_Strace -o "$TEMPDIR/JSON_Strace.out.$i" $SYSCALLS $FLAGS ./$i
+		$JSON_PARSER "$TEMPDIR/JSON_Strace.out.$i" > "$TEMPDIR/JSON_Strace.parsed.$i"
+
+		echo "> comparing Unmodified and Normal results:"
+		diff -q -s "$TEMPDIR/Unmodified_Strace.out.$i" "$TEMPDIR/Normal_Strace.out.$i"
+		echo -e "\n> comparing Unmodified and Parsed results(ignore all white space):"
+		diff -w -q -s "$TEMPDIR/Unmodified_Strace.out.$i" "$TEMPDIR/JSON_Strace.parsed.$i"
+		echo -e "\n> comparing Normal and Parsed results(ignore all white space):"
+		diff -w -q -s "$TEMPDIR/Normal_Strace.out.$i" "$TEMPDIR/JSON_Strace.parsed.$i"
+		echo -e "--- --- --- ---\n"
+	done
+}
+
+# test for io-related syscall
+IO_SYSCALL="-e read,write,readv,writev,pread,pwrite,preadv,pwritev,sendfile,sendfile64,tee,splice,vmsplice,ioctl"
+SYSCALLS=$IO_SYSCALL
+TARGETS="json_io mtd ubi select"
+start_test
+
+# test for fork-related syscall
+FLAGS="-ff"
+TARGETS="vfork fork clone childthread threaded_execve"
+
+# test for other syscall
+FLAGS=""
+TARGETS="sig skodic clone leaderkill childthread sigkill_rain wait_must_be_interruptible sigreturn"
-- 
1.9.1





More information about the Strace-devel mailing list