LCOV - code coverage report
Current view: top level - test - matrixTests.cpp (source / functions) Hit Total Coverage
Test: coverage.info.cleaned Lines: 261 261 100.0 %
Date: 2020-12-14 08:13:14 Functions: 48 48 100.0 %

          Line data    Source code
       1             : #include <gmock/gmock.h>
       2             : #include <gtest/gtest.h>
       3             : 
       4             : #include <cfloat>
       5             : #include <initializer_list>
       6             : #include <iostream>
       7             : #include <vector>
       8             : 
       9             : #include "matrix.hpp"
      10             : 
      11             : #define DOUBLE_NEAR(x) DoubleNear((x), DBL_EPSILON)
      12             : 
      13             : using namespace testing;
      14             : using namespace std;
      15             : 
      16             : class TestThatMatrix : public Test
      17             : {
      18             :  public:
      19             :   int m{3}, n{5};
      20             :   std::unique_ptr<matrix<double>> smart{nullptr};
      21             :   matrix<double>* A{nullptr};
      22             : 
      23          23 :   void SetUp() override
      24             :   {
      25          23 :     smart.reset(new matrix<double>(m, n, vector<double>(m * n, 0.0)));
      26          23 :     A = smart.get();
      27          23 :   }
      28             : 
      29          23 :   void TearDown() override {}
      30             : };
      31             : 
      32           2 : TEST_F(TestThatMatrix, CanAccessDeclaredMatrixInSetup)
      33             : {
      34           1 :   (*A)(1, 1) = 1.0;
      35           1 :   (*A)(2, 2) = 1.0;
      36           1 :   (*A)(3, 3) = 1.0;
      37             :   // For testing, exercise output operator <<
      38           1 :   cout << "Rows [" + to_string((*A).get_rows()) + "]\n";
      39           1 :   cout << "A =\n" << (*A) << '\n';
      40           1 :   ASSERT_THAT((*A)(2, 2), DoubleEq(1.0));
      41             : }
      42             : 
      43           2 : TEST_F(TestThatMatrix, CanConstructAnUninitializedMatrixSepcifyingRowsCols)
      44             : {
      45           1 :   ASSERT_NO_THROW(matrix<double> M(2, 2));
      46             : }
      47             : 
      48           2 : TEST_F(TestThatMatrix, ConstructorRowsColsThrowsWheneverRowsIsNegative)
      49             : {
      50             :   // Interesting. Didn't know this was automatically taken care of by STL
      51           4 :   ASSERT_THROW(matrix<double> M(-1, 2), std::bad_array_new_length);
      52             : }
      53             : 
      54           2 : TEST_F(TestThatMatrix, ConstructorRowsColsThrowsWheneverRowsIsZero)
      55             : {
      56           4 :   ASSERT_ANY_THROW(matrix<double> M(0, 2));
      57             : }
      58             : 
      59           2 : TEST_F(TestThatMatrix, ConstructorRowsColsThrowsWheneverColsIsNegative)
      60             : {
      61             :   // Interesting. Didn't know this was automatically taken care of by STL
      62           4 :   ASSERT_THROW(matrix<double> M(2, -1), std::bad_array_new_length);
      63             : }
      64             : 
      65           2 : TEST_F(TestThatMatrix, ConstructorRowsColsThrowsWheneverColsIsZero)
      66             : {
      67           4 :   ASSERT_THROW(matrix<double> M(2, 0), std::exception);
      68             : }
      69             : 
      70           2 : TEST_F(TestThatMatrix, get_rowsWorks)
      71             : {
      72           2 :   matrix<double> M(4, 7);
      73             : 
      74             :   // Validate these getters
      75           1 :   EXPECT_THAT(M.get_rows(), Eq(4));
      76           1 : }
      77             : 
      78           2 : TEST_F(TestThatMatrix, get_colsWorks)
      79             : {
      80           2 :   matrix<double> M(4, 7);
      81             : 
      82             :   // Validate these getters
      83           1 :   EXPECT_THAT(M.get_rows(), Eq(4));
      84           1 : }
      85             : 
      86           2 : TEST_F(TestThatMatrix,
      87             :        CanConstructAnUninitializedMatrixSepcifyingRowsColsANDInitialiseIt)
      88             : {
      89           2 :   matrix<int> M(4, 7);
      90             : 
      91             :   // Must be able to modify the element to do this
      92           1 :   M(1, 1) = 1;
      93           1 :   M(1, 2) = 5;
      94           1 :   M(1, 3) = 9;
      95           1 :   M(1, 4) = 13;
      96           1 :   M(1, 5) = 17;
      97           1 :   M(1, 6) = 21;
      98           1 :   M(1, 7) = 25;
      99           1 :   M(2, 1) = 2;
     100           1 :   M(2, 2) = 6;
     101           1 :   M(2, 3) = 10;
     102           1 :   M(2, 4) = 14;
     103           1 :   M(2, 5) = 18;
     104           1 :   M(2, 6) = 22;
     105           1 :   M(2, 7) = 26;
     106           1 :   M(3, 1) = 3;
     107           1 :   M(3, 2) = 7;
     108           1 :   M(3, 3) = 11;
     109           1 :   M(3, 4) = 15;
     110           1 :   M(3, 5) = 19;
     111           1 :   M(3, 6) = 23;
     112           1 :   M(3, 7) = 27;
     113           1 :   M(4, 1) = 4;
     114           1 :   M(4, 2) = 8;
     115           1 :   M(4, 3) = 12;
     116           1 :   M(4, 4) = 16;
     117           1 :   M(4, 5) = 20;
     118           1 :   M(4, 6) = 24;
     119           1 :   M(4, 7) = 28;
     120             : 
     121           1 :   EXPECT_THAT(M.get_rows(), Eq(4));
     122           1 :   EXPECT_THAT(M.get_cols(), Eq(7));
     123             : 
     124             :   // Must be able to access, but not modify, the element to do this
     125           8 :   for (size_t j{1}; j <= M.get_cols(); j++)
     126          35 :     for (size_t i{1}; i <= M.get_rows(); i++)
     127          28 :       EXPECT_THAT(M(i, j), Eq(M.get_rows() * (j - 1) + i));
     128             : 
     129             :   // // Printing verification does work
     130             :   // cout << "M =\n"
     131             :   //      << M << '\n';
     132           1 : }
     133             : 
     134           2 : TEST_F(TestThatMatrix, ImplementsCopyConstructorCorrectly)
     135             : {
     136           2 :   matrix<double> M1(4, 2);
     137             : 
     138           1 :   M1(1, 1) = 1;
     139           1 :   M1(1, 2) = 5;
     140           1 :   M1(2, 1) = 2;
     141           1 :   M1(2, 2) = 6;
     142           1 :   M1(3, 1) = 3;
     143           1 :   M1(3, 2) = 7;
     144           1 :   M1(4, 1) = 4;
     145           1 :   M1(4, 2) = 8;
     146             : 
     147             :   // Test that matrix inputed and retrieved correctly
     148           3 :   for (size_t j{1}; j <= M1.get_cols(); j++)
     149          10 :     for (size_t i{1}; i <= M1.get_rows(); i++)
     150           8 :       EXPECT_THAT(M1(i, j), Eq(M1.get_rows() * (j - 1) + i));
     151             : 
     152             :   // Test the copy constructor
     153           2 :   matrix<double> M2{M1};
     154             : 
     155             :   // Test that matrix M1 hasn't changed
     156           3 :   for (size_t j{1}; j <= M1.get_cols(); j++)
     157          10 :     for (size_t i{1}; i <= M1.get_rows(); i++)
     158           8 :       EXPECT_THAT(M1(i, j), Eq(M1.get_rows() * (j - 1) + i));
     159             : 
     160             :   // Test that matrix M2 equals M1 (Copy performed correctly)
     161           3 :   for (size_t j{1}; j <= M2.get_cols(); j++)
     162          10 :     for (size_t i{1}; i <= M2.get_rows(); i++)
     163           8 :       EXPECT_THAT(M2(i, j), Eq(M2.get_rows() * (j - 1) + i));
     164             : 
     165             :   // Test that copies are independent, the default copy constructor overridden
     166           1 :   M2(1, 2) = 3;
     167             : 
     168             :   // Test that matrix M1 hasn't changed
     169           3 :   for (size_t j{1}; j <= M1.get_cols(); j++)
     170          10 :     for (size_t i{1}; i <= M1.get_rows(); i++)
     171           8 :       EXPECT_THAT(M1(i, j), Eq(M1.get_rows() * (j - 1) + i));
     172             : 
     173             :   // Test that matrix M2 has 3 in correct position
     174           3 :   for (size_t j{1}; j <= M2.get_cols(); j++)
     175          10 :     for (size_t i{1}; i <= M2.get_rows(); i++)
     176           8 :       if (i == 1 and j == 2)
     177             :       {
     178           1 :         EXPECT_THAT(M2(i, j), Eq(3));
     179             :       }
     180             :       else
     181             :       {
     182           7 :         EXPECT_THAT(M2(i, j), Eq(M2.get_rows() * (j - 1) + i));
     183             :       }
     184           1 : }
     185             : 
     186           2 : TEST_F(TestThatMatrix, ImplementsCopyAssignmentCorrectly)
     187             : {
     188           2 :   matrix<double> M1(4, 2);
     189             : 
     190           1 :   M1(1, 1) = 1;
     191           1 :   M1(1, 2) = 5;
     192           1 :   M1(2, 1) = 2;
     193           1 :   M1(2, 2) = 6;
     194           1 :   M1(3, 1) = 3;
     195           1 :   M1(3, 2) = 7;
     196           1 :   M1(4, 1) = 4;
     197           1 :   M1(4, 2) = 8;
     198             : 
     199             :   // Test that matrix inputed and retrieved correctly
     200           3 :   for (size_t j{1}; j <= M1.get_cols(); j++)
     201          10 :     for (size_t i{1}; i <= M1.get_rows(); i++)
     202           8 :       EXPECT_THAT(M1(i, j), Eq(M1.get_rows() * (j - 1) + i));
     203             : 
     204             :   // Test the copy constructor
     205           2 :   matrix<double> M2(4, 2);
     206             : 
     207             :   // If quick return doesn't work, them no code coverage! No Idea how else to
     208             :   // test this.
     209           1 :   M1 = M1;
     210             : 
     211           1 :   M2 = M1;
     212             : 
     213             :   // Test that matrix M1 hasn't changed
     214           3 :   for (size_t j{1}; j <= M1.get_cols(); j++)
     215          10 :     for (size_t i{1}; i <= M1.get_rows(); i++)
     216           8 :       EXPECT_THAT(M1(i, j), Eq(M1.get_rows() * (j - 1) + i));
     217             : 
     218             :   // Test that matrix M2 equals M1 (Copy performed correctly)
     219           3 :   for (size_t j{1}; j <= M2.get_cols(); j++)
     220          10 :     for (size_t i{1}; i <= M2.get_rows(); i++)
     221           8 :       EXPECT_THAT(M2(i, j), Eq(M2.get_rows() * (j - 1) + i));
     222             : 
     223             :   // Test that copies are independent, the default copy constructor overridden
     224           1 :   M2(2, 1) = 4;
     225             : 
     226             :   // Test that matrix M1 hasn't changed
     227           3 :   for (size_t j{1}; j <= M1.get_cols(); j++)
     228          10 :     for (size_t i{1}; i <= M1.get_rows(); i++)
     229           8 :       EXPECT_THAT(M1(i, j), Eq(M1.get_rows() * (j - 1) + i));
     230             : 
     231             :   // Test that matrix M2 has 3 in correct position
     232           3 :   for (size_t j{1}; j <= M2.get_cols(); j++)
     233          10 :     for (size_t i{1}; i <= M2.get_rows(); i++)
     234           8 :       if (i == 2 and j == 1)
     235             :       {
     236           1 :         EXPECT_THAT(M2(i, j), Eq(4));
     237             :       }
     238             :       else
     239             :       {
     240           7 :         EXPECT_THAT(M2(i, j), Eq(M2.get_rows() * (j - 1) + i));
     241             :       }
     242           1 : }
     243             : 
     244           2 : TEST_F(TestThatMatrix, ImplementsMoveConstructorCorrectly)
     245             : {
     246           2 :   matrix<double> M1(4, 2);
     247             : 
     248           1 :   M1(1, 1) = 1;
     249           1 :   M1(1, 2) = 5;
     250           1 :   M1(2, 1) = 2;
     251           1 :   M1(2, 2) = 6;
     252           1 :   M1(3, 1) = 3;
     253           1 :   M1(3, 2) = 7;
     254           1 :   M1(4, 1) = 4;
     255           1 :   M1(4, 2) = 8;
     256             : 
     257             :   // Test that matrix inputed and retrieved correctly
     258           3 :   for (size_t j{1}; j <= M1.get_cols(); j++)
     259          10 :     for (size_t i{1}; i <= M1.get_rows(); i++)
     260           8 :       EXPECT_THAT(M1(i, j), Eq(M1.get_rows() * (j - 1) + i));
     261             : 
     262             :   // Test the Move constructor. Move is from smart pointer?
     263           2 :   matrix<double> M2 = move(M1);
     264             : 
     265             :   // Test that matrix M1 hasn't changed
     266           1 :   EXPECT_THAT(M1.get_cols(), Eq(0));
     267           1 :   EXPECT_THAT(M1.get_rows(), Eq(0));
     268           1 :   EXPECT_EQ(&M1(1, 1), nullptr);
     269             : 
     270             :   // Test that matrix M2 equals old M1 (Move performed correctly)
     271           3 :   for (size_t j{1}; j <= M2.get_cols(); j++)
     272          10 :     for (size_t i{1}; i <= M2.get_rows(); i++)
     273           8 :       EXPECT_THAT(M2(i, j), Eq(M2.get_rows() * (j - 1) + i));
     274             : 
     275             :   // Test that copies are independent, the default copy constructor overridden
     276           1 :   M2(1, 1) = 5;
     277             : 
     278             :   // Test that matrix M2 has 5 in correct position
     279           3 :   for (size_t j{1}; j <= M2.get_cols(); j++)
     280          10 :     for (size_t i{1}; i <= M2.get_rows(); i++)
     281           8 :       if (i == 1 and j == 1)
     282             :       {
     283           1 :         EXPECT_THAT(M2(i, j), Eq(5));
     284             :       }
     285             :       else
     286             :       {
     287           7 :         EXPECT_THAT(M2(i, j), Eq(M2.get_rows() * (j - 1) + i));
     288             :       }
     289           1 : }
     290             : 
     291           2 : TEST_F(TestThatMatrix, ImplementsMoveAssignmentCorrectly)
     292             : {
     293           2 :   matrix<double> M1(4, 2);
     294             : 
     295           1 :   M1(1, 1) = 1;
     296           1 :   M1(1, 2) = 5;
     297           1 :   M1(2, 1) = 2;
     298           1 :   M1(2, 2) = 6;
     299           1 :   M1(3, 1) = 3;
     300           1 :   M1(3, 2) = 7;
     301           1 :   M1(4, 1) = 4;
     302           1 :   M1(4, 2) = 8;
     303             : 
     304             :   // Test that matrix inputed and retrieved correctly
     305           3 :   for (size_t j{1}; j <= M1.get_cols(); j++)
     306          10 :     for (size_t i{1}; i <= M1.get_rows(); i++)
     307           8 :       EXPECT_THAT(M1(i, j), Eq(M1.get_rows() * (j - 1) + i));
     308             : 
     309             :   // Test the Move constructor. Move is from smart pointer?
     310           2 :   matrix<double> M2(4, 2);
     311             : 
     312             :   // If quick return doesn't work, them matrix erases itself and this test
     313             :   // cannot pass.
     314           1 :   M1 = move(M1);
     315             : 
     316             :   // Test that matrix inputed and retrieved correctly
     317           3 :   for (size_t j{1}; j <= M1.get_cols(); j++)
     318          10 :     for (size_t i{1}; i <= M1.get_rows(); i++)
     319           8 :       EXPECT_THAT(M1(i, j), Eq(M1.get_rows() * (j - 1) + i));
     320             : 
     321           1 :   M2 = move(M1);
     322             : 
     323             :   // Test that matrix M1 hasn't changed
     324           1 :   EXPECT_THAT(M1.get_cols(), Eq(0));
     325           1 :   EXPECT_THAT(M1.get_rows(), Eq(0));
     326           1 :   EXPECT_EQ(&M1(1, 1), nullptr);
     327             : 
     328             :   // Test that matrix M2 equals old M1 (Move performed correctly)
     329           3 :   for (size_t j{1}; j <= M2.get_cols(); j++)
     330          10 :     for (size_t i{1}; i <= M2.get_rows(); i++)
     331           8 :       EXPECT_THAT(M2(i, j), Eq(M2.get_rows() * (j - 1) + i));
     332             : 
     333             :   // Test that copies are independent, the default copy constructor overridden
     334           1 :   M2(1, 1) = 5;
     335             : 
     336             :   // Test that matrix M2 has 5 in correct position
     337           3 :   for (size_t j{1}; j <= M2.get_cols(); j++)
     338          10 :     for (size_t i{1}; i <= M2.get_rows(); i++)
     339           8 :       if (i == 1 and j == 1)
     340             :       {
     341           1 :         EXPECT_THAT(M2(i, j), Eq(5));
     342             :       }
     343             :       else
     344             :       {
     345           7 :         EXPECT_THAT(M2(i, j), Eq(M2.get_rows() * (j - 1) + i));
     346             :       }
     347           1 : }
     348             : 
     349           2 : TEST_F(TestThatMatrix, CannotDoCopyAssignmentWheneverDimensionsDonotAgree)
     350             : {
     351           1 :   matrix<double> M1(4, 2);
     352           1 :   matrix<double> M2(2, 4);
     353             : 
     354           2 :   ASSERT_THROW(M1 = M2, std::exception);
     355             : }
     356             : 
     357           2 : TEST_F(TestThatMatrix, CannotDoMoveAssignmentWheneverDimensionsDonotAgree)
     358             : {
     359           1 :   matrix<double> M1(4, 2);
     360           1 :   matrix<double> M2(2, 4);
     361             : 
     362           2 :   ASSERT_THROW(M1 = move(M2), std::exception);
     363             : }
     364             : 
     365           2 : TEST_F(TestThatMatrix, HasDiagonalMatrixConstructorWithVector)
     366             : {
     367           2 :   std::vector<int> v{1, 2, 3};
     368           2 :   matrix<int> M(v);
     369             : 
     370           1 :   EXPECT_THAT(M.get_cols(), Eq(v.size()));
     371           1 :   EXPECT_THAT(M.get_rows(), Eq(v.size()));
     372             : 
     373           4 :   for (size_t j{1}; j <= M.get_cols(); j++)
     374          12 :     for (size_t i{1}; i <= M.get_rows(); i++)
     375           9 :       if (i == j)
     376             :       {
     377           3 :         EXPECT_THAT(M(i, j), Eq(v[ i - 1 ]));
     378             :       }
     379             :       else
     380             :       {
     381           6 :         EXPECT_THAT(M(i, j), Eq(0));
     382             :       }
     383           1 : }
     384             : 
     385           2 : TEST_F(TestThatMatrix, HasDiagonalMatrixConstructorWithInitializerList)
     386             : {
     387           2 :   std::vector<int> v{1, 2, 3, 4};
     388           2 :   matrix<int> M{1, 2, 3, 4};
     389             : 
     390           1 :   EXPECT_THAT(M.get_cols(), Eq(v.size()));
     391           1 :   EXPECT_THAT(M.get_rows(), Eq(v.size()));
     392             : 
     393           5 :   for (size_t j{1}; j <= M.get_cols(); j++)
     394          20 :     for (size_t i{1}; i <= M.get_rows(); i++)
     395          16 :       if (i == j)
     396             :       {
     397           4 :         EXPECT_THAT(M(i, j), Eq(v[ i - 1 ]));
     398             :       }
     399             :       else
     400             :       {
     401          12 :         EXPECT_THAT(M(i, j), Eq(0));
     402             :       }
     403           1 : }
     404             : 
     405           2 : TEST_F(TestThatMatrix, ThrowErrorForFullMatrixConstructorWithMEqualZero)
     406             : {
     407           2 :   vector<int> v{1, 2, 3, 4, 5};
     408           1 :   EXPECT_THAT(v.size(), Eq(n));
     409           1 :   EXPECT_THAT(n, Gt(0));
     410           4 :   EXPECT_THROW(matrix<int> M(0, n, v), std::exception);
     411             :   //// Printing verification does work: Connot get here due to constructor throw
     412             :   // cout << "M =\n"
     413             :   //     << M << '\n';
     414           1 : }
     415             : 
     416           2 : TEST_F(TestThatMatrix, ThrowErrorForFullMatrixConstructorWithNEqualZero)
     417             : {
     418           2 :   vector<int> v{1, 2, 3};
     419           1 :   EXPECT_THAT(v.size(), Eq(m));
     420           1 :   EXPECT_THAT(m, Gt(0));
     421           4 :   EXPECT_THROW(matrix<int> M(m, 0, v), std::exception);
     422             :   //// Printing verification does work: Connot get here due to constructor throw
     423             :   // cout << "M =\n"
     424             :   //     << M << '\n';
     425           1 : }
     426             : 
     427           2 : TEST_F(
     428             :     TestThatMatrix,
     429             :     ThrowErrorForFullMatrixConstructorWithVectorOfSizeZeroAndMTimeNIsPositive)
     430             : {
     431           2 :   vector<int> v{};
     432           1 :   EXPECT_THAT(v.size(), Eq(0));
     433           1 :   EXPECT_THAT(m, Gt(0));
     434           1 :   EXPECT_THAT(n, Gt(0));
     435           4 :   EXPECT_THROW(matrix<int> M(m, n, v), std::exception);
     436           1 : }
     437             : 
     438           2 : TEST_F(TestThatMatrix,
     439             :        ThrowErrorForFullMatrixConstructorWithVectorOfSizeNotEqualToMByN)
     440             : {
     441           2 :   vector<int> v((m + 1) * n);
     442           1 :   EXPECT_THAT(v.size(), Eq((m + 1) * n));
     443           4 :   EXPECT_THROW(matrix<int> M(m, n, v), std::exception);
     444           1 : }
     445             : 
     446           2 : TEST_F(TestThatMatrix, HasFullMatrixConstructorWithVector)
     447             : {
     448           2 :   matrix<int> M(2, 3, vector<int>{1, 2, 3, 4, 5, 6});
     449             : 
     450           1 :   EXPECT_THAT(M.get_cols(), Eq(3));
     451           1 :   EXPECT_THAT(M.get_rows(), Eq(2));
     452             : 
     453           1 :   EXPECT_THAT(M(1, 1), Eq(1));
     454           1 :   EXPECT_THAT(M(1, 2), Eq(3));
     455           1 :   EXPECT_THAT(M(1, 3), Eq(5));
     456           1 :   EXPECT_THAT(M(2, 1), Eq(2));
     457           1 :   EXPECT_THAT(M(2, 2), Eq(4));
     458           1 :   EXPECT_THAT(M(2, 3), Eq(6));
     459           1 : }
     460             : 
     461           2 : TEST_F(TestThatMatrix, HasFullMatrixConstructorWithInitializerList)
     462             : {
     463           2 :   matrix<int> M(2, 2, {1, 2, 3, 4});
     464             : 
     465           1 :   EXPECT_THAT(M.get_cols(), Eq(2));
     466           1 :   EXPECT_THAT(M.get_rows(), Eq(2));
     467             : 
     468           1 :   EXPECT_THAT(M(1, 1), Eq(1));
     469           1 :   EXPECT_THAT(M(1, 2), Eq(3));
     470           1 :   EXPECT_THAT(M(2, 1), Eq(2));
     471           1 :   EXPECT_THAT(M(2, 2), Eq(4));
     472           1 : }
     473             : 
     474             : // This use cases are possible
     475             : // // initializer_list constructor will be used: create a 2x2 diagonal matrix
     476             : // with 1, 2 on the diagonal cout << "matrix{1, 2}:\n"; cout << matrix<int>{1,
     477             : // 2};
     478             : // // (size_t, size_t) constructor will be used: create an UNINITIALIZED 1x2
     479             : // matrix cout << "matrix(1, 2):\n"; cout << matrix<int>(1, 2);

Generated by: LCOV version 1.14