GammaLib  1.7.0.dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
GTestSuite.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * GTestSuite.cpp - Abstract test suite base class *
3  * ----------------------------------------------------------------------- *
4  * copyright (C) 2012-2016 by Jean-Baptiste Cayrou *
5  * ----------------------------------------------------------------------- *
6  * *
7  * This program is free software: you can redistribute it and/or modify *
8  * it under the terms of the GNU General Public License as published by *
9  * the Free Software Foundation, either version 3 of the License, or *
10  * (at your option) any later version. *
11  * *
12  * This program is distributed in the hope that it will be useful, *
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15  * GNU General Public License for more details. *
16  * *
17  * You should have received a copy of the GNU General Public License *
18  * along with this program. If not, see <http://www.gnu.org/licenses/>. *
19  * *
20  ***************************************************************************/
21 /**
22  * @file GTestSuite.cpp
23  * @brief Abstract test suite base class implementation
24  * @author Jean-Baptiste Cayrou
25  */
26 
27 /* __ Includes ___________________________________________________________ */
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31 #include <typeinfo>
32 #include "GTestSuite.hpp"
33 #include "GTools.hpp"
34 #include "GLog.hpp"
35 
36 /* __ OpenMP section _____________________________________________________ */
37 #ifdef _OPENMP
38 #include <omp.h>
39 #ifdef HAVE_OPENMP_DARWIN_KLUGE
40 #include <pthread.h>
41 pthread_attr_t gomp_thread_attr;
42 #endif
43 #endif
44 
45 /* __ Method name definitions ____________________________________________ */
46 #define G_OP_ACCESS "GTestSuite::operator[](int&)"
47 #define G_TRY_SUCCESS "GTestSuite::test_try_success()"
48 #define G_TRY_FAILURE1 "GTestSuite::test_try_failure(std::string&,"\
49  " std::string&)"
50 #define G_TRY_FAILURE2 "GTestSuite::test_try_failure(std::exception&)"
51 
52 /* __ Macros _____________________________________________________________ */
53 
54 /* __ Coding definitions _________________________________________________ */
55 
56 /* __ Debug definitions __________________________________________________ */
57 
58 
59 /*==========================================================================
60  = =
61  = Constructors/destructors =
62  = =
63  ==========================================================================*/
64 
65 /***********************************************************************//**
66  * @brief Void constructor
67  ***************************************************************************/
69 {
70  // Initialise members
71  init_members();
72 
73  //Return
74  return;
75 }
76 
77 
78 /***********************************************************************//**
79  * @brief Copy constructor
80  *
81  * @param[in] suite Test Suite.
82  ***************************************************************************/
84 {
85  // Initialise members
86  init_members();
87 
88  // Copy members
89  copy_members(suite);
90 
91  //Return
92  return;
93 }
94 
95 
96 /***********************************************************************//**
97  * @brief Name constructor
98  *
99  * @param[in] name Test suite name.
100  ***************************************************************************/
101 GTestSuite::GTestSuite(const std::string& name)
102 {
103  // Initialise members
104  init_members();
105 
106  // Set name
107  m_name = name;
108 
109  //Return
110  return;
111 }
112 
113 
114 /***********************************************************************//**
115  * @brief Destructor
116  ***************************************************************************/
118 {
119  // Free members
120  free_members();
121 
122  // Return
123  return;
124 }
125 
126 
127 /*==========================================================================
128  = =
129  = Operators =
130  = =
131  ==========================================================================*/
132 
133 /***********************************************************************//**
134  * @brief Assignment operator
135  *
136  * @param[in] suite Test suite.
137  * @return Test suite.
138  ***************************************************************************/
140 {
141  // Execute only if object is not identical
142  if (this != &suite) {
143 
144  // Free members
145  free_members();
146 
147  // Initialise members
148  init_members();
149 
150  // Copy members
151  copy_members(suite);
152 
153  } // endif: object was not identical
154 
155  // Return
156  return *this;
157 }
158 
159 
160 /***********************************************************************//**
161  * @brief Returns reference to test case
162  *
163  * @param[in] index Test case index [0,...,size()-1].
164  *
165  * @exception GException::out_of_range
166  * Test case index is out of range.
167  ***************************************************************************/
169 {
170  // Compile option: raise exception if index is out of range
171  #if defined(G_RANGE_CHECK)
172  if (index < 0 || index >= size()) {
173  throw GException::out_of_range(G_OP_ACCESS, "Test case index", index, size());
174  }
175  #endif
176 
177  // Return reference
178  return *(m_tests[index]);
179 }
180 
181 /***********************************************************************//**
182  * @brief Returns reference to test case
183  *
184  * @param[in] index Test case index [0,...,size()-1].
185  *
186  * @exception GException::out_of_range
187  * Test case index is out of range.
188  ***************************************************************************/
189 const GTestCase& GTestSuite::operator[](const int& index) const
190 {
191  // Compile option: raise exception if index is out of range
192  #if defined(G_RANGE_CHECK)
193  if (index < 0 || index >= size()) {
194  throw GException::out_of_range(G_OP_ACCESS, "Test case index", index, size());
195  }
196  #endif
197 
198  // Return reference
199  return *(m_tests[index]);
200 }
201 
202 
203 /*==========================================================================
204  = =
205  = Public methods =
206  = =
207  ==========================================================================*/
208 
209 /***********************************************************************//**
210  * @brief Clear test suite
211  ***************************************************************************/
213 {
214  // Free members
215  free_members();
216 
217  // Initialise members
218  init_members();
219 
220  // Return
221  return;
222 }
223 
224 
225 /***********************************************************************//**
226  * @brief Append test functions to test suite
227  *
228  * @param[in] function Test function pointer.
229  * @param[in] name Test name.
230  *
231  * This method adds test functions to the test suite. The test functions will
232  * be executed when the run method is called.
233  ***************************************************************************/
234 void GTestSuite::append(const pfunction function, const std::string& name)
235 {
236  // Add test function pointer and name to suite
237  m_functions.push_back(function);
238  m_names.push_back(name);
239 
240  // Return
241  return;
242 }
243 
244 
245 /***********************************************************************//**
246  * @brief Run all tests in test suite
247  *
248  * @return True if all tests were successful, false otherwise.
249  *
250  * Executes all test functions that have been appended to the test suite.
251  * For each test function a test case is added to the test suite.
252  ***************************************************************************/
253 bool GTestSuite::run(void)
254 {
255  // Setup the test functions. This is a pure virtual function that needs
256  // to be implemented in the derived class. It sets the function
257  // pointers and function names for all test functions that should be
258  // executed.
259  set();
260 
261  // Initialise success flag
262  bool success = true;
263 
264  // Loop over all functions in suite
265  for (m_index = 0; m_index < m_functions.size(); ++m_index) {
266 
267  // Continue only if function is valid
268  if (m_functions[m_index] != NULL) {
269 
270  // Save the number of errors and failures before test
271  // execution. We use this after the test to see if
272  // any failures occured.
273  int old_errors = errors();
274  int old_failures = failures();
275 
276  // Log the name of the test
277  std::cout << m_names[m_index] << ": ";
278 
279  // Create a test of error type for function testing
280  GTestCase* test = new GTestCase(GTestCase::ERROR_TEST, m_names[m_index]);
281 
282  // Add test case to test suite
283  m_tests.push_back(test);
284 
285  // Set start time
286  #ifdef _OPENMP
287  double t_start = omp_get_wtime();
288  #else
289  clock_t t_start = clock();
290  #endif
291 
292  // Execute test function
293  try {
294  (this->*(m_functions[m_index]))();
295  }
296  catch (std::exception& e) {
297 
298  // Signal that test did not succeed
299  test->has_passed(false);
300 
301  // Set test message to exception message
302  test->message(e.what());
303 
304  // Set type as class name
305  test->type(typeid(e).name());
306 
307  }
308  catch (...)
309  {
310  // For other exceptions
311  test->has_passed(false);
312  test->message("Non-standard C++ exception thrown");
313  }
314 
315  // Compute elapsed time
316  #ifdef _OPENMP
317  double t_elapse = omp_get_wtime()-t_start;
318  #else
319  double t_elapse = (double)(clock() - t_start) / (double)CLOCKS_PER_SEC;
320  #endif
321 
322  // Set test duration
323  test->duration(t_elapse);
324 
325  // Increment number of errors if the test did not pass
326  if (!test->has_passed()) {
327  m_errors++;
328  }
329 
330  // Log the result (".","F" or, "E")
331  std::cout << test->print();
332 
333  // Log if there are errors or failures
334  if ((m_errors == old_errors && m_failures == old_failures)) {
335  std::cout << " ok" << std::endl;
336  }
337  else {
338  std::cout << " NOK" << std::endl;
339  success = false;
340  }
341 
342  } // endif: test case has a function pointer
343 
344  } // endfor: looped over tests on the stack
345 
346  // Reset index
347  m_index = 0;
348 
349  // Return success flag
350  return success;
351 }
352 
353 
354 /***********************************************************************//**
355  * @brief Test an assert
356  *
357  * @param[in] assert Assert (true/false).
358  * @param[in] name Test case name.
359  * @param[in] message Test case name (defaults to "").
360  *
361  * Tests if a condition is true or false. This method adds a test case of
362  * type "failure" to the test suite.
363  *
364  * Examples:
365  * test_assert(x>3, "Test if x > 3");
366  * test_assert(x>3 && x<10, "Test if 3 < x < 10 ");
367  ***************************************************************************/
368 void GTestSuite::test_assert(const bool& assert,
369  const std::string& name,
370  const std::string& message)
371 {
372  // Create a test case of failure type
373  GTestCase* testcase = new GTestCase(GTestCase::FAIL_TEST, format_name(name));
374 
375  // If assert is false then signal that the test is not passed and
376  // increment the number of failures in this test suite
377  if (!assert) {
378  testcase->has_passed(false);
379  m_failures++;
380  }
381 
382  // Set message
383  testcase->message(message);
384 
385  // Log the result (".","F" or, "E")
386  std::cout << testcase->print();
387 
388  // Add test case to test suite
389  m_tests.push_back(testcase);
390 
391  // Return
392  return;
393 }
394 
395 
396 /***********************************************************************//**
397  * @brief Test an integer value
398  *
399  * @param[in] value Integer value to test.
400  * @param[in] expected Expected integer value.
401  * @param[in] name Test case name.
402  * @param[in] message Test case message.
403  *
404  * Test if integer @p value is the @p expected value.
405  ***************************************************************************/
406 void GTestSuite::test_value(const int& value,
407  const int& expected,
408  const std::string& name,
409  const std::string& message)
410 {
411  // Set test case name. If no name is specify then build the name from
412  // the actual test parameters.
413  std::string formated_name;
414  if (name != "") {
415  formated_name = format_name(name);
416  }
417  else {
418  formated_name = format_name("Test if "+gammalib::str(value)+" is "+
419  gammalib::str(expected));
420  }
421 
422  // Create a test case of failure type
423  GTestCase* testcase = new GTestCase(GTestCase::FAIL_TEST, formated_name);
424 
425  // If value is not the expected one then signal test as failed and
426  // increment the number of failures
427  if (value != expected) {
428  testcase->has_passed(false);
429  m_failures++;
430  }
431 
432  // If no message is specified then build message from test result
433  std::string formated_message;
434  if (message != "") {
435  formated_message = message;
436  }
437  else {
438  formated_message = "Value "+gammalib::str(value)+" equals not the "+
439  "expected value of "+gammalib::str(expected)+".";
440  }
441 
442  // Set message
443  testcase->message(formated_message);
444 
445  // Log the result (".","F" or, "E")
446  std::cout << testcase->print();
447 
448  // Add test case to test suite
449  m_tests.push_back(testcase);
450 
451  // Return
452  return;
453 }
454 
455 
456 /***********************************************************************//**
457  * @brief Test a double precision value
458  *
459  * @param[in] value Double precision value to test.
460  * @param[in] expected Expected double precision value.
461  * @param[in] name Test case name.
462  * @param[in] message Test case message.
463  *
464  * Test if the @p value is equal to the @p expected value within a relative
465  * precision of 1.0e-7.
466  ***************************************************************************/
467 void GTestSuite::test_value(const double& value,
468  const double& expected,
469  const std::string& name,
470  const std::string& message)
471 {
472  // Compute precision
473  double eps = (expected != 0.0) ? 1.0e-7 * std::abs(expected) : 1.0e-7;
474 
475  // Test double precision value
476  test_value(value, expected, eps, name, message);
477 
478  // Return
479  return;
480 }
481 
482 
483 /***********************************************************************//**
484  * @brief Test a double precision value
485  *
486  * @param[in] value Double precision value to test.
487  * @param[in] expected Expected double precision value.
488  * @param[in] eps Precision of the test.
489  * @param[in] name Test case name.
490  * @param[in] message Test case message.
491  *
492  * Test if the value is comprised in the interval
493  * [expected-eps, expected+eps].
494  ***************************************************************************/
495 void GTestSuite::test_value(const double& value,
496  const double& expected,
497  const double& eps,
498  const std::string& name,
499  const std::string& message)
500 {
501  // Set test case name. If no name is specify then build the name from
502  // the actual test parameters.
503  std::string formated_name;
504  if (name != "") {
505  formated_name = format_name(name);
506  }
507  else {
508  formated_name = format_name("Test if "+gammalib::str(value)+
509  " is comprised within "+
510  gammalib::str(expected)+" +/- "+
511  gammalib::str(eps));
512  }
513 
514  // Create a test case of failure type
515  GTestCase* testcase = new GTestCase(GTestCase::FAIL_TEST, formated_name);
516 
517  // If value is not between in interval [expected-eps, expected+eps]
518  // then signal test as failed and increment the number of failures
519  if (value > expected + eps || value < expected - eps) {
520  testcase->has_passed(false);
521  m_failures++;
522  }
523 
524  // If no message is specified then build message from test result
525  std::string formated_message;
526  if (message != "") {
527  formated_message = message;
528  }
529  else {
530  formated_message = "Value "+gammalib::str(value)+" not within "+
531  gammalib::str(expected)+" +/- "+gammalib::str(eps)+
532  " (value-expected = "+gammalib::str(value-expected)+
533  ").";
534  }
535 
536  // Set message
537  testcase->message(formated_message);
538 
539  // Log the result (".","F" or, "E")
540  std::cout << testcase->print();
541 
542  // Add test case to test suite
543  m_tests.push_back(testcase);
544 
545  // Return
546  return;
547 }
548 
549 
550 /***********************************************************************//**
551  * @brief Test a complex value
552  *
553  * @param[in] value Complex value to test.
554  * @param[in] expected Expected complex value.
555  * @param[in] name Test case name.
556  * @param[in] message Test case message.
557  *
558  * Test if the @p value is equal to the @p expected value within a relative
559  * precision of 1.0e-7.
560  ***************************************************************************/
561 void GTestSuite::test_value(const std::complex<double>& value,
562  const std::complex<double>& expected,
563  const std::string& name,
564  const std::string& message)
565 {
566  // Compute precision
567  double eps = (expected != 0.0) ? 1.0e-7 * std::abs(expected) : 1.0e-7;
568 
569  // Test double precision value
570  test_value(value, expected, eps, name, message);
571 
572  // Return
573  return;
574 }
575 
576 
577 /***********************************************************************//**
578  * @brief Test a complex value
579  *
580  * @param[in] value Complex value to test.
581  * @param[in] expected Expected complex value.
582  * @param[in] eps Precision of the test.
583  * @param[in] name Test case name.
584  * @param[in] message Test case message.
585  *
586  * Test if the value is comprised in the interval
587  * [expected-eps, expected+eps].
588  ***************************************************************************/
589 void GTestSuite::test_value(const std::complex<double>& value,
590  const std::complex<double>& expected,
591  const double& eps,
592  const std::string& name,
593  const std::string& message)
594 {
595  // Set test case name. If no name is specify then build the name from
596  // the actual test parameters.
597  std::string formated_name;
598  if (name != "") {
599  formated_name = format_name(name);
600  }
601  else {
602  formated_name = format_name("Test if "+gammalib::str(value)+
603  " is comprised within "+
604  gammalib::str(expected)+" +/- "+
605  gammalib::str(eps));
606  }
607 
608  // Create a test case of failure type
609  GTestCase* testcase = new GTestCase(GTestCase::FAIL_TEST, formated_name);
610 
611  // If value is not between in interval [expected-eps, expected+eps]
612  // then signal test as failed and increment the number of failures
613  if ((value.real() > expected.real() + eps) ||
614  (value.real() < expected.real() - eps) ||
615  (value.imag() > expected.imag() + eps) ||
616  (value.imag() < expected.imag() - eps)) {
617  testcase->has_passed(false);
618  m_failures++;
619  }
620 
621  // If no message is specified then build message from test result
622  std::string formated_message;
623  if (message != "") {
624  formated_message = message;
625  }
626  else {
627  formated_message = "Value "+gammalib::str(value)+" not within "+
628  gammalib::str(expected)+" +/- "+gammalib::str(eps)+
629  " (value-expected = "+gammalib::str(value-expected)+
630  ").";
631  }
632 
633  // Set message
634  testcase->message(formated_message);
635 
636  // Log the result (".","F" or, "E")
637  std::cout << testcase->print();
638 
639  // Add test case to test suite
640  m_tests.push_back(testcase);
641 
642  // Return
643  return;
644 }
645 
646 
647 /***********************************************************************//**
648  * @brief Test a string value
649  *
650  * @param[in] value String value to test.
651  * @param[in] expected Expected string value.
652  * @param[in] name Test case name (defaults to "").
653  * @param[in] message Test case message (defaults to "").
654  *
655  * Test if the string @p value corresponds to the @p expected value.
656  ***************************************************************************/
657 void GTestSuite::test_value(const std::string& value,
658  const std::string& expected,
659  const std::string& name,
660  const std::string& message)
661 {
662  // Set test case name. If no name is specify then build the name from
663  // the actual test parameters.
664  std::string formated_name;
665  if (name != "") {
666  formated_name = format_name(name);
667  }
668  else {
669  formated_name = format_name("Test if \""+value+"\" is \""+expected+"\"");
670  }
671 
672  // Create a test case of failure type
673  GTestCase* testcase = new GTestCase(GTestCase::FAIL_TEST, formated_name);
674 
675  // If value is not the expected one then signal test as failed and
676  // increment the number of failures
677  if (value != expected) {
678  testcase->has_passed(false);
679  m_failures++;
680  }
681 
682  // If no message is specified then build message from test result
683  std::string formated_message;
684  if (message != "") {
685  formated_message = message;
686  }
687  else {
688  formated_message = "String \""+value+"\" is not equal to the "+
689  "expected string \""+expected+"\".";
690  }
691 
692  // Set message
693  testcase->message(formated_message);
694 
695  // Log the result (".","F" or, "E")
696  std::cout << testcase->print();
697 
698  // Add test case to test suite
699  m_tests.push_back(testcase);
700 
701  // Return
702  return;
703 }
704 
705 
706 /***********************************************************************//**
707  * @brief Test an try block
708  *
709  * @param[in] name Test case name (defaults to "").
710  *
711  * @see test_try_sucess()
712  * @see test_try_failure(const std::string& message,const std::string& type)
713  * @see test_try_failure(const std::exception& e)
714  *
715  * Call before testing a try/catch block.
716  *
717  * Example:
718  * test_try("Test a try block");
719  * try {
720  * ... //someting to test
721  * test_try_success();
722  * }
723  * catch(...) {
724  * test_try_failure();
725  * }
726  ***************************************************************************/
727 void GTestSuite::test_try(const std::string& name)
728 {
729  // Create a test case of error type
730  GTestCase* testcase = new GTestCase(GTestCase::ERROR_TEST, format_name(name));
731 
732  // Add test case to try stack of test suite
733  m_stack_try.push_back(testcase);
734 
735  // Return
736  return;
737 }
738 
739 
740 /***********************************************************************//**
741  * @brief Notice when a try block succeeded
742  *
743  * @exception GException::test_nested_try_error
744  * Test case index is out of range.
745  *
746  * @see test_try(const std::string& name)
747  * @see test_try_failure(const std::string& message, const std::string& type)
748  * @see test_try_failure(const std::exception& e)
749  *
750  * Call this method at the last line of a try
751  *
752  * Example:
753  * test_try("Test a try block");
754  * try {
755  * ... //someting to test
756  * test_try_success();
757  * }
758  * catch(...) {
759  * test_try_failure();
760  * }
761  ***************************************************************************/
763 {
764  // If the stack is empty
765  if (m_stack_try.empty()) {
767  "Called \"G_TRY_SUCCESS\" without a previous call to test_try()");
768  }
769 
770  // Add test case to test suite
771  m_tests.push_back(m_stack_try.back());
772 
773  // Delete the test case from the try stack
774  m_stack_try.pop_back();
775 
776  // Log the result (".","F" or, "E")
777  std::cout << m_tests.back()->print();
778 
779  // Return
780  return;
781 }
782 
783 
784 /***********************************************************************//**
785  * @brief Notice when a try block failed
786  *
787  * @param[in] message Message to explain why test failed (defaults to "").
788  * @param[in] type Type of message (defaults to "").
789  *
790  * @exception GException::test_nested_try_error
791  * Test case index is out of range.
792  *
793  * @see test_try_sucess()
794  * @see test_try(const std::string& name)
795  * @see test_try_failure(const std::exception& e)
796  *
797  * Call this method in the catch block.
798  *
799  * Example:
800  * test_try("Test a try block");
801  * try {
802  * ... //someting to test
803  * test_try_success();
804  * }
805  * catch(...) {
806  * test_try_failure();
807  * }
808  ***************************************************************************/
809 void GTestSuite::test_try_failure(const std::string& message,
810  const std::string& type)
811 {
812  // If the stack is empty then create an eception test case
813  if (m_stack_try.empty()) {
814  GTestCase* testcase = new GTestCase(GTestCase::ERROR_TEST, "Exception test");
815  m_stack_try.push_back(testcase);
816  }
817 
818  // Signal that test is not ok
819  m_stack_try.back()->has_passed(false);
820 
821  // Increment the number of errors
822  m_errors++;
823 
824  // Set test type
825  m_stack_try.back()->kind(GTestCase::ERROR_TEST);
826 
827  // Set message
828  m_stack_try.back()->message(message);
829 
830  // Set type of message
831  m_stack_try.back()->type(type);
832 
833  // Add test case to test suite
834  m_tests.push_back(m_stack_try.back());
835 
836  // Delete the test case from the stack
837  m_stack_try.pop_back();
838 
839  // Log the result ( ".","F" or, "E")
840  std::cout << m_tests.back()->print();
841 
842  //Return
843  return;
844 }
845 
846 
847 /***********************************************************************//**
848  * @brief Notice when a try block failed
849  *
850  * @param[in] e Exception.
851  *
852  * @exception GException::test_nested_try_error
853  * Test case index is out of range.
854  *
855  * @see test_try_sucess()
856  * @see test_try(const std::string& name)
857  * @see test_try_failure(const std::string& message, const std::string& type)
858  *
859  * Call this method in a catch block.
860  *
861  * Example:
862  * test_try("Test a try block");
863  * try {
864  * ... //someting to test
865  * test_try_success();
866  * }
867  * catch(exception& e) {
868  * test_try_failure(e);
869  * }
870  ***************************************************************************/
871 void GTestSuite::test_try_failure(const std::exception& e)
872 {
873  // Extract message of exception and class name
874  test_try_failure(e.what(), typeid(e).name());
875 
876  // Return
877  return;
878 }
879 
880 
881 /***********************************************************************//**
882  * @brief Return a failure exception
883  *
884  * @param[in] message Message.
885  *
886  * @see test_try()
887  * @see test_error(const std::string& message)
888  *
889  * It can be use in a try test
890  *
891  * Example:
892  * test_try("Test a try block");
893  * try {
894  * throw exception_failure("a failure");
895  * test_try_success();
896  * }
897  * catch(exception& e) {
898  * test_try_failure(e);
899  * }
900  ***************************************************************************/
902 {
903  // Return exception
904  return *(new GException::test_failure(m_stack_try.back()->name(), message));
905 }
906 
907 
908 /***********************************************************************//**
909  * @brief Return an error exception
910  *
911  * @param[in] message Message.
912  *
913  * @see test_try()
914  * @see test_failure(const std::string& message)
915  *
916  * It can be use in a try test
917  *
918  * Example:
919  * test_try("Test a try block");
920  * try {
921  * throw exception_error("an error");
922  * test_try_success();
923  * }
924  * catch(exception& e) {
925  * test_try_failure(e);
926  * }
927  ***************************************************************************/
929 {
930  // Return exception
931  return *(new GException::test_error(m_stack_try.back()->name(),message));
932 }
933 
934 
935 /***********************************************************************//**
936  * @brief Return the number of successful tests
937  ***************************************************************************/
938 int GTestSuite::success(void) const
939 {
940  // Return successes
941  return size()-(m_errors+m_failures);
942 }
943 
944 
945 /***********************************************************************//**
946  * @brief Return the total duration of all tests
947  *
948  * This method sums up all test durations and returns the result.
949  ***************************************************************************/
950 double GTestSuite::duration(void) const
951 {
952  // Initialise duration
953  double duration = 0.0;
954 
955  // Add up the durations of all tests
956  for (int i = 0; i < m_tests.size(); ++i) {
957  duration += m_tests[i]->duration();
958  }
959 
960  // Return duration
961  return duration;
962 }
963 
964 
965 /***********************************************************************//**
966  * @brief Print test suite information
967  *
968  * @param[in] chatter Chattiness (defaults to NORMAL).
969  * @return String containing test suite information.
970  ***************************************************************************/
971 std::string GTestSuite::print(const GChatter& chatter) const
972 {
973  // Initialise result string
974  std::string result;
975 
976  // Continue only if chatter is not silent
977  if (chatter != SILENT) {
978 
979  // Append header
980  result.append("=== GTestSuite ===");
981 
982  // Append information
983  result.append("\n"+gammalib::parformat("Name")+m_name);
984  result.append("\n"+gammalib::parformat("Number of functions"));
985  result.append(gammalib::str(m_names.size()));
986  result.append("\n"+gammalib::parformat("Number of executed tests"));
987  result.append(gammalib::str(size()));
988  result.append("\n"+gammalib::parformat("Number of errors"));
989  result.append(gammalib::str(errors()));
990  result.append("\n"+gammalib::parformat("Number of failures"));
991  result.append(gammalib::str(failures()));
992 
993  } // endif: chatter was not silent
994 
995  // Return result
996  return result;
997 }
998 
999 
1000 /*==========================================================================
1001  = =
1002  = Private methods =
1003  = =
1004  ==========================================================================*/
1005 
1006 /***********************************************************************//**
1007  * @brief Initialise class members
1008  ***************************************************************************/
1010 {
1011  // Initialise members
1012  m_name = "Unnamed Test Suite";
1013  m_names.clear();
1014  m_functions.clear();
1015  m_tests.clear();
1016  m_stack_try.clear();
1017  m_index = 0;
1018  m_failures = 0;
1019  m_errors = 0;
1020  m_log.clear();
1021  m_timestamp = time(NULL);
1022 
1023  // Set logger parameters
1024  cout(true);
1025  m_log.buffer_size(1);
1026 
1027  // Return
1028  return;
1029 }
1030 
1031 /***********************************************************************//**
1032  * @brief Copy class members
1033  *
1034  * @param[in] suite Test suite.
1035  *
1036  * This method just clone the container not the test case.
1037  ***************************************************************************/
1039 {
1040  // Copy members
1041  m_name = suite.m_name;
1042  m_names = suite.m_names;
1043  m_functions = suite.m_functions;
1044  m_index = suite.m_index;
1045  m_failures = suite.m_failures;
1046  m_errors = suite.m_errors;
1047  m_log = suite.m_log;
1048  m_timestamp = suite.m_timestamp;
1049 
1050  // Clone test cases
1051  for (int i = 0; i < suite.m_tests.size(); ++i) {
1052  m_tests[i] = suite.m_tests[i]->clone();
1053  }
1054 
1055  // Clone try stack
1056  for (int i = 0; i < suite.m_stack_try.size(); ++i) {
1057  m_stack_try[i] = suite.m_stack_try[i]->clone();
1058  }
1059 
1060  // Return
1061  return;
1062 }
1063 
1064 
1065 /***********************************************************************//**
1066  * @brief Delete class members
1067  ***************************************************************************/
1069 {
1070  // Delete test cases
1071  for (int i = 0; i < m_tests.size(); ++i) {
1072  delete m_tests[i];
1073  m_tests[i] = NULL;
1074  }
1075 
1076  // Delete try stack
1077  for (int i = 0; i < m_stack_try.size(); ++i) {
1078  delete m_stack_try[i];
1079  m_stack_try[i] = NULL;
1080  }
1081 
1082  // Close logger
1083  m_log.close();
1084 
1085  // Return
1086  return;
1087 }
1088 
1089 
1090 /***********************************************************************//**
1091  * @brief Format Name
1092  *
1093  * Return a string with the format
1094  * "TestFunctionName:TestTryname1:TestTryName2: name"
1095  ***************************************************************************/
1096 std::string GTestSuite::format_name(const std::string& name)
1097 {
1098  // Initialise format name
1099  std::string format_name;
1100 
1101  // Set name of the try blocks
1102  if (!m_stack_try.empty()) {
1103  format_name = m_stack_try.back()->name();
1104  }
1105  else {
1106  // Set name of the test
1107  format_name = m_names[m_index];
1108  }
1109 
1110  // Append test suite name
1111  format_name += ": " + name;
1112 
1113  // Return format
1114  return format_name;
1115 }
std::string print(const GChatter &chatter=NORMAL) const
Print test suite information.
Definition: GTestSuite.cpp:971
void append(pfunction function, const std::string &name)
Append test functions to test suite.
Definition: GTestSuite.cpp:234
void test_assert(const bool &result, const std::string &name, const std::string &message="")
Test an assert.
Definition: GTestSuite.cpp:368
const int & errors(void) const
Return the number of errors.
Definition: GTestSuite.hpp:198
int success(void) const
Return the number of successful tests.
Definition: GTestSuite.cpp:938
int m_index
Index of actual test function.
Definition: GTestSuite.hpp:136
GVector abs(const GVector &vector)
Computes absolute of vector elements.
Definition: GVector.cpp:1163
Test class.
Definition: GTestCase.hpp:47
void cout(const bool &flag)
Enables/disables logging into standard output stream.
Definition: GTestSuite.hpp:185
void buffer_size(const int &size)
Set the buffer size.
Definition: GLog.hpp:328
double duration(void) const
Return the total duration of all tests.
Definition: GTestSuite.cpp:950
Gammalib tools definition.
#define G_TRY_SUCCESS
Definition: GTestSuite.cpp:47
void init_members(void)
Initialise class members.
void test_value(const int &value, const int &expected, const std::string &name="", const std::string &message="")
Test an integer value.
Definition: GTestSuite.cpp:406
virtual ~GTestSuite(void)
Destructor.
Definition: GTestSuite.cpp:117
GException::test_error & exception_error(const std::string &message)
Return an error exception.
Definition: GTestSuite.cpp:928
const double & duration(void) const
Return test case duration.
Definition: GTestCase.hpp:250
Abstract test suite base class definition.
void test_try(const std::string &name)
Test an try block.
Definition: GTestSuite.cpp:727
void test_try_success(void)
Notice when a try block succeeded.
Definition: GTestSuite.cpp:762
std::vector< pfunction > m_functions
Test functions of this suite.
Definition: GTestSuite.hpp:133
void free_members(void)
Delete class members.
int m_errors
Number of errors.
Definition: GTestSuite.hpp:138
GTestSuite & operator=(const GTestSuite &testsuite)
Assignment operator.
Definition: GTestSuite.cpp:139
std::string format_name(const std::string &name)
Format Name.
GTestCase & operator[](const int &index)
Returns reference to test case.
Definition: GTestSuite.cpp:168
void copy_members(const GTestSuite &testsuite)
Copy class members.
std::vector< std::string > m_names
Names of test functions.
Definition: GTestSuite.hpp:132
void close(void)
Close log file.
Definition: GLog.cpp:538
bool run(void)
Run all tests in test suite.
Definition: GTestSuite.cpp:253
GChatter
Definition: GTypemaps.hpp:33
Abstract test suite class for unit testing on GammaLib fixtures.
Definition: GTestSuite.hpp:53
time_t m_timestamp
Timestamp.
Definition: GTestSuite.hpp:140
const std::string & name(void) const
Return test suite name.
Definition: GTestSuite.hpp:158
int size(void) const
Return number of tests in test suite.
Definition: GTestSuite.hpp:148
#define G_OP_ACCESS
Definition: GTestSuite.cpp:46
const std::string & message(void) const
Return test case message.
Definition: GTestCase.hpp:142
GException::test_failure & exception_failure(const std::string &message)
Return a failure exception.
Definition: GTestSuite.cpp:901
int m_failures
Number of failures.
Definition: GTestSuite.hpp:137
const std::string & type(void) const
Return test case type.
Definition: GTestCase.hpp:167
void(GTestSuite::* pfunction)(void)
Definition: GTestSuite.hpp:34
Information logger class definition.
virtual void set(void)=0
GTestSuite(void)
Void constructor.
Definition: GTestSuite.cpp:68
const bool & has_passed(void) const
Return whether the test passed.
Definition: GTestCase.hpp:225
GLog m_log
Log.
Definition: GTestSuite.hpp:139
const int & failures(void) const
Return the number of failures.
Definition: GTestSuite.hpp:210
std::string m_name
Name of the test suite.
Definition: GTestSuite.hpp:131
std::vector< GTestCase * > m_stack_try
Stack for nested try blocks.
Definition: GTestSuite.hpp:135
void clear(void)
Clear test suite.
Definition: GTestSuite.cpp:212
std::vector< GTestCase * > m_tests
List of test results.
Definition: GTestSuite.hpp:134
std::string parformat(const std::string &s, const int &indent=0)
Convert string in parameter format.
Definition: GTools.cpp:1022
std::string print(const GChatter &chatter=NORMAL) const
Print test case result.
Definition: GTestCase.cpp:189
void test_try_failure(const std::string &message="", const std::string &type="")
Notice when a try block failed.
Definition: GTestSuite.cpp:809
void clear(void)
Clear object.
Definition: GLog.cpp:456
std::string str(const unsigned short int &value)
Convert unsigned short integer value into string.
Definition: GTools.cpp:413