Bug 564966 - ctypes stdcall tests borked on windows. Part 1: fix stdcall tests, and comment out failing closure test. r=benjamn
authorDan Witte <dwitte@mozilla.com>
Fri, 18 Jun 2010 10:30:44 -0700
changeset 47469 1d641507f763851a5a97acecd931876de233ad51
parent 47468 562ea92fd89a13a05a2ff21c86beb2d6eb72d9bb
child 47470 26b1820f6a8e7ebc90e10fc2a4fbdac85f8cdc7f
push idunknown
push userunknown
push dateunknown
reviewersbenjamn
bugs564966
milestone1.9.3a5pre
Bug 564966 - ctypes stdcall tests borked on windows. Part 1: fix stdcall tests, and comment out failing closure test. r=benjamn
toolkit/components/ctypes/tests/jsctypes-test.cpp
toolkit/components/ctypes/tests/unit/test_jsctypes.js.in
--- a/toolkit/components/ctypes/tests/jsctypes-test.cpp
+++ b/toolkit/components/ctypes/tests/jsctypes-test.cpp
@@ -70,70 +70,72 @@ template <> struct ValueTraits<bool> {
 
 void
 test_void_t_cdecl()
 {
   // do nothing
   return;
 }
 
-#define DEFINE_TYPE(name, type, ffiType)                                       \
+#define FUNCTION_TESTS(name, type, ffiType, suffix)                            \
 type ABI                                                                       \
-get_##name##_cdecl()                                                           \
+get_##name##_##suffix()                                                        \
 {                                                                              \
   return ValueTraits<type>::literal();                                         \
 }                                                                              \
                                                                                \
 type ABI                                                                       \
-set_##name##_cdecl(type x)                                                     \
+set_##name##_##suffix(type x)                                                  \
 {                                                                              \
   return x;                                                                    \
 }                                                                              \
                                                                                \
 type ABI                                                                       \
-sum_##name##_cdecl(type x, type y)                                             \
+sum_##name##_##suffix(type x, type y)                                          \
 {                                                                              \
   return ValueTraits<type>::sum(x, y);                                         \
 }                                                                              \
                                                                                \
 type ABI                                                                       \
-sum_alignb_##name##_cdecl(char a, type x, char b, type y, char c)              \
+sum_alignb_##name##_##suffix(char a, type x, char b, type y, char c)           \
 {                                                                              \
   return ValueTraits<type>::sum(x, y);                                         \
 }                                                                              \
                                                                                \
 type ABI                                                                       \
-sum_alignf_##name##_cdecl(float a, type x, float b, type y, float c)           \
+sum_alignf_##name##_##suffix(float a, type x, float b, type y, float c)        \
 {                                                                              \
   return ValueTraits<type>::sum(x, y);                                         \
 }                                                                              \
                                                                                \
 type ABI                                                                       \
-sum_many_##name##_cdecl(                                                       \
+sum_many_##name##_##suffix(                                                    \
   type a, type b, type c, type d, type e, type f, type g, type h, type i,      \
   type j, type k, type l, type m, type n, type o, type p, type q, type r)      \
 {                                                                              \
   return ValueTraits<type>::sum_many(a, b, c, d, e, f, g, h, i,                \
                                      j, k, l, m, n, o, p, q, r);               \
 }
 
 #define ABI /* cdecl */
+#define DEFINE_TYPE(x, y, z) FUNCTION_TESTS(x, y, z, cdecl)
 #include "typedefs.h"
 #undef ABI
 
 #if defined(_WIN32) && !defined(_WIN64)
 
 void NS_STDCALL
 test_void_t_stdcall()
 {
   // do nothing
   return;
 }
 
 #define ABI NS_STDCALL
+#define DEFINE_TYPE(x, y, z) FUNCTION_TESTS(x, y, z, stdcall)
 #include "typedefs.h"
 #undef ABI
 
 #endif /* defined(_WIN32) && !defined(_WIN64) */
 
 #define DEFINE_TYPE(name, type, ffiType)                                       \
 struct align_##name {                                                          \
   char x;                                                                      \
@@ -316,17 +318,17 @@ test_fnptr()
 PRInt32
 test_closure_cdecl(PRInt8 i, PRInt32 (*f)(PRInt8))
 {
   return f(i);
 }
 
 #if defined(_WIN32) && !defined(_WIN64)
 PRInt32
-test_closure_cdecl(PRInt8 i, PRInt32 (NS_STDCALL *f)(PRInt8))
+test_closure_stdcall(PRInt8 i, PRInt32 (NS_STDCALL *f)(PRInt8))
 {
   return f(i);
 }
 #endif /* defined(_WIN32) && !defined(_WIN64) */
 
 template <typename T> struct PromotedTraits {
   typedef T type;
 };
--- a/toolkit/components/ctypes/tests/unit/test_jsctypes.js.in
+++ b/toolkit/components/ctypes/tests/unit/test_jsctypes.js.in
@@ -648,61 +648,87 @@ function run_UInt64_tests() {
   do_check_throws(function() { ctypes.UInt64.join(0x100000000, 0); }, TypeError);
   do_check_throws(function() { ctypes.UInt64.join(0, -0x1); }, TypeError);
   do_check_throws(function() { ctypes.UInt64.join(0, 0x1000000000); }, TypeError);
 }
 
 function run_basic_abi_tests(library, t, name, toprimitive,
                              get_test, set_tests, sum_tests, sum_many_tests) {
   // Test the function call ABI for calls involving the type.
-  run_single_abi_tests(library, ctypes.default_abi, t, name + "_cdecl",
+  function declare_fn_cdecl(fn_t, prefix) {
+    return library.declare(prefix + name + "_cdecl", fn_t);
+  }
+  run_single_abi_tests(declare_fn_cdecl, ctypes.default_abi, t,
     toprimitive, get_test, set_tests, sum_tests, sum_many_tests);
-#ifdef _WIN32
-#ifndef _WIN64
-  run_single_abi_tests(library, ctypes.stdcall_abi, t, name + "_stdcall",
+
+#ifdef WIN32
+#ifndef HAVE_64BIT_OS
+  function declare_fn_stdcall(fn_t, prefix) {
+    return library.declare(
+      // stdcall functions have the symbol name postfixed with the (aligned)
+      // size of the args.
+      "_" + prefix + name + "_stdcall" + "@" + argsize(fn_t.targetType.argTypes), fn_t);
+  }
+  function argsize(arglist) {
+    let size = 0;
+    for each (let a in arglist) {
+      if (a.size % 4 == 0)
+        size += a.size;
+      else
+        size += a.size + 4 - a.size % 4;
+    }
+    return size;
+  }
+  run_single_abi_tests(declare_fn_stdcall, ctypes.stdcall_abi, t,
     toprimitive, get_test, set_tests, sum_tests, sum_many_tests);
 #endif
 #endif
 
   // Check the alignment of the type, and its behavior in a struct,
   // against what C says.
   check_struct_stats(library, t);
 }
 
-function run_single_abi_tests(library, abi, t, name, toprimitive,
+function run_single_abi_tests(decl, abi, t, toprimitive,
                               get_test, set_tests, sum_tests, sum_many_tests) {
-  let getter = library.declare("get_" + name, abi, t);
+  let getter_t = ctypes.FunctionType(abi, t).ptr;
+  let getter = decl(getter_t, "get_");
   do_check_eq(toprimitive(getter()), get_test);
 
-  let setter = library.declare("set_" + name, ctypes.default_abi, t, t);
+  let setter_t = ctypes.FunctionType(abi, t, [t]).ptr;
+  let setter = decl(setter_t, "set_");
   for each (let i in set_tests)
     do_check_eq(toprimitive(setter(i)), i);
 
-  let sum = library.declare("sum_" + name, ctypes.default_abi, t, t, t);
+  let sum_t = ctypes.FunctionType(abi, t, [t, t]).ptr;
+  let sum = decl(sum_t, "sum_");
   for each (let a in sum_tests)
     do_check_eq(toprimitive(sum(a[0], a[1])), a[2]);
 
-  let sum_alignb = library.declare("sum_alignb_" + name, ctypes.default_abi, t,
-    ctypes.char, t, ctypes.char, t, ctypes.char);
-  let sum_alignf = library.declare("sum_alignf_" + name, ctypes.default_abi, t,
-    ctypes.float, t, ctypes.float, t, ctypes.float);
+  let sum_alignb_t = ctypes.FunctionType(abi, t,
+    [ctypes.char, t, ctypes.char, t, ctypes.char]).ptr;
+  let sum_alignb = decl(sum_alignb_t, "sum_alignb_");
+  let sum_alignf_t = ctypes.FunctionType(abi, t,
+    [ctypes.float, t, ctypes.float, t, ctypes.float]).ptr;
+  let sum_alignf = decl(sum_alignf_t, "sum_alignf_");
   for each (let a in sum_tests) {
     do_check_eq(toprimitive(sum_alignb(0, a[0], 0, a[1], 0)), a[2]);
     do_check_eq(toprimitive(sum_alignb(1, a[0], 1, a[1], 1)), a[2]);
     do_check_eq(toprimitive(sum_alignf(0, a[0], 0, a[1], 0)), a[2]);
     do_check_eq(toprimitive(sum_alignf(1, a[0], 1, a[1], 1)), a[2]);
   }
 
-  let sum_many = library.declare("sum_many_" + name, ctypes.default_abi, t,
-    t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t);
+  let sum_many_t = ctypes.FunctionType(abi, t,
+    [t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t]).ptr;
+  let sum_many = decl(sum_many_t, "sum_many_");
   for each (let a in sum_many_tests)
-    do_check_eq(toprimitive(
-      sum_many(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7],
-               a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15],
-               a[16], a[17])), a[18]);
+    do_check_eq(
+      toprimitive(sum_many(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7],
+                           a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15],
+                           a[16], a[17])), a[18]);
 }
 
 function check_struct_stats(library, t) {
   let s_t = ctypes.StructType("s_t", [{ x: ctypes.char }, { y: t }]);
   let n_t = ctypes.StructType("n_t", [{ a: ctypes.char }, { b: s_t }, { c: ctypes.char }]);
   let get_stats = library.declare("get_" + t.name + "_stats",
     ctypes.default_abi, ctypes.void_t,
     ctypes.size_t.ptr, ctypes.size_t.ptr, ctypes.size_t.ptr, ctypes.size_t.ptr,
@@ -1819,21 +1845,21 @@ function run_FunctionType_tests() {
   // Test some more complex names.
   do_check_eq(fp_t.array().name, "g_t(*[])()");
   do_check_eq(fp_t.array().ptr.name, "g_t(*(*)[])()");
 
   let f3_t = ctypes.FunctionType(ctypes.default_abi,
     ctypes.char.ptr.array().ptr).ptr.ptr.array(8).array();
   do_check_eq(f3_t.name, "char*(*(**[][8])())[]");
 
-#ifdef _WIN32
-#ifndef _WIN64
+#ifdef WIN32
+#ifndef HAVE_64BIT_OS
   f3_t = ctypes.FunctionType(ctypes.stdcall_abi,
-    ctypes.char.ptr.array().ptr).ptr.array(8).array();
-  do_check_eq(f3_t.ptr.name, "char*(__stdcall *(**[][8])())[]");
+    ctypes.char.ptr.array().ptr).ptr.ptr.array(8).array();
+  do_check_eq(f3_t.name, "char*(*(__stdcall **[][8])())[]");
 #endif
 #endif
 
   let f4_t = ctypes.FunctionType(ctypes.default_abi,
     ctypes.char.ptr.array().ptr, [ ctypes.int32_t, fp_t ]);
   do_check_true(f4_t.argTypes.length == 2);
   do_check_true(f4_t.argTypes[0] === ctypes.int32_t);
   do_check_true(f4_t.argTypes[1] === fp_t);
@@ -2011,19 +2037,19 @@ function run_void_tests(library) {
   let test_void_t = library.declare("test_void_t_cdecl", ctypes.default_abi, ctypes.void_t);
   do_check_eq(test_void_t(), undefined);
 
   // Test that library.declare throws with void function args.
   do_check_throws(function() {
     library.declare("test_void_t_cdecl", ctypes.default_abi, ctypes.void_t, ctypes.void_t);
   }, Error);
 
-#ifdef _WIN32
-#ifndef _WIN64
-  test_void_t = library.declare("test_void_t_stdcall", ctypes.stdcall_abi, ctypes.void_t);
+#ifdef WIN32
+#ifndef HAVE_64BIT_OS
+  test_void_t = library.declare("_test_void_t_stdcall@0", ctypes.stdcall_abi, ctypes.void_t);
   do_check_eq(test_void_t(), undefined);
 #endif
 #endif
 }
 
 function run_string_tests(library) {
   let test_ansi_len = library.declare("test_ansi_len", ctypes.default_abi, ctypes.int32_t, ctypes.char.ptr);
   do_check_eq(test_ansi_len(""), 0);
@@ -2165,19 +2191,20 @@ function run_function_tests(library)
   do_check_eq(ptrValue(test_ansi_len), ptrValue(test_ansi_len_2));
   do_check_throws(function() { test_ansi_len_2.value = null; }, Error);
   do_check_eq(ptrValue(test_ansi_len_2), ptrValue(ptr));
 }
 
 function run_closure_tests(library)
 {
   run_single_closure_tests(library, ctypes.default_abi, "cdecl");
-#ifdef _WIN32
-#ifndef _WIN64
-  run_single_closure_tests(library, ctypes.stdcall_abi, "stdcall");
+#ifdef WIN32
+#ifndef HAVE_64BIT_OS
+  // stdcall closure tests are currently broken on windows. see bug 564966.
+  //run_single_closure_tests(library, ctypes.stdcall_abi, "stdcall");
 #endif
 #endif
 }
 
 function run_single_closure_tests(library, abi, suffix)
 {
   let b = 23;
 
@@ -2228,18 +2255,18 @@ function run_variadic_tests(library) {
     ctypes.FunctionType(ctypes.default_abi, ctypes.bool,
                         [ctypes.bool, "...", ctypes.bool]);
   }, Error);
 
   do_check_throws(function() {
     ctypes.FunctionType(ctypes.default_abi, ctypes.bool, ["..."]);
   }, Error);
 
-#ifdef _WIN32
-#ifndef _WIN64
+#ifdef WIN32
+#ifndef HAVE_64BIT_OS
   do_check_throws(function() {
       ctypes.FunctionType(ctypes.stdcall_abi, ctypes.bool,
                           [ctypes.bool, "..."]);
   }, Error);
 #endif
 #endif
 
   do_check_throws(function() {