From 36fd005bb9ce48752cf1c358d3e9f0b5b16ef8ff Mon Sep 17 00:00:00 2001 From: Thomas Geymayer Date: Mon, 15 Sep 2014 23:42:12 +0200 Subject: [PATCH] cppbind: check if ghost is of wrong type. - Throw an exception if converting an object from Nasal fails due to a wrong type (nil does not throw). - Update cppbind test cases accordingly (and refactor another test suite to use Boost. Test). --- simgear/nasal/cppbind/CMakeLists.txt | 11 +- simgear/nasal/cppbind/Ghost.hxx | 41 ++- simgear/nasal/cppbind/cppbind_test.cxx | 250 +++++++++---------- simgear/nasal/cppbind/cppbind_test_ghost.cxx | 7 +- simgear/nasal/cppbind/from_nasal.hxx | 5 +- 5 files changed, 170 insertions(+), 144 deletions(-) diff --git a/simgear/nasal/cppbind/CMakeLists.txt b/simgear/nasal/cppbind/CMakeLists.txt index e9e9e581..1e52d9b9 100644 --- a/simgear/nasal/cppbind/CMakeLists.txt +++ b/simgear/nasal/cppbind/CMakeLists.txt @@ -34,17 +34,16 @@ set(SOURCES simgear_component(nasal/cppbind nasal/cppbind "${SOURCES}" "${HEADERS}") simgear_component(nasal/cppbind/detail nasal/cppbind/detail "" "${DETAIL_HEADERS}") -if(ENABLE_TESTS) - add_executable(test_cppbind cppbind_test.cxx) - add_test(cppbind ${EXECUTABLE_OUTPUT_PATH}/test_cppbind) - target_link_libraries(test_cppbind ${TEST_LIBS}) -endif(ENABLE_TESTS) - add_boost_test(cppbind_ghost SOURCES cppbind_test_ghost.cxx LIBRARIES ${TEST_LIBS} ) +add_boost_test(cppbind_misc + SOURCES cppbind_test.cxx + LIBRARIES ${TEST_LIBS} +) + add_boost_test(nasal_num SOURCES nasal_num_test.cxx LIBRARIES ${TEST_LIBS} diff --git a/simgear/nasal/cppbind/Ghost.hxx b/simgear/nasal/cppbind/Ghost.hxx index 8b0d80c3..4c0a3e48 100644 --- a/simgear/nasal/cppbind/Ghost.hxx +++ b/simgear/nasal/cppbind/Ghost.hxx @@ -880,6 +880,41 @@ namespace nasal return strong_ref(); } + /** + * Convert Nasal object to C++ object and check if it has the correct + * type. + * + * @see fromNasal + */ + static strong_ref fromNasalChecked(naContext c, naRef me) + { + strong_ref obj = fromNasal(c, me); + if( obj ) + return obj; + if( naIsNil(me) ) + return strong_ref(); + + std::string msg = "Can not convert to '" + + getSingletonPtr()->_name_strong + + "': "; + + naGhostType* ghost_type = naGhost_type(me); + if( ghost_type ) + msg += "not a derived class (or expired weak ref): " + "'" + std::string(ghost_type->name) + "'"; + else if( naIsHash(me) ) + { + if( !naIsVector(naHash_cget(me, const_cast("parents"))) ) + msg += "missing parents vector"; + else + msg += "not a derived hash"; + } + else + msg += "not an object"; + + throw bad_nasal_cast(msg); + } + private: template @@ -1420,7 +1455,7 @@ typename boost::enable_if< from_nasal_helper(naContext c, naRef ref, const T*) { typedef typename nasal::shared_ptr_traits::strong_ref strong_ref; - return T(nasal::Ghost::fromNasal(c, ref)); + return T(nasal::Ghost::fromNasalChecked(c, ref)); } /** @@ -1455,7 +1490,7 @@ typename boost::enable_if_c< from_nasal_helper(naContext c, naRef ref, const T*) { typedef SGSharedPtr::type> TypeRef; - return T(nasal::Ghost::fromNasal(c, ref)); + return T(nasal::Ghost::fromNasalChecked(c, ref)); } /** @@ -1482,7 +1517,7 @@ typename boost::enable_if< from_nasal_helper(naContext c, naRef ref, const T*) { typedef osg::ref_ptr::type> TypeRef; - return T(nasal::Ghost::fromNasal(c, ref)); + return T(nasal::Ghost::fromNasalChecked(c, ref)); } #endif /* SG_NASAL_GHOST_HXX_ */ diff --git a/simgear/nasal/cppbind/cppbind_test.cxx b/simgear/nasal/cppbind/cppbind_test.cxx index 86de6d4d..2ea918d8 100644 --- a/simgear/nasal/cppbind/cppbind_test.cxx +++ b/simgear/nasal/cppbind/cppbind_test.cxx @@ -1,22 +1,17 @@ -#include +#define BOOST_TEST_MODULE cppbind +#include #include "Ghost.hxx" #include "NasalHash.hxx" #include "NasalString.hxx" + +#include #include #include #include #include -#include - -#define VERIFY(a) \ - if( !(a) ) \ - { \ - std::cerr << "failed: line " << __LINE__ << ": " << #a << std::endl; \ - return 1; \ - } enum MyEnum { @@ -121,7 +116,7 @@ naRef f_derivedGetX(const Derived& d, naContext c) } naRef f_freeFunction(nasal::CallContext c) { return c.requireArg(0); } -int main(int argc, char* argv[]) +BOOST_AUTO_TEST_CASE( cppbind_misc_testing ) { naContext c = naNewContext(); naRef r; @@ -129,44 +124,36 @@ int main(int argc, char* argv[]) using namespace nasal; r = to_nasal(c, ENUM_ANOTHER); - VERIFY( from_nasal(c, r) == ENUM_ANOTHER ); + BOOST_CHECK_EQUAL(from_nasal(c, r), ENUM_ANOTHER); r = to_nasal(c, "Test"); - VERIFY( strncmp("Test", naStr_data(r), naStr_len(r)) == 0 ); - VERIFY( from_nasal(c, r) == "Test" ); + BOOST_CHECK( strncmp("Test", naStr_data(r), naStr_len(r)) == 0 ); + BOOST_CHECK_EQUAL(from_nasal(c, r), "Test"); r = to_nasal(c, std::string("Test")); - VERIFY( strncmp("Test", naStr_data(r), naStr_len(r)) == 0 ); - VERIFY( from_nasal(c, r) == "Test" ); + BOOST_CHECK( strncmp("Test", naStr_data(r), naStr_len(r)) == 0 ); + BOOST_CHECK_EQUAL(from_nasal(c, r), "Test"); r = to_nasal(c, 42); - VERIFY( naNumValue(r).num == 42 ); - VERIFY( from_nasal(c, r) == 42 ); + BOOST_CHECK_EQUAL(naNumValue(r).num, 42); + BOOST_CHECK_EQUAL(from_nasal(c, r), 42); r = to_nasal(c, 4.2f); - VERIFY( naNumValue(r).num == 4.2f ); - VERIFY( from_nasal(c, r) == 4.2f ); + BOOST_CHECK_EQUAL(naNumValue(r).num, 4.2f); + BOOST_CHECK_EQUAL(from_nasal(c, r), 4.2f); float test_data[3] = {0, 4, 2}; r = to_nasal(c, test_data); SGVec2f vec(0,2); r = to_nasal(c, vec); - VERIFY( from_nasal(c, r) == vec ); + BOOST_CHECK_EQUAL(from_nasal(c, r), vec); std::vector std_vec; r = to_nasal(c, std_vec); r = to_nasal(c, "string"); - try - { - from_nasal(c, r); - - std::cerr << "failed: Expected bad_nasal_cast to be thrown" << std::endl; - return 1; - } - catch(nasal::bad_nasal_cast&) - {} + BOOST_CHECK_THROW(from_nasal(c, r), bad_nasal_cast); Hash hash(c); hash.set("vec", r); @@ -175,9 +162,10 @@ int main(int argc, char* argv[]) hash.set("string", std::string("blub")); hash.set("func", &f_freeFunction); - VERIFY( hash.size() == 5 ) + BOOST_CHECK_EQUAL(hash.size(), 5); for(Hash::const_iterator it = hash.begin(); it != hash.end(); ++it) - VERIFY( hash.get(it->getKey()) == it->getValue() ) + BOOST_CHECK_EQUAL( hash.get(it->getKey()), + it->getValue() ); Hash::iterator it1, it2; Hash::const_iterator it3 = it1, it4(it2); @@ -185,15 +173,15 @@ int main(int argc, char* argv[]) it3 = it2; r = to_nasal(c, hash); - VERIFY( naIsHash(r) ); + BOOST_REQUIRE( naIsHash(r) ); simgear::StringMap string_map = from_nasal(c, r); - VERIFY( string_map.at("vec") == "string" ) - VERIFY( string_map.at("name") == "my-name" ) - VERIFY( string_map.at("string") == "blub" ) + BOOST_CHECK_EQUAL(string_map.at("vec"), "string"); + BOOST_CHECK_EQUAL(string_map.at("name"), "my-name"); + BOOST_CHECK_EQUAL(string_map.at("string"), "blub"); - VERIFY( hash.get("name") == "my-name" ); - VERIFY( naIsString(hash.get("name")) ); + BOOST_CHECK_EQUAL(hash.get("name"), "my-name"); + BOOST_CHECK(naIsString(hash.get("name"))); Hash mod = hash.createHash("mod"); mod.set("parent", hash); @@ -201,35 +189,35 @@ int main(int argc, char* argv[]) // 'func' is a C++ function registered to Nasal and now converted back to C++ boost::function f = hash.get("func"); - VERIFY( f ); - VERIFY( f(3) == 3 ); + BOOST_REQUIRE( f ); + BOOST_CHECK_EQUAL(f(3), 3); boost::function fs = hash.get("func"); - VERIFY( fs ); - VERIFY( fs(14) == "14" ); + BOOST_REQUIRE( fs ); + BOOST_CHECK_EQUAL(fs(14), "14"); typedef boost::function FuncVoidInt; FuncVoidInt fvi = hash.get("func"); - VERIFY( fvi ); + BOOST_REQUIRE( fvi ); fvi(123); typedef boost::function FuncMultiArg; FuncMultiArg fma = hash.get("func"); - VERIFY( fma ); - VERIFY( fma("test", 3, .5) == "test" ); + BOOST_REQUIRE( fma ); + BOOST_CHECK_EQUAL(fma("test", 3, .5), "test"); typedef boost::function naRefMemFunc; naRefMemFunc fmem = hash.get("func"); - VERIFY( fmem ); + BOOST_REQUIRE( fmem ); naRef ret = fmem(hash.get_naRef()), hash_ref = hash.get_naRef(); - VERIFY( naIsIdentical(ret, hash_ref) ); + BOOST_CHECK( naIsIdentical(ret, hash_ref) ); // Check if nasal::Me gets passed as self/me and remaining arguments are // passed on to function typedef boost::function MeIntFunc; MeIntFunc fmeint = hash.get("func"); - VERIFY( fmeint(naNil(), 5) == 5 ); + BOOST_CHECK_EQUAL(fmeint(naNil(), 5), 5); //---------------------------------------------------------------------------- // Test exposing classes to Nasal @@ -276,78 +264,80 @@ int main(int argc, char* argv[]) naRef nasal_ref = to_nasal(c, weak_ptr), nasal_ptr = to_nasal(c, weak_ptr.get()); - VERIFY( naIsGhost(nasal_ref) ); - VERIFY( naIsGhost(nasal_ptr) ); + BOOST_REQUIRE( naIsGhost(nasal_ref) ); + BOOST_REQUIRE( naIsGhost(nasal_ptr) ); SGWeakRefBasedPtr ptr1 = from_nasal(c, nasal_ref), ptr2 = from_nasal(c, nasal_ptr); - VERIFY( weak_ptr == ptr1 ); - VERIFY( weak_ptr == ptr2 ); + BOOST_CHECK_EQUAL(weak_ptr, ptr1); + BOOST_CHECK_EQUAL(weak_ptr, ptr2); - VERIFY( Ghost::isInit() ); + BOOST_REQUIRE( Ghost::isInit() ); nasal::to_nasal(c, DoubleDerived2Ptr()); BasePtr d( new Derived ); naRef derived = to_nasal(c, d); - VERIFY( naIsGhost(derived) ); - VERIFY( std::string("DerivedPtr") == naGhost_type(derived)->name ); + BOOST_REQUIRE( naIsGhost(derived) ); + BOOST_CHECK_EQUAL( std::string("DerivedPtr"), naGhost_type(derived)->name ); // Get member function from ghost... naRef thisGetter = naNil(); - VERIFY( naMember_get(c, derived, to_nasal(c, "this"), &thisGetter) ); - VERIFY( naIsFunc(thisGetter) ); + BOOST_CHECK( naMember_get(c, derived, to_nasal(c, "this"), &thisGetter) ); + BOOST_CHECK( naIsFunc(thisGetter) ); // ...and check if it really gets passed the correct instance typedef boost::function MemFunc; MemFunc fGetThis = from_nasal(c, thisGetter); - VERIFY( fGetThis ); - VERIFY( fGetThis(derived) == (unsigned long)d.get() ); + BOOST_REQUIRE( fGetThis ); + BOOST_CHECK_EQUAL( fGetThis(derived), (unsigned long)d.get() ); BasePtr d2( new DoubleDerived ); derived = to_nasal(c, d2); - VERIFY( naIsGhost(derived) ); - VERIFY( std::string("DoubleDerivedPtr") == naGhost_type(derived)->name ); + BOOST_CHECK( naIsGhost(derived) ); + BOOST_CHECK_EQUAL( std::string("DoubleDerivedPtr"), + naGhost_type(derived)->name ); BasePtr d3( new DoubleDerived2 ); derived = to_nasal(c, d3); - VERIFY( naIsGhost(derived) ); - VERIFY( std::string("DoubleDerived2Ptr") == naGhost_type(derived)->name ); + BOOST_CHECK( naIsGhost(derived) ); + BOOST_CHECK_EQUAL( std::string("DoubleDerived2Ptr"), + naGhost_type(derived)->name ); SGRefBasedPtr ref_based( new SGReferenceBasedClass ); naRef na_ref_based = to_nasal(c, ref_based.get()); - VERIFY( naIsGhost(na_ref_based) ); - VERIFY( from_nasal(c, na_ref_based) - == ref_based.get() ); - VERIFY( from_nasal(c, na_ref_based) == ref_based ); - - VERIFY( from_nasal(c, derived) == d3 ); - VERIFY( from_nasal(c, derived) != d2 ); - VERIFY( from_nasal(c, derived) - == boost::dynamic_pointer_cast(d3) ); - VERIFY( from_nasal(c, derived) - == boost::dynamic_pointer_cast(d3) ); - VERIFY( !from_nasal(c, derived) ); + BOOST_CHECK( naIsGhost(na_ref_based) ); + BOOST_CHECK_EQUAL( from_nasal(c, na_ref_based), + ref_based.get() ); + BOOST_CHECK_EQUAL( from_nasal(c, na_ref_based), ref_based ); + + BOOST_CHECK_EQUAL( from_nasal(c, derived), d3 ); + BOOST_CHECK_NE( from_nasal(c, derived), d2 ); + BOOST_CHECK_EQUAL( from_nasal(c, derived), + boost::dynamic_pointer_cast(d3) ); + BOOST_CHECK_EQUAL( from_nasal(c, derived), + boost::dynamic_pointer_cast(d3) ); + BOOST_CHECK_THROW( from_nasal(c, derived), bad_nasal_cast ); std::map instances; - VERIFY( naIsHash(to_nasal(c, instances)) ); + BOOST_CHECK( naIsHash(to_nasal(c, instances)) ); std::map instances_d; - VERIFY( naIsHash(to_nasal(c, instances_d)) ); + BOOST_CHECK( naIsHash(to_nasal(c, instances_d)) ); std::map int_map; - VERIFY( naIsHash(to_nasal(c, int_map)) ); + BOOST_CHECK( naIsHash(to_nasal(c, int_map)) ); std::map > int_vector_map; - VERIFY( naIsHash(to_nasal(c, int_vector_map)) ); + BOOST_CHECK( naIsHash(to_nasal(c, int_vector_map)) ); simgear::StringMap dict = simgear::StringMap("hello", "value") ("key2", "value2"); naRef na_dict = to_nasal(c, dict); - VERIFY( naIsHash(na_dict) ); - VERIFY( Hash(na_dict, c).get("key2") == "value2" ); + BOOST_REQUIRE( naIsHash(na_dict) ); + BOOST_CHECK_EQUAL( Hash(na_dict, c).get("key2"), "value2" ); // Check converting to Ghost if using Nasal hashes with actual ghost inside // the hashes parents vector @@ -357,14 +347,14 @@ int main(int argc, char* argv[]) Hash obj(c); obj.set("parents", parents); - VERIFY( from_nasal(c, obj.get_naRef()) == d3 ); + BOOST_CHECK_EQUAL( from_nasal(c, obj.get_naRef()), d3 ); // Check recursive parents (aka parent-of-parent) std::vector parents2; parents2.push_back(obj.get_naRef()); Hash derived_obj(c); derived_obj.set("parents", parents2); - VERIFY( from_nasal(c, derived_obj.get_naRef()) == d3 ); + BOOST_CHECK_EQUAL( from_nasal(c, derived_obj.get_naRef()), d3 ); std::vector nasal_objects; nasal_objects.push_back( Ghost::makeGhost(c, d) ); @@ -373,9 +363,9 @@ int main(int argc, char* argv[]) naRef obj_vec = to_nasal(c, nasal_objects); std::vector objects = from_nasal >(c, obj_vec); - VERIFY( objects[0] == d ); - VERIFY( objects[1] == d2 ); - VERIFY( objects[2] == d3 ); + BOOST_CHECK_EQUAL( objects[0], d ); + BOOST_CHECK_EQUAL( objects[1], d2 ); + BOOST_CHECK_EQUAL( objects[2], d3 ); { // Calling fallback setter for unset values @@ -386,9 +376,9 @@ int main(int argc, char* argv[]) &errLine ); ret = naCallMethod(code, derived, 0, 0, naNil()); - VERIFY( !naGetError(c) ) // TODO real error check (this seems to always - // return 0... - VERIFY( from_nasal(c, ret) == 3 ) + BOOST_REQUIRE( !naGetError(c) ); // TODO real error check (this seems to + // always return 0... + BOOST_CHECK_EQUAL( from_nasal(c, ret), 3 ); } { // Calling generic (fallback) getter @@ -399,9 +389,9 @@ int main(int argc, char* argv[]) &errLine ); ret = naCallMethod(code, derived, 0, 0, naNil()); - VERIFY( !naGetError(c) ) // TODO real error check (this seems to always - // return 0... - VERIFY( from_nasal(c, ret) == "generic-get" ); + BOOST_REQUIRE( !naGetError(c) ); // TODO real error check (this seems to + // always return 0... + BOOST_CHECK_EQUAL( from_nasal(c, ret), "generic-get" ); } //---------------------------------------------------------------------------- @@ -418,54 +408,52 @@ int main(int argc, char* argv[]) to_nasal(c, map) }; CallContext cc(c, naNil(), sizeof(args)/sizeof(args[0]), args); - VERIFY( cc.requireArg(0) == "test-arg" ); - VERIFY( cc.getArg(0) == "test-arg" ); - VERIFY( cc.getArg(10) == "" ); - VERIFY( cc.isString(0) ); - VERIFY( !cc.isNumeric(0) ); - VERIFY( !cc.isVector(0) ); - VERIFY( !cc.isHash(0) ); - VERIFY( !cc.isGhost(0) ); - VERIFY( cc.isNumeric(1) ); - VERIFY( cc.isVector(2) ); - VERIFY( cc.isHash(3) ); + BOOST_CHECK_EQUAL( cc.requireArg(0), "test-arg" ); + BOOST_CHECK_EQUAL( cc.getArg(0), "test-arg" ); + BOOST_CHECK_EQUAL( cc.getArg(10), "" ); + BOOST_CHECK( cc.isString(0) ); + BOOST_CHECK( !cc.isNumeric(0) ); + BOOST_CHECK( !cc.isVector(0) ); + BOOST_CHECK( !cc.isHash(0) ); + BOOST_CHECK( !cc.isGhost(0) ); + BOOST_CHECK( cc.isNumeric(1) ); + BOOST_CHECK( cc.isVector(2) ); + BOOST_CHECK( cc.isHash(3) ); naRef args_vec = nasal::to_nasal(c, args); - VERIFY( naIsVector(args_vec) ); + BOOST_CHECK( naIsVector(args_vec) ); //---------------------------------------------------------------------------- // Test nasal::String //---------------------------------------------------------------------------- String string( to_nasal(c, "Test") ); - VERIFY( from_nasal(c, string.get_naRef()) == "Test" ); - VERIFY( string.c_str() == std::string("Test") ); - VERIFY( string.starts_with(string) ); - VERIFY( string.starts_with(String(c, "T")) ); - VERIFY( string.starts_with(String(c, "Te")) ); - VERIFY( string.starts_with(String(c, "Tes")) ); - VERIFY( string.starts_with(String(c, "Test")) ); - VERIFY( !string.starts_with(String(c, "Test1")) ); - VERIFY( !string.starts_with(String(c, "bb")) ); - VERIFY( !string.starts_with(String(c, "bbasdasdafasd")) ); - VERIFY( string.ends_with(String(c, "t")) ); - VERIFY( string.ends_with(String(c, "st")) ); - VERIFY( string.ends_with(String(c, "est")) ); - VERIFY( string.ends_with(String(c, "Test")) ); - VERIFY( !string.ends_with(String(c, "1Test")) ); - VERIFY( !string.ends_with(String(c, "abc")) ); - VERIFY( !string.ends_with(String(c, "estasdasd")) ); - VERIFY( string.find('e') == 1 ); - VERIFY( string.find('9') == String::npos ); - VERIFY( string.find_first_of(String(c, "st")) == 2 ); - VERIFY( string.find_first_of(String(c, "st"), 3) == 3 ); - VERIFY( string.find_first_of(String(c, "xyz")) == String::npos ); - VERIFY( string.find_first_not_of(String(c, "Tst")) == 1 ); - VERIFY( string.find_first_not_of(String(c, "Tse"), 2) == 3 ); - VERIFY( string.find_first_not_of(String(c, "abc")) == 0 ); - VERIFY( string.find_first_not_of(String(c, "abc"), 20) == String::npos ); + BOOST_CHECK_EQUAL( from_nasal(c, string.get_naRef()), "Test" ); + BOOST_CHECK_EQUAL( string.c_str(), std::string("Test") ); + BOOST_CHECK( string.starts_with(string) ); + BOOST_CHECK( string.starts_with(String(c, "T")) ); + BOOST_CHECK( string.starts_with(String(c, "Te")) ); + BOOST_CHECK( string.starts_with(String(c, "Tes")) ); + BOOST_CHECK( string.starts_with(String(c, "Test")) ); + BOOST_CHECK( !string.starts_with(String(c, "Test1")) ); + BOOST_CHECK( !string.starts_with(String(c, "bb")) ); + BOOST_CHECK( !string.starts_with(String(c, "bbasdasdafasd")) ); + BOOST_CHECK( string.ends_with(String(c, "t")) ); + BOOST_CHECK( string.ends_with(String(c, "st")) ); + BOOST_CHECK( string.ends_with(String(c, "est")) ); + BOOST_CHECK( string.ends_with(String(c, "Test")) ); + BOOST_CHECK( !string.ends_with(String(c, "1Test")) ); + BOOST_CHECK( !string.ends_with(String(c, "abc")) ); + BOOST_CHECK( !string.ends_with(String(c, "estasdasd")) ); + BOOST_CHECK_EQUAL( string.find('e'), 1 ); + BOOST_CHECK_EQUAL( string.find('9'), String::npos ); + BOOST_CHECK_EQUAL( string.find_first_of(String(c, "st")), 2 ); + BOOST_CHECK_EQUAL( string.find_first_of(String(c, "st"), 3), 3 ); + BOOST_CHECK_EQUAL( string.find_first_of(String(c, "xyz")), String::npos ); + BOOST_CHECK_EQUAL( string.find_first_not_of(String(c, "Tst")), 1 ); + BOOST_CHECK_EQUAL( string.find_first_not_of(String(c, "Tse"), 2), 3 ); + BOOST_CHECK_EQUAL( string.find_first_not_of(String(c, "abc")), 0 ); + BOOST_CHECK_EQUAL( string.find_first_not_of(String(c, "abc"), 20), String::npos ); naFreeContext(c); - - return 0; } diff --git a/simgear/nasal/cppbind/cppbind_test_ghost.cxx b/simgear/nasal/cppbind/cppbind_test_ghost.cxx index 50d42a57..98924989 100644 --- a/simgear/nasal/cppbind/cppbind_test_ghost.cxx +++ b/simgear/nasal/cppbind/cppbind_test_ghost.cxx @@ -77,7 +77,8 @@ BOOST_AUTO_TEST_CASE( ghost_weak_strong_nasal_conversion ) BOOST_CHECK_EQUAL( nasal::from_nasal(c, na_d), d ); d.reset(); - BOOST_REQUIRE( !nasal::from_nasal(c, na_d) ); + BOOST_REQUIRE_THROW( nasal::from_nasal(c, na_d), + nasal::bad_nasal_cast ); // store strong pointer and extract weak pointer d.reset(new Derived); @@ -132,8 +133,8 @@ BOOST_AUTO_TEST_CASE( ghost_casting_storage ) na_b1 = nasal::to_nasal(c, b1_ref); BOOST_CHECK_EQUAL(nasal::from_nasal(c, na_b1), b1_ref.get()); - BOOST_CHECK(!nasal::from_nasal(c, na_b1)); - BOOST_CHECK(!nasal::from_nasal(c, na_b1)); + BOOST_CHECK_THROW(nasal::from_nasal(c, na_b1), nasal::bad_nasal_cast); + BOOST_CHECK_THROW(nasal::from_nasal(c, na_b1), nasal::bad_nasal_cast); } //------------------------------------------------------------------------------ diff --git a/simgear/nasal/cppbind/from_nasal.hxx b/simgear/nasal/cppbind/from_nasal.hxx index 368d4a96..cd9a9fe4 100644 --- a/simgear/nasal/cppbind/from_nasal.hxx +++ b/simgear/nasal/cppbind/from_nasal.hxx @@ -47,7 +47,7 @@ namespace nasal /** * Get pointer to specific version of from_nasal, converting to a type - * compatible to Var. + * compatible to \a Var. */ template struct from_nasal_ptr @@ -63,6 +63,9 @@ namespace nasal } }; + /** + * Get member of hash, ghost (also searching in parent objects). + */ template T get_member(naContext c, naRef obj, const std::string& name) { -- 2.39.5