Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

systematically test CSGObject::equals #4099

Merged
merged 1 commit into from
Jan 22, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
22 changes: 21 additions & 1 deletion src/shogun/base/SGObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -500,12 +500,32 @@ class CSGObject
*/
template <typename T>
void watch_param(
const std::string& name, T* value, AnyParameterProperties properties)
const std::string& name, T* value,
AnyParameterProperties properties =
AnyParameterProperties(MS_NOT_AVAILABLE, GRADIENT_NOT_AVAILABLE))
{
BaseTag tag(name);
create_parameter(tag, AnyParameter(make_any_ref(value), properties));
}

/** Puts a pointer to some parameter array into the parameter map.
*
* @param name name of the parameter array
* @param value pointer to the first element of the parameter array
* @param properties properties of the parameter (e.g. if model selection is
* supported)
*/
template <typename T, typename S>
void watch_param(
const std::string& name, T** value, S* len,
AnyParameterProperties properties =
AnyParameterProperties(MS_NOT_AVAILABLE, GRADIENT_NOT_AVAILABLE))
{
BaseTag tag(name);
create_parameter(
tag, AnyParameter(make_any_ref_array(value, len), properties));
}

public:
/** Updates the hash of current parameter combination */
virtual void update_parameter_hash();
Expand Down
33 changes: 28 additions & 5 deletions src/shogun/lib/SGString.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,34 @@ bool SGString<T>::operator==(const SGString & other) const
if (other.slen != slen)
return false;

for (int i = 0; i < slen; i++)
{
if (other.string[i] != string[i])
return false;
}
if (string != other.string)
return false;

return true;
}

template <class T>
bool SGString<T>::equals(const SGString& other) const
{
// avoid comparing elements when both are same.
// the case where both matrices are uninitialized is handled here as well.
if (*this == other)
return true;

// both empty
if (!(slen || other.slen))
return true;

// only one empty
if (!string || !other.string)
return false;

// different size
if (slen != other.slen)
return false;

// content
return std::equal(string, string + slen, other.string);

return true;
}
Expand Down
5 changes: 4 additions & 1 deletion src/shogun/lib/SGString.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,12 @@ template<class T> class SGString
/** copy constructor */
SGString(const SGString &orig);

/** equality operator */
/** @return true iff pointer and size are equal */
bool operator==(const SGString & other) const;

/** @return true iff content is equal */
bool equals(const SGString& other) const;

/** free string */
void free_string();

Expand Down
149 changes: 149 additions & 0 deletions tests/unit/base/MockObject.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,157 @@
#include <shogun/base/SGObject.h>
#include <shogun/base/range.h>
#include <shogun/base/some.h>
#include <shogun/lib/SGMatrix.h>
#include <shogun/lib/SGSparseMatrix.h>
#include <shogun/lib/SGSparseVector.h>
#include <shogun/lib/SGString.h>
#include <shogun/lib/SGVector.h>

namespace shogun
{
/** @brief Mock class to test clone and equals for CSGObject.
* Serves as a parameter of type CSGObject for @see CCloneEqualsMock.
*/
template <class T>
class CCloneEqualsMockParameter : public CSGObject
{
public:
CCloneEqualsMockParameter()
{
m_was_cloned = false;
m_some_value = 1;

watch_param("some_value", &m_some_value);
}
const char* get_name() const
{
return "CloneEqualsMockParameter";
}

virtual CSGObject* clone()
{
auto* clone = new CCloneEqualsMockParameter<T>();
clone->m_was_cloned = true;
SG_REF(clone);
return clone;
}

bool m_was_cloned;
T m_some_value;
};

/** @brief Mock class to test clone and equals for CSGObject.
* Has members that cover (hopefully) all possibilities of parameters.
*/
template <class T>
class CCloneEqualsMock : public CSGObject
{
public:
CCloneEqualsMock()
{
m_basic = 1;
watch_param("basic", &m_basic);

m_object = new CCloneEqualsMockParameter<T>();
watch_param("object", &m_object);

m_sg_vector = SGVector<T>(2);
m_sg_vector.set_const(m_basic);
watch_param("sg_vector", &m_sg_vector);

m_sg_matrix = SGMatrix<T>(3, 4);
m_sg_matrix.set_const(m_basic);
watch_param("sg_matrix", &m_sg_matrix);

m_sg_sparse_vector = SGSparseVector<T>(4);
for (auto i : range(m_sg_sparse_vector.num_feat_entries))
{
SGSparseVectorEntry<T> entry;
entry.feat_index = i * 2;
entry.entry = 2;
m_sg_sparse_vector.features[i] = entry;
}
watch_param("sg_sparse_vector", &m_sg_sparse_vector);

m_sg_sparse_matrix =
SGSparseMatrix<T>(m_sg_sparse_vector.num_feat_entries, 6);
for (auto i : range(m_sg_sparse_matrix.num_vectors))
{
SGSparseVector<T> vec(m_sg_sparse_matrix.num_features);
for (auto j : range(vec.num_feat_entries))
{
SGSparseVectorEntry<T> entry;
entry.feat_index = i * 2;
entry.entry = 3;
vec.features[j] = entry;
}
m_sg_sparse_matrix.sparse_matrix[i] = vec;
}
watch_param("sg_sparse_matrix", &m_sg_sparse_matrix);

m_vector_basic_len = 5;
m_vector_basic = new T[m_vector_basic_len];
for (auto i : range(m_vector_basic_len))
m_vector_basic[i] = m_basic;
watch_param("vector_basic", &m_vector_basic, &m_vector_basic_len);

m_vector_sg_string_len = 7;
m_vector_sg_string = new SGString<T>[m_vector_sg_string_len];
for (auto i : range(m_vector_sg_string_len))
{
m_vector_sg_string[i] = SGString<T>(i + 1, true);
for (auto j : range(m_vector_sg_string[i].slen))
m_vector_sg_string[i].string[j] = 1;
}
watch_param(
"vector_sg_string", &m_vector_sg_string,
&m_vector_sg_string_len);

m_vector_object_len = 6;
m_vector_object =
new CCloneEqualsMockParameter<T>*[m_vector_object_len];
for (auto i : range(m_vector_object_len))
m_vector_object[i] = new CCloneEqualsMockParameter<T>();
watch_param(
"vector_object", &m_vector_object, &m_vector_object_len);
}

~CCloneEqualsMock()
{
delete m_object;
delete m_vector_basic;
for (auto i : range(m_vector_object_len))
delete m_vector_object[i];
delete m_vector_object;

for (auto i : range(m_vector_sg_string_len))
m_vector_sg_string[i].free_string();
delete m_vector_sg_string;
}

const char* get_name() const
{
return "CloneEqualsMock";
}

T m_basic;
CCloneEqualsMockParameter<T>* m_object;

SGVector<T> m_sg_vector;
SGMatrix<T> m_sg_matrix;

SGSparseVector<T> m_sg_sparse_vector;
SGSparseMatrix<T> m_sg_sparse_matrix;

T* m_vector_basic;
index_t m_vector_basic_len;

SGString<T>* m_vector_sg_string;
index_t m_vector_sg_string_len;

CCloneEqualsMockParameter<T>** m_vector_object;
index_t m_vector_object_len;
};

/** @brief Used to test the tags-parameter framework
* Allows testing of registering new member and avoiding
Expand Down