Commit 7018091c97e02f98ce78a5d00e2cc2061bf183d6

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

Add unit test for GLog class handling

ChangeLog
... ... @@ -3,7 +3,7 @@
3 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 7 Fix invalid pointer problem in GLog copies (#1823)
8 8 Fix GSkyMap::publish() bug for empty sky maps (#1835)
9 9 Fix loss of application name and version (#1835)
... ...
... ... @@ -28,6 +28,7 @@ The following methods have been added:
28 28 - GApplication::log_header2()
29 29 - GApplication::log_header3()
30 30 - GLog::is_open()
  31 +- GLog::is_empty()
31 32  
32 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 72 instance using the duplicated descriptor. This solves the problems (#1823).
72 73  
73 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 82 5. Base module
... ...
include/GLog.hpp
... ... @@ -84,10 +84,12 @@ public:
84 84  
85 85 // Methods
86 86 void clear(void);
87   - int size(void) const;
  87 + long int size(void) const;
88 88 std::string classname(void) const;
89 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 93 void close(void);
92 94 void flush(const bool& force = false);
93 95 void date(const bool& flag);
... ... @@ -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 177 * @brief Write string as centred header into logger
164 178 *
165 179 * @param[in] arg Header string.
... ...
pyext/GLog.i
... ... @@ -45,10 +45,12 @@ public:
45 45  
46 46 // Methods
47 47 void clear(void);
48   - int size(void) const;
  48 + long int size(void) const;
49 49 std::string classname(void) const;
50 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 54 void close(void);
53 55 void flush(const bool& force = false);
54 56 void date(const bool& flag);
... ...
src/app/GApplication.cpp
... ... @@ -348,15 +348,28 @@ void GApplication::logFileOpen(const bool& clobber)
348 348 /***********************************************************************//**
349 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 356 void GApplication::logFileClose(void)
354 357 {
355 358 // Continue only if log file is open
356 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 374 // Close log file
362 375 log.close();
... ... @@ -850,6 +863,8 @@ void GApplication::init_members(void)
850 863 * @brief Copy class members
851 864 *
852 865 * @param[in] app Application.
  866 + *
  867 + * Copies all class members.
853 868 ***************************************************************************/
854 869 void GApplication::copy_members(const GApplication& app)
855 870 {
... ...
src/app/GLog.cpp
... ... @@ -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 565 * @param[in] log Logger.
557 566 *
558 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 572 void GLog::copy_members(const GLog& log)
562 573 {
... ... @@ -566,7 +577,7 @@ void GLog::copy_members(const GLog&amp; log)
566 577 // doing this.
567 578 const_cast<GLog*>(&log)->flush(true);
568 579  
569   - // Copy attributes
  580 + // Copy buffer attributes
570 581 m_max_length = log.m_max_length;
571 582 m_indent = log.m_indent;
572 583 m_stdout = log.m_stdout;
... ... @@ -615,16 +626,17 @@ void GLog::free_members(void)
615 626 *
616 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 636 void GLog::flush(const bool& force)
625 637 {
626 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 641 // Flush buffer
630 642 if (flush) {
... ... @@ -801,7 +813,7 @@ void GLog::append(std::string arg)
801 813 // character is a \n then prepend a prefix at the beginning of the string
802 814 // to be inserted.
803 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 818 // Prepend prefix
807 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 5 clobber, b, h, yes,,, "Overwrite existing output files with new output files?"
6 6 debug, b, h, no,,, "Debugging mode activated"
7 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 44 name("GApplication");
45 45  
46 46 // Append tests
47   - append(static_cast<pfunction>(&TestGApplication::test_constructor),
  47 + append(static_cast<pfunction>(&TestGApplication::test_GLog),
48 48 "Test GLog constructor");
49   - append(static_cast<pfunction>(&TestGApplication::test_stream_logger),
  49 + append(static_cast<pfunction>(&TestGApplication::test_GLog_stream),
50 50 "Test stream logger");
51   - append(static_cast<pfunction>(&TestGApplication::test_C_logger),
  51 + append(static_cast<pfunction>(&TestGApplication::test_GLog_C),
52 52 "Test C logger");
53 53 append(static_cast<pfunction>(&TestGApplication::test_GApplicationPar),
54 54 "Test GApplicationPar class");
... ... @@ -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 80 // Void constructor
81 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 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 176 // Return
87 177 return;
88 178 }
... ... @@ -91,7 +181,7 @@ void TestGApplication::test_constructor(void)
91 181 /***********************************************************************//**
92 182 * @brief Test stream logger
93 183 **************************************************************************/
94   -void TestGApplication::test_stream_logger(void)
  184 +void TestGApplication::test_GLog_stream(void)
95 185 {
96 186 // Test
97 187 GLog log;
... ... @@ -114,7 +204,7 @@ void TestGApplication::test_stream_logger(void)
114 204 /***********************************************************************//**
115 205 * @brief Test C logger
116 206 **************************************************************************/
117   -void TestGApplication::test_C_logger(void)
  207 +void TestGApplication::test_GLog_C(void)
118 208 {
119 209 // Test
120 210 GLog log;
... ... @@ -377,7 +467,7 @@ void TestGApplication::test_GApplication(void)
377 467 // Test log filename
378 468 test_value(app1.par_filename(), "test_GApplication.par",
379 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 471 "Check application log file name");
382 472  
383 473 // Write something into the logfile and close it
... ... @@ -406,7 +496,7 @@ void TestGApplication::test_GApplication(void)
406 496  
407 497 // Check if log file exists
408 498 char line[200];
409   - FILE *fp = fopen("test_logfile.log", "r");
  499 + FILE *fp = fopen("test_application.log", "r");
410 500 test_assert(fp != NULL, "Check if logfile exists");
411 501  
412 502 // If log file exists then check it line by line
... ... @@ -491,21 +581,24 @@ void TestGApplication::test_GApplication(void)
491 581 test_value(line, " mode ......................: ql\n",
492 582 "Check log file line 24");
493 583 fgets(line, 100, fp);
494   - test_value(line, " logfile ...................: test_logfile.log\n",
  584 + test_value(line, " logfile ...................: test_application.log\n",
495 585 "Check log file line 25");
496 586 fgets(line, 32, fp);
497 587 test_value(line, "Application \"test_GApplication\"",
498 588 "Check log file line 26");
  589 +
499 590 // Empty remaining characters (not checked since they are machine
500 591 // dependent)
501 592 fgets(line, 200, fp);
  593 + fgets(line, 100, fp);
  594 + test_value(line, "\n", "Check log file line 27");
502 595 fgets(line, 32, fp);
503 596 test_value(line, "Application \"test_GApplication\"",
504   - "Check log file line 27");
  597 + "Check log file line 28");
505 598  
506 599 // Close log file
507 600 fclose(fp);
508   -
  601 +
509 602 } // endif: log file existed
510 603  
511 604 // Return
... ...
test/test_GApplication.hpp
... ... @@ -47,9 +47,9 @@ public:
47 47 virtual void set(void);
48 48 virtual TestGApplication* clone(void) const;
49 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 53 void test_GApplicationPar(void);
54 54 void test_GApplication(void);
55 55 };
... ...