widl: MIDL conformance testing framework

Dan Hipschman dsh at linux.ucla.edu
Wed Sep 6 19:38:18 CDT 2006


This adds a conformance test framework, and a few initial tests for widl.
It tests things like whether files do/don't compile, whether the correct
output files get created and the incorrect ones don't, and things at that
level that would be very cumbersome to test using the usual test framework
where all the tests are written in C.  The tests run (and pass) on WinXP
thanks to the MIDL and CL wrapper scripts.  Of course, it assumes Cygwin,
but it's better than having no tests at all.  The initial tests already
uncover some inconsistencies; there are nine "todos."

To run the tests on Linux (presumably any UNIX-like), just run ./widl_test.sh.
To run on Windows, you can do the same thing, but you need to make sure your
environment is set up correctly.  This depends on where things are installed,
but I've included an example batch file that sets it up on my system (where
everything was installed in the default directories).  This is meant only to
be an example, and I hope that in the future we could automatically discover
where things are installed by looking in the registry or something.  Until
then, however, you can with luck just run midl_test.bat from the DOS box, and
maybe tinker with the paths in the batch file if you've installed VC and the
SDK in non-default directories.

It would also be nice to add a Makefile so we could do "make test", but that
is also something that can be done later.  Low-level testing of widl's output
(i.e., the proxy code) is better tested with C, but I'm not trying to test
that here.  This gives us the ability to say, "that should compile," or, "that
shouldn't compile," (Rob should note I added a test for "int f(void x)"), and
back it up with conformance tests.

ChangeLog:
* Add a widl conformance test framework.
---
 tools/widl/tests/cl_wrap.sh    |   44 +++++++++++++++++
 tools/widl/tests/midl_test.bat |   17 +++++++
 tools/widl/tests/midl_wrap.sh  |  101 ++++++++++++++++++++++++++++++++++++++++
 tools/widl/tests/t1.c          |    2 +
 tools/widl/tests/t1.idl        |    1 
 tools/widl/tests/t2.idl        |    1 
 tools/widl/tests/t3.idl        |    5 ++
 tools/widl/tests/t4.idl        |    8 +++
 tools/widl/tests/t5.idl        |    5 ++
 tools/widl/tests/t6.idl        |    5 ++
 tools/widl/tests/test_env.sh   |   95 ++++++++++++++++++++++++++++++++++++++
 tools/widl/tests/widl_test.sh  |   87 ++++++++++++++++++++++++++++++++++
 12 files changed, 371 insertions(+), 0 deletions(-)

diff --git a/tools/widl/tests/cl_wrap.sh b/tools/widl/tests/cl_wrap.sh
new file mode 100755
index 0000000..94422d4
--- /dev/null
+++ b/tools/widl/tests/cl_wrap.sh
@@ -0,0 +1,44 @@
+#! /bin/sh
+
+cmd="cl /D WIN32=1"
+
+while [ -n "$*" ] ; do
+    a="$1"
+    shift
+    case "$a" in
+        -c) c_opt=1
+            cmd="$cmd /c"
+            ;;
+        -D) cmd="$cmd /D '$1'"
+            shift
+            ;;
+        -E) cmd="$cmd /E"
+            ;;
+        -I) cmd="$cmd /I '$1'"
+            shift
+            ;;
+        -o) o_opt=1
+            if [ -n "$c_opt" ]
+            then cmd="$cmd /Fo'$1'"
+            else cmd="$cmd /Fe'$1'"
+            fi
+            shift
+            ;;
+        -U) cmd="$cmd /U '$1'"
+            shift
+            ;;
+        -Werror) cmd="$cmd /WX"
+            ;;
+        *) [ -z "$filename" ] && filename="$a"
+            cmd="$cmd '$a'"
+            ;;
+    esac
+done
+
+eval "$cmd"
+result=$?
+
+base=`basename "$filename" .c`
+[ "$result" -eq 0 ] && [ -z "$c_opt" ] && [ -z "$o_opt" ] && mv "$base".exe a.out.exe
+
+exit $result
diff --git a/tools/widl/tests/midl_test.bat b/tools/widl/tests/midl_test.bat
new file mode 100644
index 0000000..11cdcc4
--- /dev/null
+++ b/tools/widl/tests/midl_test.bat
@@ -0,0 +1,17 @@
+ at rem This file is an example of how to set up your environment
+ at rem to run MIDL tests.  Adjust your paths accordingly.
+
+ at set OLD_PATH=%PATH%
+ at set OLD_INCLUDE=%INCLUDE%
+ at set OLD_LIB=%LIB%
+
+ at call vcvars32.bat
+ at set PATH=/bin;/usr/bin;%PATH%
+ at set INCLUDE=C:\Program Files\Microsoft Platform SDK\Include;%INCLUDE%
+ at set LIB=C:\Program Files\Microsoft Platform SDK\Lib;%LIB%
+
+@\cygwin\bin\bash ./widl_test.sh
+
+ at set PATH=%OLD_PATH%
+ at set INCLUDE=%OLD_INCLUDE%
+ at set LIB=%OLD_LIB%
diff --git a/tools/widl/tests/midl_wrap.sh b/tools/widl/tests/midl_wrap.sh
new file mode 100755
index 0000000..3c9a462
--- /dev/null
+++ b/tools/widl/tests/midl_wrap.sh
@@ -0,0 +1,101 @@
+#! /bin/sh
+
+cmd="midl /Os"
+
+while [ -n "$*" ] ; do
+    a="$1"
+    shift
+    case "$a" in
+        -c) c_opt=1
+            ;;
+        -C) C_arg="$1"
+            cmd="$cmd /cstub '$1'"
+            shift
+            ;;
+        -D) cmd="$cmd /D '$1'"
+            D_args="$D_args /D '$1'"
+            shift
+            ;;
+        -E) E_opt=1
+            ;;
+        -h) h_opt=1
+            ;;
+        -H) H_arg="$1"
+            cmd="$cmd /header '$1'"
+            shift
+            ;;
+        -I) cmd="$cmd /I '$1'"
+            I_args="$I_args /I '$1'"
+            shift
+            ;;
+        -N) cmd="$cmd /no_cpp"
+            ;;
+        --oldnames) cmd="$cmd /oldnames"
+            ;;
+        -p) p_opt=1
+            ;;
+        -P) P_arg="$1"
+            cmd="$cmd /proxy '$1'"
+            shift
+            ;;
+        -s) s_opt=1
+            ;;
+        -S) S_arg="$1"
+            cmd="$cmd /sstub '$1'"
+            shift
+            ;;
+        -t) t_opt=1
+            ;;
+        -T) T_arg="$1"
+            cmd="$cmd /tlb '$1'"
+            shift
+            ;;
+        -u) u_opt=1
+            ;;
+        -U) U_arg="$1"
+            cmd="$cmd /iid '$1'"
+            shift
+            ;;
+        -V) midl 2>&1 | head -n 1
+            exit 0
+            ;;
+        -W) cmd="$cmd /W4"
+            ;;
+        *) filename="$a"
+            ;;
+    esac
+done
+
+cleanup=1
+[ -z "$c_opt" ] && [ -z "$h_opt" ] && [ -z "$p_opt" ] && \
+[ -z "$s_opt" ] && [ -z "$t_opt" ] && [ -z "$u_opt" ] && \
+    cleanup=0
+
+cmd="$cmd '$filename'"
+
+if [ -n "$E_opt" ] ; then
+    eval cl /E "$D_args" "$I_args"
+    result=$?
+else
+    eval "$cmd"
+    result=$?
+fi
+
+base=`basename "$filename" .idl`
+[ -z "$C_arg" ] && C_arg="$base"_c.c
+[ -z "$H_arg" ] && H_arg="$base".h
+[ -z "$P_arg" ] && P_arg="$base"_p.c
+[ -z "$S_arg" ] && S_arg="$base"_s.c
+[ -z "$T_arg" ] && T_arg="$base".tlb
+[ -z "$U_arg" ] && U_arg="$base"_i.c
+
+if [ "$cleanup" -eq 1 ] ; then
+    [ -z "$c_opt" ] && rm -f "$C_arg"
+    [ -z "$h_opt" ] && rm -f "$H_arg"
+    [ -z "$p_opt" ] && rm -f "$P_arg"
+    [ -z "$s_opt" ] && rm -f "$S_arg"
+    [ -z "$t_opt" ] && rm -f "$T_arg"
+    [ -z "$u_opt" ] && rm -f "$U_arg"
+fi
+
+exit $result
diff --git a/tools/widl/tests/t1.c b/tools/widl/tests/t1.c
new file mode 100644
index 0000000..f898c30
--- /dev/null
+++ b/tools/widl/tests/t1.c
@@ -0,0 +1,2 @@
+#include "t1.h"
+i_t main(void) { return 0; }
diff --git a/tools/widl/tests/t1.idl b/tools/widl/tests/t1.idl
new file mode 100644
index 0000000..8dd9962
--- /dev/null
+++ b/tools/widl/tests/t1.idl
@@ -0,0 +1 @@
+typedef int i_t;
diff --git a/tools/widl/tests/t2.idl b/tools/widl/tests/t2.idl
new file mode 100644
index 0000000..c1fb837
--- /dev/null
+++ b/tools/widl/tests/t2.idl
@@ -0,0 +1 @@
+typedef int i_t
diff --git a/tools/widl/tests/t3.idl b/tools/widl/tests/t3.idl
new file mode 100644
index 0000000..497b9e1
--- /dev/null
+++ b/tools/widl/tests/t3.idl
@@ -0,0 +1,5 @@
+[ uuid(deadbeef-0000-0000-0000-000000000000) ]
+interface IT3
+{
+  int f(int x);
+}
diff --git a/tools/widl/tests/t4.idl b/tools/widl/tests/t4.idl
new file mode 100644
index 0000000..f54090a
--- /dev/null
+++ b/tools/widl/tests/t4.idl
@@ -0,0 +1,8 @@
+
+import "oaidl.idl";
+
+[ uuid(deadbeef-0000-0000-0000-000000000000), object ]
+interface IT4 : IUnknown
+{
+  HRESULT f(int x);
+}
diff --git a/tools/widl/tests/t5.idl b/tools/widl/tests/t5.idl
new file mode 100644
index 0000000..8dc2c67
--- /dev/null
+++ b/tools/widl/tests/t5.idl
@@ -0,0 +1,5 @@
+[ uuid(deadbeef-0000-0000-0000-000000000000) ]
+library LibT5
+{
+  typedef int i_t;
+}
diff --git a/tools/widl/tests/t6.idl b/tools/widl/tests/t6.idl
new file mode 100644
index 0000000..9d813bf
--- /dev/null
+++ b/tools/widl/tests/t6.idl
@@ -0,0 +1,5 @@
+[ uuid(deadbeef-0000-0000-0000-000000000000) ]
+interface IT6
+{
+  int f(void x);
+}
diff --git a/tools/widl/tests/test_env.sh b/tools/widl/tests/test_env.sh
new file mode 100644
index 0000000..918468c
--- /dev/null
+++ b/tools/widl/tests/test_env.sh
@@ -0,0 +1,95 @@
+#! /bin/sh
+
+wintest=
+uname | fgrep -i cygwin >/dev/null && wintest=1
+
+if [ -z "$wintest" ] ; then
+    widl="../widl -I ../../../include"
+    cc="gcc -I ../../../include"
+    o=.o
+    x=
+else
+    widl="./midl_wrap.sh"
+    cc="./cl_wrap.sh"
+    o=.obj
+    x=.exe
+fi
+
+numrun=0
+errcnt=0
+todone=0
+intodo=
+
+error() {
+    echo Error: "$@" >&2
+    errcnt=`expr $errcnt + 1`
+}
+
+runtest() {
+    cmp="$1"
+    msg="$2"
+    shift ; shift
+
+    numrun=`expr $numrun + 1`
+
+    "$@" >/dev/null 2>&1
+    retval=$?
+
+    if [ -n "$intodo" ] && [ -z "$wintest" ] ; then
+        if [ $retval $cmp 0 ] ; then
+            error "todo succeeded: $msg"
+        else
+            todone=`expr $todone + 1`
+        fi
+    else
+        [ $retval $cmp 0 ] || error "$msg"
+    fi
+
+    return $retval
+}
+
+ok() {
+    runtest -eq "$@"
+}
+
+fail() {
+    runtest -ne "$@"
+}
+
+todo_begin() {
+    intodo=1
+}
+
+todo_end() {
+    intodo=
+}
+
+todo() {
+    todo_begin
+    "$@"
+    todo_end
+}
+
+finish() {
+    passed=`expr $numrun - $errcnt - $todone`
+    echo "$passed passed"
+    echo "$errcnt failed"
+    echo "$todone todo"
+
+    if [ -n "$wintest" ] && [ "$errcnt" -ne 0 ] ; then
+        echo
+        echo "Tests should not fail on Windows.  Please make sure your environment"
+        echo "is set up correctly.  You may have to run 'vcvars32.bat' before starting"
+        echo "Cygwin and add the PSDK include and lib directories to the INCLUDE"
+        echo "and LIB environment variables, respectively.  See for example midl_test.bat."
+    fi
+
+    [ "$errcnt" -ne 0 ] && exit 1
+    exit 0
+}
+
+rm_out() {
+    for p ; do
+        rm -f "$p".h "$p".tlb "$p"_i.c "$p"_c.c "$p"_s.c "$p"_p.c
+    done
+}
diff --git a/tools/widl/tests/widl_test.sh b/tools/widl/tests/widl_test.sh
new file mode 100755
index 0000000..0a4896c
--- /dev/null
+++ b/tools/widl/tests/widl_test.sh
@@ -0,0 +1,87 @@
+#! /bin/sh
+
+. test_env.sh
+
+rm_out t1
+ok "t1.idl should compile" $widl t1.idl
+ok "t1.h should exist" [ -f t1.h ]
+fail "t1.tlb should not exist" [ -f t1.tlb ]
+todo fail "t1_i.c should not exist" [ -f t1_i.c ]
+fail "t1_c.c should not exist" [ -f t1_c.c ]
+fail "t1_s.c should not exist" [ -f t1_s.c ]
+fail "t1_p.c should not exist" [ -f t1_p.c ]
+ok "t1.c should compile" $cc t1.c -Werror -o t1$x
+rm -f t1$o t1$x
+rm_out t1
+ok "t1.idl should compile" $widl -H t1_test.h t1.idl
+ok "t1_test.h should exist" [ -f t1_test.h ]
+fail "t1.h should not exist" [ -f t1.h ]
+rm -f t1_test.h
+rm_out t1
+
+rm_out t2
+fail "t2.idl should not compile" $widl t2.idl
+fail "t2.h should not exist" [ -f t2.h ]
+todo fail "t2_i.c should not exist" [ -f t2_i.c ]
+rm_out t2
+
+rm_out t3
+ok "t3.idl should compile" $widl t3.idl
+ok "t3.h should exist" [ -f t3.h ]
+fail "t3.tlb should not exist" [ -f t3.tlb ]
+todo fail "t3_i.c should not exist" [ -f t3_i.c ]
+ok "t3_c.c should exist" [ -f t3_c.c ]
+ok "t3_s.c should exist" [ -f t3_s.c ]
+todo fail "t3_p.c should not exist" [ -f t3_p.c ]
+ok "t3_c.c and t3_s.c should compile" $cc -c t3_c.c t3_s.c -Werror
+rm -f t3_c$o t3_s$o
+rm_out t3
+ok "t3.idl should compile" $widl -c t3.idl
+ok "t3_c.c should exist" [ -f t3_c.c ]
+fail "t3_s.c should not exist" [ -f t3_s.c ]
+rm_out t3
+ok "t3.idl should compile" $widl -c -C t3_test.c t3.idl
+ok "t3_test.c should exist" [ -f t3_test.c ]
+fail "t3_c.c should not exist" [ -f t3_c.c ]
+rm -f t3_test.c
+rm_out t3
+ok "t3.idl should compile" $widl -H t3_test.h t3.idl
+ok "t3_test.h should exist" [ -f t3_test.h ]
+fail "t3.h should not exist" [ -f t3.h ]
+ok "t3_c.c should exist" [ -f t3_c.c ]
+ok "t3_s.c should exist" [ -f t3_s.c ]
+ok "t3_c.c and t3_s.c should include t3_test.h" $cc -c t3_c.c t3_s.c -Werror
+rm -f t3_test.h t3_c$o t3_s$o
+rm_out t3
+
+rm_out t4
+ok "t4.idl should compile" $widl t4.idl
+ok "t4.h should exist" [ -f t4.h ]
+ok "t4_p.c should exist" [ -f t4_p.c ]
+ok "t4_i.c should exist" [ -f t4_i.c ]
+todo fail "t4_c.c should not exist" [ -f t4_c.c ]
+todo fail "t4_s.c should not exist" [ -f t4_s.c ]
+fail "t4.tlb should not exist" [ -f t4.tlb ]
+ok "t4_p.c should compile" $cc -c t4_p.c -Werror
+rm -f t4_p$o
+rm_out t4
+
+rm_out t5
+ok "t5.idl should compile" $widl t5.idl
+todo fail "t5.h should not exist" [ -f t5.h ]
+todo fail "t5_i.c should not exist" [ -f t5_i.c ]
+fail "t5_p.c should not exist" [ -f t5_p.c ]
+fail "t5_c.c should not exist" [ -f t5_c.c ]
+fail "t5_s.c should not exist" [ -f t5_s.c ]
+ok "t5.tlb should exist" [ -f t5.tlb ]
+rm_out t5
+
+rm_out t6
+fail "t6.idl should not compile" $widl t6.idl
+fail "t6.h should not exist" [ -f t6.h ]
+todo fail "t6_i.c should not exist" [ -f t6_i.c ]
+fail "t6_c.c should not exist" [ -f t6_c.c ]
+fail "t6_s.c should not exist" [ -f t6_s.c ]
+rm_out t6
+
+finish



More information about the wine-patches mailing list