233 lines
7.1 KiB
C++
233 lines
7.1 KiB
C++
#define BOOST_TEST_MODULE cppbind
|
|
#include <BoostTestTargetConfig.h>
|
|
|
|
#include "TestContext.hxx"
|
|
|
|
#include <simgear/nasal/cppbind/Ghost.hxx>
|
|
#include <simgear/nasal/cppbind/NasalContext.hxx>
|
|
|
|
#include <boost/make_shared.hpp>
|
|
#include <boost/shared_ptr.hpp>
|
|
#include <boost/weak_ptr.hpp>
|
|
|
|
class Base1:
|
|
public virtual SGVirtualWeakReferenced
|
|
{};
|
|
|
|
class Base2:
|
|
public virtual SGVirtualWeakReferenced
|
|
{};
|
|
|
|
class Derived:
|
|
public Base1,
|
|
public Base2
|
|
{};
|
|
|
|
typedef SGSharedPtr<Base1> Base1Ptr;
|
|
typedef SGSharedPtr<Base2> Base2Ptr;
|
|
typedef SGSharedPtr<Derived> DerivedPtr;
|
|
typedef SGWeakPtr<Derived> DerivedWeakPtr;
|
|
|
|
typedef SGSharedPtr<SGReferenced> SGReferencedPtr;
|
|
|
|
// Check if shared_ptr_traits give correct types for strong and weak shared
|
|
// pointer
|
|
#define CHECK_PTR_TRAIT_TYPE(ptr_t, type_name, type)\
|
|
BOOST_STATIC_ASSERT((boost::is_same<\
|
|
nasal::shared_ptr_traits<ptr_t>::type_name,\
|
|
type\
|
|
>::value));
|
|
|
|
#define CHECK_PTR_TRAIT(ref, weak)\
|
|
CHECK_PTR_TRAIT_TYPE(ref, strong_ref, ref)\
|
|
CHECK_PTR_TRAIT_TYPE(weak, weak_ref, weak)\
|
|
|
|
CHECK_PTR_TRAIT(DerivedPtr, DerivedWeakPtr)
|
|
CHECK_PTR_TRAIT(boost::shared_ptr<Base1>, boost::weak_ptr<Base1>)
|
|
|
|
#undef CHECK_PTR_TRAIT
|
|
#undef CHECK_PTR_TRAIT_TYPE
|
|
|
|
BOOST_STATIC_ASSERT(( nasal::supports_weak_ref<Base1Ptr>::value));
|
|
BOOST_STATIC_ASSERT(( nasal::supports_weak_ref<Base2Ptr>::value));
|
|
BOOST_STATIC_ASSERT(( nasal::supports_weak_ref<DerivedPtr>::value));
|
|
BOOST_STATIC_ASSERT(( nasal::supports_weak_ref<DerivedWeakPtr>::value));
|
|
BOOST_STATIC_ASSERT((!nasal::supports_weak_ref<SGReferencedPtr>::value));
|
|
|
|
static void setupGhosts()
|
|
{
|
|
nasal::Ghost<Base1Ptr>::init("Base1");
|
|
nasal::Ghost<Base2Ptr>::init("Base2");
|
|
nasal::Ghost<DerivedPtr>::init("Derived")
|
|
.bases<Base1Ptr>()
|
|
.bases<Base2Ptr>();
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
BOOST_AUTO_TEST_CASE( ghost_weak_strong_nasal_conversion )
|
|
{
|
|
setupGhosts();
|
|
naContext c = naNewContext();
|
|
|
|
DerivedPtr d = new Derived();
|
|
DerivedWeakPtr weak(d);
|
|
|
|
// store weak pointer and extract strong pointer
|
|
naRef na_d = nasal::to_nasal(c, DerivedWeakPtr(d));
|
|
BOOST_REQUIRE( naIsGhost(na_d) );
|
|
BOOST_CHECK_EQUAL( nasal::from_nasal<Base1Ptr>(c, na_d), d );
|
|
BOOST_CHECK_EQUAL( nasal::from_nasal<Base2Ptr>(c, na_d), d );
|
|
BOOST_CHECK_EQUAL( nasal::from_nasal<DerivedPtr>(c, na_d), d );
|
|
|
|
d.reset();
|
|
BOOST_REQUIRE_THROW( nasal::from_nasal<DerivedPtr>(c, na_d),
|
|
nasal::bad_nasal_cast );
|
|
|
|
// store strong pointer and extract weak pointer
|
|
d.reset(new Derived);
|
|
na_d = nasal::to_nasal(c, d);
|
|
BOOST_REQUIRE( naIsGhost(na_d) );
|
|
|
|
weak = nasal::from_nasal<DerivedWeakPtr>(c, na_d);
|
|
BOOST_CHECK_EQUAL( weak.lock(), d );
|
|
|
|
d.reset();
|
|
BOOST_REQUIRE( nasal::from_nasal<DerivedPtr>(c, na_d) );
|
|
BOOST_REQUIRE( weak.lock() );
|
|
|
|
naFreeContext(c);
|
|
naGC();
|
|
nasal::ghostProcessDestroyList();
|
|
|
|
BOOST_REQUIRE( !weak.lock() );
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
BOOST_AUTO_TEST_CASE( ghost_casting_storage )
|
|
{
|
|
setupGhosts();
|
|
nasal::Context c;
|
|
|
|
// Check converting to and from every class in the hierarchy for an instance
|
|
// of the leaf class
|
|
DerivedPtr d = new Derived();
|
|
|
|
naRef na_d = nasal::to_nasal(c, d),
|
|
na_b1 = nasal::to_nasal(c, Base1Ptr(d)),
|
|
na_b2 = nasal::to_nasal(c, Base2Ptr(d));
|
|
|
|
Derived *d0 = nasal::from_nasal<Derived*>(c, na_d),
|
|
*d1 = nasal::from_nasal<Derived*>(c, na_b1),
|
|
*d2 = nasal::from_nasal<Derived*>(c, na_b2);
|
|
|
|
BOOST_CHECK_EQUAL(d0, d.get());
|
|
BOOST_CHECK_EQUAL(d1, d.get());
|
|
BOOST_CHECK_EQUAL(d2, d.get());
|
|
|
|
Base1 *b1 = nasal::from_nasal<Base1*>(c, na_b1);
|
|
BOOST_CHECK_EQUAL(b1, static_cast<Base1*>(d.get()));
|
|
|
|
Base2 *b2 = nasal::from_nasal<Base2*>(c, na_b2);
|
|
BOOST_CHECK_EQUAL(b2, static_cast<Base2*>(d.get()));
|
|
|
|
// Check converting from base class instance to derived classes is not
|
|
// possible
|
|
Base1Ptr b1_ref = new Base1();
|
|
na_b1 = nasal::to_nasal(c, b1_ref);
|
|
|
|
BOOST_CHECK_EQUAL(nasal::from_nasal<Base1*>(c, na_b1), b1_ref.get());
|
|
BOOST_CHECK_THROW(nasal::from_nasal<Base2*>(c, na_b1), nasal::bad_nasal_cast);
|
|
BOOST_CHECK_THROW(nasal::from_nasal<Derived*>(c, na_b1), nasal::bad_nasal_cast);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
#define CHECK_PTR_STORAGE_TRAIT_TYPE(ptr_t, storage)\
|
|
BOOST_STATIC_ASSERT((boost::is_same<\
|
|
nasal::shared_ptr_storage<ptr_t>::storage_type,\
|
|
storage\
|
|
>::value));
|
|
|
|
CHECK_PTR_STORAGE_TRAIT_TYPE(DerivedPtr, Derived)
|
|
CHECK_PTR_STORAGE_TRAIT_TYPE(DerivedWeakPtr, DerivedWeakPtr)
|
|
|
|
typedef boost::shared_ptr<Derived> BoostDerivedPtr;
|
|
CHECK_PTR_STORAGE_TRAIT_TYPE(BoostDerivedPtr, BoostDerivedPtr)
|
|
|
|
typedef boost::weak_ptr<Derived> BoostDerivedWeakPtr;
|
|
CHECK_PTR_STORAGE_TRAIT_TYPE(BoostDerivedWeakPtr, BoostDerivedWeakPtr)
|
|
|
|
#undef CHECK_PTR_STORAGE_TRAIT_TYPE
|
|
|
|
BOOST_STATIC_ASSERT(( nasal::shared_ptr_traits<Base1Ptr>::is_intrusive::value));
|
|
BOOST_STATIC_ASSERT(( nasal::shared_ptr_traits<Base2Ptr>::is_intrusive::value));
|
|
BOOST_STATIC_ASSERT(( nasal::shared_ptr_traits<DerivedPtr>::is_intrusive::value));
|
|
BOOST_STATIC_ASSERT(( nasal::shared_ptr_traits<DerivedWeakPtr>::is_intrusive::value));
|
|
BOOST_STATIC_ASSERT(( nasal::shared_ptr_traits<SGReferencedPtr>::is_intrusive::value));
|
|
|
|
BOOST_STATIC_ASSERT((!nasal::shared_ptr_traits<boost::shared_ptr<Derived> >::is_intrusive::value));
|
|
BOOST_STATIC_ASSERT((!nasal::shared_ptr_traits<boost::weak_ptr<Derived> >::is_intrusive::value));
|
|
|
|
BOOST_AUTO_TEST_CASE( storage_traits )
|
|
{
|
|
DerivedPtr d = new Derived();
|
|
|
|
Derived* d_raw = nasal::shared_ptr_storage<DerivedPtr>::ref(d);
|
|
BOOST_REQUIRE_EQUAL(d_raw, d.get());
|
|
BOOST_REQUIRE_EQUAL(d.getNumRefs(), 2);
|
|
|
|
DerivedWeakPtr* d_weak = nasal::shared_ptr_storage<DerivedWeakPtr>::ref(d);
|
|
BOOST_REQUIRE_EQUAL(
|
|
nasal::shared_ptr_storage<DerivedWeakPtr>::get<Derived*>(d_weak),
|
|
d_raw
|
|
);
|
|
|
|
d.reset();
|
|
BOOST_REQUIRE_EQUAL(Derived::count(d_raw), 1);
|
|
|
|
nasal::shared_ptr_storage<DerivedPtr>::unref(d_raw);
|
|
BOOST_REQUIRE(d_weak->expired());
|
|
|
|
nasal::shared_ptr_storage<DerivedWeakPtr>::unref(d_weak);
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE( bind_methods )
|
|
{
|
|
struct TestClass
|
|
{
|
|
int arg1;
|
|
std::string arg2;
|
|
std::string arg3;
|
|
int arg4;
|
|
|
|
void set(int a1, const std::string& a2, const std::string& a3, int a4)
|
|
{
|
|
arg1 = a1;
|
|
arg2 = a2;
|
|
arg3 = a3;
|
|
arg4 = a4;
|
|
}
|
|
};
|
|
using TestClassPtr = boost::shared_ptr<TestClass>;
|
|
auto set_func = boost::function<
|
|
void (TestClass&, int, const std::string&, const std::string&, int)
|
|
>(&TestClass::set);
|
|
nasal::Ghost<TestClassPtr>::init("TestClass")
|
|
.method("set", set_func)
|
|
.method("setReverse", set_func, std::index_sequence<3,2,1,0>{});
|
|
|
|
TestContext ctx;
|
|
auto test = boost::make_shared<TestClass>();
|
|
|
|
ctx.exec("me.set(1, \"s2\", \"s3\", 4);", ctx.to_me(test));
|
|
BOOST_CHECK_EQUAL(test->arg1, 1);
|
|
BOOST_CHECK_EQUAL(test->arg2, "s2");
|
|
BOOST_CHECK_EQUAL(test->arg3, "s3");
|
|
BOOST_CHECK_EQUAL(test->arg4, 4);
|
|
|
|
ctx.exec("me.setReverse(1, \"s2\", \"s3\", 4);", ctx.to_me(test));
|
|
BOOST_CHECK_EQUAL(test->arg1, 4);
|
|
BOOST_CHECK_EQUAL(test->arg2, "s3");
|
|
BOOST_CHECK_EQUAL(test->arg3, "s2");
|
|
BOOST_CHECK_EQUAL(test->arg4, 1);
|
|
}
|