summaryrefslogtreecommitdiff
path: root/TAO/IIOP/test
diff options
context:
space:
mode:
authorsumedh <sumedh@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>1997-02-17 00:09:24 +0000
committersumedh <sumedh@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>1997-02-17 00:09:24 +0000
commitc685695d30d92cc376ab180641e5faf73cd2b8c1 (patch)
treea98ed952c2f465e5bdf9df6d02da29ba7899ad59 /TAO/IIOP/test
parentc80c06ac96191632bddc35badae5886a7171ec4e (diff)
downloadATCD-c685695d30d92cc376ab180641e5faf73cd2b8c1.tar.gz
Added IIOP files
Diffstat (limited to 'TAO/IIOP/test')
-rw-r--r--TAO/IIOP/test/Makefile80
-rw-r--r--TAO/IIOP/test/clnt.cpp491
-rw-r--r--TAO/IIOP/test/cubit.cpp590
-rw-r--r--TAO/IIOP/test/cubit.hh106
-rw-r--r--TAO/IIOP/test/cubit.idl40
-rw-r--r--TAO/IIOP/test/svr.cpp423
-rw-r--r--TAO/IIOP/test/test1.cpp383
-rw-r--r--TAO/IIOP/test/test1.hh124
-rw-r--r--TAO/IIOP/test/test1.idl78
-rw-r--r--TAO/IIOP/test/test1_clnt.cpp636
-rw-r--r--TAO/IIOP/test/test1_svr.cpp644
11 files changed, 3595 insertions, 0 deletions
diff --git a/TAO/IIOP/test/Makefile b/TAO/IIOP/test/Makefile
new file mode 100644
index 00000000000..3dfca9eab2e
--- /dev/null
+++ b/TAO/IIOP/test/Makefile
@@ -0,0 +1,80 @@
+# @(#)Makefile 1.12 95/09/30
+# Makefile for sanity checks
+
+ROOT = ..
+
+include $(ROOT)/Makefile.conf
+
+CPPFLAGS += -I$(ROOT)/proto/include
+
+LDLIBS = -Qoption ld -R$(ROOT)/proto/lib -L$(ROOT)/proto/lib -lcorba
+
+PROG_SRCS = svr.cpp clnt.cpp cubit.cpp \
+ test1.cpp test1_clnt.cpp test1_svr.cpp \
+ echo_clnt.cpp echo_svr.cpp
+
+TESTS = svr clnt test1_svr test1_clnt
+# TESTS = svr clnt test1_svr test1_clnt echo_svr echo_clnt
+
+
+########
+default: $(TESTS)
+all: default
+
+
+########
+# Sanity check builds by running basic functionality tests.
+#
+# "sleep 5" in the server startup is usually enough to get the
+# objref into the file so the client can read it.
+#
+check: $(TESTS)
+ @echo "testing with 'cube' calls, stub + DII, IOR strings"
+ @./svr -i30 -o non-internet > obj.1 & sleep 5
+ @./clnt -n250 -O `cat obj.1` -x
+ @echo ''
+ @echo "testing request forwarding with 'cube' calls, stub + DII"
+ @./svr -f -i30 > obj.2 & sleep 5
+ @./clnt -n250 -O `cat obj.2` -x
+ @echo ''
+ @echo "testing transmission of primitive data types"
+ @./test1_svr -i30 > obj.3 & sleep 5
+ @./test1_clnt -n50 -O `cat obj.3` -x
+ @echo ''
+# @echo "testing echo of primitive data values"
+# @./echo_svr -i30 > obj.4 & sleep 5
+# @./echo_clnt -O `cat obj.4` -x
+# @echo ''
+ @echo "testing with 'cube' calls, MT-ized (no forwarding)"
+ @./svr -t -i30 -o non-internet > obj.5 & sleep 5
+ @./clnt -n250 -O `cat obj.5` -x
+ @echo ''
+
+########
+# CUBIT test
+svr: svr.o cubit.o
+ $(LINK.cc) -o svr svr.o cubit.o $(LDLIBS)
+clnt: cubit.o clnt.o
+ $(LINK.cc) -o clnt clnt.o cubit.o $(LDLIBS)
+
+########
+# BASIC DATATYPES test
+test1_clnt: test1.o test1_clnt.o
+ $(LINK.cc) -o test1_clnt test1_clnt.o test1.o $(LDLIBS)
+test1_svr: test1.o test1_svr.o
+ $(LINK.cc) -o test1_svr test1_svr.o test1.o $(LDLIBS)
+
+########
+# ECHO test ... "test1" where the operation semantics are violated;
+# this aids some porting work, but is a less rigorous test
+echo_clnt: test1.o echo_clnt.o
+ $(LINK.cc) -o echo_clnt echo_clnt.o test1.o $(LDLIBS)
+echo_svr: test1.o echo_svr.o
+ $(LINK.cc) -o echo_svr echo_svr.o test1.o $(LDLIBS)
+
+clean:
+ -rm -rf *.o Log $(TESTS) obj.* core Templates.DB .make.state
+
+install:
+ -@echo "Nothing to install, these are tests!"
+
diff --git a/TAO/IIOP/test/clnt.cpp b/TAO/IIOP/test/clnt.cpp
new file mode 100644
index 00000000000..28a6739f01e
--- /dev/null
+++ b/TAO/IIOP/test/clnt.cpp
@@ -0,0 +1,491 @@
+// @(#)clnt.cpp 1.2 95/09/12
+// Copyright 1994-1995 by Sun Microsystems Inc.
+// All Rights Reserved
+//
+// TEST: Simple "cube" client, calling hand-crafted stubs.
+//
+
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#if unix
+# include <unistd.h>
+# include <sys/time.h>
+
+#else // windows
+# include "getopt.h" // e.g. GNU's version
+
+#endif // unix
+
+#include "cubit.hh"
+
+#include "../lib/runtime/debug.hh"
+
+
+#if !defined (DECLARED_GETTIMEOFDAY)
+extern "C" int gettimeofday (struct timeval *, struct timezone *);
+#endif
+
+extern char *optarg; // missing on some platforms
+
+inline int func (unsigned i) { return i - 117; }
+
+extern void
+print_exception (const CORBA_Exception *, const char *, FILE *f=stdout);
+
+
+//
+// forward declarations
+//
+static void cube_union_stub(unsigned, unsigned&, unsigned&,
+ CORBA_Object_ptr, CORBA_Environment &);
+
+static void cube_union_dii(unsigned &, unsigned &,
+ CORBA_Object_ptr, CORBA_Environment &);
+
+
+int
+main (int argc, char *const *argv)
+{
+ CORBA_ORB_ptr orb_ptr;
+ CORBA_Environment env;
+ CORBA_Object_ptr objref = CORBA_Object::_nil();
+ unsigned loop_count = 1;
+ int exit_later = 0;
+
+ orb_ptr = CORBA_ORB_init (argc, argv, "internet", env);
+ if (env.exception () != 0) {
+ print_exception (env.exception (), "ORB initialisation");
+ return 1;
+ }
+
+ //
+ // Parse command line and verify parameters.
+ //
+ int c;
+
+ while ((c = getopt (argc, argv, "dn:O:x")) != EOF)
+ switch (c) {
+ case 'd': // debug flag
+ debug_level++;
+ continue;
+
+ case 'n': // loop count
+ loop_count = (unsigned) atoi (optarg);
+ continue;
+
+ case 'O': // stringified objref
+ {
+ objref = orb_ptr->string_to_object (
+ (CORBA_String)optarg, env);
+ if (env.exception () != 0) {
+ print_exception (env.exception (), "string2object");
+ return 1;
+ }
+ }
+ continue;
+
+ case 'x':
+ exit_later++;
+ continue;
+
+ case '?':
+ default:
+ fprintf (stderr, "usage: %s"
+ " [-d]"
+ " [-n loopcount]"
+ " [-O objref]"
+ " [-x]"
+ "\n", argv [0]
+ );
+ return 1;
+ }
+
+ if (CORBA_is_nil (objref) == CORBA_B_TRUE) {
+ fprintf (stderr, "%s: must identify non-null target objref\n",
+ argv [0]);
+ return 1;
+ }
+
+ //
+ // See if the type of the objref is correct ... and while we're
+ // at it, incur connection setup costs outside of the timing loop.
+ // (Should probably report setup costs.)
+ //
+ CORBA_Boolean type_ok;
+
+ type_ok = objref->_is_a (Cubit__id, env);
+ if (env.exception () != 0) {
+ print_exception (env.exception (), "check type of target");
+ return -1;
+ } else if (type_ok != CORBA_B_TRUE) {
+ fprintf (stderr, "%s: target objref is of wrong type\n",
+ argv [0]);
+ printf ("type_ok = %d\n", type_ok);
+ return 1;
+ }
+
+ //
+ // Make the calls in a loop.
+ //
+ // XXX should do two things: (a) put all the calls into a
+ // separate routine, and (b) set it up so a utility routine
+ // loops/times the calls ... these will allow (c) adding
+ // more categories of calls
+ //
+ unsigned i;
+ unsigned call_count, error_count;
+
+ call_count = 0;
+ error_count = 0;
+
+#if defined (HAVE_GETTIMEOFDAY)
+ timeval before, after;
+
+ if (gettimeofday (&before, 0) < 0)
+ dperror ("gettimeofday before");
+#endif // defined (HAVE_GETTIMEOFDAY)
+
+ for (i = 0; i < loop_count; i++) {
+ //
+ // Cube an octet.
+ //
+ CORBA_Octet arg_octet, ret_octet;
+
+ call_count++;
+ ret_octet = Cubit_cube_octet (objref, arg_octet = func (i), env);
+ if (env.exception () != 0) {
+ print_exception (env.exception (), "from cube_octet");
+ error_count++;
+ } else {
+ dmsg2 ("cube octet: %d --> %d\n", arg_octet, ret_octet);
+ arg_octet = arg_octet * arg_octet * arg_octet;
+ if (arg_octet != ret_octet) {
+ printf ("** cube_octet(%d) ERROR (--> %d)\n",
+ (CORBA_Octet) func (i), ret_octet);
+ error_count++;
+ }
+ }
+
+ //
+ // Cube a short.
+ //
+ CORBA_Short arg_short, ret_short;
+
+ call_count++;
+ ret_short = Cubit_cube_short (objref, arg_short = func (i), env);
+ if (env.exception () != 0) {
+ print_exception (env.exception (), "from cube_short");
+ error_count++;
+ } else {
+ dmsg2 ("cube short: %d --> %d\n", arg_short, ret_short);
+ arg_short = arg_short * arg_short * arg_short;
+ if (arg_short != ret_short) {
+ printf ("** cube_short(%d) ERROR (--> %d)\n",
+ (CORBA_Short) func (i), ret_short);
+ error_count++;
+ }
+ }
+
+ //
+ // Cube a long.
+ //
+ CORBA_Long arg_long, ret_long;
+
+ call_count++;
+ ret_long = Cubit_cube_long (objref, arg_long = func (i), env);
+ if (env.exception () != 0) {
+ print_exception (env.exception (), "from cube_long");
+ error_count++;
+ } else {
+ dmsg2 ("cube long: %d --> %d\n", arg_long, ret_long);
+ arg_long = arg_long * arg_long * arg_long;
+ if (arg_long != ret_long) {
+ printf ("** cube_long(%ld) ERROR (--> %ld)\n",
+ (CORBA_Long) func (i), ret_long);
+ error_count++;
+ }
+ }
+
+ //
+ // Cube a "struct" ...
+ //
+ Cubit_Many arg_struct, *ret_struct;
+
+ call_count++;
+
+ arg_struct.l = func (i);
+ arg_struct.s = func (i);
+ arg_struct.o = func (i);
+
+ ret_struct = Cubit_cube_struct (objref, arg_struct, env);
+ if (env.exception () != 0) {
+ print_exception (env.exception (), "from cube_struct");
+ error_count++;
+ } else {
+ dmsg ("cube struct ...");
+ arg_struct.l = arg_struct.l * arg_struct.l * arg_struct.l;
+ arg_struct.s = arg_struct.s * arg_struct.s * arg_struct.s;
+ arg_struct.o = arg_struct.o * arg_struct.o * arg_struct.o;
+
+ if (arg_struct.l != ret_struct->l
+ || arg_struct.s != ret_struct->s
+ || arg_struct.o != ret_struct->o) {
+ printf ("** cube_struct ERROR\n");
+ error_count++;
+ }
+ delete ret_struct;
+ }
+
+ }
+
+#if defined (HAVE_GETTIMEOFDAY)
+ if (gettimeofday (&after, 0) < 0)
+ dperror ("gettimeofday after");
+
+ if (call_count > 0) {
+ if (error_count == 0) {
+ unsigned long us;
+
+ us = after.tv_sec - before.tv_sec;
+ us *= 1000 * 1000;
+ us += after.tv_usec - before.tv_usec;
+ us /= call_count;
+
+ printf ("cube average call time\t= %ld.%.03ldms, \t"
+ "%ld calls/second\n",
+ us / 1000, us % 1000,
+ 1000000L / us);
+ }
+
+ printf ("%d calls, %d errors\n", call_count, error_count);
+ }
+#endif // defined (HAVE_GETTIMEOFDAY)
+
+ //
+ // Simple test for DII: call "cube_struct". (It's not timed
+ // since the copious mallocation of DII would bias numbers against
+ // typical stub-based calls.)
+ //
+ do {
+ //
+ // Create the request ...
+ //
+ CORBA_Request_ptr req;
+
+ req = objref->_request ((const CORBA_String) "cube_struct", env);
+ if (env.exception () != 0) {
+ print_exception (env.exception (), "DII request create");
+ break;
+ }
+
+ //
+ // ... initialise the argument list and result ...
+ //
+ Cubit_Many arg, *result;
+
+ arg.o = 3; arg.l = 5; arg.s = -7;
+
+ CORBA_Any tmp_arg (TC_Cubit_Many, &arg, CORBA_B_FALSE);
+
+ req->arguments ()->add_value (0, tmp_arg, CORBA_ARG_IN, env);
+ if (env.exception () != 0) {
+ print_exception (env.exception (), "DII request arg add");
+ CORBA_release (req);
+ break;
+ }
+
+ req->result ()->value ()
+ ->replace (TC_Cubit_Many, 0, CORBA_B_TRUE, env);
+ if (env.exception () != 0) {
+ print_exception (env.exception (), "DII request result type");
+ CORBA_release (req);
+ break;
+ }
+
+ //
+ // Make the invocation, verify the result
+ //
+ req->invoke ();
+ if (req->env ()->exception () != 0) {
+ print_exception (req->env ()->exception (), "DII invoke");
+ CORBA_release (req);
+ break;
+ }
+
+ result = (Cubit_Many *) req->result ()->value ()->value ();
+
+ if (result->o != 27 || result->l != 125 || result->s != -343)
+ fprintf (stderr, "DII cube_struct -- bad results\n");
+ else
+ dmsg ("DII cube_struct ... success!!");
+
+ CORBA_release (req);
+
+ } while (0);
+
+ //
+ // Two more tests, using the "cube_union" function
+ //
+ cube_union_dii(call_count, error_count, objref, env);
+ if (env.exception () != 0)
+ error_count++;
+
+ cube_union_stub(i, call_count, error_count, objref, env);
+ if (env.exception () != 0)
+ error_count++;
+
+ if (exit_later) {
+ Cubit_please_exit (objref, env);
+ dexc (env, "server, please exit");
+ }
+
+ CORBA_release (objref);
+
+ return (error_count == 0) ? 0 : 1;
+}
+
+
+static void
+cube_union_stub(
+ unsigned i,
+ unsigned &call_count,
+ unsigned &error_count,
+ CORBA_Object_ptr objref,
+ CORBA_Environment &env)
+{
+ //
+ // Cube a "union" ...
+ //
+ Cubit_oneof u, *r;
+
+ call_count++;
+
+ u._disc = e_2nd;
+ u.l = 3;
+
+ r = Cubit_cube_union (objref, u, env);
+ if (env.exception () != 0) {
+ print_exception (env.exception (), "from cube_union");
+ error_count++;
+ } else {
+ dmsg ("cube union ...");
+ u.l = u.l * u.l * u.l ;
+
+ if (u.l != r->l) {
+ printf ("** cube_union ERROR\n");
+ error_count++;
+ }
+
+ delete r;
+ }
+
+ //
+ // Cube another "union" which uses the default arm ...
+ //
+ call_count++;
+
+ u._disc = e_5th;
+ u.cm.l = func (i);
+ u.cm.s = func (i);
+ u.cm.o = func (i);
+
+ u.cm.l = 7;
+ u.cm.s = 5;
+ u.cm.o = 3;
+
+ r = Cubit_cube_union (objref, u, env);
+ if (env.exception () != 0) {
+ print_exception (env.exception (), "from cube_union");
+ error_count++;
+ } else {
+ dmsg ("cube union ...");
+ u.cm.l = u.cm.l * u.cm.l * u.cm.l;
+ u.cm.s = u.cm.s * u.cm.s * u.cm.s;
+ u.cm.o = u.cm.o * u.cm.o * u.cm.o;
+
+ if (u.cm.l != r->cm.l
+ || u.cm.s != r->cm.s
+ || u.cm.o != r->cm.o) {
+ printf ("** cube_union ERROR\n");
+ error_count++;
+ }
+
+ delete r;
+ }
+}
+
+
+static void
+cube_union_dii (
+ unsigned &call_count,
+ unsigned &error_count,
+ CORBA_Object_ptr objref,
+ CORBA_Environment &env)
+{
+ //
+ // Create the request ...
+ //
+ CORBA_Request_ptr req;
+
+ call_count++;
+
+ req = objref->_request ((const CORBA_String) "cube_union", env);
+ if (env.exception () != 0) {
+ error_count++;
+
+ print_exception (env.exception (), "cube_union_dii request create");
+ return;
+ }
+
+ //
+ // ... initialise the argument list and result ...
+ //
+ Cubit_oneof u, *r;
+
+ u._disc = e_3rd;
+ u.cm.l = 5;
+ u.cm.s = -7;
+ u.cm.o = 3;
+
+ CORBA_Any tmp_arg (TC_Cubit_oneof, &u, CORBA_B_FALSE);
+
+ req->arguments ()->add_value (0, tmp_arg, CORBA_ARG_IN, env);
+ if (env.exception () != 0) {
+ error_count++;
+ print_exception (env.exception (), "cube_union_dii request arg add");
+ CORBA_release (req);
+ return;
+ }
+
+ req->result ()->value ()->replace (TC_Cubit_oneof, 0, CORBA_B_TRUE, env);
+ if (env.exception () != 0) {
+ error_count++;
+ print_exception (env.exception (), "cube_union_dii result type");
+ CORBA_release (req);
+ return;
+ }
+
+ //
+ // Make the invocation, verify the result
+ //
+ req->invoke ();
+ if (req->env ()->exception () != 0) {
+ error_count++;
+ print_exception (req->env ()->exception (),"cube_union_dii invoke");
+ CORBA_release (req);
+ return;
+ }
+
+ r = (Cubit_oneof *) req->result ()->value ()->value ();
+
+ if (r->cm.o != 27 || r->cm.l != 125 || r->cm.s != -343) {
+ error_count++;
+ fprintf (stderr, "cube_union_dii -- bad results\n");
+ }
+ else
+ dmsg ("cube_union_dii ... success!!");
+
+ CORBA_release (req);
+}
diff --git a/TAO/IIOP/test/cubit.cpp b/TAO/IIOP/test/cubit.cpp
new file mode 100644
index 00000000000..077ba286522
--- /dev/null
+++ b/TAO/IIOP/test/cubit.cpp
@@ -0,0 +1,590 @@
+// @(#)cubit.cpp 1.2 95/09/29
+// Copyright 1994-1995 by Sun Microsystems Inc.
+// All Rights Reserved
+//
+// TEST: hand-written C-style "Cubit" stubs and "skeletons"
+//
+// NOTE: these "skeletons" are really the methods, using DSI. No real
+// ORB would be implemented in this particular way. Several things would
+// be more typical of real (static) skeletons:
+//
+// * Most of the "in" (and much of the "out") parameter data would
+// be preallocated on the stack, not heap allocated. (Static
+// preallocation doesnt' really work in a multithreaded system,
+// and moreover can waste a lot of space.)
+//
+// * The ORB core wouldn't be told about parameters using heap
+// allocated data structures (e.g. NVList).
+//
+// * Skeletons would need to some kind of "marshal the response NOW"
+// API so that stack-allocated "out" values wouldn't become invalid
+// up until they were safely marshaled.
+//
+// * They'd handle exceptions rather than just generating debugging
+// messages when they happen.
+//
+// * Method code would be called by the skeletons, not written as
+// part of the "skeleton" itself!
+//
+// A key part of turning this code into a complete ORB would be to ensure
+// that skeletons were always efficient and correct. They might not need
+// to be sharable between different implementations of the same OMG-IDL
+// object interface, but many ORBs choose to be structured that way.
+//
+
+#include "cubit.hh" // for stubs ...
+#include <corba/toa.hh> // ... and skeletons
+
+#include "../lib/runtime/debug.hh" // ... and debugging
+
+
+//
+// CUBE OCTET
+//
+
+static const paramdata Cubit_cube_octet_params [] = {
+ { _tc_CORBA_Octet, PARAM_RETURN, 0 },
+ { _tc_CORBA_Octet, PARAM_IN, 0 }
+};
+
+static const calldata Cubit_cube_octet_calldata = {
+ "cube_octet", CORBA_B_TRUE,
+ 2, &Cubit_cube_octet_params [0],
+ 0, 0
+};
+
+
+CORBA_Octet
+Cubit_cube_octet (
+ Cubit_ptr target,
+ CORBA_Octet o,
+ CORBA_Environment &env
+)
+{
+ CORBA_Octet retval;
+ STUB_Object *data;
+
+ if (target->QueryInterface (IID_STUB_Object, (void **)&data)
+ != NOERROR)
+ env.exception (new CORBA_INV_OBJREF (COMPLETED_NO));
+ else {
+ data->do_call (env, &Cubit_cube_octet_calldata,
+ &retval, &o);
+ data->Release ();
+ }
+ return retval;
+}
+
+static void
+_cube_octet_skel (
+ CORBA_ServerRequest &req,
+ CORBA_Environment &env
+)
+{
+ CORBA_NVList_ptr nvlist;
+ CORBA_NamedValue_ptr nv;
+ CORBA_Any temp_value (_tc_CORBA_Octet);
+
+ req.orb()->create_list (0, nvlist);
+ nv = nvlist->add_value (0, temp_value, CORBA_ARG_IN, env);
+ dexc (env, "cube_octet, add value");
+
+ req.params (nvlist, env);
+ dexc (env, "cube_octet, get params");
+
+ CORBA_Octet *value = new CORBA_Octet;
+
+ *value = *(CORBA_Octet *)nv->value ()->value ();
+ // dmsg1 ("cube octet, parameter '%d'", *value);
+ *value = (CORBA_Octet) ((*value) * (*value) * (*value));
+ // dmsg1 ("cube octet, result '%d'", *value);
+
+ CORBA_Any *any =
+ new CORBA_Any (_tc_CORBA_Octet, value, CORBA_B_TRUE);
+
+ req.result (any, env);
+ dexc (env, "cube_octet, result");
+}
+
+
+//
+// CUBE SHORT
+//
+
+static const paramdata Cubit_cube_short_params [] = {
+ { _tc_CORBA_Short, PARAM_RETURN, 0 },
+ { _tc_CORBA_Short, PARAM_IN, 0 }
+};
+
+static const calldata Cubit_cube_short_calldata = {
+ "cube_short", CORBA_B_TRUE,
+ 2, &Cubit_cube_short_params [0],
+ 0, 0
+};
+
+
+CORBA_Short
+Cubit_cube_short (
+ Cubit_ptr target,
+ CORBA_Short s,
+ CORBA_Environment &env
+)
+{
+ CORBA_Short retval;
+ STUB_Object *data;
+
+ if (target->QueryInterface (IID_STUB_Object, (void **)&data)
+ != NOERROR)
+ env.exception (new CORBA_INV_OBJREF (COMPLETED_NO));
+ else {
+ data->do_call (env, &Cubit_cube_short_calldata,
+ &retval, &s);
+ data->Release ();
+ }
+ return retval;
+}
+
+static void
+_cube_short_skel (
+ CORBA_ServerRequest &req,
+ CORBA_Environment &env
+)
+{
+ CORBA_NVList_ptr nvlist;
+ CORBA_NamedValue_ptr nv;
+ CORBA_Any temp_value (_tc_CORBA_Short);
+
+ req.orb()->create_list (0, nvlist);
+ nv = nvlist->add_value (0, temp_value, CORBA_ARG_IN, env);
+ dexc (env, "cube_short, add_value");
+
+ req.params (nvlist, env);
+ dexc (env, "cube_short, get params");
+
+ CORBA_Short *value = new CORBA_Short;
+
+ *value = *(CORBA_Short *)nv->value ()->value ();
+ // dmsg1 ("cube short, parameter '%d'", *value);
+ *value =(CORBA_Short) ((*value) * (*value) * (*value));
+ // dmsg1 ("cube short, result '%d'", *value);
+
+ CORBA_Any *any =
+ new CORBA_Any (_tc_CORBA_Short, value, CORBA_B_TRUE);
+
+ req.result (any, env);
+ dexc (env, "cube_short, result");
+}
+
+
+//
+// CUBE LONG
+//
+
+static const paramdata Cubit_cube_long_params [] = {
+ { _tc_CORBA_Long, PARAM_RETURN, 0 },
+ { _tc_CORBA_Long, PARAM_IN, 0 }
+};
+
+static const calldata Cubit_cube_long_calldata = {
+ "cube_long", CORBA_B_TRUE,
+ 2, &Cubit_cube_long_params [0],
+ 0, 0
+};
+
+
+CORBA_Long
+Cubit_cube_long (
+ Cubit_ptr target,
+ CORBA_Long l,
+ CORBA_Environment &env
+)
+{
+ CORBA_Long retval;
+ STUB_Object *data;
+
+ if (target->QueryInterface (IID_STUB_Object, (void **)&data)
+ != NOERROR)
+ env.exception (new CORBA_INV_OBJREF (COMPLETED_NO));
+ else {
+ data->do_call (env, &Cubit_cube_long_calldata,
+ &retval, &l);
+ data->Release ();
+ }
+ return retval;
+}
+
+
+static void
+_cube_long_skel (
+ CORBA_ServerRequest &req,
+ CORBA_Environment &env
+)
+{
+ CORBA_NVList_ptr nvlist;
+ CORBA_NamedValue_ptr nv;
+ CORBA_Any temp_value (_tc_CORBA_Long);
+
+ req.orb()->create_list (0, nvlist);
+ nv = nvlist->add_value (0, temp_value, CORBA_ARG_IN, env);
+ dexc (env, "cube_long, add_value");
+
+ req.params (nvlist, env);
+ dexc (env, "cube_long, get params");
+
+ CORBA_Long *value = new CORBA_Long;
+
+ *value = *(CORBA_Long *)nv->value ()->value ();
+ // dmsg1 ("cube long, parameter '%d'", *value);
+ *value = (*value) * (*value) * (*value);
+ // dmsg1 ("cube long, result '%d'", *value);
+
+ CORBA_Any *any =
+ new CORBA_Any (_tc_CORBA_Long, value, CORBA_B_TRUE);
+
+ req.result (any, env);
+ dexc (env, "cube_long, result");
+}
+
+//
+// Encapsulated parameters for struct "Cubit_Many" typecode.
+// None of these parameters is complicated, so this is just
+// a linear sequence of element encodings
+//
+// NOTE: it's important that this be longword aligned!!
+//
+static const CORBA_Long _oc_Cubit_Many [] = {
+ 1, // byte order flag (TRICKY!)
+
+ 1, 0, // empty string: repository/type ID
+ 1, 0, // empty string: struct name
+
+ 3, // three struct elements
+
+ // First structure element: name, typecode for Octet
+ 1, 0, // empty string: name "o"
+ tk_octet,
+
+ // Second structure element: name, typecode for Long
+ 1, 0, // empty string: name "l"
+ tk_long,
+
+ // Third structure element: name, typecode for Short
+ 1, 0, // empty string: name "s"
+ tk_short,
+};
+
+static CORBA_TypeCode _tc_Cubit_Many (tk_struct,
+ sizeof _oc_Cubit_Many, (unsigned char *) &_oc_Cubit_Many,
+ CORBA_B_FALSE);
+CORBA_TypeCode_ptr TC_Cubit_Many = &_tc_Cubit_Many;
+
+
+//
+// CUBE STRUCT
+//
+
+static const paramdata Cubit_cube_struct_params [] = {
+ { &_tc_Cubit_Many, PARAM_RETURN, sizeof (Cubit_Many) },
+ { &_tc_Cubit_Many, PARAM_IN, 0 }
+};
+
+static const calldata Cubit_cube_struct_calldata = {
+ "cube_struct", CORBA_B_TRUE,
+ 2, &Cubit_cube_struct_params [0],
+ 0, 0
+};
+
+Cubit_Many *
+Cubit_cube_struct (
+ Cubit_ptr target,
+ Cubit_Many &values,
+ CORBA_Environment &env
+)
+{
+ Cubit_Many *retval;
+ STUB_Object *data;
+
+ if (target->QueryInterface (IID_STUB_Object, (void **)&data)
+ != NOERROR)
+ env.exception (new CORBA_INV_OBJREF (COMPLETED_NO));
+ else {
+ data->do_call (env, &Cubit_cube_struct_calldata,
+ &retval, &values);
+ data->Release ();
+ }
+ return retval;
+}
+
+
+static void
+_cube_struct_skel (
+ CORBA_ServerRequest &req,
+ CORBA_Environment &env
+)
+{
+ CORBA_NVList_ptr nvlist;
+ CORBA_NamedValue_ptr nv;
+ CORBA_Any temp_value (TC_Cubit_Many);
+
+ req.orb()->create_list (0, nvlist);
+ nv = nvlist->add_value (0, temp_value, CORBA_ARG_IN, env);
+ dexc (env, "cube_struct, add_value");
+
+ req.params (nvlist, env);
+ dexc (env, "cube_struct, get params");
+
+ Cubit_Many *value;
+ Cubit_Many *retval = new Cubit_Many;
+
+ value = (Cubit_Many *)nv->value ()->value ();
+
+ retval->o = (CORBA_Octet) (value->o * value->o * value->o);
+ retval->s = (CORBA_Short) (value->s * value->s * value->s);
+ retval->l = value->l * value->l * value->l;
+
+ // dmsg2 ("cube struct.o, %d -> %d", value->o, retval->o);
+ // dmsg2 ("cube struct.s, %d -> %d", value->s, retval->s);
+ // dmsg2 ("cube struct.l, %d -> %d", value->l, retval->l);
+
+ CORBA_Any *any =
+ new CORBA_Any (TC_Cubit_Many, retval, CORBA_B_TRUE);
+
+ req.result (any, env);
+ dexc (env, "cube_struct, result");
+}
+
+//
+// CUBE UNION
+//
+
+//
+// NOTE: not all union typecodes can be encoded as an array
+// of "long "values, but this one can. Ones with discriminants
+// that are one or two bytes long can't easily be coded portably.
+//
+// The benefit of doing it as an array of "long" values is
+// twofold: (a) easier to read; (b) on most systems it's then
+// adequately aligned for the typecode interpreter to use, so
+// no additional runtime copy needs to be made.
+//
+static const CORBA_Long _oc_Cubit_oneof [] = {
+ 1, // byte order flag (TRICKY)
+ 1, 0, // omitted repository/type ID
+ 1, 0, // omitted struct name, "oneof"
+
+ //
+ // discriminant typecode:
+ //
+ tk_enum, // tk_enum
+ 72, // encapsulation length
+
+ 1, // byte order flag (TRICKY)
+ 1, 0, // omitted repository/type ID
+ 1, 0, // omitted enum name, "discrim"
+ 6, // 5 elements in the enum
+
+ 1, 0, // omitted member name, "e_0th"
+ 1, 0, // omitted member name, "e_1st"
+ 1, 0, // omitted member name, "e_2nd"
+ 1, 0, // omitted member name, "e_3rd"
+ 1, 0, // omitted member name, "e_4th"
+ 1, 0, // omitted member name, "e_5th"
+
+ 4, // default member index (zero based)
+ 5, // number of union members
+
+ // the 1st union branch arm
+ e_0th, // member label value
+ 1, 0, // omitted member name, "o"
+ tk_octet, // member typecode
+
+ // the 2nd union branch arm
+ e_1st, // member label value
+ 1, 0, // omitted member name, "s"
+ tk_short, // member typecode
+
+ // the 3rd union branch arm
+ e_2nd, // member label value
+ 1, 0, // omitted member name, "l"
+ tk_long, // member typecode
+
+ // the 4th union branch arm
+ e_3rd, // member label value
+ 1, 0, // omitted member name, "cm"
+
+ // the 4th union member typecode
+ tk_struct, // tk_struct
+ 60, // encap length
+
+ 1, // byte order flag (TRICKY)
+ 1, 0, // omitted repository/type ID
+ 1, 0, // omitted struct name, "Many"
+ 3, // three struct members
+
+ // First structure element
+ 1, 0, // omitted member name, "o"
+ tk_octet, // member type, tk_octet
+
+ // Second structure element
+ 1, 0, // omitted member name, "l"
+ tk_long, // member type, tk_long
+
+ // Third structure element
+ 1, 0, // omitted member name, "s"
+ tk_short, // member type, tk_short
+
+ // the 5th union branch arm
+ 4, // the 5th member label value
+ 1, 0, // omitted member name, "cm"
+ ~0, // indirected typecode (~0)
+ -84 // offset to struct "Many" typecode
+};
+
+static CORBA_TypeCode _tc_Cubit_oneof (tk_union,
+ (sizeof _oc_Cubit_oneof), (unsigned char *) &_oc_Cubit_oneof,
+ CORBA_B_FALSE);
+CORBA_TypeCode_ptr TC_Cubit_oneof = &_tc_Cubit_oneof;
+
+static const paramdata Cubit_cube_union_params [] = {
+ { &_tc_Cubit_oneof, PARAM_RETURN, sizeof (Cubit_oneof) },
+ { &_tc_Cubit_oneof, PARAM_IN, 0 }
+};
+
+static const calldata Cubit_cube_union_calldata = {
+ "cube_union", CORBA_B_TRUE,
+ 2, &Cubit_cube_union_params [0],
+ 0, 0
+};
+
+Cubit_oneof *
+Cubit_cube_union (
+ Cubit_ptr target,
+ Cubit_oneof &values,
+ CORBA_Environment &env
+)
+{
+ Cubit_oneof *retval;
+ STUB_Object *data;
+
+ if (target->QueryInterface (IID_STUB_Object, (void **)&data)
+ != NOERROR)
+ env.exception (new CORBA_INV_OBJREF (COMPLETED_NO));
+ else {
+ data->do_call (env, &Cubit_cube_union_calldata,
+ &retval, &values);
+ data->Release ();
+ }
+ return retval;
+}
+
+
+static void
+_cube_union_skel (
+ CORBA_ServerRequest &req,
+ CORBA_Environment &env
+)
+{
+ CORBA_NVList_ptr nvlist;
+ CORBA_NamedValue_ptr nv;
+ CORBA_Any temp_value (TC_Cubit_oneof);
+
+ req.orb()->create_list (0, nvlist);
+ nv = nvlist->add_value (0, temp_value, CORBA_ARG_IN, env);
+ dexc (env, "cube_union_3rd, add_value");
+
+ req.params (nvlist, env);
+ dexc (env, "cube_union_3rd, get params");
+
+ Cubit_oneof *v;
+ Cubit_oneof *r = new Cubit_oneof;
+
+ v = (Cubit_oneof *)nv->value ()->value ();
+ r->_disc = v->_disc;
+
+ switch (v->_disc) {
+ case e_0th:
+ r->o = (CORBA_Octet) (v->o * v->o * v->o);
+ break;
+
+ case e_1st:
+ r->s = (CORBA_Short) (v->s * v->s * v->s);
+ break;
+
+ case e_2nd:
+ r->l = v->l * v->l * v->l;
+ break;
+
+ case e_3rd:
+ default:
+ r->cm.o = (CORBA_Octet) (v->cm.o * v->cm.o * v->cm.o);
+ r->cm.s = (CORBA_Short) (v->cm.s * v->cm.s * v->cm.s);
+ r->cm.l = v->cm.l * v->cm.l * v->cm.l;
+ break;
+ }
+
+ CORBA_Any *any = new CORBA_Any (TC_Cubit_oneof, r, CORBA_B_TRUE);
+
+ req.result (any, env);
+ dexc (env, "cube_struct, result");
+}
+
+
+//
+// PLEASE EXIT
+//
+
+static const calldata Cubit_please_exit_calldata = {
+ "please_exit", CORBA_B_FALSE,
+ 0, 0,
+ 0, 0
+};
+
+void
+Cubit_please_exit (
+ Cubit_ptr target,
+ CORBA_Environment &env
+)
+{
+ STUB_Object *data;
+
+ if (target->QueryInterface (IID_STUB_Object, (void **)&data)
+ != NOERROR)
+ env.exception (new CORBA_INV_OBJREF (COMPLETED_NO));
+ else {
+ data->do_call (env, &Cubit_please_exit_calldata
+ );
+ data->Release ();
+ }
+}
+
+static void
+_please_exit_skel (
+ CORBA_ServerRequest &req,
+ CORBA_Environment &env
+)
+{
+ dmsg ("I've been asked to shut down...");
+ req.oa ()->please_shutdown (env);
+ dexc (env, "please_exit, please_shutdown");
+}
+
+
+const CORBA_Char *Cubit__id = (CORBA_Char *)
+ "IDL:Eng.SUN.COM/Cubit:1.1";
+
+
+//
+// table of all operations, used by operation dispatch to get to the
+// right skeleton ... could be sorted by the IDL compiler so bsearch
+// is effective, perhaps with help from opname hashes and a small cache
+// (e.g. like Obj-C?). for now, just lsearch.
+//
+const skel_entry Cubit_operations [] = {
+ { &Cubit_cube_octet_calldata, _cube_octet_skel },
+ { &Cubit_cube_short_calldata, _cube_short_skel },
+ { &Cubit_cube_long_calldata, _cube_long_skel },
+ { &Cubit_cube_struct_calldata, _cube_struct_skel },
+ { &Cubit_cube_union_calldata, _cube_union_skel },
+ { &Cubit_please_exit_calldata, _please_exit_skel },
+ { 0, 0 } // last entry
+};
diff --git a/TAO/IIOP/test/cubit.hh b/TAO/IIOP/test/cubit.hh
new file mode 100644
index 00000000000..aae2c06bd31
--- /dev/null
+++ b/TAO/IIOP/test/cubit.hh
@@ -0,0 +1,106 @@
+// @(#)cubit.hh 1.1 95/09/10
+// Copyright 1994-1995 by Sun Microsystems Inc.
+// All Rights Reserved
+//
+// Hand-crafted C language binding glue ...
+//
+// This doesn't use C++ since doing the obvious derivation
+// (all parent interfaces are virtual public parents) makes
+// object references have different "views". That is, a
+// pointer to a Cubit (i.e. a Cubit_ptr) would not have
+// the same binary value as a pointer to a CORBA_Object
+// (i.e. a CORBA_Object_ptr, generic objref). That'd
+// mean lots of narrowing/widening/RTTI infrastructure.
+//
+
+#ifndef _CUBIT_HH
+#define _CUBIT_HH
+
+#ifdef _MSC_VER
+#pragma pack (push, 1) // VC++, known padding rules
+#endif // VC++
+
+#include <corba/orb.hh>
+#include <corba/stub.hh>
+
+
+//
+// C style binding
+//
+
+typedef CORBA_Object Cubit;
+typedef Cubit *Cubit_ptr, *CubitRef;
+
+extern CORBA_TypeCode_ptr TC_Cubit_Many;
+extern CORBA_TypeCode_ptr TC_Cubit_oneof;
+
+struct Cubit_Many {
+ CORBA_Octet o;
+ CORBA_Long l;
+ CORBA_Short s;
+};
+
+enum Cubit_discrim {e_0th = 0, e_1st = 1, e_2nd = 2,
+ e_3rd = 3, e_4th = 4, e_5th = 5};
+
+struct Cubit_oneof {
+ Cubit_discrim _disc;
+
+ union {
+ CORBA_Octet o;
+ CORBA_Short s;
+ CORBA_Long l;
+ Cubit_Many cm;
+ };
+};
+
+CORBA_Octet
+Cubit_cube_octet (
+ Cubit_ptr target,
+ CORBA_Octet o,
+ CORBA_Environment &env
+);
+
+CORBA_Short
+Cubit_cube_short (
+ Cubit_ptr target,
+ CORBA_Short s,
+ CORBA_Environment &env
+);
+
+CORBA_Long
+Cubit_cube_long (
+ Cubit_ptr target,
+ CORBA_Long l,
+ CORBA_Environment &env
+);
+
+Cubit_Many *
+Cubit_cube_struct (
+ Cubit_ptr target,
+ Cubit_Many &values,
+ CORBA_Environment &env
+);
+
+Cubit_oneof *
+Cubit_cube_union (
+ Cubit_ptr target,
+ Cubit_oneof &values,
+ CORBA_Environment &env
+);
+
+void
+Cubit_please_exit (
+ Cubit_ptr target,
+ CORBA_Environment &env
+);
+
+extern const CORBA_Char *Cubit__id; // type ID
+
+extern const skel_entry Cubit_operations [];
+
+#ifdef _MSC_VER
+#pragma pack (pop) // VC++, go back to other padding rules
+#endif // VC++
+
+#endif // _CUBIT_HH
diff --git a/TAO/IIOP/test/cubit.idl b/TAO/IIOP/test/cubit.idl
new file mode 100644
index 00000000000..d9b38c34a2a
--- /dev/null
+++ b/TAO/IIOP/test/cubit.idl
@@ -0,0 +1,40 @@
+// @(#)cubit.idl 1.1 95/09/10
+// Copyright 1994-1995 by Sun Microsystems, Inc.
+
+#pragma prefix "Eng.SUN.COM"
+#pragma version Cubit 1.1
+
+interface Cubit {
+ octet cube_octet (in octet o);
+ short cube_short (in short s);
+ long cube_long (in long l);
+
+ struct Many {
+ octet o; // + 3 bytes padding (normally) ...
+ long l;
+ short s; // + 2 bytes padding (normally) ...
+ };
+
+ Many cube_struct (in Many values);
+
+ enum discrim {e_0th, e_1st, e_2nd, e_3rd, e_4th, e_5th};
+
+ union oneof
+ switch (discrim) {
+ // this is an easy union to interpret; no padding
+ // is needed between discriminant and value.
+ case e_0th:
+ octet o;
+ case e_1st:
+ short s;
+ case e_2nd:
+ long l;
+ case e_3rd:
+ default:
+ Many cm;
+ };
+
+ oneof cube_union (in oneof values);
+
+ oneway void please_exit ();
+};
diff --git a/TAO/IIOP/test/svr.cpp b/TAO/IIOP/test/svr.cpp
new file mode 100644
index 00000000000..cb34263c82c
--- /dev/null
+++ b/TAO/IIOP/test/svr.cpp
@@ -0,0 +1,423 @@
+// @(#)svr.cpp 1.6 95/10/02
+// Copyright 1994-1995 by Sun Microsystems Inc.
+// All Rights Reserved
+//
+// TEST: simple IIOP server for "cubit.idl" interface.
+//
+// Starts up, builds an objref, prints its string, listens for
+// messages, responds to them.
+//
+
+#include <stdio.h>
+#include <string.h>
+
+#if unix
+# include <unistd.h> // for getopt on some systems
+
+#else // windows
+# include "getopt.h" // e.g. GNU's version
+
+#endif
+
+#include "cubit.hh"
+#include <corba/toa.hh>
+
+
+//
+// XXX a general debug/trace facility would be handy
+//
+#include "../lib/runtime/debug.hh"
+
+//
+// XXX this stuff is ugly but needed, since this exposes features
+// (IIOP forwarding) that TOA doesn't provide.
+//
+#include "../lib/bridge/connmgr.hh"
+#include "../lib/bridge/tcpoa.hh"
+
+
+extern char *optarg; // missing on some platforms
+
+extern void
+print_exception (const CORBA_Exception *, const char *, FILE *f=stdout);
+
+
+static void
+is_a_skel (
+ CORBA_ServerRequest &req,
+ CORBA_Environment &env
+)
+{
+ CORBA_NVList_ptr nvlist;
+ CORBA_NamedValue_ptr nv;
+ CORBA_Any temp_value (_tc_CORBA_String);
+
+ req.orb()->create_list (0, nvlist);
+ nv = nvlist->add_value (0, temp_value, CORBA_ARG_IN, env);
+
+ req.params (nvlist, env);
+ if (env.exception () != 0) {
+ dexc (env, "is_a_skel, get params");
+ return;
+ }
+
+ CORBA_Boolean *retval;
+ CORBA_String value = *(CORBA_String *)
+ nv->value ()->value ();
+
+ //
+ // This object's type "is_a" conformant subtype of the type whose
+ // ID ("Repository ID") is passed if it's (a) either the same type
+ // as indicated by the ID, or (b) one of the classes from which it
+ // inherits is_a subtype, or (c) the ID is for the generic CORBA
+ // object.
+ //
+ // XXX IDs should be compared recognizing that the "IDL" and "DCE"
+ // ID types have a minor version code, and that if the minor code
+ // (a 16 bit unsigned integer, in ASCII form) of the ID passed is
+ // not greater than one of the IDs we know, it's still compatible.
+ //
+ // XXX "env" should be checked to see if TypeCode::id() reported
+ // an exception ...
+ //
+ if (strcmp ((char *)value, (char *)Cubit__id) == 0
+ || strcmp ((char *)value, _tc_CORBA_Object->id (env)) == 0)
+ retval = new CORBA_Boolean (CORBA_B_TRUE);
+ else
+ retval = new CORBA_Boolean (CORBA_B_FALSE);
+
+ CORBA_Any *any =
+ new CORBA_Any (_tc_CORBA_Boolean, retval, CORBA_B_TRUE);
+
+ req.result (any, env);
+ dexc (env, "_is_a, result");
+}
+
+
+//
+// Dispatch to Skeletons
+//
+// XXX explore packaging most of this as part of the TCP_OA !!
+//
+static void
+tcpoa_dispatch (
+ CORBA_OctetSeq &key,
+ CORBA_ServerRequest &req,
+ void *context,
+ CORBA_Environment &env
+)
+{
+ //
+ // Verify that the target object and "this" object have the
+ // same key. Normally, this would be used to figure out
+ // which object was the target, and hence which operations
+ // vector to dispatch the request.
+ //
+ CORBA_OctetSeq *obj_key;
+
+ obj_key = (CORBA_OctetSeq *) context;
+
+ if (obj_key->length != key.length
+ || memcmp (obj_key->buffer, key.buffer,
+ obj_key->length) != 0) {
+ env.exception (new CORBA_OBJECT_NOT_EXIST (COMPLETED_NO));
+#ifdef DEBUG
+ if (debug_level)
+ dmsg_opaque ("request to nonexistent object, key = ",
+ key.buffer, key.length);
+#endif
+ return;
+ }
+
+ //
+ // Find a "skeleton" (nyet :-) entry for this operation,
+ // then call it with the right per-object state. (Someday this
+ // search will be sped up, e.g. by hashing or binary search.)
+ //
+ const skel_entry *entry;
+ CORBA_String opname;
+
+ opname = req.op_name ();
+
+ for (entry = &Cubit_operations [0]; entry->op_descriptor; entry++) {
+ if (strcmp ((char *)opname, entry->op_descriptor->opname) == 0) {
+ entry->impl_skeleton (req, env);
+ return;
+ }
+ }
+
+ //
+ // Try one of the ORB's built-in operations.
+ //
+ // XXX the rest too: _non_existent (just return false),
+ // _get_interface (needs an interface repository reference for this
+ // objref's type), and _get_implementation (needs an implementation
+ // repository).
+ //
+ if (strcmp ((char *)opname, "_is_a") == 0) {
+ is_a_skel (req, env);
+ return;
+ }
+
+ //
+ // No match. Operation not implemented; say so.
+ //
+ dmsg1 ("unknown operation, %s", opname);
+ env.exception (new CORBA_BAD_OPERATION (COMPLETED_NO));
+}
+
+//
+// forwarding support
+//
+static CORBA_Object_ptr fwd_ref;
+
+static void
+tcpoa_forwarder (
+ CORBA_OctetSeq &key,
+ CORBA_Object_ptr &the_ref,
+ void *context,
+ CORBA_Environment &env
+)
+{
+ CORBA_OctetSeq *obj_key;
+
+ obj_key = (CORBA_OctetSeq *) context;
+
+ if (obj_key->length == key.length
+ && memcmp (obj_key->buffer, key.buffer, key.length) == 0) {
+ the_ref = fwd_ref->_duplicate (fwd_ref);
+ } else
+ env.exception (new CORBA_OBJECT_NOT_EXIST (COMPLETED_NO));
+}
+
+
+//
+// Socket-based passive OA entry point
+//
+int
+OA_listen (
+ CORBA_ORB_ptr orb_ptr,
+ TCP_OA_ptr oa_ptr,
+ CORBA_String key,
+ int idle,
+ CORBA_Boolean do_fork,
+ CORBA_Boolean do_threads
+)
+{
+ //
+ // Create the object we'll be implementing.
+ //
+ CORBA_OctetSeq obj_key;
+ CORBA_Object_ptr obj;
+ CORBA_Environment env;
+
+ obj_key.buffer = (CORBA_Octet *) key;
+ obj_key.length = obj_key.maximum = strlen ((char *)key);
+
+ obj = oa_ptr->create (obj_key, (CORBA_String) "", env);
+ if (env.exception () != 0) {
+ print_exception (env.exception (), "TCP_OA::create");
+ return 1;
+ }
+
+ //
+ // Stringify the objref we'll be implementing, and
+ // print it to stdout. Someone will take that string
+ // and give it to some client. Then release the object.
+ //
+ CORBA_String str;
+
+ str = orb_ptr->object_to_string (obj, env);
+ if (env.exception () != 0) {
+ print_exception (env.exception (), "object2string");
+ return 1;
+ }
+ puts ((char *)str);
+ fflush (stdout);
+ dmsg1 ("listening as object '%s'", str);
+ CORBA_release (obj);
+ obj = 0;
+
+ //
+ // If we're forking a child server, do so -- read the objref
+ // it'll use, and prepare to forward all requests to it. That
+ // objref has a dynamically assigned port.
+ //
+ if (do_fork) {
+#if defined (HAVE_POPEN)
+ FILE *f = popen ("exec ./svr -i120 -kbaskerville", "r");
+ char buffer [BUFSIZ];
+
+ if (fgets (buffer, sizeof buffer, f) != buffer) {
+ fprintf (stderr, "error: can't read from child\n");
+ return 1;
+ }
+ fwd_ref = orb_ptr->string_to_object ((CORBA_String) buffer, env);
+ if (env.exception () != 0) {
+ print_exception (env.exception (), "string2object");
+ return 1;
+ }
+
+ //
+ // NOTE: don't fclose("f") since some systems make that the
+ // same as pclose("f"). Pclose waits for the child to exit,
+ // causing a deadlock since the child won't exit until it's
+ // told to do so by a client, but no client can be redirected
+ // to the child until the pclose returns ...
+ //
+#else
+ fprintf (stderr, "error: no popen(), can't create child\n");
+ env.exception (new CORBA_IMP_LIMIT);
+ return 1;
+#endif // !defined (HAVE_POPEN)
+ }
+
+ //
+ // Handle requests for this object until we're killed, or one of
+ // the methods asks us to exit.
+ //
+ // NOTE: for multithreaded environments (e.g. POSIX threads) also
+ // want to use threads. The current notion is to dedicate a thread
+ // to a "read" on each client file descriptor, and then when that
+ // successfully gets a Request message, to start another thread
+ // reading that descriptor while the first one creates the Reply.
+ //
+ // This will accentuate the need for server-side policies to address
+ // resource management, such as shutting down connections that have
+ // no requests in progress after they've been idle for some time
+ // period (e.g. 10 minutes), and reclaiming the thread used by that
+ // connection.
+ //
+ while (oa_ptr->shutting_down () != CORBA_B_TRUE) {
+ if (idle == -1)
+ oa_ptr->get_request (tcpoa_dispatch,
+ fwd_ref ? tcpoa_forwarder : 0,
+ do_threads, &obj_key, 0, env);
+ else {
+ timeval tv;
+
+ tv.tv_sec = idle;
+ tv.tv_usec = 0;
+ oa_ptr->get_request (tcpoa_dispatch,
+ fwd_ref ? tcpoa_forwarder : 0,
+ do_threads, &obj_key, &tv, env);
+ }
+
+ //
+ // XXX "env2" should be checked to see if TypeCode::id() reported
+ // an exception ...
+ //
+ CORBA_Environment env2;
+
+ if (env.exception () != 0
+ && strcmp ((char *)env.exception ()->id (),
+ _tc_CORBA_INITIALIZE->id (env2)) == 0) {
+ print_exception (env.exception (), "TCP_OA::get_request");
+ return 1;
+ }
+ env.clear ();
+ }
+
+ //
+ // Shut down the OA -- recycles all underlying resources (e.g. file
+ // descriptors, etc).
+ //
+ oa_ptr->clean_shutdown (env);
+ return 0;
+}
+
+
+//
+// Standard command line parsing utilities used.
+//
+int
+main (
+ int argc,
+ char *const *argv
+)
+{
+ CORBA_Environment env;
+ CORBA_ORB_ptr orb_ptr;
+ TCP_OA_ptr oa_ptr;
+ CORBA_Boolean do_fork = CORBA_B_FALSE;
+ CORBA_Boolean do_threads = CORBA_B_FALSE;
+ CORBA_String key = (CORBA_String) "key0";
+ char *oa_name = 0;
+ char *orb_name = "internet";
+ int idle = -1;
+
+ //
+ // Parse the command line, get options
+ //
+ int c;
+
+ while ((c = getopt (argc, argv, "di:fk:o:p:t")) != EOF)
+ switch (c) {
+ case 'd': // more debug noise
+ debug_level++;
+ continue;
+
+ case 'i': // idle seconds b4 exit
+ idle = atoi (optarg);
+ continue;
+
+ case 'f': // fork child server
+ do_fork = CORBA_B_TRUE;
+ continue;
+
+ case 'k': // key (str)
+ key = (CORBA_String) optarg;
+ continue;
+
+ case 'o': // orb name
+ orb_name = optarg;
+ continue;
+
+ case 'p': // portnum
+ oa_name = optarg;
+ continue;
+
+ case 't': // create thread-per-request
+ do_threads = CORBA_B_TRUE;
+ continue;
+
+ // XXX set debug filters ...
+
+ //
+ // XXX ignore OMG-specified options ... hope nobody ever tries
+ // to use that "-ORB* param" and "-OA* param" syntax, it flies
+ // in the face of standard command parsing algorithms which
+ // require single-character option specifiers.
+ //
+
+ case '?':
+ default:
+ fprintf (stderr, "usage: %s"
+ " [-d]"
+ " [-f]"
+ " [-i idle_seconds]"
+ " [-k]"
+ " [-k object_key=key0]"
+ " [-o orb_name=internet]"
+ " [-p portnum=5555]"
+ " [-t]"
+ "\n", argv [0]
+ );
+ return 1;
+ }
+
+ orb_ptr = CORBA_ORB_init (argc, argv, orb_name, env);
+ if (env.exception () != 0) {
+ print_exception (env.exception (), "ORB init");
+ return 1;
+ }
+
+ oa_ptr = TCP_OA::init (orb_ptr, oa_name, env);
+ if (env.exception () != 0) {
+ print_exception (env.exception (), "OA init");
+ return 1;
+ }
+
+ return OA_listen (orb_ptr, oa_ptr, key, idle, do_fork, do_threads);
+}
+
diff --git a/TAO/IIOP/test/test1.cpp b/TAO/IIOP/test/test1.cpp
new file mode 100644
index 00000000000..78506e07e24
--- /dev/null
+++ b/TAO/IIOP/test/test1.cpp
@@ -0,0 +1,383 @@
+// @(#)test1.cpp 1.4 95/09/28
+// Copyright 1995 by Sun Microsystems, Inc.
+// All Rights Reserved
+//
+// TEST stubs for "test1"
+//
+
+#include <stdio.h>
+
+#include "test1.hh"
+
+
+//
+// Define all the stubs ... it's a lot less error prone to do it with
+// macros than by hand!
+//
+// NOTE: the "calldata" is exported for use by the skeletons. At some
+// point skeletons will probably be fully abstracted; for now they aren't.
+//
+// Also, for some reason, name mangling is changed by the explicit
+// declaration as "extern" -- if it's not done, linking fails.
+//
+#define DEFINE_TEST3(typename, truetype, truetypename) \
+ static const paramdata test1_ ## typename ## _paramdata [4] = { \
+ { _tc_CORBA_ ## truetypename, PARAM_RETURN, 0 }, \
+ { _tc_CORBA_ ## truetypename, PARAM_IN, 0 }, \
+ { _tc_CORBA_ ## truetypename, PARAM_OUT, 0 }, \
+ { _tc_CORBA_ ## truetypename, PARAM_INOUT, 0 }, \
+ }; \
+ \
+ extern const calldata test1_ ## typename ## _calldata; \
+ \
+ const calldata test1_ ## typename ## _calldata = { \
+ "test_" #typename, CORBA_B_TRUE, \
+ 4, &test1_ ## typename ## _paramdata [0], \
+ 0, 0, \
+ }; \
+ \
+ CORBA_ ## truetype \
+ test1_test_ ## typename (test1_ptr target, \
+ CORBA_ ## truetype in_a1, \
+ CORBA_ ## truetype &out_a2, \
+ CORBA_ ## truetype &inout_a3, \
+ CORBA_Environment &env) { \
+ CORBA_ ## truetype _retval = 0; \
+ STUB_Object *_obj; \
+ if (target->QueryInterface (IID_STUB_Object, (void **)&_obj) \
+ != NOERROR) \
+ env.exception (new CORBA_INV_OBJREF (COMPLETED_NO)); \
+ else { \
+ _obj->do_call (env, &test1_ ## typename ## _calldata, \
+ &_retval, &in_a1, &out_a2, &inout_a3); \
+ _obj->Release (); \
+ } \
+ return _retval; \
+ }
+
+#define DEFINE_TEST(typename, truetype) \
+ DEFINE_TEST3(typename, truetype, truetype)
+
+
+//
+// Generate a system exception, passing an operation ID that's
+// not allowed by IIOP (much less this interface) and verifying
+// that the server returns some kind of system exception.
+//
+static const calldata illegal_calldata = {
+ "+_illegal", CORBA_B_TRUE,
+ 0, 0,
+ 0, 0
+};
+
+void
+test_illegal (test1_ptr target, CORBA_Environment &env)
+{
+ STUB_Object *data;
+
+ if (target->QueryInterface (IID_STUB_Object, (void **)&data)
+ != NOERROR)
+ env.exception (new CORBA_INV_OBJREF (COMPLETED_NO));
+ else {
+ data->do_call (env, &illegal_calldata
+ );
+ data->Release ();
+ }
+}
+
+
+extern const calldata test1_void_calldata;
+const calldata test1_void_calldata = {
+ "test_void", CORBA_B_TRUE,
+ 0, 0,
+ 0, 0
+};
+
+void
+test1_test_void (test1_ptr target, CORBA_Environment &env)
+{
+ STUB_Object *data;
+
+ if (target->QueryInterface (IID_STUB_Object, (void **)&data)
+ != NOERROR)
+ env.exception (new CORBA_INV_OBJREF (COMPLETED_NO));
+ else {
+ data->do_call (env, &test1_void_calldata
+ );
+ data->Release ();
+ }
+}
+
+DEFINE_TEST (short, Short);
+DEFINE_TEST (long, Long);
+DEFINE_TEST (ushort, UShort);
+DEFINE_TEST (ulong, ULong);
+
+#if defined(MIPS)
+//
+// NOTE: C/C++ compilers as a rule pass a "float" in the space that
+// a "double" takes up. Conversions are evidently optional; portability
+// forces the following "explicit temporary" hack to work on at least
+// one MIPS platform, which converts the parameter to "double" and
+// hence changes the binary representation. (Even if that is a compiler
+// bug, it's probably required by now for binary compatibility!)
+//
+// A "-k ansi" compiler flag may be needed to get correct behaviour;
+// passing the "in" parameters by reference apparently works too. At
+// this time, none of these solutions is used by default.
+//
+// This stub-level hackery seems like it could be replaced inside of the
+// stub interpreter, which could just manually convert "float" parameters
+// (all of them) as special cases. But of course, that would slow the
+// interpreter down on _every_ call, not just the ones that require it
+// (such as this one). Tradeoffs!
+//
+static const paramdata test1_float_paramdata [4] = {
+ { _tc_CORBA_Float , PARAM_RETURN , 0 },
+ { _tc_CORBA_Float , PARAM_IN , 0 },
+ { _tc_CORBA_Float , PARAM_OUT , 0 },
+ { _tc_CORBA_Float , PARAM_INOUT , 0 }
+};
+
+extern const calldata test1_float_calldata;
+
+const calldata test1_float_calldata = {
+ "test_float", CORBA_B_TRUE,
+ 4 , &test1_float_paramdata [0],
+ 0 , 0
+};
+
+CORBA_Float
+test1_test_float (
+ test1_ptr target,
+ CORBA_Float in_a1,
+ CORBA_Float &out_a2,
+ CORBA_Float &inout_a3,
+ CORBA_Environment &env
+)
+{
+ CORBA_Float _retval;
+
+ // These three temporaries required due to MIPS compiler bug
+ CORBA_Float _in_a1 = in_a1;
+ CORBA_Float _out_a2 = out_a2;
+ CORBA_Float _inout_a3 = inout_a3;
+
+ target -> data -> do_call (env,
+ &test1_float_calldata,
+ &_retval,
+ &_in_a1,
+ &_out_a2,
+ &_inout_a3);
+ return _retval;
+}
+
+#else
+DEFINE_TEST (float, Float);
+#endif // MIPS
+
+
+DEFINE_TEST (double, Double);
+DEFINE_TEST (boolean, Boolean);
+DEFINE_TEST (char, Char);
+DEFINE_TEST (octet, Octet);
+
+/*
+CORBA_Any *
+test1_test_any (test1_ptr target,
+ const CORBA_Any &in_a1,
+ CORBA_Any *&out_a2,
+ CORBA_Any &inout_a3,
+ CORBA_Environment &env)
+{
+ // XXX implement this stub! ... annoying that C++ mapping
+ // calls for so much special casing
+}
+*/
+
+
+DEFINE_TEST3 (TypeCode, TypeCode_ptr, TypeCode);
+DEFINE_TEST3 (Principal, Principal_ptr, Principal);
+DEFINE_TEST3 (Object, Object_ptr, Object);
+
+// NOTE: C++ mapping has "in" strings as "const", which doesn't
+// show up in this macro ...
+DEFINE_TEST3 (string, Char *, String);
+
+DEFINE_TEST (longlong, LongLong);
+DEFINE_TEST (ulonglong, ULongLong);
+DEFINE_TEST (wchar, WChar);
+
+// NOTE: C++ mapping has "in" strings as "const", which doesn't
+// show up in this macro ...
+DEFINE_TEST3 (wstring, WChar *, WString);
+
+DEFINE_TEST (longdouble, LongDouble);
+
+#undef DEFINE_TEST
+
+
+//
+// Utility macros used to construct octet codes that are aligned
+// on longword boundaries, and with a known byte order. This
+// happens to use big endian encoding since it was convenient.
+// (Longword alignment is a happy accident of the specification
+// of OMG-IDL ... it could have been much worse!)
+//
+// It'd be much simpler to lay out such data in assembler!
+//
+
+#if defined (WORDS_BIGENDIAN)
+# define MAKE_BIG_LONG(a,b,c,d) \
+ ((((a) & 0xff) << 24) | (((b) & 0xff) << 16) \
+ | (((c) & 0xff) << 8) | ((d) & 0xff))
+# define BIG_ENDIAN_LONG(x) (x)
+
+#else // LITTLE_ENDIAN
+# define MAKE_BIG_LONG(a,b,c,d) \
+ ((((d) & 0xff) << 24) | (((c) & 0xff) << 16) \
+ | (((b) & 0xff) << 8) | ((a) & 0xff))
+# define BYTE_FROM(n,integer) (((integer)>>(8*(n)))&0xff)
+# define BIG_ENDIAN_LONG(integer) \
+ MAKE_BIG_LONG (BYTE_FROM(3,integer), BYTE_FROM(2,integer),\
+ BYTE_FROM(1,integer), BYTE_FROM(0,integer))
+#endif
+
+
+
+//
+// "x1" exception typecode ... must be longword aligned
+//
+static CORBA_Long oc_x1 [] = {
+ 0, // big endian flag + padding
+ BIG_ENDIAN_LONG (29), // length of ID string + NUL
+ MAKE_BIG_LONG ('I', 'D', 'L', ':'), // bytes of ID string
+ MAKE_BIG_LONG ('E', 'n', 'g', '.'),
+ MAKE_BIG_LONG ('S', 'U', 'N', '.'),
+ MAKE_BIG_LONG ('C', 'O', 'M', '/'),
+ MAKE_BIG_LONG ('t', 'e', 's', 't'),
+ MAKE_BIG_LONG ('1', '/', 'x', '1'),
+ MAKE_BIG_LONG (':', '1', '.', '0'),
+ 0,
+ BIG_ENDIAN_LONG (1), // (empty) namelen + NUL
+ 0,
+ BIG_ENDIAN_LONG (1), // only one struct member
+ BIG_ENDIAN_LONG (1), // (empty) member name + NUL
+ 0,
+ BIG_ENDIAN_LONG (tk_long)
+};
+static CORBA_TypeCode tc_x1 (tk_except, sizeof oc_x1,
+ (unsigned char *)&oc_x1, CORBA_B_FALSE);
+CORBA_TypeCode_ptr _tc_test1_x1 = &tc_x1;
+
+
+
+//
+// "x2" exception typecode ... must be longword aligned
+//
+static CORBA_Long oc_x2 [] = {
+ 0, // big endian flag + padding
+ BIG_ENDIAN_LONG (29), // length of ID string + NUL
+ MAKE_BIG_LONG ('I', 'D', 'L', ':'), // bytes of ID string
+ MAKE_BIG_LONG ('E', 'n', 'g', '.'),
+ MAKE_BIG_LONG ('S', 'U', 'N', '.'),
+ MAKE_BIG_LONG ('C', 'O', 'M', '/'),
+ MAKE_BIG_LONG ('t', 'e', 's', 't'),
+ MAKE_BIG_LONG ('1', '/', 'x', '2'),
+ MAKE_BIG_LONG (':', '1', '.', '0'),
+ 0,
+ BIG_ENDIAN_LONG (1), // (empty) namelen + NUL
+ 0,
+ BIG_ENDIAN_LONG (2), // two struct members
+
+ BIG_ENDIAN_LONG (1), // (empty) member name + NUL
+ 0,
+ BIG_ENDIAN_LONG (tk_objref),
+ BIG_ENDIAN_LONG (29), // type ID + NUL
+ MAKE_BIG_LONG ('I', 'D', 'L', ':'), // bytes of ID string
+ MAKE_BIG_LONG ('o', 'm', 'g', '.'),
+ MAKE_BIG_LONG ('o', 'r', 'g', '/'),
+ MAKE_BIG_LONG ('C', 'O', 'R', 'B'),
+ MAKE_BIG_LONG ('A', '/', 'O', 'b'),
+ MAKE_BIG_LONG ('j', 'e', 'c', 't'),
+ MAKE_BIG_LONG (':', '1', '.', '0'),
+ 0,
+
+ BIG_ENDIAN_LONG (1), // (empty) member name + NUL
+ 0,
+ BIG_ENDIAN_LONG (tk_long)
+};
+static CORBA_TypeCode tc_x2 (tk_except, sizeof oc_x2,
+ (unsigned char *)&oc_x2, CORBA_B_FALSE);
+CORBA_TypeCode_ptr _tc_test1_x2 = &tc_x2;
+
+
+//
+// parameter, exception, and call descriptions for "test_throw"
+//
+static const paramdata test1_test_throw_paramdata [1] = {
+ { _tc_CORBA_Long, PARAM_IN, 0 }
+};
+
+static CORBA_TypeCode_ptr test1_test_throw_excepts [2] = {
+ &tc_x1, &tc_x2
+};
+
+extern const calldata test1_test_throw_calldata;
+
+const calldata test1_test_throw_calldata = {
+ "test_throw", CORBA_B_TRUE,
+ 1, &test1_test_throw_paramdata [0],
+ 2, &test1_test_throw_excepts [0]
+};
+
+//
+// "test_throw" stub
+//
+void
+test1_test_throw (
+ test1_ptr target,
+ CORBA_Long case_num,
+ CORBA_Environment &env // throw (x1, x2)
+)
+{
+ STUB_Object *data;
+
+ if (target->QueryInterface (IID_STUB_Object, (void **)&data)
+ != NOERROR)
+ env.exception (new CORBA_INV_OBJREF (COMPLETED_NO));
+ else {
+ data->do_call (env, &test1_test_throw_calldata,
+ &case_num);
+ data->Release ();
+ }
+}
+
+//
+// PLEASE EXIT
+//
+
+static const calldata test1_please_exit_calldata = {
+ "please_exit", CORBA_B_FALSE,
+ 0, 0,
+ 0, 0
+};
+
+void
+test1_please_exit (
+ test1_ptr target,
+ CORBA_Environment &env
+)
+{
+ STUB_Object *data;
+
+ if (target->QueryInterface (IID_STUB_Object, (void **)&data)
+ != NOERROR)
+ env.exception (new CORBA_INV_OBJREF (COMPLETED_NO));
+ else {
+ data->do_call (env, &test1_please_exit_calldata
+ );
+ data->Release ();
+ }
+}
+
diff --git a/TAO/IIOP/test/test1.hh b/TAO/IIOP/test/test1.hh
new file mode 100644
index 00000000000..3d5f2fed7bb
--- /dev/null
+++ b/TAO/IIOP/test/test1.hh
@@ -0,0 +1,124 @@
+// @(#)test1.hh 1.2 95/09/12
+// Copyright 1995 by Sun Microsystems, Inc.
+// All Rights Reserved
+//
+// TEST interface for "test1"
+//
+
+#ifndef _TEST1_HH
+#define _TEST1_HH
+
+#include <corba/orb.hh>
+#include <corba/stub.hh>
+
+
+#ifdef _MSC_VER
+#pragma pack (push, 1) // VC++, known padding rules
+#endif // VC++
+
+typedef CORBA_UShort test1_ushort;
+typedef CORBA_ULong test1_ulong;
+
+typedef CORBA_LongLong test1_longlong;
+typedef CORBA_ULongLong test1_ulonglong;
+typedef CORBA_LongDouble test1_longdouble;
+
+typedef CORBA_Object test1;
+typedef test1 *test1_ptr;
+
+#define DECL_TEST(typename, truetype) \
+ truetype \
+ test1_test_ ## typename ( \
+ test1_ptr target, \
+ truetype in_a1, \
+ truetype &out_a2, \
+ truetype &inout_a3, \
+ CORBA_Environment &env \
+ )
+
+void test_illegal (test1_ptr target, CORBA_Environment &env);
+void test1_test_void (test1_ptr target, CORBA_Environment &env);
+
+DECL_TEST (short, CORBA_Short);
+DECL_TEST (long, CORBA_Long);
+DECL_TEST (ushort, CORBA_UShort);
+DECL_TEST (ulong, CORBA_ULong);
+DECL_TEST (float, CORBA_Float);
+DECL_TEST (double, CORBA_Double);
+DECL_TEST (boolean, CORBA_Boolean);
+DECL_TEST (char, CORBA_Char);
+DECL_TEST (octet, CORBA_Octet);
+
+CORBA_Any *
+test1_test_any (
+ test1_ptr target,
+ const CORBA_Any &in_a1,
+ CORBA_Any *&out_a2,
+ CORBA_Any &inout_a3,
+ CORBA_Environment &env
+);
+
+DECL_TEST (TypeCode, CORBA_TypeCode_ptr);
+DECL_TEST (Principal, CORBA_Principal_ptr);
+DECL_TEST (Object, CORBA_Object_ptr);
+
+// NOTE: CORBA C++ mapping says the "in" string is const
+DECL_TEST (string, CORBA_String);
+
+DECL_TEST (longlong, CORBA_LongLong);
+DECL_TEST (ulonglong, CORBA_ULongLong);
+DECL_TEST (wchar, CORBA_WChar);
+
+// NOTE: CORBA C++ mapping says the "in" string is const
+DECL_TEST (wstring, CORBA_WString);
+
+DECL_TEST (longdouble, CORBA_LongDouble);
+
+#undef DECL_TEST
+
+extern CORBA_TypeCode_ptr _tc_test1_x1;
+
+class test1_x1 : public CORBA_UserException {
+ public:
+ CORBA_Long case_num;
+
+ test1_x1 (CORBA_Long n)
+ : CORBA_UserException (_tc_test1_x1), case_num (n)
+ { }
+};
+
+extern CORBA_TypeCode_ptr _tc_test1_x2;
+
+class test1_x2 : public CORBA_UserException {
+ public:
+ CORBA_Object_ptr obj;
+ CORBA_Long case_num;
+
+ test1_x2 (CORBA_Object_ptr obj1,
+ CORBA_Long n)
+ : CORBA_UserException (_tc_test1_x2),
+ obj (obj1), case_num (n) { }
+
+ ~test1_x2 ()
+ { CORBA_release (obj); }
+};
+
+void
+test1_test_throw (
+ test1_ptr target,
+ CORBA_Long case_num,
+ CORBA_Environment &env // throw (x1, x2)
+);
+
+void
+test1_please_exit (
+ test1_ptr target,
+ CORBA_Environment &env
+);
+
+#ifdef _MSC_VER
+#pragma pack (pop) // VC++, go back to other padding rules
+#endif // VC++
+
+#endif // _TEST1_HH
+
diff --git a/TAO/IIOP/test/test1.idl b/TAO/IIOP/test/test1.idl
new file mode 100644
index 00000000000..e6cf20cd2de
--- /dev/null
+++ b/TAO/IIOP/test/test1.idl
@@ -0,0 +1,78 @@
+// @(#)test1.idl 1.1 95/09/11
+// Copyright 1994-1995 by Sun Microsystems, Inc.
+//
+// TEST basic marshaling tests for all IDL primitive types, modes
+//
+// This test omits constructed types (struct, union, enum, sequence, and
+// array types), and only tests very simple user defined exceptions.
+//
+// Values returned are well defined functions of the input values:
+//
+// * For numeric types (octet, short, long, longlong, float, double,
+// longdouble, and unsigned variants) the value is cubed.
+// * For Boolean, it's the negation.
+// * For Any, TypeCode, Principal, Object, char and wchar,
+// string and wstring, it's the input value.
+//
+// The "return" and "out" parameter is the function of the "in" parameter;
+// the "inout" parameter is the function of its original value.
+//
+// The "echo" test has all output values be the input values, with no
+// changes to the bit patterns originally transmitted. While easier to
+// use to identify some kinds of problem, it is not as complete a test.
+//
+
+#define DECL_TEST(type) \
+ type test_ ## type ( in type a1, out type a2, inout type a3)
+
+#pragma prefix "Eng.SUN.COM" // only for Sun-defined interfaces
+
+interface test1 {
+ void test_void ();
+
+ typedef unsigned short ushort;
+ typedef unsigned long ulong;
+
+ typedef long long longlong;
+ typedef unsigned long long ulonglong;
+ typedef long double longdouble;
+
+ DECL_TEST (short);
+ DECL_TEST (long);
+ DECL_TEST (ushort);
+ DECL_TEST (ulong);
+ DECL_TEST (float);
+ DECL_TEST (double);
+ DECL_TEST (boolean);
+ DECL_TEST (char);
+ DECL_TEST (octet);
+ DECL_TEST (any);
+ DECL_TEST (TypeCode);
+ DECL_TEST (Principal);
+ DECL_TEST (Object); // CORBA::Object
+ DECL_TEST (string); // unbounded string
+
+ DECL_TEST (longlong);
+ DECL_TEST (ulonglong);
+ DECL_TEST (wchar);
+ DECL_TEST (wstring); // unbounded wstring
+ DECL_TEST (longdouble);
+
+ //
+ // All cases, "case_num" in the exception is the same as the 'in' param
+ // * negative or zero, throws x1
+ // * positive even cases, throws x2 with obj = null objref
+ // * positive odd cases, throws x2 with obj = target objref
+ //
+ exception x1 { long case_num; };
+ exception x2 { Object obj; long case_num; };
+
+ void test_throw (in long case_num) raises (x1, x2);
+
+ //
+ // Aid for test cleanup in case server's not told to quit after
+ // being idle for some time period
+ //
+ oneway void please_exit ();
+};
+
diff --git a/TAO/IIOP/test/test1_clnt.cpp b/TAO/IIOP/test/test1_clnt.cpp
new file mode 100644
index 00000000000..53a0c504580
--- /dev/null
+++ b/TAO/IIOP/test/test1_clnt.cpp
@@ -0,0 +1,636 @@
+// @(#)test1_clnt.cpp 1.5 95/09/24
+// Copyright 1995 by Sun Microsystems, Inc.
+// All Rights Reserved
+//
+// TEST client driver for "test1"
+//
+
+#ifdef USE_IOSTREAM
+#include <iostream.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#if unix
+# include <unistd.h>
+
+#else // windows
+# include "getopt.h" // e.g. GNU's version
+
+#endif // unix
+
+#include "test1.hh"
+#include "../lib/runtime/debug.hh"
+
+
+extern char *optarg; // missing on some platforms
+
+extern void
+print_exception (const CORBA_Exception *, const char *, FILE *f=stdout);
+
+
+//
+// All tests are specified so that the return value and "out" (second)
+// parameters are easily tested functions of the "in" (first) parameter,
+// and the "inout" (third) parameter is the same function the its
+// initial value. Caller is expected to specify two different "in"
+// values. This helps make the marshaled bits vary, and turn up a class
+// of potential problems that'd be hidden if parameter order had no
+// effect on the test.
+//
+// PERFORM_TEST calls a test for a given type, reporting in cases where
+// the ORB or operation failed. The COMPARE symbol can be redefined
+// to achieve different functions -- e.g. cubing numbers, identity,
+// negation, etc. It should return true iff the correct result was
+// returned.
+//
+// BAD_COMPARE_VALUES is to produce diagnostics when a test fails,
+// showing the actual and expected values of returned parameters.
+// This helps diagnose specific porting problems.
+//
+// The RELEASE symbol may be defined to free memory, eliminating client
+// side memory leaks in the test.
+//
+#define RELEASE(X) // NOP by default
+#define PERFORM_TEST(name,type,value1,value2) \
+ { \
+ CORBA_ ## type v1, v2, v3; \
+ \
+ v1 = (CORBA_ ## type)(value1); \
+ v2 = 0; \
+ v3 = (CORBA_ ## type)(value2); \
+ \
+ test_count++; \
+ v1 = test1_test_ ## name (target, v1, v2, v3, env); \
+ if (env.exception () != 0) { \
+ print_exception (env.exception (), "perform test_" #name); \
+ error_count++; \
+ } else if (!COMPARE (CORBA_ ## type, v1, value1) \
+ || !COMPARE (CORBA_ ## type, v2, value1) \
+ || !COMPARE (CORBA_ ## type, v3, value2) ) { \
+ fprintf (stderr, "bad comparison, test_" #name "\n"); \
+ BAD_COMPARE_VALUES(type,v1,v2,v3,value1,value2) \
+ error_count++; \
+ } \
+ RELEASE (v1); RELEASE (v2); RELEASE (v3); \
+ }
+
+//
+// This messing about is because the ostream op << cannot always
+// be used with all kinds of data ... e.g. LongDouble, TypeCode.
+//
+#ifdef USE_IOSTREAM
+# define DO_IO(x) x
+#else
+# define DO_IO(x)
+#endif
+#define BAD_COMPARE_VALUE_OUT(type,v1,v2,v3,value1,value2) \
+ DO_IO( cerr << " v1=" << v1; \
+ cerr << " expecting " << EXPVAL(CORBA_ ## type, value1) << "\n"; \
+ cerr << " v2=" << v2; \
+ cerr << " expecting " << EXPVAL(CORBA_ ## type, value1) << "\n"; \
+ cerr << " v3=" << v3; \
+ cerr << " expecting " << EXPVAL(CORBA_ ## type, value2) << "\n");
+#define BAD_COMPARE_VALUES(type,v1,v2,v3,value1,value2) \
+ BAD_COMPARE_VALUE_OUT(type,v1,v2,v3,value1,value2)
+
+
+//
+// test utility -- should be able to just use is_equivalent() directly
+// but this implementation uses null pointers for nil, so this must
+// check for nulls first. (May be noncompliant with C++ mapping!)
+//
+static CORBA_Boolean
+compare_objrefs (
+ CORBA_Object_ptr v1,
+ CORBA_Object_ptr v2
+)
+{
+ CORBA_Boolean temp;
+ CORBA_Environment env;
+
+ if (v1 == v2)
+ return CORBA_B_TRUE;
+
+ if (CORBA_is_nil (v1))
+ return CORBA_is_nil (v2);
+
+ temp = v1->_is_equivalent (v2, env);
+ if (env.exception () != 0) {
+ print_exception (env.exception (), "compare objref");
+ return CORBA_B_FALSE;
+ }
+ return temp;
+}
+
+
+//
+// Helper routine to help sure math (especially for floating point)
+// gets done correctly.
+//
+template <class Type>
+Type cube (Type arg)
+{
+ Type temp = arg;
+
+ temp = temp * arg;
+ temp = temp * arg;
+ return temp;
+}
+
+
+static int skip_longdouble = 0;
+
+//
+// This just performs the tests ...
+//
+void
+do_tests (
+ test1_ptr target,
+ unsigned loop_count,
+ unsigned &test_count,
+ unsigned &error_count
+)
+{
+ int count;
+
+ for (count = 0; count < loop_count; count++) {
+ CORBA_Environment env;
+ CORBA_Environment env2; // XXX
+
+ //
+ // test_void
+ //
+ test_count++;
+ test1_test_void (target, env);
+ if (env.exception () != 0) {
+ print_exception (env.exception (), "perform test_void");
+ error_count++;
+ }
+
+ //
+ // Numeric tests ... try some variety in computation, no real
+ // rationale in the choice of initial parameter values except
+ // not to use the same values all the time.
+ //
+#define EXPVAL(type,original_value) ((type) cube((type)(original_value)))
+#define COMPARE(type,retval,original_value) \
+ ((retval) == EXPVAL(type, original_value))
+
+ PERFORM_TEST (octet, Octet, count + 29, count - 22);
+
+ PERFORM_TEST (short, Short, count - 23, count + 19);
+ PERFORM_TEST (ushort, UShort, count + 23, count - 19);
+
+ PERFORM_TEST (long, Long, count - 17, count + 20);
+ PERFORM_TEST (ulong, ULong, count + 17, count - 20);
+
+#if !defined (NONNATIVE_LONGLONG)
+ // don't try this on platforms that don't support
+ // math on longlongs ...
+ PERFORM_TEST (longlong, LongLong, count - 177, count + 3);
+ PERFORM_TEST (ulonglong, ULongLong, count + 177, count - 3);
+#endif // !NONNATIVE_LONGLONG
+
+#if !defined (i386)
+ //
+ // XXX not sure what's wrong with the COMPARE macro with respect to
+ // floating point on x86, since fprintf shows the values basically
+ // look correct ... but these float/double tests fail.
+ //
+ PERFORM_TEST (float, Float, count - 0.29, count + 3.14159);
+ PERFORM_TEST (double, Double, count * 1.77, count * 2.71);
+#endif // !defined (i386)
+
+
+#ifndef NONNATIVE_LONGDOUBLE
+#undef BAD_COMPARE_VALUES
+#define BAD_COMPARE_VALUES(type,v1,v2,v3,value1,value2) // NOP
+
+ //
+ // don't try this between two platforms that don't provide
+ // arithmetic support for LongDouble values ...
+ //
+ if (!skip_longdouble) {
+ PERFORM_TEST (longdouble, LongDouble,
+ count - 2.33, count * 3.14159);
+ }
+
+# undef BAD_COMPARE_VALUES
+# define BAD_COMPARE_VALUES(type,v1,v2,v3,value1,value2) \
+ BAD_COMPARE_VALUE_OUT(type,v1,v2,v3,value1,value2)
+#endif // !NONNATIVE_LONGDOUBLE
+
+#undef COMPARE
+#undef EXPVAL
+
+
+ //
+ // Boolean -- negation
+ //
+#define EXPVAL(type,original_value) (!(type)(original_value))
+#define COMPARE(type,retval,original_value) \
+ (((type)(retval)) == EXPVAL(type,original_value))
+
+ PERFORM_TEST (boolean, Boolean,
+ (count & 0x01) != 0, (count & 0x01) == 0);
+#undef COMPARE
+#undef EXPVAL
+
+ //
+ // Char, WChar -- identity
+ //
+#define EXPVAL(type,original_value) ((type)(original_value))
+#define COMPARE(type,retval,original_value) \
+ (((type)(retval)) == EXPVAL(type,original_value))
+
+ PERFORM_TEST (char, Char, count + 26, count - 5);
+ PERFORM_TEST (wchar, WChar, count, count + 25);
+#undef COMPARE
+#undef EXPVAL
+
+ //
+ // Object_ptr -- identity (special comparision)
+ //
+#define EXPVAL(type,original_value) ((type)(original_value))
+#define COMPARE(type,retval,original_value) \
+ (compare_objrefs (retval, original_value) == CORBA_B_TRUE)
+#undef RELEASE
+#define RELEASE(obj) \
+ { CORBA_release (obj); }
+
+ PERFORM_TEST (Object, Object_ptr, target, CORBA_Object::_nil ());
+#undef COMPARE
+#undef EXPVAL
+
+ //
+ // TypeCode_ptr -- identity (special comparision), and verifies
+ // that most of the built-in typecode constants exist.
+ //
+ // XXX should try this on all standard and system exceptions!
+ //
+ // XXX this currently tests only marshaling/unmarshaling of
+ // "no parameter" TypeCodes ... complex ones (objref, struct,
+ // union, enum, sequence, array, alias, exception) are _NOT_
+ // currently attempted.
+ //
+ // XXX for the simple typecodes (string, wstring), the single
+ // "bound" parameter isn't exercised/verified as it should be.
+ //
+#define EXPVAL(type,original_value) ((type)(original_value))
+#define COMPARE(type,retval,original) \
+ (((retval) == (original)) || \
+ ((retval)->_kind == (original)->_kind))
+
+#undef RELEASE
+#define RELEASE(tc) \
+ { CORBA_release (tc); }
+
+#undef BAD_COMPARE_VALUES
+#define BAD_COMPARE_VALUES(type,v1,v2,v3,value1,value2) // NOP
+
+ {
+ PERFORM_TEST (TypeCode, TypeCode_ptr,
+ _tc_CORBA_Null, _tc_CORBA_Void);
+
+ PERFORM_TEST (TypeCode, TypeCode_ptr,
+ _tc_CORBA_Short, _tc_CORBA_UShort);
+ PERFORM_TEST (TypeCode, TypeCode_ptr,
+ _tc_CORBA_Long, _tc_CORBA_ULong);
+ PERFORM_TEST (TypeCode, TypeCode_ptr,
+ _tc_CORBA_LongLong, _tc_CORBA_ULongLong);
+
+ PERFORM_TEST (TypeCode, TypeCode_ptr,
+ _tc_CORBA_Float, _tc_CORBA_Double);
+
+ PERFORM_TEST (TypeCode, TypeCode_ptr,
+ _tc_CORBA_Boolean, _tc_CORBA_Octet);
+
+ PERFORM_TEST (TypeCode, TypeCode_ptr,
+ _tc_CORBA_Any, _tc_CORBA_TypeCode);
+
+ PERFORM_TEST (TypeCode, TypeCode_ptr,
+ _tc_CORBA_LongDouble, _tc_CORBA_Principal);
+
+ PERFORM_TEST (TypeCode, TypeCode_ptr,
+ _tc_CORBA_Char, _tc_CORBA_String);
+ PERFORM_TEST (TypeCode, TypeCode_ptr,
+ _tc_CORBA_WChar, _tc_CORBA_WString);
+
+ PERFORM_TEST (TypeCode, TypeCode_ptr,
+ _tc_CORBA_LongDouble, _tc_CORBA_Octet);
+
+ //
+ // Try all of the standard exception typecodes.
+ //
+ PERFORM_TEST (TypeCode, TypeCode_ptr,
+ _tc_CORBA_UNKNOWN, _tc_CORBA_BAD_PARAM);
+ PERFORM_TEST (TypeCode, TypeCode_ptr,
+ _tc_CORBA_NO_MEMORY, _tc_CORBA_IMP_LIMIT);
+ PERFORM_TEST (TypeCode, TypeCode_ptr,
+ _tc_CORBA_COMM_FAILURE, _tc_CORBA_INV_OBJREF);
+ PERFORM_TEST (TypeCode, TypeCode_ptr,
+ _tc_CORBA_OBJECT_NOT_EXIST, _tc_CORBA_NO_PERMISSION);
+ PERFORM_TEST (TypeCode, TypeCode_ptr,
+ _tc_CORBA_INTERNAL, _tc_CORBA_MARSHAL);
+ PERFORM_TEST (TypeCode, TypeCode_ptr,
+ _tc_CORBA_INITIALIZE, _tc_CORBA_NO_IMPLEMENT);
+ PERFORM_TEST (TypeCode, TypeCode_ptr,
+ _tc_CORBA_BAD_TYPECODE, _tc_CORBA_BAD_OPERATION);
+ PERFORM_TEST (TypeCode, TypeCode_ptr,
+ _tc_CORBA_NO_RESOURCES, _tc_CORBA_NO_RESPONSE);
+ PERFORM_TEST (TypeCode, TypeCode_ptr,
+ _tc_CORBA_PERSIST_STORE, _tc_CORBA_BAD_INV_ORDER);
+ PERFORM_TEST (TypeCode, TypeCode_ptr,
+ _tc_CORBA_TRANSIENT, _tc_CORBA_FREE_MEM);
+ PERFORM_TEST (TypeCode, TypeCode_ptr,
+ _tc_CORBA_INV_IDENT, _tc_CORBA_INV_FLAG);
+ PERFORM_TEST (TypeCode, TypeCode_ptr,
+ _tc_CORBA_INTF_REPOS, _tc_CORBA_BAD_CONTEXT);
+ PERFORM_TEST (TypeCode, TypeCode_ptr,
+ _tc_CORBA_OBJ_ADAPTER, _tc_CORBA_DATA_CONVERSION);
+
+ //
+ // All the built-in "user defined" system exceptions.
+ //
+ PERFORM_TEST (TypeCode, TypeCode_ptr,
+ _tc_CORBA_BadKind, _tc_CORBA_Bounds);
+ }
+#undef COMPARE
+#undef RELEASE
+
+ //
+ // string (unbounded)-- identity (special comparision)
+ //
+#define COMPARE(type,retval,original_value) \
+ (strcmp ((char *)(retval), (char*)(original_value)) == 0)
+#undef RELEASE
+#define RELEASE(obj) CORBA_string_free(obj)
+ static const CORBA_Char str1 [] = "small";
+ static const CORBA_Char str2 [] =
+ "relatively long string, constructed"
+ " with the aid of C++ implicit string"
+ " catenation, which simplifies much stuff";
+ PERFORM_TEST (string, String, str1, str2);
+#undef COMPARE
+#undef RELEASE
+
+
+ // XXX any, principal, wstring ... output _is_ input
+
+
+ //
+ // Three test cases involve throwing user-defined exceptions.
+ //
+ {
+ CORBA_Exception *xp;
+
+ //
+ // Case one: with parameter <= zero, must throw
+ // an "x1" exception whose "case_num" is that parameter
+ //
+ test_count++;
+
+ test1_test_throw (target, -5, env);
+ if (env.exception () != 0) {
+ xp = env.exception ();
+
+ if (strcmp ((char *)xp->id (),
+ (char *) _tc_test1_x1->id (env2)) != 0) {
+ error_count++;
+ fprintf (stderr, "test_throw case 1, "
+ "wrong exception thrown (id = '%s')\n",
+ xp->id ());
+ } else {
+ test1_x1 *xp2 = (test1_x1 *) xp;
+
+ if (xp2->case_num != -5) {
+ error_count++;
+ fprintf (stderr, "test_throw case 1, "
+ "wrong value (case_num = '%ld')\n",
+ xp2->case_num);
+ }
+
+ // else, right exception was thrown
+ }
+ } else {
+ error_count++;
+ fprintf (stderr, "test_throw case 1, "
+ "no exception thrown !!\n");
+ }
+
+
+ //
+ // Case two: with positive odd parameter, must throw
+ // an "x2" exception whose obj is null, and whose case_num
+ // is that parameter
+ //
+ test_count++;
+
+ test1_test_throw (target, 101, env);
+ if (env.exception () != 0) {
+ xp = env.exception ();
+
+ if (strcmp ((char *)xp->id (),
+ (char *) _tc_test1_x2->id (env2)) != 0) {
+ error_count++;
+ fprintf (stderr, "test_throw case 2, "
+ "wrong exception thrown (id = '%s')\n",
+ xp->id ());
+ } else {
+ test1_x2 *xp2 = (test1_x2 *) xp;
+
+ if (xp2->case_num != 101) {
+ error_count++;
+ fprintf (stderr, "test_throw case 2, "
+ "wrong value (case_num = '%ld')\n",
+ xp2->case_num);
+ }
+
+ if (!CORBA_is_nil (xp2->obj)) {
+ error_count++;
+ fprintf (stderr, "test_throw case 2, "
+ "non-null objref thrown\n");
+ }
+
+ // else, right exception was thrown
+ }
+ } else {
+ error_count++;
+ fprintf (stderr, "test_throw case 2, "
+ "no exception thrown !!\n");
+ }
+
+
+#if 0
+// 18-sept-95: commented this out. Work remains to be done in
+// this area: (a) ServerRequest::target operation unimplemented,
+// so for the servers of current interest this test is no help;
+// (b) probable pointer leak in exceptions holding data.
+
+ //
+ // Case three: with positive even parameter, must throw
+ // an "x2" exception whose obj is the target, and whose
+ // case_num is that parameter
+ //
+ test_count++;
+
+ test1_test_throw (target, 42, env);
+ if (env.exception () != 0) {
+ xp = env.exception ();
+
+ if (strcmp ((char *)xp->id (),
+ (char *) _tc_test1_x2->id (env2)) != 0) {
+ error_count++;
+ fprintf (stderr, "test_throw case 3, "
+ "wrong exception thrown (id = '%s')\n",
+ xp->id ());
+ } else {
+ test1_x2 *xp2 = (test1_x2 *) xp;
+
+ if (xp2->case_num != 42) {
+ error_count++;
+ fprintf (stderr, "test_throw case 3, "
+ "wrong value (case_num = '%ld')\n",
+ xp2->case_num);
+ }
+
+ CORBA_Boolean status;
+
+ status = target->_is_equivalent (xp2->obj, env);
+
+ if (env.exception () != 0) {
+ error_count++;
+ print_exception (env.exception (),
+ "test_throw/3 call to is_equivalent");
+ } else if (status != CORBA_B_TRUE) {
+ error_count++;
+ fprintf (stderr, "test_throw case 3, "
+ "non-equivalent objref thrown\n");
+ }
+
+ // else, right exception was thrown
+ }
+ } else {
+ error_count++;
+ fprintf (stderr, "test_throw case 3, "
+ "no exception thrown !!\n");
+ }
+
+ env.clear ();
+#endif // 0
+
+ }
+
+ //
+ // test_illegal -- generate a BAD_OPERATION system exception
+ // from the remote process
+ //
+ test_count++;
+ test_illegal (target, env);
+ if (env.exception () == 0
+ || strcmp ((char *) env.exception()->id(),
+ (char *) _tc_CORBA_BAD_OPERATION->id (env2)) != 0) {
+ fprintf (stderr, "couldn't generate BAD_OPERATION exception\n");
+ error_count++;
+ }
+ }
+}
+
+
+int
+main (
+ int argc,
+ char *const *argv
+)
+{
+ CORBA_ORB_ptr orb_ptr;
+ CORBA_Environment env;
+ CORBA_Object_ptr objref = CORBA_Object::_nil();
+ unsigned loop_count = 1;
+ unsigned tests = 0, errors = 0;
+ int exit_later = 0;
+
+ orb_ptr = CORBA_ORB_init (argc, argv, "internet", env);
+ if (env.exception () != 0) {
+ dexc (env, "ORB initialisation");
+ return 1;
+ }
+
+ //
+ // Parse and verify parameters.
+ //
+ int c;
+
+ while ((c = getopt (argc, argv, "dln:O:x")) != EOF)
+ switch (c) {
+ case 'd': // debug flag
+ debug_level++;
+ continue;
+
+ case 'l': // skip "long double" test
+ skip_longdouble++;
+ continue;
+
+ case 'n': // loop count
+ loop_count = (unsigned) atoi (optarg);
+ continue;
+
+ case 'O': // stringified objref
+ {
+ objref = orb_ptr->string_to_object (
+ (CORBA_String)optarg, env);
+ if (env.exception () != 0) {
+ dexc (env, "string2object");
+ return 1;
+ }
+ }
+ continue;
+
+ case 'x':
+ exit_later++;
+ continue;
+
+ case '?':
+ default:
+ fprintf (stderr, "usage: %s"
+ " [-d]"
+ " [-l]"
+ " [-n loopcount]"
+ " [-O objref]"
+ " [-x]"
+ "\n", argv [0]
+ );
+ return 1;
+ }
+
+ if (CORBA_is_nil (objref) == CORBA_B_TRUE) {
+ fprintf (stderr, "%s: must identify non-null target objref\n",
+ argv [0]);
+ return 1;
+ }
+
+
+ do_tests (objref, loop_count, tests, errors);
+
+ char *progname = strrchr (argv [0], '/');
+
+ if (progname != 0)
+ progname += 1;
+ else
+ progname = argv [0];
+
+ fprintf (stderr, "%s: %d loops, %d tests (%d errors)\n",
+ progname, loop_count, tests, errors);
+
+ if (exit_later) {
+ test1_please_exit (objref, env);
+ if (env.exception () != 0)
+ print_exception (env.exception (), "test1_please_exit");
+ }
+
+ CORBA_release (objref);
+
+ return errors != 0;
+}
diff --git a/TAO/IIOP/test/test1_svr.cpp b/TAO/IIOP/test/test1_svr.cpp
new file mode 100644
index 00000000000..668fbae2afc
--- /dev/null
+++ b/TAO/IIOP/test/test1_svr.cpp
@@ -0,0 +1,644 @@
+// @(#)test1_svr.cpp 1.7 95/09/25
+// Copyright 1995 by Sun Microsystems Inc.
+// All Rights Reserved
+//
+// TEST: simple IIOP server for "test1.idl" interface.
+//
+// Starts up, builds an objref, prints its string, listens for
+// messages, responds to them.
+//
+
+#include <stdio.h>
+#include <string.h>
+
+#if unix
+# include <unistd.h> // for getopt on some systems
+
+#else // windows
+# include "getopt.h" // e.g. GNU's version
+
+#endif
+
+#include "test1.hh"
+#include <corba/toa.hh>
+
+#include "../lib/runtime/debug.hh"
+
+
+
+extern char *optarg; // missing on some platforms
+
+//
+// Skeleton code ... just a macro for a bunch of DSI-based method code,
+// in lieu of having an IDL compmiler generate static skeletons. Static
+// skeletons would be more efficient; most mallocation could go away.
+//
+// Use by: defining OPERATION macro, call DEFINE_SKEL3 as needed, then
+// undef OPERATION.
+//
+// NOTE: "v1_copy" below is needed to work around a bug with the
+// HP9000 G++ 2.6.3 compiler, with "LongLong".
+//
+// XXX this could probably be a template ... or could even be merged
+// directly into the Dynamic Implementation Routine below.
+//
+// XXX we must currently use IN_COPY_VALUE since the memory consumed
+// by the parameters must be deallocated by the ORB. When we get an
+// updated version of DSI which provides "send it now" semantics,
+// these should preallocate the values and not use IN_COPY_VALUE. A
+// net decrease in malloc overhead can be had that way. (NVList should
+// also get a public constructor, and a way to provide the buffer.)
+//
+#define DEFINE_SKEL3(name,truetype,truetypename) \
+ static void \
+ _test1_test_ ## name ( \
+ CORBA_ServerRequest &req, \
+ CORBA_Environment &env \
+ ) \
+ { \
+ CORBA_NVList_ptr nvlist; \
+ CORBA_ ## truetype scratch = 0; \
+ CORBA_Any temp_value (_tc_CORBA_ ## truetypename, \
+ &scratch, CORBA_B_FALSE); \
+ \
+ req.orb ()->create_list (3, nvlist); \
+ (void) nvlist->add_value (0, temp_value, \
+ CORBA_IN_COPY_VALUE|CORBA_ARG_IN, env); \
+ (void) nvlist->add_value (0, temp_value, \
+ CORBA_IN_COPY_VALUE|CORBA_ARG_OUT, env); \
+ (void) nvlist->add_value (0, temp_value, \
+ CORBA_IN_COPY_VALUE|CORBA_ARG_INOUT, env); \
+ \
+ req.params (nvlist, env); \
+ if (env.exception () != 0) { \
+ dexc (env, "test1_test_" # name "skeleton, req.params"); \
+ return; \
+ } \
+ \
+ CORBA_ ## truetype *v1, *v2, *retval; \
+ \
+ v1 = (CORBA_ ## truetype *) nvlist->item (0)->value ()->value (); \
+ v2 = new CORBA_ ## truetype; \
+ *v2 = (CORBA_ ## truetype) OPERATION (*v1); \
+ retval = new CORBA_ ## truetype; \
+ *retval = (CORBA_ ## truetype) OPERATION (*v1); \
+ \
+ CORBA_Any_ptr any_val; \
+ \
+ any_val = nvlist->item (1)->value (); \
+ any_val->replace (any_val->type (), v2, CORBA_B_TRUE, env); \
+ if (env.exception () != 0) { \
+ dexc (env, "test1_test_" # name "skeleton, val2 replace"); \
+ return; \
+ } \
+ \
+ v1 = (CORBA_ ## truetype *) nvlist->item (2)->value ()->value (); \
+ CORBA_ ## truetype v1copy = *v1; \
+ *v1 = (CORBA_ ## truetype) OPERATION (v1copy); \
+ \
+ any_val = new CORBA_Any (_tc_CORBA_ ## truetypename, \
+ retval, CORBA_B_TRUE); \
+ req.result (any_val, env); \
+ if (env.exception () != 0) { \
+ dexc (env, "test1_test_" # name "skeleton, result"); \
+ return; \
+ } \
+ } \
+ extern calldata test1_ ## name ## _calldata;
+
+
+extern const calldata test1_void_calldata;
+
+static void
+_test1_test_void (
+ CORBA_ServerRequest &req,
+ CORBA_Environment &env
+)
+{
+ CORBA_NVList_ptr nvlist;
+
+ req.orb ()->create_list (0, nvlist);
+ req.params (nvlist, env);
+
+ if (env.exception () != 0)
+ dexc (env, "test_throw, get params");
+}
+
+
+//
+// Dynamic Skeleton methods for numeric types ... these all just
+// cube their parameters in various permutations
+//
+template <class Type>
+Type cube (Type arg)
+{
+ Type temp = arg;
+
+ temp = temp * arg;
+ temp = temp * arg;
+ return temp;
+}
+
+#define OPERATION(n) cube(n)
+
+DEFINE_SKEL3 (octet, Octet, Octet)
+
+DEFINE_SKEL3 (short, Short, Short)
+DEFINE_SKEL3 (ushort, UShort, UShort)
+
+DEFINE_SKEL3 (long, Long, Long)
+DEFINE_SKEL3 (ulong, ULong, ULong)
+
+#if !defined (NONNATIVE_LONGLONG)
+ // don't try this on platforms that don't support
+ // math on longlongs ...
+DEFINE_SKEL3 (longlong, LongLong, LongLong)
+DEFINE_SKEL3 (ulonglong, ULongLong, ULongLong)
+#endif // !NONNATIVE_LONGLONG
+
+DEFINE_SKEL3 (float, Float, Float)
+DEFINE_SKEL3 (double, Double, Double)
+
+#if !defined (NONNATIVE_LONGDOUBLE)
+ // don't try this on platforms that don't support
+ // math on long doubles ...
+DEFINE_SKEL3 (longdouble, LongDouble, LongDouble)
+#endif // !NONNATIVE_LONGDOUBLE
+
+#undef OPERATION
+
+//
+// Dynamic Skeleton methods for Boolean type ... just negates its
+// parameters
+//
+#define OPERATION(x) (!(x))
+DEFINE_SKEL3 (boolean, Boolean, Boolean)
+#undef OPERATION
+
+//
+// For character types, output is same as input, no magic needed.
+//
+#define OPERATION(x) (x)
+DEFINE_SKEL3 (char, Char, Char)
+DEFINE_SKEL3 (wchar, WChar, WChar)
+#undef OPERATION
+
+//
+// For objref, typecode, output is same as input but duplication
+// is needed
+//
+#define OPERATION(x) ((x) ? (x)->AddRef() : 0, x)
+DEFINE_SKEL3 (Object, Object_ptr, Object)
+DEFINE_SKEL3 (TypeCode, TypeCode_ptr, TypeCode)
+#undef OPERATION
+
+//
+// For string, output is copy of input
+//
+#define OPERATION(x) (CORBA_string_copy(x))
+DEFINE_SKEL3 (string, String, String)
+#undef OPERATION
+
+//
+// For wstring, output is copy of input
+//
+#define OPERATION(x) (CORBA_wstring_copy(x))
+DEFINE_SKEL3 (wstring, WString, WString)
+#undef OPERATION
+
+//
+// XXX IMPLEMENT THE REST OF THE DATA TYPES
+//
+// any, principal -- out is in
+//
+
+
+//
+// All cases, "case_num" in the exception is the same as the 'in' param
+// * negative or zero, throws x1
+// * positive even cases, throws x2 with obj = null objref
+// * positive odd cases, throws x2 with obj = target objref
+//
+// exception x1 { long case_num; };
+// exception x2 { Object obj; long case_num; };
+//
+// void test_throw (in long case_num) raises (x1, x2);
+//
+
+extern const calldata test1_test_throw_calldata;
+
+static void
+_test1_test_throw (
+ CORBA_ServerRequest &req,
+ CORBA_Environment &env
+)
+{
+ CORBA_NVList_ptr nvlist;
+ CORBA_NamedValue_ptr nv;
+ CORBA_Any temp_value (_tc_CORBA_Long);
+ CORBA_Long value;
+
+ req.orb ()->create_list (0, nvlist);
+ nv = nvlist->add_value (0, temp_value, CORBA_ARG_IN, env);
+
+ req.params (nvlist, env);
+ if (env.exception () != 0) {
+ dexc (env, "test_throw, get params");
+ return;
+ }
+
+ value = *(CORBA_Long *)nv->value ()->value ();
+ if (env.exception () != 0) {
+ dexc (env, "test_throw, param value");
+ return;
+ }
+
+ CORBA_Any_ptr any;
+
+ if (value <= 0) {
+ test1_x1 *x;
+
+ x = new test1_x1 (value);
+ any = new CORBA_Any (_tc_test1_x1, x, CORBA_B_TRUE);
+
+ } else if (value & 0x01) {
+ test1_x2 *x;
+
+ x = new test1_x2 (CORBA_Object::_nil (), value);
+ any = new CORBA_Any (_tc_test1_x2, x, CORBA_B_TRUE);
+
+ } else {
+#if 0
+ test1_x2 *x;
+
+ x = new test1_x2 (req.oa()->target (), value);
+ any = new CORBA_Any (_tc_test1_x2, x, CORBA_B_TRUE);
+#else
+ //
+ // XXX right now, we don't have a target() operation on the
+ // TOA ... needs to be added. Verify the client side memory
+ // leak of pointers embedded in user exceptions is fixed, too.
+ //
+ env.exception (new CORBA_IMP_LIMIT (COMPLETED_NO));
+ return;
+#endif
+ }
+
+ req.exception (USER_EXCEPTION, any, env);
+}
+
+
+//
+// This table is used to associate operation names with the Dynamic
+// Skeleton method ... someday it could return static skeletons.
+//
+#define DECL_SKEL(name) \
+ { & test1_ ## name ## _calldata, _test1_test_ ## name }
+
+static const skel_entry test1_operations [] = {
+ DECL_SKEL (void),
+
+ DECL_SKEL (octet),
+ DECL_SKEL (char),
+
+ DECL_SKEL (wchar),
+
+ DECL_SKEL (short),
+ DECL_SKEL (ushort),
+ DECL_SKEL (long),
+ DECL_SKEL (ulong),
+
+#if !defined (NONNATIVE_LONGLONG)
+ // don't try this on platforms that don't support
+ // math on longlongs ...
+ DECL_SKEL (longlong),
+ DECL_SKEL (ulonglong),
+#endif
+
+ DECL_SKEL (float),
+ DECL_SKEL (double),
+
+#if !defined (NONNATIVE_LONGDOUBLE)
+ // don't try this on platforms that don't support
+ // math on long doubles ...
+ DECL_SKEL (longdouble),
+#endif // !NONNATIVE_LONGDOUBLE
+
+ DECL_SKEL (boolean),
+
+ DECL_SKEL (Object),
+ DECL_SKEL (TypeCode),
+
+ DECL_SKEL (string),
+ DECL_SKEL (wstring),
+
+ { & test1_test_throw_calldata, _test1_test_throw },
+
+ { 0, 0 }
+};
+
+
+//
+// Dispatch to method code ...
+//
+// Knows how to interpret "context" to get target objref, and where to
+// get second level skeletons for that target. Both of those operations
+// will generally be abstracted (into library and stub code) so the main
+// body of this routine would be invisible to most applications.
+//
+// However, there are applications that need to do this stuff themselves
+// (like bridging between environments, e.g. different ORBs, languages, or
+// other object systems). Everything needed to work without using an IDL
+// compiler is a public, supported API.
+//
+static void
+level1_skeleton (
+ CORBA_OctetSeq &key,
+ CORBA_ServerRequest &req,
+ void *context,
+ CORBA_Environment &env
+)
+{
+ //
+ // Verify that the target object and "this" object have the
+ // same key. Normally, this would be used to figure out
+ // which object was the target, and hence which operations
+ // vector to dispatch the request.
+ //
+ CORBA_OctetSeq *obj_key;
+
+ obj_key = (CORBA_OctetSeq *) context;
+ if (obj_key->length != key.length
+ || memcmp (obj_key->buffer, key.buffer,
+ obj_key->length) != 0) {
+ env.exception (new CORBA_OBJECT_NOT_EXIST (COMPLETED_NO));
+#ifdef DEBUG
+ if (debug_level)
+ dmsg_opaque ("request to nonexistent object, key = ",
+ key.buffer, key.length);
+#endif
+ return;
+ }
+
+ //
+ // Find a "level 2 skeleton" for this operation, then
+ // call it with the right per-object state.
+ //
+ const skel_entry *entry;
+ CORBA_String opname;
+
+ opname = req.op_name ();
+ for (entry = &test1_operations [0]; entry->op_descriptor; entry++) {
+ if (strcmp ((char *)opname, entry->op_descriptor->opname) == 0) {
+ entry->impl_skeleton (req, env);
+ return;
+ }
+ }
+
+ //
+ // XXX True top-level skeleton code would also have to understand
+ // the built-in operations:
+ //
+ // * _is_a (for narrowing tests) ... can be derived by searching an
+ // appropriately structured graph of level2 skeletons.
+ //
+ // * _non_existent ... if the level1 skeleton consults a module
+ // which understands object lifespans, this should be simple.
+ //
+ // * _get_interface ... could either (a) fail; (b) return the ref
+ // from some IFR; or most interestingly (c) return a ref to some
+ // code in this process that can answer all IFR queries from the
+ // skeleton data structures.
+ //
+ // * _get_implementation ... return some administrative hook to
+ // the object implementation:
+ //
+ // No other legal operations start with a character that's not an
+ // ASCII alphanumeric, for what it's worth.
+ //
+ // The skeleton might want to use data in the object key to find
+ // the objref's type; if it's integrated with object creation, and
+ // an per-process implementation repository, this should be easy.
+ //
+
+ //
+ // bypass level 2 skeletons for this one ...
+ //
+ if (strcmp ((char *) opname, "please_exit") == 0) {
+ dmsg ("I've been asked to shut down...");
+ req.oa ()->please_shutdown (env);
+ dexc (env, "please_exit, please_shutdown");
+ return;
+ }
+
+ //
+ // No match. Operation not implemented; say so.
+ //
+ dmsg1 ("unknown operation, %s", opname);
+ env.exception (new CORBA_BAD_OPERATION (COMPLETED_NO));
+}
+
+
+//
+// Create and print the objref, listen for calls on it until done.
+//
+extern void
+print_exception (const CORBA_Exception *, const char *, FILE *f=stdout);
+
+int
+OA_listen (
+ CORBA_ORB_ptr orb_ptr,
+ TOA_ptr oa_ptr,
+ CORBA_String key,
+ int idle
+)
+{
+ //
+ // Create the object we'll be implementing.
+ //
+ CORBA_OctetSeq obj_key;
+ CORBA_Object_ptr obj;
+ CORBA_Environment env;
+
+ obj_key.buffer = (CORBA_Octet *) key;
+ obj_key.length = obj_key.maximum = strlen (key);
+
+ obj = oa_ptr->create (obj_key, (CORBA_String) "", env);
+ if (env.exception () != 0) {
+ print_exception (env.exception (), "TOA::create");
+ return 1;
+ }
+
+ //
+ // Stringify the objref we'll be implementing, and
+ // print it to stdout. Someone will take that string
+ // and give it to some client.
+ //
+ CORBA_String str;
+
+ str = orb_ptr->object_to_string (obj, env);
+ if (env.exception () != 0) {
+ print_exception (env.exception (), "object2string");
+ return 1;
+ }
+ puts ((char *)str);
+ fflush (stdout);
+ dmsg1 ("listening as object '%s'", str);
+
+ //
+ // Clean up -- "key" is sufficient to dispatch all requests.
+ //
+ CORBA_release (obj);
+ CORBA_string_free (str);
+ env.clear ();
+
+ //
+ // Handle requests for this object until we're killed, or one of
+ // the methods makes us exit.
+ //
+ // NOTE: apart from registering the top level skeleton, the rest
+ // of this loop is exactly what TOA::run() does. It's here to
+ // show there's no magic.
+ //
+ oa_ptr->register_dir (level1_skeleton, &obj_key, env);
+ if (env.exception () != 0) {
+ print_exception (env.exception (), "register_dir");
+ return 1;
+ }
+
+ for (;;) {
+ if (idle == -1)
+ oa_ptr->get_request (CORBA_B_FALSE, 0, env);
+ else {
+ timeval tv;
+
+ tv.tv_sec = idle;
+ tv.tv_usec = 0;
+ oa_ptr->get_request (CORBA_B_FALSE, &tv, env);
+ }
+
+ CORBA_Exception_ptr xp;
+
+ if ((xp = env.exception ()) != 0) {
+ CORBA_Environment env2; // XXX
+ char *id;
+
+ id = env.exception ()->id ();
+
+ //
+ // We get BAD_INV_ORDER if we call get_request() after
+ // shutdown was initiated. Simpler to rely on that
+ // than to arrange any handshaking in this simple app.
+ //
+ if (strcmp (id, _tc_CORBA_BAD_INV_ORDER->id (env2)) == 0) {
+ break;
+
+ //
+ // Other exceptions are errors.
+ //
+ } else {
+ print_exception (env.exception (), "TOA::get_request");
+ return 1;
+ }
+ }
+ env.clear ();
+ }
+
+ //
+ // Shut down the OA -- recycles all underlying resources (e.g. file
+ // descriptors, etc).
+ //
+ // XXX shutdown is not quite the same as release, unless we want mem
+ // leaks to cause some rude failure modes. TOA just hasn't been
+ // updated yet to have any handshake about this though.
+ //
+ oa_ptr->Release ();
+ return 0;
+}
+
+
+//
+// Standard command line parsing utilities used.
+//
+int
+main (
+ int argc,
+ char *const *argv
+)
+{
+ CORBA_Environment env;
+ CORBA_ORB_ptr orb_ptr;
+ TOA_ptr oa_ptr;
+ CORBA_String key = (CORBA_String) "elvis";
+ char *oa_name = 0;
+ char *orb_name = "internet";
+ int idle = -1;
+
+ //
+ // Parse the command line, get options
+ //
+ int c;
+
+ while ((c = getopt (argc, argv, "di:k:o:p:")) != EOF)
+ switch (c) {
+ case 'd': // more debug noise
+ debug_level++;
+ continue;
+
+ case 'i': // idle seconds b4 exit
+ idle = atoi (optarg);
+ continue;
+
+ case 'k': // key (str)
+ key = (CORBA_String) optarg;
+ continue;
+
+ case 'o': // orb name
+ orb_name = optarg;
+ continue;
+
+ case 'p': // portnum
+ oa_name = optarg;
+ continue;
+
+ // XXX set debug filters ...
+
+ //
+ // XXX ignore OMG-specified options ... hope nobody ever tries
+ // to use that "-ORB* param" and "-OA* param" syntax, it flies
+ // in the face of standard command parsing algorithms which
+ // require single-character option specifiers.
+ //
+
+
+ case '?':
+ default:
+ fprintf (stderr, "usage: %s"
+ " [-d]"
+ " [-i idle_seconds]"
+ " [-k object_key=elvis]"
+ " [-o orbname=internet]"
+ " [-p oa_name]"
+ "\n", argv [0]
+ );
+ return 1;
+ }
+
+ orb_ptr = CORBA_ORB_init (argc, argv, orb_name, env);
+ if (env.exception () != 0) {
+ print_exception (env.exception (), "ORB init");
+ return 1;
+ }
+
+ //
+ // The TOA may or may not actually be named ...
+ //
+ oa_ptr = TOA::get_named_toa (orb_ptr, oa_name, env);
+ if (env.exception () != 0) {
+ print_exception (env.exception (), "OA init");
+ return 1;
+ }
+
+ return OA_listen (orb_ptr, oa_ptr, key, idle);
+}
+