[2/2] rpcrt4: Add tests for RPC and widl generated code (take 2)

Dan Hipschman dsh at linux.ucla.edu
Tue Apr 24 19:16:23 CDT 2007


This patch adds basic tests for RPC and widl generated code.  It's an
improvement on the previous attempt as it also tests RPC over named pipes.
Everything passes on XP SP1.  There's one todo on wine.  It uses a slightly
roundabout waiting scheme since RpcMgmtWaitServerListen doesn't actually
wait in wine, so I wait for an event instead, which works fine for now.

---
 dlls/rpcrt4/tests/Makefile.in |    6 +-
 dlls/rpcrt4/tests/server.c    |  262 +++++++++++++++++++++++++++++++++++++++++
 dlls/rpcrt4/tests/server.idl  |   45 +++++++
 3 files changed, 312 insertions(+), 1 deletions(-)
 create mode 100644 dlls/rpcrt4/tests/server.c
 create mode 100644 dlls/rpcrt4/tests/server.idl

diff --git a/dlls/rpcrt4/tests/Makefile.in b/dlls/rpcrt4/tests/Makefile.in
index 036cd21..aeac237 100644
--- a/dlls/rpcrt4/tests/Makefile.in
+++ b/dlls/rpcrt4/tests/Makefile.in
@@ -5,12 +5,16 @@ VPATH     = @srcdir@
 TESTDLL   = rpcrt4.dll
 IMPORTS   = ole32 rpcrt4 kernel32
 EXTRALIBS = -luuid
+EXTRAIDLFLAGS  = --prefix-server=s_
+IDL_C_SRCS = server.idl
+IDL_S_SRCS = server.idl
 
 CTESTS = \
 	cstub.c \
 	generated.c \
 	ndr_marshall.c \
-	rpc.c
+	rpc.c \
+	server.c
 
 @MAKE_TEST_RULES@
 
diff --git a/dlls/rpcrt4/tests/server.c b/dlls/rpcrt4/tests/server.c
new file mode 100644
index 0000000..68bd6fa
--- /dev/null
+++ b/dlls/rpcrt4/tests/server.c
@@ -0,0 +1,262 @@
+/*
+ * Tests for WIDL and RPC server/clients.
+ *
+ * Copyright (C) Google 2007 (Dan Hipschman)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "wine/test.h"
+#include "server.h"
+
+#include <stdio.h>
+
+#define PORT "4114"
+#define PIPE "\\pipe\\wine_rpcrt4_test"
+
+#define INT_CODE 4198
+
+static const char *progname;
+
+static HANDLE stop_event;
+
+void __RPC_FAR *__RPC_USER
+midl_user_allocate(size_t n)
+{
+  return malloc(n);
+}
+
+void __RPC_USER
+midl_user_free(void __RPC_FAR *p)
+{
+  free(p);
+}
+
+int
+s_int_return(void)
+{
+  return INT_CODE;
+}
+
+int
+s_square(int x)
+{
+  return x * x;
+}
+
+int
+s_sum(int x, int y)
+{
+  return x + y;
+}
+
+void
+s_square_out(int x, int *y)
+{
+  *y = s_square(x);
+}
+
+void
+s_square_ref(int *x)
+{
+  *x = s_square(*x);
+}
+
+int
+s_str_length(const char *s)
+{
+  return strlen(s);
+}
+
+int
+s_dot_self(vector_t *v)
+{
+  return s_square(v->x) + s_square(v->y) + s_square(v->z);
+}
+
+double
+s_square_half(double x, double *y)
+{
+  *y = x / 2.0;
+  return x * x;
+}
+
+float
+s_square_half_float(float x, float *y)
+{
+  *y = x / 2.0f;
+  return x * x;
+}
+
+long
+s_square_half_long(long x, long *y)
+{
+  *y = x / 2;
+  return x * x;
+}
+
+void
+s_stop(void)
+{
+  ok(RPC_S_OK == RpcMgmtStopServerListening(NULL), "RpcMgmtStopServerListening\n");
+  ok(RPC_S_OK == RpcServerUnregisterIf(NULL, NULL, FALSE), "RpcServerUnregisterIf\n");
+  ok(SetEvent(stop_event), "SetEvent\n");
+}
+
+static void
+make_cmdline(char buffer[MAX_PATH], const char *test)
+{
+  sprintf(buffer, "%s server %s", progname, test);
+}
+
+static int
+run_client(const char *test)
+{
+  char cmdline[MAX_PATH];
+  PROCESS_INFORMATION info;
+  STARTUPINFOA startup;
+  DWORD exitcode;
+
+  memset(&startup, 0, sizeof startup);
+  startup.cb = sizeof startup;
+
+  make_cmdline(cmdline, test);
+  ok(CreateProcessA(NULL, cmdline, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n");
+  ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
+  ok(GetExitCodeProcess(info.hProcess, &exitcode), "GetExitCodeProcess\n");
+  ok(CloseHandle(info.hProcess), "CloseHandle\n");
+  ok(CloseHandle(info.hThread), "CloseHandle\n");
+
+  return exitcode == 0;
+}
+
+static void
+basic_tests(void)
+{
+  static char string[] = "I am a string";
+  static vector_t a = {1, 3, 7};
+  double u, v;
+  float s, t;
+  long q, r;
+  int x;
+
+  ok(int_return() == INT_CODE, "RPC int_return\n");
+
+  ok(square(7) == 49, "RPC square\n");
+  ok(sum(23, -4) == 19, "RPC sum\n");
+
+  x = 0;
+  square_out(11, &x);
+  ok(x == 121, "RPC square_out\n");
+
+  x = 5;
+  square_ref(&x);
+  ok(x == 25, "RPC square_ref\n");
+
+  ok(str_length(string) == strlen(string), "RPC str_length\n");
+  ok(dot_self(&a) == 59, "RPC dot_self\n");
+
+  v = 0.0;
+  u = square_half(3.0, &v);
+  ok(u == 9.0, "RPC square_half\n");
+  ok(v == 1.5, "RPC square_half\n");
+
+  t = 0.0f;
+  s = square_half_float(3.0f, &t);
+  ok(s == 9.0f, "RPC square_half_float\n");
+  ok(t == 1.5f, "RPC square_half_float\n");
+
+  r = 0;
+  q = square_half_long(3, &r);
+  ok(q == 9, "RPC square_half_long\n");
+  ok(r == 1, "RPC square_half_long\n");
+}
+
+static void
+client(const char *test)
+{
+  if (strcmp(test, "tcp_basic") == 0)
+  {
+    static unsigned char iptcp[] = "ncacn_ip_tcp";
+    static unsigned char address[] = "127.0.0.1";
+    static unsigned char port[] = PORT;
+    unsigned char *binding;
+
+    ok(RPC_S_OK == RpcStringBindingCompose(NULL, iptcp, address, port, NULL, &binding), "RpcStringBindingCompose\n");
+    ok(RPC_S_OK == RpcBindingFromStringBinding(binding, &IServer_IfHandle), "RpcBindingFromStringBinding\n");
+
+    basic_tests();
+
+    ok(RPC_S_OK == RpcStringFree(&binding), "RpcStringFree\n");
+    ok(RPC_S_OK == RpcBindingFree(&IServer_IfHandle), "RpcBindingFree\n");
+  }
+  else if (strcmp(test, "np_basic") == 0)
+  {
+    static unsigned char np[] = "ncacn_np";
+    static unsigned char address[] = "\\\\.";
+    static unsigned char pipe[] = PIPE;
+    unsigned char *binding;
+
+    ok(RPC_S_OK == RpcStringBindingCompose(NULL, np, address, pipe, NULL, &binding), "RpcStringBindingCompose\n");
+    ok(RPC_S_OK == RpcBindingFromStringBinding(binding, &IServer_IfHandle), "RpcBindingFromStringBinding\n");
+    
+    basic_tests();
+    stop();
+
+    ok(RPC_S_OK == RpcStringFree(&binding), "RpcStringFree\n");
+    ok(RPC_S_OK == RpcBindingFree(&IServer_IfHandle), "RpcBindingFree\n");
+  }
+}
+
+static void
+server(void)
+{
+  static unsigned char iptcp[] = "ncacn_ip_tcp";
+  static unsigned char port[] = PORT;
+  static unsigned char np[] = "ncacn_np";
+  static unsigned char pipe[] = PIPE;
+
+  ok(RPC_S_OK == RpcServerUseProtseqEp(iptcp, 20, port, NULL), "RpcServerUseProtseqEp\n");
+  ok(RPC_S_OK == RpcServerRegisterIf(s_IServer_v0_0_s_ifspec, NULL, NULL), "RpcServerRegisterIf\n");
+  ok(RPC_S_OK == RpcServerListen(1, 20, TRUE), "RpcServerListen\n");
+
+  stop_event = CreateEvent(NULL, FALSE, FALSE, NULL);
+  ok(stop_event != NULL, "CreateEvent failed\n");
+
+  ok(run_client("tcp_basic"), "tcp_basic client test failed\n");
+
+  ok(RPC_S_OK == RpcServerUseProtseqEp(np, 0, pipe, NULL), "RpcServerUseProtseqEp\n");
+  ok(run_client("np_basic"), "np_basic client test failed\n");
+
+  ok(WAIT_OBJECT_0 == WaitForSingleObject(stop_event, 60000), "WaitForSingleObject\n");
+  todo_wine {
+    ok(RPC_S_OK == RpcMgmtWaitServerListen(), "RpcMgmtWaitServerListening\n");
+  }
+}
+
+START_TEST(server)
+{
+  int argc;
+  char **argv;
+
+  argc = winetest_get_mainargs(&argv);
+  progname = argv[0];
+
+  if (argc == 3)
+    client(argv[2]);
+  else
+    server();
+}
+
diff --git a/dlls/rpcrt4/tests/server.idl b/dlls/rpcrt4/tests/server.idl
new file mode 100644
index 0000000..d42a3a9
--- /dev/null
+++ b/dlls/rpcrt4/tests/server.idl
@@ -0,0 +1,45 @@
+/*
+ * A simple interface to test the RPC server.
+ *
+ * Copyright (C) Google 2007 (Dan Hipschman)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+typedef struct tag_vector
+{
+  int x;
+  int y;
+  int z;
+} vector_t;
+
+[
+  uuid(00000000-4114-0704-2301-000000000000),
+  implicit_handle(handle_t IServer_IfHandle)
+]
+interface IServer
+{
+  int int_return(void);
+  int square(int x);
+  int sum(int x, int y);
+  void square_out(int x, [out] int *y);
+  void square_ref([in, out] int *x);
+  int str_length([string] const char *s);
+  int dot_self(vector_t *v);
+  double square_half(double x, [out] double *y);
+  float square_half_float(float x, [out] float *y);
+  long square_half_long(long x, [out] long *y);
+  void stop(void);
+}



More information about the wine-patches mailing list