// **********************************************************************
//
// Copyright (c) 1999
// Object Oriented Concepts, Inc.
// Billerica, MA, USA
//
// All Rights Reserved
//
// **********************************************************************

#include <OB/CORBA.h>
#include <Test1.h>
#include <Test2.h>
#include <TestMacro.h>

#include <string.h>

void
TestAny()
{
    CORBA_Any any;
    CORBA_ULong i;

    {
	CORBA_Short v = -32768;
	CORBA_Short vSave = v;

	any <<= v;

	TEST(any >>= v);
	TEST(v == vSave);
    }

    {
	CORBA_UShort v = 65535U;
	CORBA_UShort vSave = v;

	any <<= v;

	TEST(any >>= v);
	TEST(v == vSave);
    }
    
    {
	CORBA_Long v = -2147483647 - 1;
	CORBA_Long vSave = v;

	any <<= v;

	TEST(any >>= v);
	TEST(v == vSave);
    }
    
    {
	CORBA_ULong v = 2147483647;
	CORBA_ULong vSave = v;

	any <<= v;

	TEST(any >>= v);
	TEST(v == vSave);
    }
    
    {
	CORBA_Float v = (CORBA_Float)1.23456789;
	CORBA_Float vSave = v;

	any <<= v;

	TEST(any >>= v);
	TEST(v == vSave);
    }
    
    {
	CORBA_Double v = 1E200;
	CORBA_Double vSave = v;

	any <<= v;

	TEST(any >>= v);
	TEST(v == vSave);
    }

    {
	CORBA_Octet v = 0xff;
	CORBA_Octet vSave = v;

	any <<= CORBA_Any::from_octet(v);

	TEST(any >>= CORBA_Any::to_octet(v));
	TEST(v == vSave);
    }

    {
	CORBA_Char v = 'x';
	CORBA_Char vSave = v;

	any <<= CORBA_Any::from_char(v);

	TEST(any >>= CORBA_Any::to_char(v));
	TEST(v == vSave);
    }

    {
	CORBA_Boolean v = true;
	CORBA_Boolean vSave = v;

	any <<= CORBA_Any::from_boolean(v);

	TEST(any >>= CORBA_Any::to_boolean(v));
	TEST(v == vSave);
    }

    {
	const char* v = "Hello!";

	CORBA_Any any;
	any <<= v;
	
	char* v2;

	TEST(any >>= v2);
	TEST(strcmp(v2, v) == 0);
    }

    {
	CORBA_Double v = 1E200;
	CORBA_Double vSave = v;
	CORBA_Any any2;
	CORBA_Any any3;
	CORBA_Any any4;

	CORBA_Any* any5;
	CORBA_Any* any6;
	CORBA_Any* any7;

	any <<= v;
	any2 <<= any;
	any3 <<= any2;
	any4 <<= any3;

	TEST(any4 >>= any5);
	TEST(*any5 >>= any6);
	TEST(*any6 >>= any7);
	TEST(*any7 >>= v);

	TEST(v == vSave);
    }

    {
	const char* v = "Hello world!";
	CORBA_Any any2;
	CORBA_Any any3;
	CORBA_Any any4;

	CORBA_Any* any5;
	CORBA_Any* any6;
	CORBA_Any* any7;
	char* v2;

	any <<= v;
	any2 <<= any;
	any3 <<= any2;
	any4 <<= any3;

	TEST(any4 >>= any5);
	TEST(*any5 >>= any6);
	TEST(*any6 >>= any7);
	TEST(*any7 >>= v2);
	TEST(strcmp(v2, v) == 0);
    }

    {
	CORBA_Char v = '*';
	CORBA_Char vSave = v;
	CORBA_Any any2;
	CORBA_Any any3;
	CORBA_Any any4;

	CORBA_Any* any5;
	CORBA_Any* any6;
	CORBA_Any* any7;

	any <<= CORBA_Any::from_char(v);
	any2 <<= any;
	any3 <<= any2;
	any4 <<= any3;

	TEST(any4 >>= any5);
	TEST(*any5 >>= any6);
	TEST(*any6 >>= any7);
	TEST(*any7 >>= CORBA_Any::to_char(v));
	TEST(v == vSave);
    }

    {
	TestStruct1 v;
	v.s = -32768;
	v.l = -2147483647 - 1;
	v.d = 1E200;
	v.b = true;
	v.c = 'x';
	v.o = 0xff;
	v.str = (const char*)"abc";
	TestStruct1 vSave = v;

	any <<= v;

	TestStruct1* vp;

	TEST(any >>= vp);
	TEST(vp -> s == vSave.s);
	TEST(vp -> l == vSave.l);
	TEST(vp -> d == vSave.d);
	TEST(vp -> c == vSave.c);
	TEST(vp -> b == vSave.b);
	TEST(vp -> o == vSave.o);
	TEST(strcmp(vp -> str, v.str) == 0);

	vp -> str = (const char*)"def";

	TEST(any >>= vp);
	TEST(vp -> s == vSave.s);
	TEST(vp -> l == vSave.l);
	TEST(vp -> d == vSave.d);
	TEST(vp -> c == vSave.c);
	TEST(vp -> b == vSave.b);
	TEST(vp -> o == vSave.o);
	TEST(strcmp(vp -> str, "def") == 0);

	CORBA_Any any2(any);

	TestStruct2* v2p = new TestStruct2;
	v2p -> s = v;
	v2p -> a = any2;
	v2p -> da[0][0][0] = 1.23;
	v2p -> da[2][3][4] = -1.11;
	v2p -> sa[50] = CORBA_string_dup("Hi!");

	any <<= v2p;

	TestStruct2* v3p;

	TEST(any >>= v3p);
	TEST(v3p -> s.s == vSave.s);
	TEST(v3p -> s.l == vSave.l);
	TEST(v3p -> s.d == vSave.d);
	TEST(v3p -> s.c == vSave.c);
	TEST(v3p -> s.b == vSave.b);
	TEST(v3p -> s.o == vSave.o);
	TEST(strcmp(v3p -> s.str, v.str) == 0);
	TEST(v3p -> da[0][0][0] == 1.23);
	TEST(v3p -> da[2][3][4] == -1.11);
	TEST(strcmp(v3p -> sa[50], "Hi!") == 0);

	v2p -> s.d = 3.14;
	v2p -> da[1][2][3] = 0.001;
	v2p -> sa[99] = CORBA_string_dup("99");
	TEST(v3p -> s.d == 3.14);
	TEST(v3p -> da[1][2][3] == 0.001);
	TEST(strcmp(v3p -> sa[99], "99") == 0);
    }

    {
	TestEnum v = B;
	any <<= v;
	TEST(any >>= v);
	TEST(v == B);

	CORBA_Any* anyp = new CORBA_Any(any);
	TEST(*anyp >>= v);
	TEST(v == B);

	CORBA_Any any2;
	any2 <<= anyp;

	TEST(any2 >>= anyp);
	TEST(*anyp >>= v);
	TEST(v == B);
    }

    {
	OctetSeq v;
	CORBA_Octet o;

	for(o = 0 ; o < 100 ; o++)
	    v.append(o);

	any <<= v;

	OctetSeq* vp;

	TEST(any >>= vp);

	for(o = 0 ; o < 100 ; o++)
	    TEST((*vp)[o] == o);

	CORBA_Any* anyp = new CORBA_Any(any);

	TEST(*anyp >>= vp);

	for(o = 0 ; o < 100 ; o++)
	    TEST((*vp)[o] == o);

	CORBA_Any any2;
	any2 <<= anyp;

	(*vp)[0] = 3;

	TEST(any2 >>= anyp);
	TEST(*anyp >>= vp);

	TEST((*vp)[0] == 3);

	for(o = 1 ; o < 100 ; o++)
	    TEST((*vp)[o] == o);
    }

    {
	DoubleSeq v;
	CORBA_ULong i;
	CORBA_Double d;

	for(d = 0 ; d < 10 ; d += 0.1)
	    v.append(d);

	any <<= v;

	DoubleSeq* vp;

	TEST(any >>= vp);

	for(i = 0, d = 0 ; d < 10 ; i++, d += 0.1)
	    TEST((*vp)[i] == v[i]);

	CORBA_Any* anyp = new CORBA_Any(any);

	TEST(*anyp >>= vp);

	for(i = 0, d = 0 ; d < 10 ; i++, d += 0.1)
	    TEST((*vp)[i] == v[i]);

	CORBA_Any any2;
	any2 <<= anyp;

	double pi = 3.14;
	(*vp)[0] = pi;

	TEST(any2 >>= anyp);
	TEST(*anyp >>= vp);

	TEST((*vp)[0] == pi);

	for(i = 1, d = 0.1 ; d < 10 ; i++, d += 0.1)
	    TEST((*vp)[i] == v[i]);
    }

    {
	Double10Seq v;
	v.length(10);

	for(i = 0 ; i < 10 ; i++)
	    v[i] = (double)i;

	any <<= v;

	Double10Seq* vp;

	TEST(any >>= vp);

	for(i = 0 ; i < 10 ; i++)
	    TEST((*vp)[i] == v[i]);

	CORBA_Any* anyp = new CORBA_Any(any);

	TEST(*anyp >>= vp);

	for(i = 0 ; i < 10 ; i++)
	    TEST((*vp)[i] == v[i]);

	CORBA_Any any2;
	any2 <<= anyp;

	double pi = 3.14;
	(*vp)[0] = pi;

	TEST(any2 >>= anyp);
	TEST(*anyp >>= vp);

	TEST((*vp)[0] == pi);

	for(i = 1 ; i < 10 ; i++)
	    TEST((*vp)[i] == v[i]);
    }

    {
	CharSeq v;
	CORBA_Char o;

	for(o = 0 ; o < 100 ; o++)
	    v.append(o);

	any <<= v;

	CharSeq* vp;

	TEST(any >>= vp);

	for(o = 0 ; o < 100 ; o++)
	    TEST((*vp)[o] == o);

	CORBA_Any* anyp = new CORBA_Any(any);

	TEST(*anyp >>= vp);

	for(o = 0 ; o < 100 ; o++)
	    TEST((*vp)[o] == o);

	CORBA_Any any2;
	any2 <<= anyp;

	(*vp)[0] = 3;

	TEST(any2 >>= anyp);
	TEST(*anyp >>= vp);

	TEST((*vp)[0] == 3);

	for(o = 1 ; o < 100 ; o++)
	    TEST((*vp)[o] == o);
    }

    {
	String40Seq v;
	v.length(40);

	for(i = 0 ; i < 40 ; i++)
	    v[i] = CORBA_string_dup("abc");

	any <<= v;

	String40Seq* vp;

	TEST(any >>= vp);

	for(i = 0 ; i < 40 ; i++)
	    TEST(strcmp((*vp)[i], "abc") == 0);

	CORBA_Any* anyp = new CORBA_Any(any);

	TEST(*anyp >>= vp);

	for(i = 0 ; i < 40 ; i++)
	    TEST(strcmp((*vp)[i], "abc") == 0);

	CORBA_Any any2;
	any2 <<= anyp;

	(*vp)[0] = CORBA_string_dup("hello");

	TEST(any2 >>= anyp);
	TEST(*anyp >>= vp);

	TEST(strcmp((*vp)[0], "hello") == 0);

	for(i = 1 ; i < 40 ; i++)
	    TEST(strcmp((*vp)[i], "abc") == 0);
    }

    {
	TestStruct1 s0;
	s0.s = -32768;
	s0.l = -2147483647 - 1;
	s0.d = 1E200;
	s0.b = true;
	s0.c = 'x';
	s0.o = 0xff;
	s0.str = (const char*)"Hi!";

	TestStruct1 s1;
	s1.s = 32767;
	s1.l = 2147483647;
	s1.d = -1E200;
	s1.b = false;
	s1.c = 'y';
	s1.o = 0x12;
	s1.str = (const char*)"Bye!";

	OBVarSeq<TestStruct1> v;
	v.append(s0);
	v.append(s1);

	any <<= v;

	OBVarSeq<TestStruct1>* vp;

	TEST(any >>= vp);

	TEST((*vp)[0].s == s0.s);
	TEST((*vp)[0].l == s0.l);
	TEST((*vp)[0].d == s0.d);
	TEST((*vp)[0].b == s0.b);
	TEST((*vp)[0].c == s0.c);
	TEST((*vp)[0].o == s0.o);
	TEST(strcmp((*vp)[0].str, s0.str) == 0);

	TEST((*vp)[1].s == s1.s);
	TEST((*vp)[1].l == s1.l);
	TEST((*vp)[1].d == s1.d);
	TEST((*vp)[1].b == s1.b);
	TEST((*vp)[1].c == s1.c);
	TEST((*vp)[1].o == s1.o);
	TEST(strcmp((*vp)[1].str, s1.str) == 0);

	CORBA_Any* anyp = new CORBA_Any(any);

	TEST(*anyp >>= vp);

	TEST((*vp)[0].s == s0.s);
	TEST((*vp)[0].l == s0.l);
	TEST((*vp)[0].d == s0.d);
	TEST((*vp)[0].b == s0.b);
	TEST((*vp)[0].c == s0.c);
	TEST((*vp)[0].o == s0.o);
	TEST(strcmp((*vp)[0].str, s0.str) == 0);

	TEST((*vp)[1].s == s1.s);
	TEST((*vp)[1].l == s1.l);
	TEST((*vp)[1].d == s1.d);
	TEST((*vp)[1].b == s1.b);
	TEST((*vp)[1].c == s1.c);
	TEST((*vp)[1].o == s1.o);
	TEST(strcmp((*vp)[1].str, s1.str) == 0);

	CORBA_Any any2;
	any2 <<= anyp;

	(*vp)[0].str = (const char*)"Hello!";
	(*vp)[1].str = (const char*)"Bye-Bye!";

	TEST(any2 >>= anyp);
	TEST(*anyp >>= vp);

	TEST((*vp)[0].s == s0.s);
	TEST((*vp)[0].l == s0.l);
	TEST((*vp)[0].d == s0.d);
	TEST((*vp)[0].b == s0.b);
	TEST((*vp)[0].c == s0.c);
	TEST((*vp)[0].o == s0.o);
	TEST(strcmp((*vp)[0].str, "Hello!") == 0);

	TEST((*vp)[1].s == s1.s);
	TEST((*vp)[1].l == s1.l);
	TEST((*vp)[1].d == s1.d);
	TEST((*vp)[1].b == s1.b);
	TEST((*vp)[1].c == s1.c);
	TEST((*vp)[1].o == s1.o);
	TEST(strcmp((*vp)[1].str, "Bye-Bye!") == 0);
    }

    {
	CORBA_Double v[10][20][30];
	v[0][0][0] = -999;
	v[1][2][3] = 1.23;
	v[9][19][29] = 9.1929;
	any <<= DoubleArray_forany(v);

	DoubleArray_forany v2;
	TEST(any >>= v2);

	v[1][2][3] = 1e6;
	TEST(v2[0][0][0] == -999);
	TEST(v2[1][2][3] == 1.23);
	TEST(v2[9][19][29] == 9.1929);

	DoubleArray_slice* v3;
	v3 = DoubleArray_dup(v);
	any <<= DoubleArray_forany(v3, true);

	DoubleArray_forany v4;
	TEST(any >>= v4);

	TEST(v4[0][0][0] == -999);
	TEST(v4[1][2][3] == 1e6);
	TEST(v4[9][19][29] == 9.1929);

	v3[1][2][3] = -1e8;
	TEST(v4[0][0][0] == -999);
	TEST(v4[1][2][3] == -1e8);
	TEST(v4[9][19][29] == 9.1929);
    }

    {
	CORBA_TypeCode_ptr tc;

	any <<= _tc_TestStruct1;
	TEST(any >>= tc);
	TEST(tc -> exactly_equal(_tc_TestStruct1));

	CORBA_Any any2 = any;
	any <<= _tc_TestStruct2;
	TEST(any2 >>= tc);
	TEST(tc -> exactly_equal(_tc_TestStruct1));
	TEST(any >>= tc);
	TEST(tc -> exactly_equal(_tc_TestStruct2));
    }
}
