Skip to content

Commit

Permalink
first systematic unit test for SGObject::clone (#4148)
Browse files Browse the repository at this point in the history
  • Loading branch information
karlnapf committed Feb 5, 2018
1 parent 0b519ee commit f3ad96b
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 10 deletions.
17 changes: 9 additions & 8 deletions src/shogun/base/SGObject.cpp
Expand Up @@ -673,14 +673,15 @@ void CSGObject::build_gradient_parameter_dictionary(CMap<TParameter*, CSGObject*
CSGObject* CSGObject::clone()
{
SG_DEBUG("Constructing an empty instance of %s\n", get_name());
CSGObject* copy = create(get_name(), this->m_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))
Expand Down
5 changes: 5 additions & 0 deletions tests/unit/base/MockObject.h
@@ -1,3 +1,4 @@
#include <shogun/base/Parameter.h>
#include <shogun/base/SGObject.h>
#include <shogun/base/range.h>
#include <shogun/base/some.h>
Expand Down Expand Up @@ -77,6 +78,10 @@ namespace shogun

m_object = new CCloneEqualsMockParameter<T>();
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()
Expand Down
39 changes: 37 additions & 2 deletions tests/unit/base/SGObject_unittest.cc
Expand Up @@ -30,17 +30,25 @@ template <typename T>
class SGObjectEquals : public ::testing::Test
{
};

// fixture for SGObject::clone tests
template <typename T>
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<bool, char, int8_t, int16_t, int32_t, int64_t,
float32_t, float64_t, floatmax_t>
SGBasicTypes;

TYPED_TEST_CASE(SGObjectEquals, SGBasicTypes);
TYPED_TEST_CASE(SGObjectClone, SGBasicTypes);

TYPED_TEST(SGObjectEquals, mock_allocate_delete)
{
auto obj = some<CCloneEqualsMock<int32_t>>();
auto obj = some<CCloneEqualsMock<TypeParam>>();
}

TYPED_TEST(SGObjectEquals, same)
Expand Down Expand Up @@ -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<CCloneEqualsMock<int>>();
auto obj2 = some<CCloneEqualsMock<float>>();
Expand All @@ -181,6 +189,33 @@ TEST(SGObject, equals_different_type)
EXPECT_FALSE(obj2->equals(obj1));
}

TYPED_TEST(SGObjectClone, basic)
{
auto obj = some<CCloneEqualsMock<TypeParam>>();

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<CCloneEqualsMock<TypeParam>*>(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<CGaussianKernel>();
Expand Down

0 comments on commit f3ad96b

Please sign in to comment.