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

#include <assert.h>
#include <stdlib.h>
#include <string.h>

#include <OB/CORBA.h>
#include <OB/Util.h>

#include <OB/CosNaming.h>

#include "TestObject_impl.h"
#include "TestMacro.h"


//
// Test CosNaming::NamingContext::resolve()
//
void
TestResolve(CORBA_ORB_ptr orb, CosNaming_NamingContext_ptr root)
{
    CORBA_Object_var obj;
    TestObject_var test = new TestObject_impl;
    CosNaming_Name name1, name2;
    CosNaming_NamingContext_var context;

    //
    // Test exceptions
    //

    try
    {
        //
        // Try to resolve a binding that doesn't exist
        //
        name1.length(1);
        name1[0].id = CORBA_string_dup("bad");
        name1[0].kind = CORBA_string_dup("node");
        obj = root -> resolve(name1);
        assert("resolve should not have succeeded" == 0);
    }
    catch(CosNaming_NamingContext::NotFound& ex)
    {
        assert(ex.why == CosNaming_NamingContext::missing_node);
	assert(strcmp(ex.rest_of_name[0].id, "bad") == 0 &&
	       strcmp(ex.rest_of_name[0].kind, "node") == 0);
    }

    name1.length(1);
    name1[0].id = CORBA_string_dup("object");
    name1[0].kind = CORBA_string_dup("");
    SUCCEED(root -> bind(name1, test));

    try
    {
        //
        // Try to resolve a binding when an object is in the path
        //
        name2.length(2);
        name2[0].id = CORBA_string_dup("object");
        name2[0].kind = CORBA_string_dup("");
        name2[1].id = CORBA_string_dup("my");
        name2[1].kind = CORBA_string_dup("node");
        obj = root -> resolve(name2);
        assert("resolve should not have succeeded" == 0);
    }
    catch(CosNaming_NamingContext::NotFound& ex)
    {
        assert(ex.why == CosNaming_NamingContext::not_context);
    }

    //
    // Test resolve
    //
    SUCCEED(obj = root -> resolve(name1));
    assert(obj -> _is_equivalent(test));
    SUCCEED(root -> rebind(name1, CORBA_Object::_nil()));
    SUCCEED(obj = root -> resolve(name1));
    assert(CORBA_is_nil(obj));
    SUCCEED(root -> unbind(name1));

    try
    {
        //
        // Try to resolve a binding with an invalid name
        //
        name1.length(0);
        root -> resolve(name1);
        assert("resolve should not have succeeded" == 0);
    }
    catch(CosNaming_NamingContext::InvalidName&)
    {
        // expected
    }

#if 0
    try
    {
        //
        // Try to resolve a binding with an invalid name
        //
        name1.length(1);
        name1[0].id = CORBA_string_dup("");
        name1[0].kind = CORBA_string_dup("");
        root -> resolve(name1);
        assert("resolve should not have succeeded" == 0);
    }
    catch(CosNaming_NamingContext::InvalidName&)
    {
        // expected
    }
#endif

    //
    // Bind an intermediate context for use in more tests
    //
    context = root -> new_context();
    name1.length(1);
    name1[0].id = CORBA_string_dup("ctx");
    name1[0].kind = CORBA_string_dup("");
    SUCCEED(root -> bind_context(name1, context));

    try
    {
        //
        // Try to resolve a binding when an intermediate context
        // doesn't exist
        //
        name1.length(3);
        name1[0].id = CORBA_string_dup("ctx");
        name1[0].kind = CORBA_string_dup("");
        name1[1].id = CORBA_string_dup("bad");
        name1[1].kind = CORBA_string_dup("node");
        name1[2].id = CORBA_string_dup("my");
        name1[2].kind = CORBA_string_dup("node");
        root -> resolve(name1);
        assert("resolve should not have succeeded" == 0);
    }
    catch(CosNaming_NamingContext::NotFound& ex)
    {
        assert(ex.why == CosNaming_NamingContext::missing_node);
    }

    name1.length(1);
    name1[0].id = CORBA_string_dup("object");
    name1[0].kind = CORBA_string_dup("");
    SUCCEED(context -> bind(name1, test));

    try
    {
        //
        // Try to resolve a binding when an object is in the path
        //
        name2.length(3);
        name2[0].id = CORBA_string_dup("ctx");
        name2[0].kind = CORBA_string_dup("");
        name2[1].id = CORBA_string_dup("object");
        name2[1].kind = CORBA_string_dup("");
        name2[2].id = CORBA_string_dup("my");
        name2[2].kind = CORBA_string_dup("node");
        root -> resolve(name2);
        assert("resolve should not have succeeded" == 0);
    }
    catch(CosNaming_NamingContext::NotFound& ex)
    {
        assert(ex.why == CosNaming_NamingContext::not_context);
    }

    //
    // Test resolve
    //
    name2.length(2);
    name2[0].id = CORBA_string_dup("ctx");
    name2[0].kind = CORBA_string_dup("");
    name2[1].id = CORBA_string_dup("object");
    name2[1].kind = CORBA_string_dup("");
    SUCCEED(obj = root -> resolve(name2));
    assert(obj -> _is_equivalent(test));

    SUCCEED(context -> unbind(name1));

    //
    // Clean up context
    //
    name1.length(1);
    name1[0].id = CORBA_string_dup("ctx");
    name1[0].kind = CORBA_string_dup("");
    SUCCEED(root -> unbind(name1));
    SUCCEED(context -> destroy());


    //
    // Test name equality to make sure kind is included in comparisons
    //
    CORBA_Object_var o;
    name1.length(1);
    name1[0].id = CORBA_string_dup("object");
    name1[0].kind = CORBA_string_dup("kind1");
    name2.length(1);
    name2[0].id = CORBA_string_dup("object");
    name2[0].kind = CORBA_string_dup("kind2");
    SUCCEED(root -> bind(name1, test));
    SUCCEED(root -> bind(name2, CORBA_Object::_nil()));
    SUCCEED(o = root -> resolve(name1));
    assert(! CORBA_is_nil(o));
    SUCCEED(o = root -> resolve(name2));
    assert(CORBA_is_nil(o));
    SUCCEED(root -> unbind(name1));
    SUCCEED(root -> unbind(name2));
}
