Commit 7018091c97e02f98ce78a5d00e2cc2061bf183d6

Authored by Jürgen Knödlseder
1 parent 2ee39e3b

Add unit test for GLog class handling

ChangeLog
@@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
3 * Version 1.2.0 released 3 * Version 1.2.0 released
4 ========================= 4 =========================
5 5
6 - Add GLog::is_open() method (#1837) 6 + Add GLog::is_open() and GLog::is_empty() methods (#1837)
7 Fix invalid pointer problem in GLog copies (#1823) 7 Fix invalid pointer problem in GLog copies (#1823)
8 Fix GSkyMap::publish() bug for empty sky maps (#1835) 8 Fix GSkyMap::publish() bug for empty sky maps (#1835)
9 Fix loss of application name and version (#1835) 9 Fix loss of application name and version (#1835)
@@ -28,6 +28,7 @@ The following methods have been added: @@ -28,6 +28,7 @@ The following methods have been added:
28 - GApplication::log_header2() 28 - GApplication::log_header2()
29 - GApplication::log_header3() 29 - GApplication::log_header3()
30 - GLog::is_open() 30 - GLog::is_open()
  31 +- GLog::is_empty()
31 32
32 The following methods have been removed: 33 The following methods have been removed:
33 - ... 34 - ...
@@ -71,7 +72,11 @@ duplicating the file descriptor and opening the log file in the copied @@ -71,7 +72,11 @@ duplicating the file descriptor and opening the log file in the copied
71 instance using the duplicated descriptor. This solves the problems (#1823). 72 instance using the duplicated descriptor. This solves the problems (#1823).
72 73
73 A GLog::is_open() method has been added to assess whether a log file is 74 A GLog::is_open() method has been added to assess whether a log file is
74 -actually opened (#1837). 75 +actually opened. The GLog::is_empty() method has been added to assess whether
  76 +a log file is actually empty (#1837).
  77 +
  78 +The GLog::size() method now returns the actual size of the log file, including
  79 +the number of characters on disk.
75 80
76 81
77 5. Base module 82 5. Base module
include/GLog.hpp
@@ -84,10 +84,12 @@ public: @@ -84,10 +84,12 @@ public:
84 84
85 // Methods 85 // Methods
86 void clear(void); 86 void clear(void);
87 - int size(void) const; 87 + long int size(void) const;
88 std::string classname(void) const; 88 std::string classname(void) const;
89 bool is_open(void) const; 89 bool is_open(void) const;
90 - void open(const GFilename& filename, const bool& clobber = false); 90 + bool is_empty(void) const;
  91 + void open(const GFilename& filename,
  92 + const bool& clobber = false);
91 void close(void); 93 void close(void);
92 void flush(const bool& force = false); 94 void flush(const bool& force = false);
93 void date(const bool& flag); 95 void date(const bool& flag);
@@ -160,6 +162,18 @@ bool GLog::is_open(void) const @@ -160,6 +162,18 @@ bool GLog::is_open(void) const
160 162
161 163
162 /***********************************************************************//** 164 /***********************************************************************//**
  165 + * @brief Signal if log file is empty
  166 + *
  167 + * @return True if log file is empty, false otherwise.
  168 + ***************************************************************************/
  169 +inline
  170 +bool GLog::is_empty(void) const
  171 +{
  172 + return (size() == 0);
  173 +}
  174 +
  175 +
  176 +/***********************************************************************//**
163 * @brief Write string as centred header into logger 177 * @brief Write string as centred header into logger
164 * 178 *
165 * @param[in] arg Header string. 179 * @param[in] arg Header string.
pyext/GLog.i
@@ -45,10 +45,12 @@ public: @@ -45,10 +45,12 @@ public:
45 45
46 // Methods 46 // Methods
47 void clear(void); 47 void clear(void);
48 - int size(void) const; 48 + long int size(void) const;
49 std::string classname(void) const; 49 std::string classname(void) const;
50 bool is_open(void) const; 50 bool is_open(void) const;
51 - void open(const GFilename& filename, const bool& clobber = false); 51 + bool is_empty(void) const;
  52 + void open(const GFilename& filename,
  53 + const bool& clobber = false);
52 void close(void); 54 void close(void);
53 void flush(const bool& force = false); 55 void flush(const bool& force = false);
54 void date(const bool& flag); 56 void date(const bool& flag);
src/app/GApplication.cpp
@@ -348,15 +348,28 @@ void GApplication::logFileOpen(const bool& clobber) @@ -348,15 +348,28 @@ void GApplication::logFileOpen(const bool& clobber)
348 /***********************************************************************//** 348 /***********************************************************************//**
349 * @brief Close log file 349 * @brief Close log file
350 * 350 *
351 - * Logs trailer and close application log file. 351 + * Writer trailer into the log file and close application log file.
  352 + *
  353 + * The trailer is only written in case that there is some content in the
  354 + * log file.
352 ***************************************************************************/ 355 ***************************************************************************/
353 void GApplication::logFileClose(void) 356 void GApplication::logFileClose(void)
354 { 357 {
355 // Continue only if log file is open 358 // Continue only if log file is open
356 if (log.is_open()) { 359 if (log.is_open()) {
357 360
358 - // Write trailer into log file  
359 - log_trailer(); 361 + // If log file is not empty then write the trailer into log file.
  362 + // This kluge avoids writing a trailer in an empty log file that
  363 + // is for example occuring in copy operations.
  364 + if (!log.is_empty()) {
  365 +
  366 + // Put line feed
  367 + log << std::endl;
  368 +
  369 + // Write trailer into logger
  370 + log_trailer();
  371 +
  372 + } // endif: logger was not empty
360 373
361 // Close log file 374 // Close log file
362 log.close(); 375 log.close();
@@ -850,6 +863,8 @@ void GApplication::init_members(void) @@ -850,6 +863,8 @@ void GApplication::init_members(void)
850 * @brief Copy class members 863 * @brief Copy class members
851 * 864 *
852 * @param[in] app Application. 865 * @param[in] app Application.
  866 + *
  867 + * Copies all class members.
853 ***************************************************************************/ 868 ***************************************************************************/
854 void GApplication::copy_members(const GApplication& app) 869 void GApplication::copy_members(const GApplication& app)
855 { 870 {
src/app/GLog.cpp
@@ -460,12 +460,21 @@ void GLog::clear(void) @@ -460,12 +460,21 @@ void GLog::clear(void)
460 460
461 461
462 /***********************************************************************//** 462 /***********************************************************************//**
463 - * @brief Return the number of characters that are actually in the buffer 463 + * @brief Return the number of characters in the log file
  464 + *
  465 + * @return Number of characters in log file.
464 ***************************************************************************/ 466 ***************************************************************************/
465 -int GLog::size(void) const 467 +long int GLog::size(void) const
466 { 468 {
467 - // Return  
468 - return m_buffer.size(); 469 +std::cout << "GLog::size m_buffer.size()=" << m_buffer.size() << std::endl;
  470 + // Determine the number of characters written to disk
  471 + long int size = (m_file != NULL) ? std::ftell(m_file) : 0;
  472 +
  473 + // Add in buffer size
  474 + size += m_buffer.size();
  475 +
  476 + // Return total size
  477 + return size;
469 } 478 }
470 479
471 480
@@ -556,7 +565,9 @@ void GLog::init_members(void) @@ -556,7 +565,9 @@ void GLog::init_members(void)
556 * @param[in] log Logger. 565 * @param[in] log Logger.
557 * 566 *
558 * Copy all class members from @p log to the current logger instance. This 567 * Copy all class members from @p log to the current logger instance. This
559 - * method will flush the buffer of @p log before copying. 568 + * method will flush the buffer of @p log before copying. It will duplicate
  569 + * the file pointer on the log file so that the copy can safely work on the
  570 + * file without having to worry that the file pointer goes out of scope.
560 ***************************************************************************/ 571 ***************************************************************************/
561 void GLog::copy_members(const GLog& log) 572 void GLog::copy_members(const GLog& log)
562 { 573 {
@@ -566,7 +577,7 @@ void GLog::copy_members(const GLog&amp; log) @@ -566,7 +577,7 @@ void GLog::copy_members(const GLog&amp; log)
566 // doing this. 577 // doing this.
567 const_cast<GLog*>(&log)->flush(true); 578 const_cast<GLog*>(&log)->flush(true);
568 579
569 - // Copy attributes 580 + // Copy buffer attributes
570 m_max_length = log.m_max_length; 581 m_max_length = log.m_max_length;
571 m_indent = log.m_indent; 582 m_indent = log.m_indent;
572 m_stdout = log.m_stdout; 583 m_stdout = log.m_stdout;
@@ -615,16 +626,17 @@ void GLog::free_members(void) @@ -615,16 +626,17 @@ void GLog::free_members(void)
615 * 626 *
616 * @param[in] force If true, force flushing. 627 * @param[in] force If true, force flushing.
617 * 628 *
618 - * Flush string buffer if it is full or if flushing is enforced. This method  
619 - * writes the output string in the relevant streams. It decomposes the  
620 - * buffer in lines that a separated by a '\n' character. The following  
621 - * streams are currently implemented (and will be filled in parallel):  
622 - * stdout, stderr, and an ASCII file. 629 + * Flush string buffer if it is full or if flushing is enforced.
  630 + *
  631 + * This method writes the output string in the relevant streams. It
  632 + * decomposes the buffer in lines that a separated by a '\n' character.
  633 + * The following streams are currently implemented (and will be filled in
  634 + * parallel): stdout, stderr, and - if available - an ASCII file.
623 ***************************************************************************/ 635 ***************************************************************************/
624 void GLog::flush(const bool& force) 636 void GLog::flush(const bool& force)
625 { 637 {
626 // Check if buffer should be flushed 638 // Check if buffer should be flushed
627 - bool flush = (force || size() > m_max_length); 639 + bool flush = (force || m_buffer.size() > m_max_length);
628 640
629 // Flush buffer 641 // Flush buffer
630 if (flush) { 642 if (flush) {
@@ -801,7 +813,7 @@ void GLog::append(std::string arg) @@ -801,7 +813,7 @@ void GLog::append(std::string arg)
801 // character is a \n then prepend a prefix at the beginning of the string 813 // character is a \n then prepend a prefix at the beginning of the string
802 // to be inserted. 814 // to be inserted.
803 if ((m_buffer.size() == 0 && m_linestart) || 815 if ((m_buffer.size() == 0 && m_linestart) ||
804 - (m_buffer.size() > 0 && m_buffer[m_buffer.size()-1] == '\n')) { 816 + (m_buffer.size() > 0 && m_buffer[m_buffer.size()-1] == '\n')) {
805 817
806 // Prepend prefix 818 // Prepend prefix
807 arg.insert(0, prefix()); 819 arg.insert(0, prefix());
test/data/test_GApplication.par
@@ -5,4 +5,4 @@ chatter, i, h, 2,0,4, &quot;Chattiness of output&quot; @@ -5,4 +5,4 @@ chatter, i, h, 2,0,4, &quot;Chattiness of output&quot;
5 clobber, b, h, yes,,, "Overwrite existing output files with new output files?" 5 clobber, b, h, yes,,, "Overwrite existing output files with new output files?"
6 debug, b, h, no,,, "Debugging mode activated" 6 debug, b, h, no,,, "Debugging mode activated"
7 mode, s, h, ql,,, "Mode of automatic parameters" 7 mode, s, h, ql,,, "Mode of automatic parameters"
8 -logfile, f, h, test_logfile.log,,, "Log filename" 8 +logfile, f, h, test_application.log,,, "Log filename"
test/test_GApplication.cpp
@@ -44,11 +44,11 @@ void TestGApplication::set(void) @@ -44,11 +44,11 @@ void TestGApplication::set(void)
44 name("GApplication"); 44 name("GApplication");
45 45
46 // Append tests 46 // Append tests
47 - append(static_cast<pfunction>(&TestGApplication::test_constructor), 47 + append(static_cast<pfunction>(&TestGApplication::test_GLog),
48 "Test GLog constructor"); 48 "Test GLog constructor");
49 - append(static_cast<pfunction>(&TestGApplication::test_stream_logger), 49 + append(static_cast<pfunction>(&TestGApplication::test_GLog_stream),
50 "Test stream logger"); 50 "Test stream logger");
51 - append(static_cast<pfunction>(&TestGApplication::test_C_logger), 51 + append(static_cast<pfunction>(&TestGApplication::test_GLog_C),
52 "Test C logger"); 52 "Test C logger");
53 append(static_cast<pfunction>(&TestGApplication::test_GApplicationPar), 53 append(static_cast<pfunction>(&TestGApplication::test_GApplicationPar),
54 "Test GApplicationPar class"); 54 "Test GApplicationPar class");
@@ -73,16 +73,106 @@ TestGApplication* TestGApplication::clone(void) const @@ -73,16 +73,106 @@ TestGApplication* TestGApplication::clone(void) const
73 73
74 74
75 /***********************************************************************//** 75 /***********************************************************************//**
76 - * @brief Test GLog constructor 76 + * @brief Test GLog class
77 **************************************************************************/ 77 **************************************************************************/
78 -void TestGApplication::test_constructor(void) 78 +void TestGApplication::test_GLog(void)
79 { 79 {
80 // Void constructor 80 // Void constructor
81 GLog log1; 81 GLog log1;
82 82
83 - // Copy constructor 83 + // Check empty logger
  84 + test_assert(log1.is_empty(), "Check whether logger is empty");
  85 + test_value(log1.size(), 0, "Check whether logger size is 0");
  86 + test_assert(!log1.is_open(), "Check whether log file is closed");
  87 +
  88 + // Copy empty logger
84 GLog log2 = log1; 89 GLog log2 = log1;
85 90
  91 + // Check whether copied logger isempty
  92 + test_assert(log2.is_empty(), "Check whether copied logger is empty");
  93 + test_value(log2.size(), 0, "Check whether copied logger size is 0");
  94 + test_assert(!log2.is_open(), "Check whether copied log file is closed");
  95 +
  96 + // Write a few characters and check the logger size
  97 + log2 << "Honeymoon";
  98 + test_value(log2.size(), 9, "Check logger size in memory");
  99 +
  100 + // Flush to disk for a closed file. This should make the text disappear.
  101 + log2.flush(true);
  102 + test_value(log2.size(), 0,
  103 + "Check logger size in memory after flushing without file");
  104 + test_assert(log2.is_empty(),
  105 + "Check whether logger is empty after flushing without file");
  106 +
  107 + // Open log file and check whether it's open now
  108 + log2.open("test_logfile.log", true);
  109 + test_assert(log2.is_open(), "Check whether log file is now open");
  110 +
  111 + // Write a few characters and check the logger size
  112 + log2 << "Honeymoon";
  113 + test_value(log2.size(), 9, "Check logger size in memory");
  114 +
  115 + // Flush to disk and check again the logger size
  116 + log2.flush(true);
  117 + test_value(log2.size(), 9,
  118 + "Check logger size on disk after flushing to disk");
  119 + test_assert(!log2.is_empty(),
  120 + "Check whether logger is not empty after flushing to disk");
  121 +
  122 + // Write more characters and check the logger size
  123 + log2 << " and Milk!";
  124 + test_value(log2.size(), 19, "Check logger size on disk+memory");
  125 +
  126 + // Close log file and check whether the logger is empty again
  127 + log2.close();
  128 + test_assert(log2.is_empty(), "Check whether logger is empty again");
  129 + test_value(log2.size(), 0, "Check whether logger size is again 0");
  130 +
  131 + // Open log file again and check whether it's open now
  132 + log1.open("test_logfile.log", true);
  133 + test_assert(log1.is_open(), "Check whether log file is now open");
  134 +
  135 + // Write a few characters and check the logger size
  136 + log1 << "Honeymoon";
  137 + test_value(log1.size(), 9, "Check logger size in memory");
  138 +
  139 + // Copy filled logger
  140 + log2 = log1;
  141 +
  142 + // Now fill both loggers with more characters
  143 + log1 << " and";
  144 + log2 << " Milk!";
  145 +
  146 + // Check the logger size in memory. They should be different.
  147 + test_value(log1.size(), 13, "Check logger 1 size in memory");
  148 + test_value(log2.size(), 15, "Check logger 2 size in memory");
  149 +
  150 + // Flush both loggers. Each logger flushes what he has.
  151 + log1.flush(true);
  152 + log2.flush(true);
  153 +
  154 + // Check that logger size on disk. Both loggers flushed their
  155 + // content, first logger 1, then logger 2, and the sum should
  156 + // be on disk. Both logger sizes are now identical.
  157 + test_value(log1.size(), 19, "Check logger 1 size on disk");
  158 + test_value(log2.size(), 19, "Check logger 2 size on disk");
  159 +
  160 + // Close loggers
  161 + log1.close();
  162 + log2.close();
  163 +
  164 + // Check if log file exists
  165 + char line[100];
  166 + FILE *fp = fopen("test_logfile.log", "r");
  167 + test_assert(fp != NULL, "Check if logfile exists");
  168 +
  169 + // If log file exists then check it and close file
  170 + if (fp != NULL) {
  171 + fgets(line, 100, fp);
  172 + test_value(line, "Honeymoon and Milk!", "Check log file content");
  173 + fclose(fp);
  174 + }
  175 +
86 // Return 176 // Return
87 return; 177 return;
88 } 178 }
@@ -91,7 +181,7 @@ void TestGApplication::test_constructor(void) @@ -91,7 +181,7 @@ void TestGApplication::test_constructor(void)
91 /***********************************************************************//** 181 /***********************************************************************//**
92 * @brief Test stream logger 182 * @brief Test stream logger
93 **************************************************************************/ 183 **************************************************************************/
94 -void TestGApplication::test_stream_logger(void) 184 +void TestGApplication::test_GLog_stream(void)
95 { 185 {
96 // Test 186 // Test
97 GLog log; 187 GLog log;
@@ -114,7 +204,7 @@ void TestGApplication::test_stream_logger(void) @@ -114,7 +204,7 @@ void TestGApplication::test_stream_logger(void)
114 /***********************************************************************//** 204 /***********************************************************************//**
115 * @brief Test C logger 205 * @brief Test C logger
116 **************************************************************************/ 206 **************************************************************************/
117 -void TestGApplication::test_C_logger(void) 207 +void TestGApplication::test_GLog_C(void)
118 { 208 {
119 // Test 209 // Test
120 GLog log; 210 GLog log;
@@ -377,7 +467,7 @@ void TestGApplication::test_GApplication(void) @@ -377,7 +467,7 @@ void TestGApplication::test_GApplication(void)
377 // Test log filename 467 // Test log filename
378 test_value(app1.par_filename(), "test_GApplication.par", 468 test_value(app1.par_filename(), "test_GApplication.par",
379 "Check application parameter file name"); 469 "Check application parameter file name");
380 - test_value(app1.log_filename(), "test_logfile.log", 470 + test_value(app1.log_filename(), "test_application.log",
381 "Check application log file name"); 471 "Check application log file name");
382 472
383 // Write something into the logfile and close it 473 // Write something into the logfile and close it
@@ -406,7 +496,7 @@ void TestGApplication::test_GApplication(void) @@ -406,7 +496,7 @@ void TestGApplication::test_GApplication(void)
406 496
407 // Check if log file exists 497 // Check if log file exists
408 char line[200]; 498 char line[200];
409 - FILE *fp = fopen("test_logfile.log", "r"); 499 + FILE *fp = fopen("test_application.log", "r");
410 test_assert(fp != NULL, "Check if logfile exists"); 500 test_assert(fp != NULL, "Check if logfile exists");
411 501
412 // If log file exists then check it line by line 502 // If log file exists then check it line by line
@@ -491,21 +581,24 @@ void TestGApplication::test_GApplication(void) @@ -491,21 +581,24 @@ void TestGApplication::test_GApplication(void)
491 test_value(line, " mode ......................: ql\n", 581 test_value(line, " mode ......................: ql\n",
492 "Check log file line 24"); 582 "Check log file line 24");
493 fgets(line, 100, fp); 583 fgets(line, 100, fp);
494 - test_value(line, " logfile ...................: test_logfile.log\n", 584 + test_value(line, " logfile ...................: test_application.log\n",
495 "Check log file line 25"); 585 "Check log file line 25");
496 fgets(line, 32, fp); 586 fgets(line, 32, fp);
497 test_value(line, "Application \"test_GApplication\"", 587 test_value(line, "Application \"test_GApplication\"",
498 "Check log file line 26"); 588 "Check log file line 26");
  589 +
499 // Empty remaining characters (not checked since they are machine 590 // Empty remaining characters (not checked since they are machine
500 // dependent) 591 // dependent)
501 fgets(line, 200, fp); 592 fgets(line, 200, fp);
  593 + fgets(line, 100, fp);
  594 + test_value(line, "\n", "Check log file line 27");
502 fgets(line, 32, fp); 595 fgets(line, 32, fp);
503 test_value(line, "Application \"test_GApplication\"", 596 test_value(line, "Application \"test_GApplication\"",
504 - "Check log file line 27"); 597 + "Check log file line 28");
505 598
506 // Close log file 599 // Close log file
507 fclose(fp); 600 fclose(fp);
508 - 601 +
509 } // endif: log file existed 602 } // endif: log file existed
510 603
511 // Return 604 // Return
test/test_GApplication.hpp
@@ -47,9 +47,9 @@ public: @@ -47,9 +47,9 @@ public:
47 virtual void set(void); 47 virtual void set(void);
48 virtual TestGApplication* clone(void) const; 48 virtual TestGApplication* clone(void) const;
49 virtual std::string classname(void) const { return "TestGApplication"; } 49 virtual std::string classname(void) const { return "TestGApplication"; }
50 - void test_constructor(void);  
51 - void test_stream_logger(void);  
52 - void test_C_logger(void); 50 + void test_GLog(void);
  51 + void test_GLog_stream(void);
  52 + void test_GLog_C(void);
53 void test_GApplicationPar(void); 53 void test_GApplicationPar(void);
54 void test_GApplication(void); 54 void test_GApplication(void);
55 }; 55 };