// Collection of code snippets by Arne Vajhøj 
// (from articles on eksperten.dk / vajhoej.dk written sometime between 2004 and now) 
#include <iostream>
#include <ctime>

using namespace std;

#include "test.h"

using namespace CORBA;
using namespace CosNaming;
using namespace omniORB;

using namespace corbatest::common;

static Test_var getStub(ORB_var orb, const char *name)
{
    NamingContext_var nc = NamingContext::_narrow(orb->resolve_initial_references("NameService"));
    Name n;
    n.length(1);
    n[0].id   = (const char *)name;
    n[0].kind = (const char *)"";
    return Test::_narrow(nc->resolve(n));
}

static void testFunctional(ORB_var orb, const char *name)
{
    Test_var tst = getStub(orb, name);
    int a = 123;
    int b = 456;
    int c = tst->add(a, b);
    cout << c << endl;
    char *s = "ABC";
    char *s2 = tst->dup(s);
    cout << s2 << endl;
    Data *d = new Data();
    d->iv = 123;
    d->sv = "ABC";
    Data *d2 = tst->process(*d);
    cout << d2->iv << " " << d2->sv << endl;
}

static void testInstantiation(ORB_var orb, const char *name)
{
    Test_var tst1 = getStub(orb, name);
    for(int i = 0; i < 2; i++)
    {
        int n = tst1->getCounter();
        cout << n << endl;
    }
    Test_var tst2 = getStub(orb, name);
    for(int i = 0; i < 2; i++)
    {
        int n = tst2->getCounter();
        cout << n << endl;
    }
}

static const int REP = 100000;

static void testPerformance(ORB_var orb, const char *name)
{
    Test_var tst = getStub(orb, name);
    time_t t1 = time(NULL);
    for(int i = 0; i < REP; i++)
    {
        tst->noop();
    }
    time_t t2 = time(NULL);
    cout << (REP / (t2 - t1)) << " requests per second" << endl;
}

static void test(char *lbl, int argc, char *argv[], const char *ns, const char *name)
{
    cout << lbl << ":" << endl;
    try
    {
        const char *options[][2] = { { "InitRef", ns }, { 0, 0 } };
        ORB_var orb = ORB_init(argc, argv, "omniORB4", options);
        testFunctional(orb, name);
        testInstantiation(orb, name);
        testPerformance(orb, name);
        orb->destroy();
    }
    catch(Exception& ex)
    {
         cerr << ex._name() << endl;
    }
    catch(fatalException& fe)
    {
        cerr << fe.errmsg() << endl;
    }
    catch(...) 
    {
        cerr << "Ooops" << endl;
    }
}

static const char *JAVASE_NS = "NameService=corbaname::localhost:1050";
static const char *JAVASE_NAME1 = "TestJ1";
static const char *JAVASE_NAME2 = "TestJ2";
static const char *IIOPNET_NS = "NameService=corbaname::localhost:12345";
static const char *IIOPNET_NAME = "TestN";
static const char *OMNIORB_NS = "NameService=corbaname::localhost:2809";
static const char *OMNIORB_NAME1 = "TestC1";
static const char *OMNIORB_NAME2 = "TestC2";
static const char *OMNIORB_NAME3 = "TestPy";

int main(int argc, char *argv[])
{
    test("Java SE ORB and Java Server (old style)", argc, argv, JAVASE_NS, JAVASE_NAME1);
    test("Java SE ORB and Java Server (new style)", argc, argv, JAVASE_NS, JAVASE_NAME2);
    test("IIOP.NET ORB and .NET Server", argc, argv, IIOPNET_NS, IIOPNET_NAME);
    test("OmniORB ORB and C++ Server (old style)", argc, argv, OMNIORB_NS, OMNIORB_NAME1);
    test("OmniORB ORB and C++ Server (new style)", argc, argv, OMNIORB_NS, OMNIORB_NAME2);
    test("OmniORB ORB and Python Server", argc, argv, OMNIORB_NS, OMNIORB_NAME3);
    return 0;
}

