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 ------------------------------------------------------------------------------ HPCC Systems Open Source Big Data Platform from LexisNexis Risk Solutions Find What Matters Most in Your Big Data with HPCC Systems Open Source. Fast. Scalable. Simple. Ideal for Dirty Data. Leverages Graph Analysis for Fast Processing & Easy Data Exploration http://p.sf.net/sfu/hpccsystems _______________________________________________ Strace-devel mailing list Strace-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/strace-devel