Skip to content

Commit 9344fea

Browse files
committed
vclient: Add tests for C API thunks.
1 parent d8f1c49 commit 9344fea

9 files changed

+45862
-0
lines changed

build_proton.sh

+35
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,23 @@ function build_vrclient64
384384
cp -a vrclient_x64.dll.fake "$DST_DIR"/lib64/wine/fakedlls/vrclient_x64.dll
385385
}
386386

387+
function build_vrclient64_tests
388+
{
389+
build_vrclient64
390+
391+
cp -a vrclient_x64/flatapi.c tests/
392+
$AMD64_WRAPPER "$TOP"/wine/tools/winemaker/winemaker \
393+
--nosource-fix --nolower-include --nodlls --nomsvcrt \
394+
-I"$TOOLS_DIR64"/include/ \
395+
-I"$TOOLS_DIR64"/include/wine/ \
396+
-I"$TOOLS_DIR64"/include/wine/windows/ \
397+
-I../vrclient_x64/ \
398+
-L"$TOOLS_DIR64"/lib64/ \
399+
-L"$TOOLS_DIR64"/lib64/wine/ \
400+
tests
401+
CXXFLAGS="-Wno-attributes -std=c++0x -O2 -g" CFLAGS="-O2 -g" PATH="$TOOLS_DIR64/bin:$PATH" $AMD64_WRAPPER make $JOBS -C tests
402+
}
403+
387404
function build_vrclient32
388405
{
389406
cd "$TOP"
@@ -410,6 +427,23 @@ function build_vrclient32
410427
cp -a vrclient.dll.fake "$DST_DIR"/lib/wine/fakedlls/vrclient.dll
411428
}
412429

430+
function build_vrclient32_tests
431+
{
432+
build_vrclient32
433+
434+
cp -a vrclient/flatapi.c tests/
435+
$I386_WRAPPER "$TOP"/wine/tools/winemaker/winemaker \
436+
--nosource-fix --nolower-include --nodlls --nomsvcrt \
437+
-I"$TOOLS_DIR32"/include/ \
438+
-I"$TOOLS_DIR32"/include/wine/ \
439+
-I"$TOOLS_DIR32"/include/wine/windows/ \
440+
-I../vrclient/ \
441+
-L"$TOOLS_DIR32"/lib/ \
442+
-L"$TOOLS_DIR32"/lib/wine/ \
443+
tests
444+
CXXFLAGS="-Wno-attributes -std=c++0x -O2 -g" CFLAGS="-O2 -g" PATH="$TOOLS_DIR32/bin:$PATH" $I386_WRAPPER make $JOBS -C tests
445+
}
446+
413447
function build_dxvk
414448
{
415449
#unfortunately the Steam chroots are too old to build DXVK, so we have to
@@ -596,6 +630,7 @@ case "$BUILD_COMPONENTS" in
596630
"lsteamclient") build_lsteamclient32; build_lsteamclient64 ;;
597631
"lsteamclient32") build_lsteamclient32 ;;
598632
"lsteamclient64") build_lsteamclient64 ;;
633+
"vrclient_tests") build_vrclient32_tests; build_vrclient64_tests ;;
599634
*) echo "Invalid build components: $BUILD_COMPONENTS" ;;
600635
esac
601636

vrclient_x64/gen.sh

+3
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,7 @@ rm vrclient_x64/cpp*.h
88
rm vrclient_x64/struct*.h
99
rm vrclient_x64/struct*.cpp
1010

11+
rm tests/*_autogen.c
12+
rm tests/*_autogen.h
13+
1114
./gen_wrapper.py

vrclient_x64/gen_wrapper.py

+190
Original file line numberDiff line numberDiff line change
@@ -553,6 +553,8 @@ def handle_class(sdkver, classnode):
553553
for alias in aliases[iface_version]:
554554
constructors.write(" {\"%s\", &create_%s}, /* alias */\n" % (alias, winclassname))
555555

556+
generate_c_api_thunk_tests(winclassname, methods, method_names)
557+
556558

557559
generated_struct_handlers = []
558560
cpp_files_need_close_brace = []
@@ -757,6 +759,190 @@ def generate_flatapi_c():
757759

758760
f.write("#endif\n")
759761

762+
def generate_c_api_method_test(f, header, thunks_c, class_name, method_name, method):
763+
thunk_params = get_capi_thunk_params(method)
764+
f.write("\n init_thunk(t, this_ptr_value, %s_%s, %s);\n" % (class_name, method_name, thunk_params))
765+
f.write(" ")
766+
header.write("\n")
767+
thunks_c.write("\n")
768+
769+
returns_record = method.result_type.get_canonical().kind == clang.cindex.TypeKind.RECORD
770+
if returns_record:
771+
f.write("%s *" % strip_ns(method.result_type.spelling))
772+
header.write("%s *" % strip_ns(method.result_type.spelling))
773+
thunks_c.write("%s *" % strip_ns(method.result_type.spelling))
774+
else:
775+
f.write("%s " % strip_ns(method.result_type.spelling))
776+
header.write("%s " % strip_ns(method.result_type.spelling))
777+
thunks_c.write("%s " % strip_ns(method.result_type.spelling))
778+
first_param = True
779+
f.write('(__stdcall *capi_%s_%s)(' % (class_name, method_name))
780+
header.write('__thiscall %s_%s(void *_this' % (class_name, method_name))
781+
thunks_c.write('__thiscall %s_%s(void *_this' % (class_name, method_name))
782+
if returns_record:
783+
f.write("%s *_r" % strip_ns(method.result_type.spelling))
784+
first_param = False
785+
header.write(", %s *_r" % strip_ns(method.result_type.spelling))
786+
thunks_c.write(", %s *_r" % strip_ns(method.result_type.spelling))
787+
788+
for param in get_params(method):
789+
if param.type.kind == clang.cindex.TypeKind.POINTER \
790+
and param.type.get_pointee().kind == clang.cindex.TypeKind.UNEXPOSED:
791+
typename = "void *"
792+
else:
793+
typename = param.type.spelling.split("::")[-1].replace("&", "*");
794+
if not first_param:
795+
f.write(", ")
796+
first_param = False
797+
f.write("%s %s" % (typename, param.spelling))
798+
header.write(", %s %s" % (typename, param.spelling))
799+
thunks_c.write(", %s %s" % (typename, param.spelling))
800+
f.write(") = (void *)t;\n")
801+
header.write(");\n")
802+
thunks_c.write(")\n{\n")
803+
804+
thunks_c.write(" push_ptr_parameter(_this);\n")
805+
if returns_record:
806+
thunks_c.write(" push_ptr_parameter(_r);\n")
807+
for param in get_params(method):
808+
param_size = param.type.get_size()
809+
if param.type.kind == clang.cindex.TypeKind.POINTER \
810+
or param.type.spelling.endswith("&") \
811+
or param.type.spelling == "vr::glSharedTextureHandle_t":
812+
typename = "ptr"
813+
elif param.type.spelling == "bool":
814+
typename = "bool"
815+
elif param.type.spelling == "float":
816+
typename = "float"
817+
elif param.type.spelling == "vr::HmdRect2_t":
818+
typename = "HmdRect2"
819+
elif param.type.spelling == "vr::HmdVector2_t":
820+
typename = "HmdVector2"
821+
elif param.type.spelling == "vr::HmdVector3_t":
822+
typename = "HmdVector3"
823+
elif param.type.spelling == "vr::HmdColor_t":
824+
typename = "HmdColor"
825+
elif param_size == 8:
826+
typename = "uint64"
827+
elif param_size == 4 or param_size == 2:
828+
typename = "uint32"
829+
else:
830+
typename = "unknown"
831+
thunks_c.write(" push_%s_parameter(%s);\n" % (typename, param.spelling))
832+
if method.result_type.kind != clang.cindex.TypeKind.VOID:
833+
thunks_c.write(" return 0;\n")
834+
thunks_c.write("}\n")
835+
836+
parameter_checks = []
837+
def add_parameter_check(typename, value):
838+
parameter_checks.append("check_%s_parameter(\"%s_%s\", %s)" % (typename, class_name, method_name, value))
839+
add_parameter_check("ptr", "this_ptr_value")
840+
f.write("\n")
841+
f.write(" clear_parameters();\n")
842+
f.write(" capi_%s_%s(" % (class_name, method_name))
843+
first_param = True
844+
if returns_record:
845+
f.write("data_ptr_value")
846+
first_param = False
847+
add_parameter_check("ptr", "data_ptr_value")
848+
for i, param in enumerate(get_params(method)):
849+
i += 1
850+
param_size = param.type.get_size()
851+
if param.type.kind == clang.cindex.TypeKind.POINTER \
852+
or param.type.spelling.endswith("&") \
853+
or param.type.spelling == "vr::glSharedTextureHandle_t":
854+
v = "(void *)%s" % i
855+
add_parameter_check("ptr", v)
856+
elif param.type.spelling == "bool":
857+
v = "1"
858+
add_parameter_check("bool", v)
859+
elif param.type.spelling == "float":
860+
v = "%s.0f" % i
861+
add_parameter_check("float", v)
862+
elif param.type.spelling == "vr::HmdRect2_t":
863+
v = "DEFAULT_RECT";
864+
add_parameter_check("HmdRect2", v)
865+
elif param.type.spelling == "vr::HmdVector2_t":
866+
v = "DEFAULT_VECTOR2";
867+
add_parameter_check("HmdVector2", v)
868+
elif param.type.spelling == "vr::HmdVector3_t":
869+
v = "DEFAULT_VECTOR3";
870+
add_parameter_check("HmdVector3", v)
871+
elif param.type.spelling == "vr::HmdColor_t":
872+
v = "DEFAULT_COLOR";
873+
add_parameter_check("HmdColor", v)
874+
elif param_size == 8:
875+
v = str(i)
876+
add_parameter_check("uint64", v)
877+
elif param_size == 4 or param_size == 2:
878+
v = str(i)
879+
add_parameter_check("uint32", v)
880+
if not first_param:
881+
f.write(", ")
882+
first_param = False
883+
f.write(v)
884+
f.write(");\n")
885+
for c in parameter_checks:
886+
f.write(" %s;\n" % c)
887+
888+
def generate_c_api_thunk_tests(winclassname, methods, method_names):
889+
class_name = re.sub(r'^win[A-Za-z]+_', '', winclassname)
890+
891+
filename = "tests/capi_thunks_autogen.h"
892+
file_exists = os.path.isfile(filename)
893+
header = open(filename, "a")
894+
if not file_exists:
895+
header.write("""/* This file is auto-generated, do not edit. */
896+
#include <stdarg.h>
897+
#include <stdint.h>
898+
899+
#include "windef.h"
900+
#include "winbase.h"
901+
902+
#include "cxx.h"
903+
#include "flatapi.h"
904+
#include "vrclient_defs.h"
905+
906+
#include "capi_thunks.h"
907+
""")
908+
header.write("\nvoid test_capi_thunks_%s(void);\n" % class_name)
909+
910+
filename = "tests/capi_thunks_autogen.c"
911+
file_exists = os.path.isfile(filename)
912+
thunks_c = open(filename, "a")
913+
if not file_exists:
914+
thunks_c.write("""/* This file is auto-generated, do not edit. */
915+
#include "capi_thunks_autogen.h"
916+
""")
917+
918+
filename = "tests/capi_thunks_tests_autogen.c"
919+
file_exists = os.path.isfile(filename)
920+
with open(filename, "a") as f:
921+
if not file_exists:
922+
f.write("""/* This file is auto-generated, do not edit. */
923+
#include "capi_thunks_autogen.h"
924+
""")
925+
f.write("\nvoid test_capi_thunks_%s(void)\n{\n" % class_name)
926+
f.write(" struct thunk *t = alloc_thunks(1);\n");
927+
for i in range(len(methods)):
928+
generate_c_api_method_test(f, header, thunks_c, class_name, method_names[i], methods[i])
929+
f.write(" VirtualFree(t, 0, MEM_RELEASE);\n")
930+
f.write("}\n")
931+
932+
filename = "tests/main_autogen.c"
933+
file_exists = os.path.isfile(filename)
934+
with open(filename, "a") as f:
935+
if not file_exists:
936+
f.write("""/* This file is auto-generated, do not edit. */
937+
#include "capi_thunks_autogen.h"
938+
939+
#include <stdio.h>
940+
941+
int main(void)
942+
{
943+
""")
944+
f.write(" test_capi_thunks_%s();\n" % class_name)
945+
760946

761947
#clang.cindex.Config.set_library_file("/usr/lib/llvm-3.8/lib/libclang-3.8.so.1");
762948

@@ -806,4 +992,8 @@ def generate_flatapi_c():
806992
m = open(f, "a")
807993
m.write("\n}\n")
808994

995+
with open("tests/main_autogen.c", "a") as f:
996+
f.write(" printf(\"All tests executed.\\n\");\n")
997+
f.write("}\n")
998+
809999
generate_flatapi_c()

0 commit comments

Comments
 (0)