#include #include #include #include "gtest/gtest.h" #include "mbase/MEnv.h" #include "mbase/MLog.h" #include "../mbase/MParContainer.h" #include "mfileio/MMatrix.h" using namespace std; class testMMatrix : public ::testing::Test { protected: // You can remove any or all of the following functions if its body // is empty. const std::string path2test = "./mtest/MMatrixTEST/"; testMMatrix() { // You can do set-up work for each test here. } virtual ~testMMatrix() { // You can do clean-up work that doesn't throw exceptions here. } // If the constructor and destructor are not enough for setting up // and cleaning up each test, you can define the following methods: virtual void SetUp() { // Code here will be called immediately after the constructor (right // before each test). } virtual void TearDown() { // Code here will be called immediately after each test (right // before the destructor). } // Objects declared here can be used by all tests in the test case for Foo. }; //------------------------------------------------------------------------------ TEST_F(testMMatrix, ParseCorrectFile) { // The MMatrix will parse a text file specified in the configuration file // e.g. ceres.rc. The Data can then be used in the simulation. // For example it is used to parse and contain the 1440 temporal offsets of // the telkscope pixels. try{ // first we need an Menv to parse in the config file MEnv env( (path2test + "config_where_the_path_to_MyData_is_defined.rc" ).c_str() ); // now we create the data container itself. The constructor has two // parameters: // 1) A name // 2) I dont know... its called titel internal in the MParContainer. MMatrix A("Any name related with A","titel"); // the MMatrix container is still empty yet. We now call the ReadEnv() // method inherited by MParContainer. // Parameters: // 1) the MEnv class which has parsed in the config file // 2) the keyword used in the configfile for this data container // 3) A verbosity flag which tells you wether the file defined in the config // has been found or not. // the integer return value is ignored here A.ReadEnv(env,"MyData",kFALSE); // The file specified in the config file is supposed to hold a 3 x 3 Matrix // Since the data matrix called 'fM' of the MMatrix is public we can // directly access the data and check. ASSERT_EQ( 3, A.fM.size() ); ASSERT_EQ( 3, A.fM[0].size() ); ASSERT_EQ( 3, A.fM[1].size() ); ASSERT_EQ( 3, A.fM[2].size() ); EXPECT_EQ( 1.1, A.fM[0][0] ); EXPECT_EQ( 2, A.fM[0][1] ); EXPECT_EQ( 3, A.fM[0][2] ); EXPECT_EQ( 4, A.fM[1][0] ); EXPECT_EQ( 5.5, A.fM[1][1] ); EXPECT_EQ( 6, A.fM[1][2] ); EXPECT_EQ( 7, A.fM[2][0] ); EXPECT_EQ( 8, A.fM[2][1] ); EXPECT_EQ( 9.9, A.fM[2][2] ); } catch (std::exception &error){ cout << error.what(); } } //------------------------------------------------------------------------------ TEST_F(testMMatrix, LineBreak_CRLF) { // Check the CRLF linebreak as it is used by several Computers as Mac and // Windows. // For example Dominik and Sebastian exchanged emails with data.csv. Both had // Ubuntu 14 machines. The file was mangeled from LF only, as it is common on // Linux to CRLF ! try{ // CR and LF i.e. \r\n i.e. 10 and 13 MEnv env( (path2test + "LineBreak_CRLF.rc" ).c_str() ); MMatrix A("Any name related with A","titel"); A.ReadEnv(env,"MyData",kFALSE); ASSERT_EQ( 3, A.fM.size() ); ASSERT_EQ( 3, A.fM[0].size() ); ASSERT_EQ( 3, A.fM[1].size() ); ASSERT_EQ( 3, A.fM[2].size() ); EXPECT_EQ( 1.1, A.fM[0][0] ); EXPECT_EQ( 2, A.fM[0][1] ); EXPECT_EQ( 3, A.fM[0][2] ); EXPECT_EQ( 4, A.fM[1][0] ); EXPECT_EQ( 5.5, A.fM[1][1] ); EXPECT_EQ( 6, A.fM[1][2] ); EXPECT_EQ( 7, A.fM[2][0] ); EXPECT_EQ( 8, A.fM[2][1] ); EXPECT_EQ( 9.9, A.fM[2][2] ); } catch (std::exception &error){ cout << error.what(); } } //------------------------------------------------------------------------------ TEST_F(testMMatrix, LineBreak_CR) { // CR only linebreak is hopefully not common anymore. It was used by Mac. try{ // CR and LF i.e. \r\n i.e. 10 and 13 MEnv env( (path2test + "LineBreak_CR.rc" ).c_str() ); MMatrix A("Any name related with A","titel"); A.ReadEnv(env,"MyData",kFALSE); ASSERT_EQ( 3, A.fM.size() ); ASSERT_EQ( 3, A.fM[0].size() ); ASSERT_EQ( 3, A.fM[1].size() ); ASSERT_EQ( 3, A.fM[2].size() ); EXPECT_EQ( 1.1, A.fM[0][0] ); EXPECT_EQ( 2, A.fM[0][1] ); EXPECT_EQ( 3, A.fM[0][2] ); EXPECT_EQ( 4, A.fM[1][0] ); EXPECT_EQ( 5.5, A.fM[1][1] ); EXPECT_EQ( 6, A.fM[1][2] ); EXPECT_EQ( 7, A.fM[2][0] ); EXPECT_EQ( 8, A.fM[2][1] ); EXPECT_EQ( 9.9, A.fM[2][2] ); } catch (std::exception &error){ cout << error.what(); } } //------------------------------------------------------------------------------ TEST_F(testMMatrix, CommentOnly) { // We read in a csv file with only comments line in there. The resulting // Matrix shall be empty. try{ MEnv env( (path2test + "comment_only.rc" ).c_str() ); MMatrix A("Any name related with A","titel"); A.ReadEnv(env,"MyData",kFALSE); ASSERT_EQ( 0, A.fM.size() ); } catch (std::exception &error){ cout << error.what(); } } //------------------------------------------------------------------------------ TEST_F(testMMatrix, DataOnly) { // The file has no comments at all. 3x3 Matrix data only try{ MEnv env( (path2test + "data_only.rc" ).c_str() ); MMatrix A("Any name related with A","titel"); A.ReadEnv(env,"MyData",kFALSE); ASSERT_EQ( 3, A.fM.size() ); ASSERT_EQ( 3, A.fM[0].size() ); ASSERT_EQ( 3, A.fM[1].size() ); ASSERT_EQ( 3, A.fM[2].size() ); EXPECT_EQ( 1.1, A.fM[0][0] ); EXPECT_EQ( 2, A.fM[0][1] ); EXPECT_EQ( 3, A.fM[0][2] ); EXPECT_EQ( 4, A.fM[1][0] ); EXPECT_EQ( 5.5, A.fM[1][1] ); EXPECT_EQ( 6, A.fM[1][2] ); EXPECT_EQ( 7, A.fM[2][0] ); EXPECT_EQ( 8, A.fM[2][1] ); EXPECT_EQ( 9.9, A.fM[2][2] ); } catch (std::exception &error){ cout << error.what(); } } //------------------------------------------------------------------------------ TEST_F(testMMatrix, data_and_comments_mixed) { try{ MEnv env( (path2test + "data_and_comments_mixed.rc" ).c_str() ); MMatrix A("Any name related with A","titel"); A.ReadEnv(env,"MyData",kFALSE); ASSERT_EQ( 3, A.fM.size() ); ASSERT_EQ( 3, A.fM[0].size() ); ASSERT_EQ( 3, A.fM[1].size() ); ASSERT_EQ( 3, A.fM[2].size() ); EXPECT_EQ( 1.1, A.fM[0][0] ); EXPECT_EQ( 2, A.fM[0][1] ); EXPECT_EQ( 3, A.fM[0][2] ); EXPECT_EQ( 4, A.fM[1][0] ); EXPECT_EQ( 5.5, A.fM[1][1] ); EXPECT_EQ( 6, A.fM[1][2] ); EXPECT_EQ( 7, A.fM[2][0] ); EXPECT_EQ( 8, A.fM[2][1] ); EXPECT_EQ( 9.9, A.fM[2][2] ); } catch (std::exception &error){ cout << error.what(); } } //------------------------------------------------------------------------------ TEST_F(testMMatrix, missing_delimiter) { // when a delimiter is missing, a fatal exception must be thrown bool error_detected = false; try{ MEnv env( (path2test + "missing_delimiter.rc" ).c_str() ); MMatrix A("Any name related with A","titel"); // right here an exception shall be thrown because of the missing delimiter A.ReadEnv(env,"MyData",kFALSE); } catch (std::exception error){ error_detected = true; } EXPECT_TRUE(error_detected); } //------------------------------------------------------------------------------ TEST_F(testMMatrix, bad_floating_point_number) { // when a floating point number is bad, a fatal exception must be thrown bool error_detected = false; try{ MEnv env( (path2test + "bad_floating_point_number.rc" ).c_str() ); MMatrix A("Any name related with A","titel"); // expect exception because of bad floating point number A.ReadEnv(env,"MyData",kFALSE); } catch (std::exception error){ error_detected = true; } EXPECT_TRUE(error_detected); } //------------------------------------------------------------------------------ TEST_F(testMMatrix, NaN_Inf_exponent) { // +Inf, -Inf, Inf // NaN, 1e3, 42e13.37 try{ MEnv env( (path2test + "NaN_Inf_exponent.rc" ).c_str() ); MMatrix A("Any name related with A","titel"); A.ReadEnv(env,"MyData",kFALSE); // check dimension ASSERT_EQ( 2, A.fM.size() ); ASSERT_EQ( 3, A.fM[0].size() ); ASSERT_EQ( 3, A.fM[1].size() ); // +Inf EXPECT_FALSE( std::signbit( A.fM[0][0]) ); EXPECT_TRUE( std::isinf( A.fM[0][0]) ); // -Inf EXPECT_TRUE( std::signbit( A.fM[0][1]) ); EXPECT_TRUE( std::isinf( A.fM[0][1]) ); // Inf EXPECT_FALSE( std::signbit( A.fM[0][2]) ); EXPECT_TRUE( std::isinf( A.fM[0][2]) ); EXPECT_TRUE( std::isnan( A.fM[1][0]) ); EXPECT_EQ( 1e3, A.fM[1][1] ); EXPECT_EQ( 13.37e42, A.fM[1][2] ); } catch (std::exception &error){ cout << error.what(); } } //------------------------------------------------------------------------------ TEST_F(testMMatrix, whitespaces_and_tabs) { // whitespaces are allowd and must not effect the parsing try{ MEnv env( (path2test + "whitespaces_and_tabs.rc" ).c_str() ); MMatrix A("Any name related with A","titel"); A.ReadEnv(env,"MyData",kFALSE); // check dimension // we expect 9 row and 3 columns each with 1,2,3 in there ASSERT_EQ( 9, A.fM.size() ); for(int row=0; row<9; row++){ ASSERT_EQ( 3, A.fM[row].size() ); for(int col=0; col<3; col++){ EXPECT_EQ( (col+1) , A.fM[row][col] ); } } } catch (std::exception &error){ cout << error.what(); } } //------------------------------------------------------------------------------ TEST_F(testMMatrix, csv_file_does_not_exist) { // There must be a fatal exception when the csv file does not exist bool error_detected = false; try{ MEnv env( (path2test + "csv_file_does_not_exist.rc" ).c_str() ); MMatrix A("Any name related with A","titel"); A.ReadEnv(env,"MyData",kFALSE); } catch (std::exception &error){ error_detected = true; } EXPECT_TRUE(error_detected); } //------------------------------------------------------------------------------ TEST_F(testMMatrix, key_does_not_exist_in_config_file) { // There must be a fatal exception when the key can not be found in the // config file. bool error_detected = false; try{ MEnv env( (path2test + "key_does_not_exist_in_config_file.rc" ).c_str() ); MMatrix A("Any name related with A","titel"); A.ReadEnv(env,"KeyToDataThatDoesNotExistInTheConfigFile",kFALSE); } catch (std::exception &error){ error_detected = true; } EXPECT_TRUE(error_detected); } //------------------------------------------------------------------------------