| 1 | #include <iostream>
|
|---|
| 2 | #include <string>
|
|---|
| 3 | #include <math.h>
|
|---|
| 4 |
|
|---|
| 5 | #include "gtest/gtest.h"
|
|---|
| 6 | #include "mbase/MEnv.h"
|
|---|
| 7 | #include "mbase/MLog.h"
|
|---|
| 8 | #include "../mbase/MParContainer.h"
|
|---|
| 9 | #include "mfileio/MMatrix.h"
|
|---|
| 10 |
|
|---|
| 11 | using namespace std;
|
|---|
| 12 |
|
|---|
| 13 | class testMMatrix : public ::testing::Test {
|
|---|
| 14 | protected:
|
|---|
| 15 | // You can remove any or all of the following functions if its body
|
|---|
| 16 | // is empty.
|
|---|
| 17 | const std::string path2test = "./mtest/MMatrixTEST/";
|
|---|
| 18 |
|
|---|
| 19 | testMMatrix() {
|
|---|
| 20 | // You can do set-up work for each test here.
|
|---|
| 21 | }
|
|---|
| 22 |
|
|---|
| 23 | virtual ~testMMatrix() {
|
|---|
| 24 | // You can do clean-up work that doesn't throw exceptions here.
|
|---|
| 25 | }
|
|---|
| 26 |
|
|---|
| 27 | // If the constructor and destructor are not enough for setting up
|
|---|
| 28 | // and cleaning up each test, you can define the following methods:
|
|---|
| 29 |
|
|---|
| 30 | virtual void SetUp() {
|
|---|
| 31 | // Code here will be called immediately after the constructor (right
|
|---|
| 32 | // before each test).
|
|---|
| 33 | }
|
|---|
| 34 |
|
|---|
| 35 | virtual void TearDown() {
|
|---|
| 36 | // Code here will be called immediately after each test (right
|
|---|
| 37 | // before the destructor).
|
|---|
| 38 | }
|
|---|
| 39 |
|
|---|
| 40 | // Objects declared here can be used by all tests in the test case for Foo.
|
|---|
| 41 | };
|
|---|
| 42 | //------------------------------------------------------------------------------
|
|---|
| 43 | TEST_F(testMMatrix, ParseCorrectFile) {
|
|---|
| 44 |
|
|---|
| 45 | // The MMatrix will parse a text file specified in the configuration file
|
|---|
| 46 | // e.g. ceres.rc. The Data can then be used in the simulation.
|
|---|
| 47 | // For example it is used to parse and contain the 1440 temporal offsets of
|
|---|
| 48 | // the telkscope pixels.
|
|---|
| 49 | try{
|
|---|
| 50 |
|
|---|
| 51 | // first we need an Menv to parse in the config file
|
|---|
| 52 | MEnv env(
|
|---|
| 53 | (path2test + "config_where_the_path_to_MyData_is_defined.rc" ).c_str()
|
|---|
| 54 | );
|
|---|
| 55 |
|
|---|
| 56 | // now we create the data container itself. The constructor has two
|
|---|
| 57 | // parameters:
|
|---|
| 58 | // 1) A name
|
|---|
| 59 | // 2) I dont know... its called titel internal in the MParContainer.
|
|---|
| 60 | MMatrix A("Any name related with A","titel");
|
|---|
| 61 |
|
|---|
| 62 | // the MMatrix container is still empty yet. We now call the ReadEnv()
|
|---|
| 63 | // method inherited by MParContainer.
|
|---|
| 64 | // Parameters:
|
|---|
| 65 | // 1) the MEnv class which has parsed in the config file
|
|---|
| 66 | // 2) the keyword used in the configfile for this data container
|
|---|
| 67 | // 3) A verbosity flag which tells you wether the file defined in the config
|
|---|
| 68 | // has been found or not.
|
|---|
| 69 | // the integer return value is ignored here
|
|---|
| 70 | A.ReadEnv(env,"MyData",kFALSE);
|
|---|
| 71 |
|
|---|
| 72 | // The file specified in the config file is supposed to hold a 3 x 3 Matrix
|
|---|
| 73 | // Since the data matrix called 'fM' of the MMatrix is public we can
|
|---|
| 74 | // directly access the data and check.
|
|---|
| 75 | ASSERT_EQ( 3, A.fM.size() );
|
|---|
| 76 | ASSERT_EQ( 3, A.fM[0].size() );
|
|---|
| 77 | ASSERT_EQ( 3, A.fM[1].size() );
|
|---|
| 78 | ASSERT_EQ( 3, A.fM[2].size() );
|
|---|
| 79 |
|
|---|
| 80 | EXPECT_EQ( 1.1, A.fM[0][0] );
|
|---|
| 81 | EXPECT_EQ( 2, A.fM[0][1] );
|
|---|
| 82 | EXPECT_EQ( 3, A.fM[0][2] );
|
|---|
| 83 | EXPECT_EQ( 4, A.fM[1][0] );
|
|---|
| 84 | EXPECT_EQ( 5.5, A.fM[1][1] );
|
|---|
| 85 | EXPECT_EQ( 6, A.fM[1][2] );
|
|---|
| 86 | EXPECT_EQ( 7, A.fM[2][0] );
|
|---|
| 87 | EXPECT_EQ( 8, A.fM[2][1] );
|
|---|
| 88 | EXPECT_EQ( 9.9, A.fM[2][2] );
|
|---|
| 89 | }
|
|---|
| 90 | catch (std::exception &error){
|
|---|
| 91 | cout << error.what();
|
|---|
| 92 | }
|
|---|
| 93 | }
|
|---|
| 94 | //------------------------------------------------------------------------------
|
|---|
| 95 | TEST_F(testMMatrix, LineBreak_CRLF) {
|
|---|
| 96 |
|
|---|
| 97 | // Check the CRLF linebreak as it is used by several Computers as Mac and
|
|---|
| 98 | // Windows.
|
|---|
| 99 | // For example Dominik and Sebastian exchanged emails with data.csv. Both had
|
|---|
| 100 | // Ubuntu 14 machines. The file was mangeled from LF only, as it is common on
|
|---|
| 101 | // Linux to CRLF !
|
|---|
| 102 | try{
|
|---|
| 103 |
|
|---|
| 104 | // CR and LF i.e. \r\n i.e. 10 and 13
|
|---|
| 105 | MEnv env( (path2test + "LineBreak_CRLF.rc" ).c_str() );
|
|---|
| 106 | MMatrix A("Any name related with A","titel");
|
|---|
| 107 | A.ReadEnv(env,"MyData",kFALSE);
|
|---|
| 108 |
|
|---|
| 109 | ASSERT_EQ( 3, A.fM.size() );
|
|---|
| 110 | ASSERT_EQ( 3, A.fM[0].size() );
|
|---|
| 111 | ASSERT_EQ( 3, A.fM[1].size() );
|
|---|
| 112 | ASSERT_EQ( 3, A.fM[2].size() );
|
|---|
| 113 |
|
|---|
| 114 | EXPECT_EQ( 1.1, A.fM[0][0] );
|
|---|
| 115 | EXPECT_EQ( 2, A.fM[0][1] );
|
|---|
| 116 | EXPECT_EQ( 3, A.fM[0][2] );
|
|---|
| 117 | EXPECT_EQ( 4, A.fM[1][0] );
|
|---|
| 118 | EXPECT_EQ( 5.5, A.fM[1][1] );
|
|---|
| 119 | EXPECT_EQ( 6, A.fM[1][2] );
|
|---|
| 120 | EXPECT_EQ( 7, A.fM[2][0] );
|
|---|
| 121 | EXPECT_EQ( 8, A.fM[2][1] );
|
|---|
| 122 | EXPECT_EQ( 9.9, A.fM[2][2] );
|
|---|
| 123 | }
|
|---|
| 124 | catch (std::exception &error){
|
|---|
| 125 | cout << error.what();
|
|---|
| 126 | }
|
|---|
| 127 | }
|
|---|
| 128 | //------------------------------------------------------------------------------
|
|---|
| 129 | TEST_F(testMMatrix, LineBreak_CR) {
|
|---|
| 130 |
|
|---|
| 131 | // CR only linebreak is hopefully not common anymore. It was used by Mac.
|
|---|
| 132 | try{
|
|---|
| 133 |
|
|---|
| 134 | // CR and LF i.e. \r\n i.e. 10 and 13
|
|---|
| 135 | MEnv env( (path2test + "LineBreak_CR.rc" ).c_str() );
|
|---|
| 136 | MMatrix A("Any name related with A","titel");
|
|---|
| 137 | A.ReadEnv(env,"MyData",kFALSE);
|
|---|
| 138 |
|
|---|
| 139 | ASSERT_EQ( 3, A.fM.size() );
|
|---|
| 140 | ASSERT_EQ( 3, A.fM[0].size() );
|
|---|
| 141 | ASSERT_EQ( 3, A.fM[1].size() );
|
|---|
| 142 | ASSERT_EQ( 3, A.fM[2].size() );
|
|---|
| 143 |
|
|---|
| 144 | EXPECT_EQ( 1.1, A.fM[0][0] );
|
|---|
| 145 | EXPECT_EQ( 2, A.fM[0][1] );
|
|---|
| 146 | EXPECT_EQ( 3, A.fM[0][2] );
|
|---|
| 147 | EXPECT_EQ( 4, A.fM[1][0] );
|
|---|
| 148 | EXPECT_EQ( 5.5, A.fM[1][1] );
|
|---|
| 149 | EXPECT_EQ( 6, A.fM[1][2] );
|
|---|
| 150 | EXPECT_EQ( 7, A.fM[2][0] );
|
|---|
| 151 | EXPECT_EQ( 8, A.fM[2][1] );
|
|---|
| 152 | EXPECT_EQ( 9.9, A.fM[2][2] );
|
|---|
| 153 | }
|
|---|
| 154 | catch (std::exception &error){
|
|---|
| 155 | cout << error.what();
|
|---|
| 156 | }
|
|---|
| 157 | }
|
|---|
| 158 | //------------------------------------------------------------------------------
|
|---|
| 159 | TEST_F(testMMatrix, CommentOnly) {
|
|---|
| 160 |
|
|---|
| 161 | // We read in a csv file with only comments line in there. The resulting
|
|---|
| 162 | // Matrix shall be empty.
|
|---|
| 163 | try{
|
|---|
| 164 |
|
|---|
| 165 | MEnv env( (path2test + "comment_only.rc" ).c_str() );
|
|---|
| 166 | MMatrix A("Any name related with A","titel");
|
|---|
| 167 | A.ReadEnv(env,"MyData",kFALSE);
|
|---|
| 168 |
|
|---|
| 169 | ASSERT_EQ( 0, A.fM.size() );
|
|---|
| 170 | }
|
|---|
| 171 | catch (std::exception &error){
|
|---|
| 172 | cout << error.what();
|
|---|
| 173 | }
|
|---|
| 174 | }
|
|---|
| 175 | //------------------------------------------------------------------------------
|
|---|
| 176 | TEST_F(testMMatrix, DataOnly) {
|
|---|
| 177 |
|
|---|
| 178 | // The file has no comments at all. 3x3 Matrix data only
|
|---|
| 179 | try{
|
|---|
| 180 |
|
|---|
| 181 | MEnv env( (path2test + "data_only.rc" ).c_str() );
|
|---|
| 182 | MMatrix A("Any name related with A","titel");
|
|---|
| 183 | A.ReadEnv(env,"MyData",kFALSE);
|
|---|
| 184 |
|
|---|
| 185 | ASSERT_EQ( 3, A.fM.size() );
|
|---|
| 186 | ASSERT_EQ( 3, A.fM[0].size() );
|
|---|
| 187 | ASSERT_EQ( 3, A.fM[1].size() );
|
|---|
| 188 | ASSERT_EQ( 3, A.fM[2].size() );
|
|---|
| 189 |
|
|---|
| 190 | EXPECT_EQ( 1.1, A.fM[0][0] );
|
|---|
| 191 | EXPECT_EQ( 2, A.fM[0][1] );
|
|---|
| 192 | EXPECT_EQ( 3, A.fM[0][2] );
|
|---|
| 193 | EXPECT_EQ( 4, A.fM[1][0] );
|
|---|
| 194 | EXPECT_EQ( 5.5, A.fM[1][1] );
|
|---|
| 195 | EXPECT_EQ( 6, A.fM[1][2] );
|
|---|
| 196 | EXPECT_EQ( 7, A.fM[2][0] );
|
|---|
| 197 | EXPECT_EQ( 8, A.fM[2][1] );
|
|---|
| 198 | EXPECT_EQ( 9.9, A.fM[2][2] );
|
|---|
| 199 | }
|
|---|
| 200 | catch (std::exception &error){
|
|---|
| 201 | cout << error.what();
|
|---|
| 202 | }
|
|---|
| 203 | }
|
|---|
| 204 | //------------------------------------------------------------------------------
|
|---|
| 205 | TEST_F(testMMatrix, data_and_comments_mixed) {
|
|---|
| 206 |
|
|---|
| 207 | try{
|
|---|
| 208 |
|
|---|
| 209 | MEnv env( (path2test + "data_and_comments_mixed.rc" ).c_str() );
|
|---|
| 210 | MMatrix A("Any name related with A","titel");
|
|---|
| 211 | A.ReadEnv(env,"MyData",kFALSE);
|
|---|
| 212 |
|
|---|
| 213 | ASSERT_EQ( 3, A.fM.size() );
|
|---|
| 214 | ASSERT_EQ( 3, A.fM[0].size() );
|
|---|
| 215 | ASSERT_EQ( 3, A.fM[1].size() );
|
|---|
| 216 | ASSERT_EQ( 3, A.fM[2].size() );
|
|---|
| 217 |
|
|---|
| 218 | EXPECT_EQ( 1.1, A.fM[0][0] );
|
|---|
| 219 | EXPECT_EQ( 2, A.fM[0][1] );
|
|---|
| 220 | EXPECT_EQ( 3, A.fM[0][2] );
|
|---|
| 221 | EXPECT_EQ( 4, A.fM[1][0] );
|
|---|
| 222 | EXPECT_EQ( 5.5, A.fM[1][1] );
|
|---|
| 223 | EXPECT_EQ( 6, A.fM[1][2] );
|
|---|
| 224 | EXPECT_EQ( 7, A.fM[2][0] );
|
|---|
| 225 | EXPECT_EQ( 8, A.fM[2][1] );
|
|---|
| 226 | EXPECT_EQ( 9.9, A.fM[2][2] );
|
|---|
| 227 | }
|
|---|
| 228 | catch (std::exception &error){
|
|---|
| 229 | cout << error.what();
|
|---|
| 230 | }
|
|---|
| 231 | }
|
|---|
| 232 | //------------------------------------------------------------------------------
|
|---|
| 233 | TEST_F(testMMatrix, missing_delimiter) {
|
|---|
| 234 | // when a delimiter is missing, a fatal exception must be thrown
|
|---|
| 235 | bool error_detected = false;
|
|---|
| 236 | try{
|
|---|
| 237 |
|
|---|
| 238 | MEnv env( (path2test + "missing_delimiter.rc" ).c_str() );
|
|---|
| 239 | MMatrix A("Any name related with A","titel");
|
|---|
| 240 |
|
|---|
| 241 | // right here an exception shall be thrown because of the missing delimiter
|
|---|
| 242 | A.ReadEnv(env,"MyData",kFALSE);
|
|---|
| 243 |
|
|---|
| 244 | }
|
|---|
| 245 | catch (std::exception error){
|
|---|
| 246 | error_detected = true;
|
|---|
| 247 | }
|
|---|
| 248 | EXPECT_TRUE(error_detected);
|
|---|
| 249 | }
|
|---|
| 250 | //------------------------------------------------------------------------------
|
|---|
| 251 | TEST_F(testMMatrix, bad_floating_point_number) {
|
|---|
| 252 | // when a floating point number is bad, a fatal exception must be thrown
|
|---|
| 253 | bool error_detected = false;
|
|---|
| 254 | try{
|
|---|
| 255 |
|
|---|
| 256 | MEnv env( (path2test + "bad_floating_point_number.rc" ).c_str() );
|
|---|
| 257 | MMatrix A("Any name related with A","titel");
|
|---|
| 258 |
|
|---|
| 259 | // expect exception because of bad floating point number
|
|---|
| 260 | A.ReadEnv(env,"MyData",kFALSE);
|
|---|
| 261 |
|
|---|
| 262 | }
|
|---|
| 263 | catch (std::exception error){
|
|---|
| 264 | error_detected = true;
|
|---|
| 265 | }
|
|---|
| 266 | EXPECT_TRUE(error_detected);
|
|---|
| 267 | }
|
|---|
| 268 | //------------------------------------------------------------------------------
|
|---|
| 269 | TEST_F(testMMatrix, NaN_Inf_exponent) {
|
|---|
| 270 |
|
|---|
| 271 | // +Inf, -Inf, Inf
|
|---|
| 272 | // NaN, 1e3, 42e13.37
|
|---|
| 273 | try{
|
|---|
| 274 |
|
|---|
| 275 | MEnv env( (path2test + "NaN_Inf_exponent.rc" ).c_str() );
|
|---|
| 276 | MMatrix A("Any name related with A","titel");
|
|---|
| 277 |
|
|---|
| 278 | A.ReadEnv(env,"MyData",kFALSE);
|
|---|
| 279 |
|
|---|
| 280 | // check dimension
|
|---|
| 281 | ASSERT_EQ( 2, A.fM.size() );
|
|---|
| 282 | ASSERT_EQ( 3, A.fM[0].size() );
|
|---|
| 283 | ASSERT_EQ( 3, A.fM[1].size() );
|
|---|
| 284 |
|
|---|
| 285 | // +Inf
|
|---|
| 286 | EXPECT_FALSE( std::signbit( A.fM[0][0]) );
|
|---|
| 287 | EXPECT_TRUE( std::isinf( A.fM[0][0]) );
|
|---|
| 288 | // -Inf
|
|---|
| 289 | EXPECT_TRUE( std::signbit( A.fM[0][1]) );
|
|---|
| 290 | EXPECT_TRUE( std::isinf( A.fM[0][1]) );
|
|---|
| 291 | // Inf
|
|---|
| 292 | EXPECT_FALSE( std::signbit( A.fM[0][2]) );
|
|---|
| 293 | EXPECT_TRUE( std::isinf( A.fM[0][2]) );
|
|---|
| 294 |
|
|---|
| 295 | EXPECT_TRUE( std::isnan( A.fM[1][0]) );
|
|---|
| 296 | EXPECT_EQ( 1e3, A.fM[1][1] );
|
|---|
| 297 | EXPECT_EQ( 13.37e42, A.fM[1][2] );
|
|---|
| 298 | }
|
|---|
| 299 | catch (std::exception &error){
|
|---|
| 300 | cout << error.what();
|
|---|
| 301 | }
|
|---|
| 302 | }
|
|---|
| 303 | //------------------------------------------------------------------------------
|
|---|
| 304 | TEST_F(testMMatrix, whitespaces_and_tabs) {
|
|---|
| 305 | // whitespaces are allowd and must not effect the parsing
|
|---|
| 306 | try{
|
|---|
| 307 |
|
|---|
| 308 | MEnv env( (path2test + "whitespaces_and_tabs.rc" ).c_str() );
|
|---|
| 309 | MMatrix A("Any name related with A","titel");
|
|---|
| 310 |
|
|---|
| 311 | A.ReadEnv(env,"MyData",kFALSE);
|
|---|
| 312 |
|
|---|
| 313 | // check dimension
|
|---|
| 314 | // we expect 9 row and 3 columns each with 1,2,3 in there
|
|---|
| 315 |
|
|---|
| 316 | ASSERT_EQ( 9, A.fM.size() );
|
|---|
| 317 | for(int row=0; row<9; row++){
|
|---|
| 318 |
|
|---|
| 319 | ASSERT_EQ( 3, A.fM[row].size() );
|
|---|
| 320 | for(int col=0; col<3; col++){
|
|---|
| 321 |
|
|---|
| 322 | EXPECT_EQ( (col+1) , A.fM[row][col] );
|
|---|
| 323 | }
|
|---|
| 324 | }
|
|---|
| 325 | }
|
|---|
| 326 | catch (std::exception &error){
|
|---|
| 327 | cout << error.what();
|
|---|
| 328 | }
|
|---|
| 329 | }
|
|---|
| 330 | //------------------------------------------------------------------------------
|
|---|
| 331 | TEST_F(testMMatrix, csv_file_does_not_exist) {
|
|---|
| 332 | // There must be a fatal exception when the csv file does not exist
|
|---|
| 333 | bool error_detected = false;
|
|---|
| 334 | try{
|
|---|
| 335 |
|
|---|
| 336 | MEnv env( (path2test + "csv_file_does_not_exist.rc" ).c_str() );
|
|---|
| 337 | MMatrix A("Any name related with A","titel");
|
|---|
| 338 |
|
|---|
| 339 | A.ReadEnv(env,"MyData",kFALSE);
|
|---|
| 340 | }
|
|---|
| 341 | catch (std::exception &error){
|
|---|
| 342 | error_detected = true;
|
|---|
| 343 | }
|
|---|
| 344 | EXPECT_TRUE(error_detected);
|
|---|
| 345 | }
|
|---|
| 346 | //------------------------------------------------------------------------------
|
|---|
| 347 | TEST_F(testMMatrix, key_does_not_exist_in_config_file) {
|
|---|
| 348 | // There must be a fatal exception when the key can not be found in the
|
|---|
| 349 | // config file.
|
|---|
| 350 | bool error_detected = false;
|
|---|
| 351 | try{
|
|---|
| 352 |
|
|---|
| 353 | MEnv env( (path2test + "key_does_not_exist_in_config_file.rc" ).c_str() );
|
|---|
| 354 | MMatrix A("Any name related with A","titel");
|
|---|
| 355 |
|
|---|
| 356 | A.ReadEnv(env,"KeyToDataThatDoesNotExistInTheConfigFile",kFALSE);
|
|---|
| 357 | }
|
|---|
| 358 | catch (std::exception &error){
|
|---|
| 359 | error_detected = true;
|
|---|
| 360 | }
|
|---|
| 361 | EXPECT_TRUE(error_detected);
|
|---|
| 362 | }
|
|---|
| 363 | //------------------------------------------------------------------------------ |
|---|