--- /dev/null
+#include <forb.h>
+#include <executor_test.h>
+#define WVTEST_CONFIGURED
+#include <wvtest.h>
+#include <forb/executor.h>
+#include <forb/object.h>
+
+static CORBA_long add(executor_test obj, CORBA_long val, CORBA_Environment *ev)
+{
+ int to_add = (intptr_t)forb_object_instance_data(obj);
+ return val + to_add;
+}
+
+static CORBA_long add_indirect(executor_test obj, executor_test indirect_obj, CORBA_long val, CORBA_Environment *ev)
+{
+ return executor_test_add(indirect_obj, val, ev);
+}
+
+static const struct forb_executor_test_impl executor_test_impl = {
+ .add = add,
+ .add_indirect = add_indirect,
+};
+
+
+void *executor_thread(void *arg)
+{
+ forb_executor_t *executor = arg;
+ forb_executor_run(executor);
+ return NULL;
+}
+
+WVTEST_MAIN("remote (inter-server) invocation")
+{
+ forb_orb orb1, orb2;
+ fosa_thread_id_t tid;
+ executor_test testobj, remote_obj;
+ forb_executor_t executor;
+ char *str;
+ struct forb_env env;
+
+ /* Create the first FORB server */
+ WVPASS(orb1 = forb_init(NULL, NULL,
+ &(struct forb_init_attr){.orb_id = "server1"}));
+
+ /* This object adds 1 to the argument of add() */
+ WVPASS(testobj = forb_executor_test_new(orb1, &executor_test_impl, (void*)1));
+ WVPASSEQ(forb_executor_init(&executor), 0);
+ WVPASSEQ(forb_executor_register_object(&executor, testobj), 0);
+
+ /* Execute executor in a separate thread */
+ fosa_thread_create(&tid, NULL, executor_thread, &executor);
+
+ /* Create the second FORB server in the same process */
+ WVPASS(orb2 = forb_init(NULL, NULL,
+ &(struct forb_init_attr){.orb_id = "server2"}));
+
+ str = forb_object_to_string(testobj);
+ remote_obj = forb_string_to_object(orb2, str);
+
+ WVPASS(forb_object_is_local(testobj));
+ WVFAIL(forb_object_is_local(remote_obj));
+
+ /* Remote invocation of the object */
+ WVPASSEQ(executor_test_add(remote_obj, 1, &env), 2);
+ WVFAIL(forb_exception_occurred(&env));
+}
+
+WVTEST_MAIN("inter_thread_invocation")
+{
+ forb_orb orb;
+ fosa_thread_id_t tid1, tid2;
+ executor_test testobj1, testobj2;
+ forb_executor_t executor1, executor2;
+ struct forb_env env;
+
+ /* Create the first FORB server */
+ WVPASS(orb = forb_init(NULL, NULL,
+ &(struct forb_init_attr){.orb_id = "server"}));
+
+ /* This object adds 1 to the argument of add() */
+ WVPASS(testobj1 = forb_executor_test_new(orb, &executor_test_impl, (void*)1));
+ WVPASSEQ(forb_executor_init(&executor1), 0);
+ WVPASSEQ(forb_executor_register_object(&executor1, testobj1), 0);
+
+ /* This object adds 2 to the argument of add() */
+ WVPASS(testobj2 = forb_executor_test_new(orb, &executor_test_impl, (void*)2));
+ WVPASSEQ(forb_executor_init(&executor2), 0);
+ WVPASSEQ(forb_executor_register_object(&executor2, testobj2), 0);
+
+ /* Execute executors in separate threads */
+ fosa_thread_create(&tid1, NULL, executor_thread, &executor1);
+ fosa_thread_create(&tid2, NULL, executor_thread, &executor2);
+
+ WVPASS(forb_object_is_local(testobj1));
+ WVPASS(forb_object_is_local(testobj2));
+
+ /* Inter-thread invocation: application->executor */
+ WVPASSEQ(executor_test_add(testobj1, 1, &env), 2);
+ WVFAIL(forb_exception_occurred(&env));
+
+ /* Inter-thread invocation: (application->)executor->executor */
+ WVPASSEQ(executor_test_add_indirect(testobj1, testobj2, 1, &env), 3);
+ WVFAIL(forb_exception_occurred(&env));
+
+ /* Direct invocation in the same executor: (application->)executor->executor */
+ WVPASSEQ(executor_test_add_indirect(testobj1, testobj1, 1, &env), 2);
+ WVFAIL(forb_exception_occurred(&env));
+}