diff --git a/src/shogun/base/SGObject.cpp b/src/shogun/base/SGObject.cpp index d8d88341d9d..8ea913a01b7 100644 --- a/src/shogun/base/SGObject.cpp +++ b/src/shogun/base/SGObject.cpp @@ -673,14 +673,15 @@ void CSGObject::build_gradient_parameter_dictionary(CMapm_generic); - - SG_REF(copy); - - REQUIRE(copy, "Could not create empty instance of \"%s\". The reason for " - "this usually is that get_name() of the class returns something " - "wrong, or that a class has a wrongly set generic type.\n", - get_name()); + CSGObject* copy = create_empty(); + + REQUIRE( + copy, "Could not create empty instance of %s. The reason for " + "this usually is that get_name() of the class returns something " + "wrong, that a class has a wrongly set generic type, or that it " + "lies outside the main source tree and does not have " + "CSGObject::create_empty() overridden.\n", + get_name()); SG_DEBUG("Cloning all parameters of %s\n", get_name()); if (!copy->clone_parameters(this)) diff --git a/tests/unit/base/MockObject.h b/tests/unit/base/MockObject.h index 8c3aad6705e..bd7489c7ec4 100644 --- a/tests/unit/base/MockObject.h +++ b/tests/unit/base/MockObject.h @@ -1,3 +1,4 @@ +#include #include #include #include @@ -77,6 +78,10 @@ namespace shogun m_object = new CCloneEqualsMockParameter(); watch_param("object", &m_object); + + // TODO: delete once clone is based on tags + m_parameters->add( + (CSGObject**)&m_object, "object", "The object (tm)"); } void free_single() diff --git a/tests/unit/base/SGObject_unittest.cc b/tests/unit/base/SGObject_unittest.cc index 3cf6fd32e8c..ebc04acb594 100644 --- a/tests/unit/base/SGObject_unittest.cc +++ b/tests/unit/base/SGObject_unittest.cc @@ -30,6 +30,13 @@ template class SGObjectEquals : public ::testing::Test { }; + +// fixture for SGObject::clone tests +template +class SGObjectClone : public ::testing::Test +{ +}; + // types that go into SGVector<> and co // TODO: SGString doesn't support complex128_t, so omitted here typedef ::testing::Types>(); + auto obj = some>(); } TYPED_TEST(SGObjectEquals, same) @@ -172,7 +180,7 @@ TYPED_TEST(SGObjectEquals, different_raw_matrix_basic) EXPECT_FALSE(obj2->equals(obj1)); } -TEST(SGObject, equals_different_type) +TEST(SGObjectEquals, different_type) { auto obj1 = some>(); auto obj2 = some>(); @@ -181,6 +189,33 @@ TEST(SGObject, equals_different_type) EXPECT_FALSE(obj2->equals(obj1)); } +TYPED_TEST(SGObjectClone, basic) +{ + auto obj = some>(); + + CSGObject* clone = nullptr; + try + { + clone = obj->clone(); + } + catch (...) + { + } + + EXPECT_NE(clone, obj); + ASSERT_NE(clone, nullptr); + EXPECT_EQ(clone->ref_count(), 1); + + auto clone_casted = dynamic_cast*>(clone); + ASSERT_NE(clone_casted, nullptr); + ASSERT_NE(clone_casted->m_object, obj->m_object); + EXPECT_EQ(clone_casted->m_object->m_was_cloned, true); + + EXPECT_EQ(std::string(clone->get_name()), std::string(obj->get_name())); + + SG_UNREF(clone); +} + TEST(SGObject, clone_basic_parameter) { auto object = some();