Files
unison/src/core/test/val-array-test-suite.cc

298 lines
9.9 KiB
C++

/*
* Copyright (c) 2022 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Biljana Bojovic <bbojovic@cttc.es>
*/
#include "ns3/log.h"
#include "ns3/test.h"
#include "ns3/val-array.h"
/**
* \ingroup core-tests
*/
namespace ns3
{
namespace tests
{
NS_LOG_COMPONENT_DEFINE("ValArrayTest");
/**
* @brief ValArray test case for testing ValArray class
*
* @tparam T the template parameter that can be a complex number, double or int
*/
template <class T>
class ValArrayTestCase : public TestCase
{
public:
/** Default constructor*/
ValArrayTestCase<T>() = default;
/**
* Constructor
*
* \param [in] name reference name
*/
ValArrayTestCase<T>(const std::string& name);
/** Destructor. */
~ValArrayTestCase<T>() override;
/**
* \brief Copy constructor.
* Instruct the compiler to generate the implicitly declared copy constructor
*/
ValArrayTestCase<T>(const ValArrayTestCase<T>&) = default;
/**
* \brief Copy assignment operator.
* Instruct the compiler to generate the implicitly declared copy assignment operator.
* \return A reference to this ValArrayTestCase
*/
ValArrayTestCase<T>& operator=(const ValArrayTestCase<T>&) = default;
/**
* \brief Move constructor.
* Instruct the compiler to generate the implicitly declared move constructor
*/
ValArrayTestCase<T>(ValArrayTestCase<T>&&) = default;
/**
* \brief Move assignment operator.
* Instruct the compiler to generate the implicitly declared copy constructor
* \return A reference to this ValArrayTestCase
*/
ValArrayTestCase<T>& operator=(ValArrayTestCase<T>&&) = default;
private:
void DoRun() override;
};
template <class T>
ValArrayTestCase<T>::ValArrayTestCase(const std::string& name)
: TestCase(name)
{
}
template <class T>
ValArrayTestCase<T>::~ValArrayTestCase<T>()
{
}
template <class T>
void
ValArrayTestCase<T>::DoRun()
{
ValArray<T> v1 = ValArray<T>(2, 3);
for (size_t i = 0; i < v1.GetNumRows(); ++i)
{
for (size_t j = 0; j < v1.GetNumCols(); ++j)
{
v1(i, j) = 1;
}
}
ValArray<T> v2 = ValArray<T>(v1);
NS_TEST_ASSERT_MSG_EQ(v1.GetNumRows(), v2.GetNumRows(), "The number of rows are not equal.");
NS_TEST_ASSERT_MSG_EQ(v1.GetNumCols(), v2.GetNumCols(), "The number of cols are not equal.");
// test copy constructor
for (size_t i = 0; i < v1.GetNumRows(); ++i)
{
for (size_t j = 0; j < v1.GetNumCols(); ++j)
{
NS_TEST_ASSERT_MSG_EQ(v1(i, j), v2(i, j), "The elements are not equal.");
}
}
// test assign constructor
ValArray<T> v3 = v1;
NS_TEST_ASSERT_MSG_EQ(v1.GetNumRows(), v3.GetNumRows(), "The number of rows are not equal.");
NS_TEST_ASSERT_MSG_EQ(v1.GetNumCols(), v3.GetNumCols(), "The number of cols are not equal.");
for (size_t i = 0; i < v1.GetNumRows(); ++i)
{
for (size_t j = 0; j < v1.GetNumCols(); ++j)
{
NS_TEST_ASSERT_MSG_EQ(v1(i, j), v2(i, j), "The elements are not equal.");
}
}
// test move assignment operator
ValArray<T> v4;
NS_LOG_INFO("v1 size before move: " << v1.GetSize());
NS_LOG_INFO("v4 size before move: " << v4.GetSize());
size_t v1size = v1.GetSize();
v4 = std::move(v1);
NS_LOG_INFO("v4 size after move: " << v4.GetSize());
NS_TEST_ASSERT_MSG_EQ(v1size, v4.GetSize(), "The number of elements are not equal.");
for (size_t i = 0; i < v4.GetNumRows(); ++i)
{
for (size_t j = 0; j < v4.GetNumCols(); ++j)
{
// Use v3 for comparison since it hasn't moved
NS_TEST_ASSERT_MSG_EQ(v3(i, j), v4(i, j), "The elements are not equal.");
}
}
// test move constructor
NS_LOG_INFO("v3 size before move: " << v3.GetSize());
size_t v3size = v3.GetSize();
ValArray<T> v5(std::move(v3));
NS_TEST_ASSERT_MSG_EQ(v3size, v5.GetSize(), "The number of elements are not equal.");
for (size_t i = 0; i < v5.GetNumRows(); ++i)
{
for (size_t j = 0; j < v5.GetNumCols(); ++j)
{
// Use v4 for comparison since it hasn't moved
NS_TEST_ASSERT_MSG_EQ(v4(i, j), v5(i, j), "The elements are not equal.");
}
}
// test constructor with initialization valArray
std::valarray<int> initArray1{0, 1, 2, 3, 4, 5, 6, 7};
std::valarray<T> valArray1(initArray1.size()); // length is 8 elements
for (size_t i = 0; i < initArray1.size(); i++)
{
valArray1[i] = static_cast<T>(initArray1[i]);
}
ValArray<T> v6 = ValArray<T>(2, 4, valArray1);
// test constructor that moves valArray
NS_LOG_INFO("valarray1 size before move: " << valArray1.size());
ValArray<T> v11 = ValArray<T>(2, 4, std::move(valArray1));
NS_LOG_INFO("valarray1 size after move: " << valArray1.size());
NS_LOG_INFO("v11 size after move: " << v11.GetSize());
// test whether column-major order was respected during the initialization and
// also in the access operator if we iterate over rows first we should find 0, 2, 4, 6, ...
std::valarray<int> initArray2{0, 2, 4, 6, 1, 3, 5, 7};
size_t testIndex = 0;
for (size_t i = 0; i < v6.GetNumRows(); ++i)
{
for (size_t j = 0; j < v6.GetNumCols(); ++j)
{
NS_TEST_ASSERT_MSG_EQ(v6(i, j),
static_cast<T>(initArray2[testIndex]),
"The values are not equal.");
testIndex++;
}
}
// test constructor with initialization valArray for 3D array
std::valarray<int> initArray3{0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7};
std::valarray<T> valArray2(initArray3.size()); // length is 8 elements
for (size_t i = 0; i < initArray3.size(); i++)
{
valArray2[i] = static_cast<T>(initArray3[i]);
}
ValArray<T> v7 = ValArray<T>(2, 4, 2, valArray2);
// test whether column-major order was respected during the initialization and
// also in the access operator
// if we iterate over rows first we should find 0, 2, 4, 6, ...
std::valarray<int> initArray4{0, 2, 4, 6, 1, 3, 5, 7, 0, 2, 4, 6, 1, 3, 5, 7};
testIndex = 0;
for (size_t p = 0; p < v7.GetNumPages(); ++p)
{
for (size_t i = 0; i < v7.GetNumRows(); ++i)
{
for (size_t j = 0; j < v7.GetNumCols(); ++j)
{
NS_TEST_ASSERT_MSG_EQ(v7(i, j, p),
static_cast<T>(initArray4[testIndex]),
"The values are not equal.");
testIndex++;
}
}
}
// multiplication with a scalar value with 3D array
ValArray<T> v8 = v7 * (static_cast<T>(5.0));
for (size_t p = 0; p < v8.GetNumPages(); ++p)
{
for (size_t i = 0; i < v8.GetNumRows(); ++i)
{
for (size_t j = 0; j < v8.GetNumCols(); ++j)
{
NS_TEST_ASSERT_MSG_EQ(v7(i, j, p) * (static_cast<T>(5.0)),
v8(i, j, p),
"The values are not equal");
}
}
}
NS_LOG_INFO("v8 = v7 * 5:" << v8);
// test +, - (binary, unary) operators
NS_LOG_INFO("v8 + v8" << v8 + v8);
NS_LOG_INFO("v8 - v8" << v8 - v8);
NS_LOG_INFO("-v8" << -v8);
// test += and -= assignment operators
ValArray<T> v9(v8.GetNumRows(), v8.GetNumCols(), v8.GetNumPages());
v9 += v8;
NS_LOG_INFO("v9 += v8" << v9);
ValArray<T> v10(v8.GetNumRows(), v8.GetNumCols(), v8.GetNumPages());
v10 -= v8;
NS_LOG_INFO("v10 -= v8" << v10);
// test == and != operators
NS_TEST_ASSERT_MSG_EQ(bool(v9 == v8), true, "Matrices v8 and v9 should be equal");
NS_TEST_ASSERT_MSG_EQ(bool(v10 == v8), false, "Matrices v8 and v10 should not be equal");
NS_TEST_ASSERT_MSG_EQ(bool(v10 != v8), true, "Matrices v8 and v10 should not be equal");
// test whether arrays are equal when they have different lengths
NS_TEST_ASSERT_MSG_NE(ValArray<int>(std::valarray({1, 2, 3})),
ValArray<int>(std::valarray({1, 2, 3, 4})),
"Arrays should not be equal, they have different dimensions.");
// test the function IsAlmostEqual
v9(0, 0, 0) = v9(0, 0, 0) + static_cast<T>(1);
NS_TEST_ASSERT_MSG_EQ(v9.IsAlmostEqual(v8, 2) && (v9 != v8),
true,
"Matrices should be almost equal, but not equal.");
// test the initialization with std::vector
ValArray<T> v12 = ValArray(std::vector<T>({1, 2, 3}));
NS_LOG_INFO("v12:" << v12);
}
/**
* \ingroup valArray-tests
* ValArray test suite
*
* \brief The test checks the correct behaviour of ValArray class
*/
class ValArrayTestSuite : public TestSuite
{
public:
/** Constructor. */
ValArrayTestSuite();
};
ValArrayTestSuite::ValArrayTestSuite()
: TestSuite("val-array-test")
{
AddTestCase(new ValArrayTestCase<double>("Test ValArray<double>"));
AddTestCase(new ValArrayTestCase<std::complex<double>>("Test ValArray<std::complex<double>>"));
AddTestCase(new ValArrayTestCase<int>("Test ValArray<int>"));
}
/**
* \ingroup valArray-tests
* ValArrayTestSuite instance variable.
*/
static ValArrayTestSuite g_valArrayTestSuite;
} // namespace tests
} // namespace ns3