diff --git a/ChangeLog.md b/ChangeLog.md index 5db65559..ca8db7be 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -15,6 +15,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Multi-line continuation support for pFUnit macros (issue #532) - Assertion macros (e.g., `@assertEqual`) now support Fortran `&` line continuation - Whitespace is preserved exactly as written when joining continued lines +- Fix documentation generation with Doxygen. + - Split single documentation file into pages for easier management. + - Add documentation missing for assertions. + - Added a failure message to the assertEqual test. ## [4.16.0] - 2026-02-23 diff --git a/bin/funit/tests/test_parser_assertions.py b/bin/funit/tests/test_parser_assertions.py index b790aa8c..5970854a 100644 --- a/bin/funit/tests/test_parser_assertions.py +++ b/bin/funit/tests/test_parser_assertions.py @@ -27,12 +27,13 @@ def testMatchAtAssertEqual(self): self.assertTrue(atAssert.match("@assertEqual(a, b)")) self.assertTrue(atAssert.match("@assertequal(a, b)")) # case insensitive self.assertTrue(atAssert.match("@ASSERTEQUAL(a, b)")) # case insensitive + self.assertTrue(atAssert.match("@assertEqual(a, b, \"failure message\")")) parser.fileName = "foo.pfunit" parser.currentLineNumber = 8 - atAssert.apply(" @assertEqual(1, 2)\n") + atAssert.apply(" @assertEqual(1, 2, \"failure message\")\n") self.assertEqual('#line 8 "foo.pfunit"\n', parser.outLines[0]) - self.assertEqual(" call assertEqual(1, 2, &\n", parser.outLines[1]) + self.assertEqual(" call assertEqual(1, 2, \"failure message\", &\n", parser.outLines[1]) self.assertEqual(" & location=SourceLocation( &\n", parser.outLines[2]) self.assertEqual(" & 'foo.pfunit', &\n", parser.outLines[3]) self.assertEqual(" & 8)", parser.outLines[4]) diff --git a/documentation/.gitignore b/documentation/.gitignore index 4f925685..5c75d14d 100644 --- a/documentation/.gitignore +++ b/documentation/.gitignore @@ -1,2 +1,3 @@ /.DS_Store -/*.el \ No newline at end of file +/*.el +documentation diff --git a/documentation/CMakeLists.txt b/documentation/CMakeLists.txt index 2b04bda2..6370fe91 100644 --- a/documentation/CMakeLists.txt +++ b/documentation/CMakeLists.txt @@ -209,7 +209,7 @@ if (${DOXYGEN_FOUND}) endif () if (ENABLE_BUILD_DOXYGEN) -doxygen_add_docs(docs-internal +doxygen_add_docs(documentation "${CMAKE_SOURCE_DIR}/bin" "${CMAKE_SOURCE_DIR}/documentation" "${CMAKE_SOURCE_DIR}/Examples" @@ -217,5 +217,6 @@ doxygen_add_docs(docs-internal "${CMAKE_SOURCE_DIR}/include" "${CMAKE_SOURCE_DIR}/tests" COMMENT "Generate pFUnit Fortran documentation" + CONFIG_FILE "${CMAKE_SOURCE_DIR}/documentation/doxygen.conf" ) endif() diff --git a/documentation/documentation.dox b/documentation/documentation.dox deleted file mode 100644 index 61060bd7..00000000 --- a/documentation/documentation.dox +++ /dev/null @@ -1,1048 +0,0 @@ - -/*! - -\page page_ObtainingPFUNIT Obtaining pFUnit - -The best way to obtain pFUnit is to clone -pFUnit from the git repository from SourceForge as follows. - -\code -# Read Only Access -git clone git@github.com:Goddard-Fortran-Ecosystem/pFUnit.git pFUnit\endcode - -This will create the directory pFUnit in the current working -directory. - -You may also visit the project page at SourceForge and -download the source tarfile "pFUnit.tar.gz" there. - -https://github.com/Goddard-Fortran-Ecosystem/pFUnit -or -https://github.com/Goddard-Fortran-Ecosystem/pFUnit/releases - -Extracting this tarfile via a command like - -`$ tar zxf ./pFUnit-4.2.2.tar.gz` - -will place the pFUnit files into the current working directory. - -For other ways to acquire the code visit - -https://github.com/Goddard-Fortran-Ecosystem/pFUnit - -or contact the pFUnit team. - -\page page_Installation Installation - -\section sec_InstallingPFUNIT Installing pFUnit - -Comentatry for the page. - -\li \ref sec_Prerequisites -\li \ref sec_ObtainingPFUNIT -\li \ref sec_Manifest -\li \ref sec_Configuration -\li \ref sec_Building - -\li \ref sec_Installation - -\section sec_Prerequisites Prerequisites - -The development work for pFUnit has mostly been carried out on a -mixture of systems, including high-end computers, Apple Mac OSX, and -linux-based systems. A preliminary Windows/CYGWIN port has been -contributed by a user. Full use of the system depends on the following -being available. - -- Fortran 2003+ (Tested with Intel 14+, NAG 6.0, GCC 4.9.+, IBM's XLF, PGI 15.4) -- The Message Passing Interface (MPI) -- OpenMP -- GNU Make -- Python - -Note: Recent changes have exposed a latent bug in GCC 4.8.2. The fix -is available in the GCC 4.9 development branch and will also appear in -GCC 4.8.3 when that is released. Users that require older versions of -GCC should use pFUnit 2.1.x. - -Doxygen is used to generate documentation. - -The system routinely undergoes regression testing with GNU, Intel, and NAG fortran -compilers and OpenMPI. - -\section sec_ObtainingPFUNIT Obtaining pFUnit - -The best way to obtain pFUnit is to clone -pFUnit from the git repository from SourceForge as follows. - -\code -# Read Only Access -git clone git://git.code.sf.net/p/pfunit/code pFUnit\endcode - -This will create the directory pFUnit in the current working -directory. - -You may also visit the project page at SourceForge and -download the source tarfile "pFUnit.tar.gz" there. - -http://sourceforge.net/projects/pfunit/ -or -http://sourceforge.net/projects/pfunit/files/latest/download - -Extracting this tarfile via a command like - -`$ tar zxf ./pFUnit.tar.gz` - -will place the pFUnit files into the current working directory. - -For other ways to acquire the code visit - -https://sourceforge.net/p/pfunit/code/ci/master/tree/ - -or contact the pFUnit team. - -\section sec_Manifest Manifest - What's in the directory? - -In the top level of the pFUnit distribution you will see the following -files. - -CMakeLists.txt - Initial support for cmake-based builds. - -COPYRIGHT - Contains information pertaining to the use and -distribution of pFUnit. - -Examples - Contains examples of how to use pFUnit once it is -installed. - -GNUmakefile - The top level makefile for building and installing -pFUnit. - -LICENSE - The NASA Open Source Agreement for GSC-15,137-1 F-UNIT, also -known as pFUnit. - -README-INSTALL - Basic documentation on pFUnit installation and use. - -bin - Executables used to construct and perform unit tests. - -include - Files to be included into makefiles or source, including use -code. - -source - Source code and scripts of the pFUnit library and framework. - -tests - Source code for unit testing pFUnit itself. - -tools - Tools used to help develop, build, and install pFUnit. - -VERSION - Contains a string describing the current version of the framework. - -\section sec_Configuration Configuration -Little needs to be done to configure pFUnit for the build, however -there are several environment variables on which the package depends. - -`F90_VENDOR` - is set to include the correct makefile in $(TOP_DIR)/include, -i.e. GNU, Intel, NAG, or PGI. Case insensitive file systems may cause -some confusion from time-to-time. - -`F90` - is set to the Fortran compiler being used: e.g. ifort for Intel, -gfortran for GNU. - -`COMPILER` - is set according to `F90_VENDOR` and is automatically set in -the top level makefile. - -For MPI-based unit testing, your setup may require the following as well. - -`MPIF90`\code -$ export MPIF90=mpif90\endcode - -As a convenience for working with multiple MPI configurations, you may -also set the following. - -`MPIRUN`\code -$ export MPIRUN=/some.path/mpirun\endcode - -PFUNIT_MAX_ARRAY_RANK - -`PFUNIT_MAX_ARRAY_RANK` - controls the maximum size of the arrays asserts are -defined over. If PFUNIT_MAX_ARRAY_RANK is not set, the default is 5 and pFUnit's assertions will be able to handle arrays up to rank 5, i.e. A(:,:,:,:,:). PFUNIT_MAX_ARRAY_RANK and MAX_RANK do not refer to MPI ranks (process id within a group). Example:\code -$ export PFUNIT_MAX_ARRAY_RANK=5\endcode - -`PFUNIT_MAX_RANK` is a deprecated way to set maximum rank and is to be removed in version 4. - - -`DOXYGEN` - To generate documentation, set DOXYGEN to the desired -executable. NOTE: Doxygen Version 1.8.5 does not respect CamelCase -names from Fortran source code by currently converting all to -lowercase. It does this to get HTML links correct for references in -the source code that also do not respect the CamelCase convention. -The Fortran standard specifies case insensitivity. Doxygen 1.7.x -seems to better respect CamelCase. -\code -$ export DOXYGEN=/opt/local/share/doxygen/doxygen-1.7.6/bin/doxygen\endcode - -\section sec_Building Building pFUnit -\subsection sec_BuildingPFUNITSerial Building pFUnit for testing serial codes (Non-MPI) - -1. Change to the directory into which pFUnit has been placed. -2. Set the environment variables (for example in bash): -\code -$ export F90=gfortran-mp-4.8 -$ export F90_VENDOR=GNU\endcode -3. To build pFUnit for unit testing of serial codes, execute make. -The unit tests for pFUnit itself will run automatically. -\code -$ make tests\endcode -3.1 Occasionally on the first run through, one will get a spurious -(runtime) error, for example in the unix process component. -\code -Re-execute "make tests" to check again.\endcode -4. At this point the pFUnit object library is in the source directory, -along with a large number of Fortran module files. - -\subsection sec_BuildingPFUNITMPI Building pFUnit for testing parallel codes (MPI) - -To build pFUnit for unit testing MPI-based codes, be sure that the -environment is properly set up for the MPI implementation you are -using. Depending on your local environment, you may need execute the -build within a batch or other job queing system, e.g. an interactive -batch job under PBS. The steps for building pFUnit start out the same -as for the serial case above, but add MPI=YES to the environment to -switch on MPI support. The MPI-based unit tests for pFUnit itself -will run automatically. Again, occasionally a spurious (runtime) -error may appear on the first execution. - -3. Execute make as follows. -\code -$ make tests MPI=YES \endcode - -4. At this point an MPI-enabled pFUnit object library is in the source -directory, along with a large number of Fortran module files. - -Also, one may get some harmless "no symbols" warnings when the pFUnit library is constructed. - -\subsection sec_BuildingPFUNITOPENMP OPENMP - -Initial (limited) support for OPENMP has been implemented. At this -writing, a basic functionality is available. - -The process for building pFUnit for testing OPENMP-based codes is -similar to that for other paradigms. - -3. To compile for OPENMP support execute make as follows. -\code -$ make tests OPENMP=YES\endcode - -4. At this point the OPENMP-enabled pFUnit is ready to be installed. - -\subsection sec_BuildingPFUNITCleaning Cleaning - -To clean the pFUnit build directory for the space or to rebuild there -are two options. - -1. Make clean to remove object files and other intermediate products. -\code -$ make clean\endcode - -2. Make distclean to remove libraries and other more final products. -\code -$ make distclean\endcode - -3. Some directories support a `make src_clean` to remove intermediate -products in subdirectories. - -\subsection sec_BuildingPFUNITDocumentation Documentation - -A start at documentation for pFUnit is in the documentation directory. -Doxygen is our primary -documentation tool. To make the documentation, which will be -generated in the documentation directory, please invoke the following -from the top level of your pFUnit distribution. - -\code -$ make documentation\endcode - -Or to make a reference manual. - -\code -$ make documentation/pFUnit2-ReferenceManual.pdf\endcode - -To select a specific version of Doxygen, please set the DOXYGEN -environment variable as in \ref sec_Configuration. You may wish to do -this if your code uses CamelCase names as current versions of Doxygen -(1.8.5) do not respect this convention for Fortran. - -\subsection sec_BuildingPFUNITCMAKE CMAKE - -Initial support for CMAKE has been implemented. At this -writing, a basic functionality is available. - -3. The process for building pFUnit using cmake is as follows. In the -top directory of the distribution make a new directory to support the -build, then change to that directory and run cmake (pointing back to -the source) to generate the required makefiles. -\code -$ mkdir build -$ cd build -$ # e.g. cmake -DMPI=YES -DOPENMP=NO -DINSTALL_PATH= -$ cmake -DMPI=NO .. -$ make tests\endcode - -One may also set the environment variable PFUNIT instead of setting -INSTALL_PATH on the cmake command line as given above. - -If your MPI installation does not provide mpirun, you may try to set --DMPI_USE_MPIEXEC=YES to tell CMake to use its FindMPI function to -find out how to execute the tests. - -4. If the build is successful, then at this point make install should work. - -\section sec_Installation Installation -\subsection sec_InstallationSerial Installation - Serial - -To install pFUnit for regular use, set INSTALL_DIR to the location in -which to place pFUnit. This can be done on the make command line. -For example, after compiling pFUnit for serial use (MPI absent or -MPI=NO), please try. -\code -$ # In the top of the pFUnit build directory. -$ make install INSTALL_DIR=/opt/pfunit/pfunit-serial\endcode - -Note: you may need special priveleges to install in some locations, -e.g. via sudo. - -To test the installation set PFUNIT to INSTALL_DIR, then change the -working directory to Examples in pFUnit distribution and execute -"make," which will run a number of examples. These include some -expected (intentional) failures. -\code -$ # In the top pFUnit build directory... -$ export PFUNIT=/opt/pfunit/pfunit-serial -$ cd Examples -$ make\endcode - -\subsection sec_InstallationMPI Installation - MPI - -For installing an MPI-enabled pFUnit library, change to the top of the -distribution and execute make with MPI=YES. You may need to "make -distclean" first. After compilation and pFUnit passes its self-tests, -then installation proceeds as for the serial case above. -\code -$ make install INSTALL_DIR=/opt/pfunit/pfunit-parallel\endcode - -To test, set PFUNIT and go into Examples/MPI_Halo directory. -\code -$ # In the top pFUnit build directory... -$ export PFUNIT=/opt/pfunit/pfunit-parallel -$ # The variable MPIF90 must be set to the appropriate build script. -$ export MPIF90=mpif90 -$ cd Examples/MPI_Halo -$ make\endcode - -This will compile and run a set of parallel examples that includes -intentional failures. To run all of the examples try executing -"make MPI=YES" in the Examples directory. - -\subsection sec_InstallationOPENMP Installation - OPENMP - -At this time the OPENMP version of pFUnit can be installed in the same -way as for the serial or MPI-parallel codes. OPENMP support, tests, -and examples are limited as of this writing. - -\subsection sec_InstallationDefaultDirectory Installation - DEFAULT DIRECTORY - -If INSTALL_DIR is not set, "make install" will attempt to install -pFUnit into the top build directory. This will create directories -such as lib and mod in the top level of the build directory and will -overwrite the include/base.mk with include/base-install.mk. If this -is not desired, then "make develop" will put back the original -base.mk, which is the file to be used for development and building -pFUnit. In general, we recommend installing to a directory that is not also the -build directory. - - - -\page page_Usage Usage - -\li \ref sec_UsageConfiguration -\li \ref sec_UsageHelloWorld -\li \ref sec_UsagePreprocessor -\li \ref sec_UsageExecutingTheTest - -\section Usage -\subsection sec_UsageConfiguration Usage - Configuration - -For regular use, after installation, the same compiler/MPI development -configuration that was used to build pFUnit should be used. Once the -environment variables and paths associated with the environment are -set, to configure pFUnit, please set the following. - -`PFUNIT` - set to the directory into which pFUnit was installed. - -`F90_VENDOR` - set to Intel, GNU, NAG, or PGI accordingly. - -\subsection sec_UsageHelloWorld Usage - Hello World - -For an example of a simple usage of pFUnit, see Examples/Simple/tests. - -The simplest way to write a test is to write a preprocessor input file (extension ".pf"), which is a Fortran free format file with preprocessor directives added. An example from "helloWorld.pf" follows. -\code -! from helloWorld.pf -@test -subroutine testHelloWorld() - use pfunit_mod - implicit none - @assertEqual("Hello World!","Hello World!") -end subroutine testHelloWorld\endcode -One then instructs the preprocessor to construct a suite to execute these tests via the "testSuites.inc" file as follows. -\code -! from testSuites.inc -ADD_TEST_SUITE(helloWorld_suite)\endcode - -At this point, one can invoke the preprocessor to generate a Fortran file that when compiled and linked with pFUnit will execute the tests. For more information please see \ref page_funitproc or try out the examples in Example/Simple. - -\section sec_UsagePreprocessor Usage - Preprocessor -Please see \ref page_funitproc. - -\section sec_UsageExecutingTheTest Compiling and Executing The Test - -An example of a GNU make rule for for the final step of compiling a test follows. - -\code -# This step presumes "include $(PFUNIT)/include/base.mk" earlier in the makefile. -tests.x: testSuites.inc myTests.pf - $(F90) -o $@ -I$(PFUNIT)/mod -I$(PFUNIT)/include \ - $(PFUNIT)/include/driver.F90 \ - ./*$(OBJ_EXT) $(LIBS) $(FFLAGS)\endcode - -To execute the tests, one invokes "./tests.x" with the appropriate command line options (see below). - -In some cases, since include/driver.F90 is "implicit none," it may be -necessary to insert a "use" clause to identify external suite-wide -fixture code to the compiler. As a convenience, the CPP macro -PFUNIT_EXTRA_USAGE can be set to a module of fixture code via a -compiler command line argument turning on a "use PFUNIT_EXTRA_USAGE" -line at the beginning of include/driver.F90. - -\subsection ss_UsageExecutingTheTestParallel - Compiling and Executing the Tests (MPI PARALLEL) - -One invokes MPI-based parallel tests according to the MPI framework being used. For example: - -\code -$ mpirun -np 4 tests.x\endcode - - -\subsection ss_CommandLineOptions Command Line Options - -The executable test program provides several command line options, -when "include/driver.F90" is used, as it is automatically when using -the PFUNIT preprocessor. - - - - - - - - - - - -
-v or -verbose Verbose execution.
-d or -debug Provide debugging information.
-h Print help message.
-o \ Direct pFUnit messages to a file. -
-robust Use the robust runner. Runs tests as processes so failures do not halt testing.
-max-timeout-duration Limit detection time for robust runner.
-max-launch-duration Limit detection time for robust runner.
-skip \Use the subset runner, which runs a subset of the tests in a suite.
-xml \Generate XML output in JUnit -compatible format, write it to given file. This XML output can be used -in integration with e.g. Jenkins. To ensure the XML file is written -correctly, it is recommended to also use the -robust flag.
-name \Give the set of tests an identifying -name, which is used in the XML output.
- -An example from Examples/Robust: - -\code -$ ./tests.x -robust\endcode - -\subsection ss_XML XML output - -To output JUnit XML, execute tests with the -xml flag: -\code -$ ./tests.x -robust -xml test.xml -name my_suite_name\endcode - -This creates a file named test.xml. As an example, the output may look like this: - -\code - - - - - - - - - -\endcode - -Output explained: The test suite took 2.1020 seconds to execute. One -test (test_addition) succeeded, one (test_division) crashed for some -reason, and one test (test_foo) failed at line 24 of test_other.pf. - -\page page_Development Development - -Generally pFUnit development is performed in the build directory -structure. Care should be taken to make clean or distclean in between -configuration changes. As stated in \ref sec_Installation, it is best -to set INSTALL_DIR and "make install" pFUnit to another directory that -can be placed in a -user's paths. - - -\page page_FeedbackAndSupport Feedback & Support - -\li \ref sec_Feedback \li \ref sec_Support - -\section sec_Feedback Feedback - -Feedback is welcome, please use the facilities at
oddard-Fortran-Ecosystem/pFUnit/issues to share your views. - -Open a issue for bugs, features, and patch recommendations. - -If you use pFUnit, please let us know by leaving a note in our Applications of pFUnit forum, or email Tom Clune, Ph.D., NASA Goddard Space Flight Center. Letting us know about your application helps us seek support for pFUnit's continued development and improvement. - -\section sec_Support Support - -Please open a issue for bugs, features, and patch recommendations. For longer term needs or considerations, please visit our discussion forums or contact Tom Clune, Ph.D., NASA Goddard Space Flight Center. - -You may also find some help at \ref page_FAQAndTips. - -pFUnit supports the software development of several weather and climate simulations efforts. We constantly seek to improve and correct pFUnit for our users' benefit, granting priority to the needs of our major users. Please share with us information about your application on our Applications of pFUnit forum. - - - -\page page_FAQAndTips FAQ and Tips - - - -\section sec_FAQ FAQ - -\subsection ZeroTestsRun Zero Tests Run -

Symptom: The system under test compiles and runs fine, but reports zero tests run.

-

Solutions: -

-\subsection SomeOfMyTestsAreNotRunning Some Tests Are Not Running -Symptom: The system under test compiles and runs fine, but reports that some tests don't run. -

Solutions: -

- -\subsection FAQIntel13 Intel Fortran Version 13: -DINTEL_13 - -Using version 13 is deprecated. We have encountered problems using -version 13, which we believe may be due to subtle compiler bugs. We -strongly recommend upgrading to the latest version possible. - -To make pFUnit work with Intel Fortran Version 13, please ensure that --DINTEL_13 is passed to the compiler when building or -using pFUnit. In the build process for pFUnit, this is added to the -make variables CPPFLAGS and FPPFLAGS. - -\subsection FAQSegAndLinkFaults Segmentation Faults and Odd Link Errors - -Q. pFUnit fails to build or now leads to segmentation faults. Did something change? - -A. One cause for failure to build or odd runtime segmentation faults is when we change compiler configurations and some object or library files are left over from a previous environment. This might be hard to spot, for example, during compiler upgrades. Switching from one compiler to another, e.g. from Intel to GNU, is more likely to generate link-time errors if old code is still around. A few items to check follow. - - - -Finally, it is quite possible that a bug has been uncovered. Please contact the development team or open a bug ticket. - - -\section sec_Tips Tips - -\subsection TipEnvironmentModules Environment Modules -Though not strictly required, the Environment -Modules package can be a convenient way to package, maintain, and -switch between environments. This can be particularly important for -pFUnit, which must be built using the same tool suite being used for -development, e.g. compilers, linkers, etc. [To do: A sample pFUnit -modulefile is provided in the OTHER directory.] - -\subsection TipCompileTimeErrors Compile Time Errors -Compile time errors like '"include [...]include/.mk" not found' -likely signify that you are not executing make in the top level -directory during a build. Alternatively, during regular usage after -installation, PFUNIT has not been set. - -During building, if you wish to compile in a subdirectory within the -pFUnit heriarchy, please try setting the COMPILER environment variable -on the make command line. For example: - -\code -$ make all COMPILER=Intel\endcode - -\subsection TipIntermediateFiles Intermediate files used by pFUnit -If you wish to see the intermediate files, use the target .PRECIOUS -in the makefile to keep them from being deleted. For example: - -\code -# In GNUmakefile -.PRECIOUS: %_cpp.F90\endcode - -\subsection TipWhitespace Ignoring whitespace differences in assertions on strings. -Several options exist for how to compare strings with assertEqual. - -\code -call assertEqual(expectedString, foundString, & - & whitespace=IGNORE_DIFFERENCES )\endcode - -WhitespaceOptions: - - -Example usages can be seen in tests/Test_AssertBasic.F90 or -Examples/Simple/tests/helloWorld.pf. - - -\page page_PlatformSpecific Platform Specific Notes - -\section sec_MacOSX Mac OSX - -The MacPorts package management system is a convenient way to install -and maintain many packages, including gcc which includes gfortran. - -\section sec_WindowsCYGWIN Windows/CYGWIN - -User contributed code for Windows/CYGWIN has been added, but is -currently not tested and supported by the pFUnit team. At this -writing, 2013-1031, serial Examples and MPI are not known to be -supported. Please contact us if you wish to either contribute or -otherwise discuss this port. - -\section sec_Intel13 Intel Fortran Version 13: -DINTEL_13 -To make pFUnit work with Intel Fortran Version 13, please ensure that --DINTEL_13 is passed to the compiler when building or -using pFUnit. In the build process for pFUnit, this is added to the -make variables CPPFLAGS and FPPFLAGS. - - -\page page_Acknowledgments Acknowledgments - - -Thanks to the follwing for their review and comments: B. Van Aartsen, T. Clune. - -Windows/CYGWIN contributions from E. Lezar. - -PGI port contributions from M. Leair (PG Group). - -Other acknowledgments: S.P. Santos (NCAR), M. Hambley (UK Met Office)., J. Krishna (ANL). - -The design of pFUnit is strongly influenced by JUnit. - -Initial pFUnit 2 documentation by Michael Rilee (Rilee Systems Technologies). - - -\page page_KnownInstallationsAndVersions Known Installations & Versions - -master - The current release. - -development - The cutting edge of pFUnit development. - -mock_services - Experimental support for mocking. - -pfunit_2.1.0 - A feature freeze prior to a major upgrade of the preprocessor. - -\page page_TODO TODO - -- Make other directory. -- Make Environment Modules example in other directory. - -\page page_funitproc The Preprocessor - funitproc - -Overview of Preprocessor (funitproc) - - - -/////////////////////////////////////////////////////////////////////// -\section sec_UsingThePreprocessor Using The Preprocessor - -How to write tests using the ".pf" files. We expect this to be the -main way people write pFUnit-based tests. Please see the Examples -directory for a wide range of examples. The .pf files themselves are -generally to be found in an example's "tests" subdirectory. - -\subsection ss_Configuration Configuration - testSuites.inc - -The include file "testSuites.inc" tells the preprocessor to generate -code for TestSuites listed therein. The suite names are based on the -TestCases provided in the preprocessor input file or the name of the -preprocessor input file (.pf) itself. For example, if no module is defined -in a .pf file, i.e. the preprocessor will define the module, one -can set up a "testSuites.inc" as follows. -\code -! To load "exampleTestsNoModule.pf". -ADD_TEST_SUITE(exampleTestsNoModule_suite)\endcode -For a .pf file that contains a module associated with a test suite the -syntax is as follows. -\code -! To load "exampleTests.pf" implementing the module exampleTests_mod. -ADD_TEST_SUITE(exampleTests_mod_suite)\endcode - -\subsection ss_Invocation Invocation - -To run the preprocessor on on a preprocessor input file "exampleTests.pf", invoke: -\code -$ ${PFUNIT}/bin/funitproc exampleTests.pf exampleTests.F90 \endcode -A convenient GNUmakefile rule is as follows. -\code -%.F90: %.pf - $(PFUNIT)/bin/funitproc $< $@ \endcode - -\subsection ss_PreprocessorInput Preprocessor Input File (.pf) - -The preprocessor input file is a Fortran free format file that -contains subroutines, including those implementing the suite of tests, -or a module with the tests, TestCases, and support for parameters. -The preprocessor reads and parses this file producing a fortran file -implementing the tests, automating some boilerplate code. Embedded -"@" directives inform the preprocessor about information needed to -generate the test suite. If the .pf file does not implement a module -providing a test suite, the preprocessor will use the name of .pf file -referred to by "testSuites.inc". Currently only one test suite per -.pf file is allowed, a limitation of the current implementation of the -parser. - -Many example .pf files may be found in the examples' -"tests" subdirectories in the Examples directory. - -Below we present the most commonly used directives first, but in a .pf -file using all of these capabilities, the most common order is as -follows. - - - -\subsection ss_Directives Directives - -Preprocessor "@" directives, which in keeping with Fortran style are -not case sensitive, instruct the preprocessor how to interpret parts -of the code relevant to the generation of the test suite. The most -important directives follow. - -\subsubsection s3_atTest @Test - -This directive is used to indicate a test routine to the preprocessor, -which then includes it in the test suite. There may be multiple -tests in the .pf file, each annotated by the \@Test directive. - -\@Test also supports MPI-parallel tests (see \ref s3_atMPITest ). - -An example, from Examples/Fixture: - -\code -@Test - subroutine testBracketInterior(this) - class (Test_LinearInterpolator), intent(inout) :: this - @assertEqual([3,4], this%interpolator%getBracket(at=4.)) - end subroutine testBracketInterior - -@Test - subroutine testInterpolateAtNode(this) - class (Test_LinearInterpolator), intent(inout) :: this - @assertEqual(2., this%interpolator%interpolate(at=3.)) - end subroutine testInterpolateAtNode\endcode - - -\subsubsection s3_atMPITest @MPITest - -\ref s3_atMPITest is deprecated as \@Test now handles this case. - -This directive indicates an MPI parallel test to the preprocessor, -which then includes it in an MPI enabled test suite. The directive -takes a single argument, the requested number of MPI processes to run. -The syntax, exemplified by one of the tests from Examples/MPI_Halo: - -\code -@Test( npes=[1,2,3]) -subroutine testHaloInterior(this) - use Halo_mod - use pfunit_mod - implicit none - class (MpiTestMethod) :: this - - integer, parameter :: N = 2 - real :: a(N,0:N+1) - integer :: p - - p = this%getProcessRank() - a(:,1:N) = p - a(:,0) = -1 - a(:,N+1) = -1 - - call haloFill(a, this%getMpiCommunicator()) - - @assertEqual(real(p), a(1,1)) - @assertEqual(real(p), a(2,1)) - @assertEqual(real(p), a(1,2)) - @assertEqual(real(p), a(2,2)) - -end subroutine testHaloInterior\endcode - -\subsubsection s3_atAssert @Assert - -The \@Assert directives are expanded into calls to similarly named -pFUnit library routines. The syntax for the directives follows the -pattern for \@assertEqual below. - -\code -@assertEqual(expected,found,'An identifying or explanatory message.')\endcode - -The preprocessor will automatically add information about source -location (file & line number) to the call emitted to the test suite -code. It also adds the check for exceptions. - -For more information about \@assert directives, please refer to the following. - - - - -\subsubsection s3_atParameters @Parameters - -The \@Parameter directive indicates the declaration of the -parameterized type used to generate the iteration over the multiple -parameter values. It also identifies the names of the parameters to -be iterated over. The preprocessor extracts type information from the -declaration of the parameter type collection that immediately follows -the directive. This directive will set up the iteration. To define -the parameter values per iteration the getParameters -method of the abstract ParameterizedTest must be implemented. For -example: - -\code - @Parameters = [p1,p2] - type, extends(AbstractTestParameter) :: exampleCase - integer :: i - real :: x - end type exampleCase\endcode - -\subsubsection s3_atTestCase @TestCase - -This directive identifies to the preprocessor the TestCase -declaration. The type declared at this point extends TestCase (or its -extension), which includes setting methods such as the following: -setUp, tearDown, runMethod, userMethod. For the extension -MPITestCase, as with ParameterizedTestCase, you have the option -(requirement if parameters are used) to set getParameters and -getParameterString. For example: - -\code - @TestCase - type, extends(MPITestCase) :: Test_Parameters - integer :: p1, p2 - procedure(runMethod), pointer :: userMethod => null() - contains - procedure, nopass :: getParameters - procedure :: getParameterString => getParameterString_ - procedure :: runMethod - end type Test_Parameters\endcode - -\page page_Assert @Assert Preprocessor Directives - - - -\section sec_AssertPreprocessorDirectives @Assert Preprocessor Directives -\subsection ss_assertEqual @assertEqual -\subsection ss_assertTrue @assertTrue -\subsection ss_assertEqualUserDefined @assertEqualUserDefined -A convenience function that allows a user to write -\code -@assertEqualUserDefined(a,b)\endcode -instead of -\code -call assertTrue(a==b,...)\endcode -while a more instructive error message about the arguments and -source code position is added by the preprocessor. The user may -add an error message as follows. -\code -@assertEqualUserDefined(a,b,message='a and b should be equal here.')\endcode - -\subsection ss_assertFalse @assertFalse -\subsection ss_assertLessThan @assertLessThan -\subsection ss_assertLessThanOrEqual @assertLessThanOrEqual -\subsection ss_assertGreaterThan @assertGreaterThan -\subsection ss_assertGreaterThanOrEqual @assertGreaterThanOrEqual -\subsection ss_assertIsMemberOf @assertIsMemberOf -\subsection ss_assertContains @assertContains -\subsection ss_assertAny @assertAny -\subsection ss_assertAll @assertAll -\subsection ss_assertNotAll @assertNotAll -\subsection ss_assertNone @assertNone -\subsection ss_assertIsPermutationOf @assertIsPermutationOf -\subsection ss_assertExceptionRaised @assertExceptionRaised -\subsection ss_assertSameShape @assertSameShape -\subsection ss_assertIsNaN @assertIsNaN -\subsection ss_assertIsFinite @assertIsFinite -\subsection ss_assertAssociated @assertAssociated -@assertAssociated maps to a call to the logical intrinsic function associated. -\code -@assertAssociated(a)\endcode -becomes -\code -call assertTrue(associated(a))\endcode - -The directive also handles the two-argument pointer-target case. -\code -@assertAssociated(pointer,target)\endcode -becomes -\code -call assertTrue(associated(pointer,target))\endcode -neglecting message and source location information. - -A message may be passed as follows. -\code -@assertAssociated(a,message="A message.")\endcode - -\code -@assertAssociated(pointer,target,message="A message.")\endcode - -\subsection ss_assertNotAssociated @assertNotAssociated - -This directive is the same as assertAssociated, except that it maps to assertFalse. This directive was originally released as assertUnAssociated. - -\subsection ss_assertEquivalent @assertEquivalent -This directive compares two logical values and throws an exception annotated with some useful information. -We get a special directive for this one because comparing logicals uses the .eqv. infix operator in standard -Fortran. The arguments a and b below may be 1d arrays. -\code -@assertEquivalent(a,b)\endcode -becomes -\code -call assertTrue(a.eqv.b)\endcode -neglecting the specification of message and source location information. - -\page page_RevisionNotes Revision Notes - - - -*/ diff --git a/documentation/doxygen.conf b/documentation/doxygen.conf index 370f3fc7..97de13c6 100644 --- a/documentation/doxygen.conf +++ b/documentation/doxygen.conf @@ -738,7 +738,7 @@ WARN_LOGFILE = # spaces. # Note: If this tag is empty the current directory is searched. -INPUT = +INPUT = main.dox pages/ ../src ../test ../include # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses @@ -1350,7 +1350,7 @@ DISABLE_INDEX = NO # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. -GENERATE_TREEVIEW = NO +GENERATE_TREEVIEW = YES # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that # doxygen will group on one line in the generated HTML documentation. diff --git a/documentation/pages/acknowledgments.dox b/documentation/pages/acknowledgments.dox new file mode 100644 index 00000000..784a3889 --- /dev/null +++ b/documentation/pages/acknowledgments.dox @@ -0,0 +1,18 @@ + +/*! + +\page page_Acknowledgments Acknowledgments + +Thanks to the follwing for their review and comments: B. Van Aartsen, T. Clune. + +Windows/CYGWIN contributions from E. Lezar. + +PGI port contributions from M. Leair (PG Group). + +Other acknowledgments: S.P. Santos (NCAR), M. Hambley (UK Met Office)., J. Krishna (ANL). + +The design of pFUnit is strongly influenced by JUnit. + +Initial pFUnit 2 documentation by Michael Rilee (Rilee Systems Technologies). + +*/ diff --git a/documentation/pages/assert-preprocessor-directives.dox b/documentation/pages/assert-preprocessor-directives.dox new file mode 100644 index 00000000..62fac7e9 --- /dev/null +++ b/documentation/pages/assert-preprocessor-directives.dox @@ -0,0 +1,369 @@ + +/*! + +\page page_Assert Assertion Reference + + + +> Note that for all assertions in which a scalar is compared with an array, the scalar expected +value is converted to an array of shape equal to the actual value before comparison. + +\section ss_customfailuremessages Custom Failure Messages + +For each assert preprocessor directive documented below, an instructive error message about +the arguments and source code position is added by the preprocessor. However, for both +directives and subroutines, the user may add an error message as follows (using \ref ss_assertEqual +as an example). + +\code +@assertEqual(a,b,message='a and b should be equal here.') +\endcode + +\section sec_AssertPreprocessorDirectivesReference Assert Preprocessor Directives Reference + +\subsection ss_assertEqual @assertEqual + +Performs an exact match comparison of expected and actual values of various types. +Will register a test failure if `expected` does not equal `actual`. + +
+ Integer comparison + \code + @assertEqual(INTEGER expected, INTEGER actual, CHARACTER(len=*) OPTIONAL message) + @assertEqual(INTEGER expected, INTEGER actual(*), CHARACTER(len=*) OPTIONAL message) + @assertEqual(INTEGER expected(*), INTEGER actual(*), CHARACTER(len=*) OPTIONAL message) + \endcode +
+ +
+ Character Array comparison + \code + @assertEqual(CHARACTER(len=*) expected, CHARACTER(len=*) actual, CHARACTER(len=*) OPTIONAL message, TYPE(WhitespaceOptions) OPTIONAL whitespace) + @assertEqual(CHARACTER(len=*) expected, CHARACTER(len=*) actual(:), CHARACTER(len=*) OPTIONAL message, TYPE(WhitespaceOptions) OPTIONAL whitespace) + @assertEqual(CHARACTER(len=*) expected(:), CHARACTER(len=*) actual(:), CHARACTER(len=*) OPTIONAL message, TYPE(WhitespaceOptions) OPTIONAL whitespace) + \endcode + + Where `WhitespaceOptions` can be one of + +
+ +\subsection ss_assertTrue @assertTrue + +Verifies a provided condition is true. Will register a test failure if `condition` is `.False.`. + +\code +@assertTrue(LOGICAL condition, CHARACTER(len=*) OPTIONAL message) +@assertTrue(LOGICAL condition(:), CHARACTER(len=*) OPTIONAL message) +\endcode + +When verifying an array of logicals, all elements of the condition array must be true. + +\subsection ss_assertEqualUserDefined @assertEqualUserDefined + +A convenience function that allows a user to write + +\code +@assertEqualUserDefined(a, b) +\endcode + +instead of + +\code +call assertTrue(a==b,...) +\endcode + +while a more instructive error message about the arguments and +source code position is added by the preprocessor. The user may +add an error message as follows. + +\code +@assertEqualUserDefined(a,b,message='a and b should be equal here.') +\endcode + +\subsection ss_assertFalse @assertFalse + +Verifies a provided condition is false. Will registers a test failure if +`condition` is `.True.`. + +\code +@assertFalse(LOGICAL condition, CHARACTER(len=*) OPTIONAL message) +@assertFalse(LOGICAL condition(:), CHARACTER(len=*) OPTIONAL message) +\endcode + +When verifying an array of logicals, all elements of the condition array must be false. + +\subsection ss_assertLessThan @assertLessThan + +Performs a less than comparison of expected and actual values of various types. Will +register a test failure if the `expected` value is more than or equal to the `actual` +value + +
+ Integer comparison + \code + @assertLessThan(INTEGER expected, INTEGER actual, CHARACTER(len=*) OPTIONAL message) + @assertLessThan(INTEGER expected, INTEGER actual(*), CHARACTER(len=*) OPTIONAL message) + @assertLessThan(INTEGER expected(*), INTEGER actual(*), CHARACTER(len=*) OPTIONAL message) + \endcode +
+ +
+ Real comparison + \code + @assertLessThan(REAL expected, REAL actual, REAL OPTIONAL tolerance, CHARACTER(len=*) OPTIONAL message) + @assertLessThan(REAL expected, REAL actual(*), REAL OPTIONAL tolerance, CHARACTER(len=*) OPTIONAL message) + @assertLessThan(REAL expected(*), REAL actual(*), REAL OPTIONAL tolerance, CHARACTER(len=*) OPTIONAL message) + \endcode +
+ +
+ Mixed type comparison + \code + @assertLessThan(INTEGER expected, REAL actual, REAL OPTIONAL tolerance, CHARACTER(len=*) OPTIONAL message) + @assertLessThan(INTEGER expected, REAL actual(*), REAL OPTIONAL tolerance, CHARACTER(len=*) OPTIONAL message) + @assertLessThan(INTEGER expected(*), REAL actual(*), REAL OPTIONAL tolerance, CHARACTER(len=*) OPTIONAL message) + \endcode +
+ + +\subsection ss_assertLessThanOrEqual @assertLessThanOrEqual + +Performs a less than or equal comparison of expected and actual values of real and integer types. +Will register a test failure if `expected` is more than `actual`. + +
+ Integer comparison + \code + @assertLessThanOrEqual(INTEGER expected, INTEGER actual, CHARACTER(len=*) OPTIONAL message) + @assertLessThanOrEqual(INTEGER expected, INTEGER actual(*), CHARACTER(len=*) OPTIONAL message) + @assertLessThanOrEqual(INTEGER expected(*), INTEGER actual(*), CHARACTER(len=*) OPTIONAL message) + \endcode +
+ +
+ Real comparison + \code + @assertLessThanOrEqual(REAL expected, REAL actual, CHARACTER(len=*) OPTIONAL message) + @assertLessThanOrEqual(REAL expected, REAL actual(*), CHARACTER(len=*) OPTIONAL message) + @assertLessThanOrEqual(REAL expected(*), REAL actual(*), CHARACTER(len=*) OPTIONAL message) + \endcode +
+ +\subsection ss_assertGreaterThan @assertGreaterThan + +Performs a greater than comparison of expected and actual values of real and integer types. +Will register a test failure if `expected` is less than or equal to `actual`. + +
+ Integer comparison + \code + @assertGreaterThan(INTEGER expected, INTEGER actual, CHARACTER(len=*) OPTIONAL message) + @assertGreaterThan(INTEGER expected, INTEGER actual(*), CHARACTER(len=*) OPTIONAL message) + @assertGreaterThan(INTEGER expected(*), INTEGER actual(*), CHARACTER(len=*) OPTIONAL message) + \endcode +
+ +
+ Real comparison + \code + @assertGreaterThan(REAL expected, REAL actual, CHARACTER(len=*) OPTIONAL message) + @assertGreaterThan(REAL expected, REAL actual(*), CHARACTER(len=*) OPTIONAL message) + @assertGreaterThan(REAL expected(*), REAL actual(*), CHARACTER(len=*) OPTIONAL message) + \endcode +
+ +\subsection ss_assertGreaterThanOrEqual @assertGreaterThanOrEqual + +Performs a greater than or equal comparison of expected and actual values of real and integer types. +Will register a test failure if `expected` is less than `actual`. + +
+ Integer comparison + \code + @assertGreaterThanOrEqual(INTEGER expected, INTEGER actual, CHARACTER(len=*) OPTIONAL message) + @assertGreaterThanOrEqual(INTEGER expected, INTEGER actual(*), CHARACTER(len=*) OPTIONAL message) + @assertGreaterThanOrEqual(INTEGER expected(*), INTEGER actual(*), CHARACTER(len=*) OPTIONAL message) + \endcode +
+ +
+ Real comparison + \code + @assertGreaterThanOrEqual(REAL expected, REAL actual, CHARACTER(len=*) OPTIONAL message) + @assertGreaterThanOrEqual(REAL expected, REAL actual(*), CHARACTER(len=*) OPTIONAL message) + @assertGreaterThanOrEqual(REAL expected(*), REAL actual(*), CHARACTER(len=*) OPTIONAL message) + \endcode +
+ +\subsection ss_assertIsMemberOf @assertIsMemberOf + +> Not currently implemented + +\subsection ss_assertContains @assertContains + +> Not currently implemented + +\subsection ss_assertIsPermutationOf @assertIsPermutationOf + +> Not currently implemented + +\subsection ss_assertExceptionRaised @assertExceptionRaised +\subsection ss_assertAssociated @assertAssociated +@assertAssociated maps to a call to the logical intrinsic function associated. + +\code +@assertAssociated(a) +\endcode + +becomes +\code +call assertTrue(associated(a)) +\endcode + +The directive also handles the two-argument pointer-target case. + +\code +@assertAssociated(pointer,target) +\endcode + +becomes + +\code +call assertTrue(associated(pointer,target)) +\endcode + +neglecting message and source location information. + +A message may be passed as follows. + +\code +@assertAssociated(a,message="A message.") +\endcode + +\code +@assertAssociated(pointer,target,message="A message.") +\endcode + +\subsection ss_assertNotAssociated @assertNotAssociated + +This directive is the same as assertAssociated, except that it maps to assertFalse. This directive was originally released as assertUnAssociated. + +\subsection ss_assertEquivalent @assertEquivalent +This directive compares two logical values and throws an exception annotated with some useful information. +We get a special directive for this one because comparing logicals uses the .eqv. infix operator in standard +Fortran. The arguments a and b below may be 1d arrays. +\code +@assertEquivalent(a,b) +\endcode +becomes +\code +call assertTrue(a.eqv.b) +\endcode +neglecting the specification of message and source location information. + +\section sec_AssertionSubroutines Assert Subroutines Reference + +\subsection ss_assertAny assertAny + +Verifies an array of conditions contains at least one `.true.`. Will register a test failure +if all elements of `conditions` are `.false.`. + +\code +call assertAny(LOGICAL conditions(:), CHARACTER(len=*) OPTIONAL message) +\endcode + +\subsection ss_assertAll assertAll + +Verifies every element of an array of conditions are `.true.`. Will register a test failure +if any element of `conditions` is `.false.`. + +\code +call assertAll(LOGICAL conditions(:), CHARACTER(len=*) OPTIONAL message) +\endcode + +\subsection ss_assertNotAll assertNotAll + +Verifies that an array of conditions does not solely contain values of `.true.`. Will register +a test failure if all element of `conditions` are `.true.`. + +\code +call assertNotAll(LOGICAL conditions(:), CHARACTER(len=*) OPTIONAL message) +\endcode + +\subsection ss_assertNone assertNone + +Verifies that an array of conditions does not contain `.true.` values. Will register +a test failure if any element of `conditions` is `.true.`. + +\code +call assertNone(LOGICAL conditions(:), CHARACTER(len=*) OPTIONAL message) +\endcode + +\subsection ss_assertSameShape assertSameShape + +Performs an exact match comparison of expected and actual 1D integer arrays used to +represent array shapes. Will register a test failure if the `expected` shape does +not exactly match the `actual` shape. + +\code +call assertSameShape(INTEGER expected(:), INTEGER actual(:), CHARACTER(len=*) OPTIONAL message) +\endcode + +\subsection ss_assertIsNaN assertIsNaN + +Verifies if a provided real value is Not-a-Number (NaN). Will register a test failure if +`value` is NaN. + +\code +call assertIsNaN(REAL value, CHARACTER(len=*) OPTIONAL message) +\endcode + +\subsection ss_assertIsFinite assertIsFinite + +Verifies is a provided real value is finite. Will register a test failure if `value` +is infinite. + +\code +call assertIsFinite(REAL value, CHARACTER(len=*) OPTIONAL message) +\endcode + +*/ diff --git a/documentation/pages/development.dox b/documentation/pages/development.dox new file mode 100644 index 00000000..59931c13 --- /dev/null +++ b/documentation/pages/development.dox @@ -0,0 +1,13 @@ + +/*! + +\page page_Development Development + +Generally pFUnit development is performed in the build directory +structure. Care should be taken to make clean or distclean in between +configuration changes. As stated in \ref sec_Installation, it is best +to set INSTALL_DIR and "make install" pFUnit to another directory that +can be placed in a +user's paths. + +*/ diff --git a/documentation/pages/documentation.dox b/documentation/pages/documentation.dox new file mode 100644 index 00000000..42e43063 --- /dev/null +++ b/documentation/pages/documentation.dox @@ -0,0 +1,9 @@ + +/*! + +\page page_TODO TODO + +- Make other directory. +- Make Environment Modules example in other directory. + +*/ diff --git a/documentation/pages/faq-and-tips.dox b/documentation/pages/faq-and-tips.dox new file mode 100644 index 00000000..624ea263 --- /dev/null +++ b/documentation/pages/faq-and-tips.dox @@ -0,0 +1,123 @@ + +/*! + +\page page_FAQAndTips FAQ and Tips + + + +\section sec_FAQ FAQ + +\subsection ZeroTestsRun Zero Tests Run +

Symptom: The system under test compiles and runs fine, but reports zero tests run.

+

Solutions: +

+\subsection SomeOfMyTestsAreNotRunning Some Tests Are Not Running +Symptom: The system under test compiles and runs fine, but reports that some tests don't run. +

Solutions: +

+ +\subsection FAQIntel13 Intel Fortran Version 13: -DINTEL_13 + +Using version 13 is deprecated. We have encountered problems using +version 13, which we believe may be due to subtle compiler bugs. We +strongly recommend upgrading to the latest version possible. + +To make pFUnit work with Intel Fortran Version 13, please ensure that +-DINTEL_13 is passed to the compiler when building or +using pFUnit. In the build process for pFUnit, this is added to the +make variables CPPFLAGS and FPPFLAGS. + +\subsection FAQSegAndLinkFaults Segmentation Faults and Odd Link Errors + +Q. pFUnit fails to build or now leads to segmentation faults. Did something change? + +A. One cause for failure to build or odd runtime segmentation faults is when we change compiler configurations and some object or library files are left over from a previous environment. This might be hard to spot, for example, during compiler upgrades. Switching from one compiler to another, e.g. from Intel to GNU, is more likely to generate link-time errors if old code is still around. A few items to check follow. + + + +Finally, it is quite possible that a bug has been uncovered. Please contact the development team or open a bug ticket. + + +\section sec_Tips Tips + +\subsection TipEnvironmentModules Environment Modules +Though not strictly required, the Environment +Modules package can be a convenient way to package, maintain, and +switch between environments. This can be particularly important for +pFUnit, which must be built using the same tool suite being used for +development, e.g. compilers, linkers, etc. [To do: A sample pFUnit +modulefile is provided in the OTHER directory.] + +\subsection TipCompileTimeErrors Compile Time Errors +Compile time errors like '"include [...]include/.mk" not found' +likely signify that you are not executing make in the top level +directory during a build. Alternatively, during regular usage after +installation, PFUNIT has not been set. + +During building, if you wish to compile in a subdirectory within the +pFUnit heriarchy, please try setting the COMPILER environment variable +on the make command line. For example: + +\code +$ make all COMPILER=Intel\endcode + +\subsection TipIntermediateFiles Intermediate files used by pFUnit +If you wish to see the intermediate files, use the target .PRECIOUS +in the makefile to keep them from being deleted. For example: + +\code +# In GNUmakefile +.PRECIOUS: %_cpp.F90\endcode + +\subsection TipWhitespace Ignoring whitespace differences in assertions on strings. +Several options exist for how to compare strings with assertEqual. + +\code +call assertEqual(expectedString, foundString, & + & whitespace=IGNORE_DIFFERENCES )\endcode + +WhitespaceOptions: + + +Example usages can be seen in tests/Test_AssertBasic.F90 or +Examples/Simple/tests/helloWorld.pf. + +*/ diff --git a/documentation/pages/feedback-and-support.dox b/documentation/pages/feedback-and-support.dox new file mode 100644 index 00000000..7c8fa9af --- /dev/null +++ b/documentation/pages/feedback-and-support.dox @@ -0,0 +1,24 @@ + +/*! + +\page page_FeedbackAndSupport Feedback & Support + +\li \ref sec_Feedback \li \ref sec_Support + +\section sec_Feedback Feedback + +Feedback is welcome, please use the facilities at oddard-Fortran-Ecosystem/pFUnit/issues to share your views. + +Open a issue for bugs, features, and patch recommendations. + +If you use pFUnit, please let us know by leaving a note in our Applications of pFUnit forum, or email Tom Clune, Ph.D., NASA Goddard Space Flight Center. Letting us know about your application helps us seek support for pFUnit's continued development and improvement. + +\section sec_Support Support + +Please open a issue for bugs, features, and patch recommendations. For longer term needs or considerations, please visit our discussion forums or contact Tom Clune, Ph.D., NASA Goddard Space Flight Center. + +You may also find some help at \ref page_FAQAndTips. + +pFUnit supports the software development of several weather and climate simulations efforts. We constantly seek to improve and correct pFUnit for our users' benefit, granting priority to the needs of our major users. Please share with us information about your application on our Applications of pFUnit forum. + +*/ diff --git a/documentation/pages/installation.dox b/documentation/pages/installation.dox new file mode 100644 index 00000000..9d7bed4a --- /dev/null +++ b/documentation/pages/installation.dox @@ -0,0 +1,337 @@ + +/*! + +\page page_Installation Installation + +\section sec_InstallingPFUNIT Installing pFUnit + +Comentatry for the page. + +\li \ref sec_Prerequisites +\li \ref sec_ObtainingPFUNIT +\li \ref sec_Manifest +\li \ref sec_Configuration +\li \ref sec_Building + +\li \ref sec_Installation + +\section sec_Prerequisites Prerequisites + +The development work for pFUnit has mostly been carried out on a +mixture of systems, including high-end computers, Apple Mac OSX, and +linux-based systems. A preliminary Windows/CYGWIN port has been +contributed by a user. Full use of the system depends on the following +being available. + +- Fortran 2003+ (Tested with Intel 14+, NAG 6.0, GCC 4.9.+, IBM's XLF, PGI 15.4) +- The Message Passing Interface (MPI) +- OpenMP +- GNU Make +- Python + +Note: Recent changes have exposed a latent bug in GCC 4.8.2. The fix +is available in the GCC 4.9 development branch and will also appear in +GCC 4.8.3 when that is released. Users that require older versions of +GCC should use pFUnit 2.1.x. + +Doxygen is used to generate documentation. + +The system routinely undergoes regression testing with GNU, Intel, and NAG fortran +compilers and OpenMPI. + +\section sec_ObtainingPFUNIT Obtaining pFUnit + +The best way to obtain pFUnit is to clone +pFUnit from the git repository from SourceForge as follows. + +\code +# Read Only Access +git clone git://git.code.sf.net/p/pfunit/code pFUnit\endcode + +This will create the directory pFUnit in the current working +directory. + +You may also visit the project page at SourceForge and +download the source tarfile "pFUnit.tar.gz" there. + +http://sourceforge.net/projects/pfunit/ +or +http://sourceforge.net/projects/pfunit/files/latest/download + +Extracting this tarfile via a command like + +`$ tar zxf ./pFUnit.tar.gz` + +will place the pFUnit files into the current working directory. + +For other ways to acquire the code visit + +https://sourceforge.net/p/pfunit/code/ci/master/tree/ + +or contact the pFUnit team. + +\section sec_Manifest Manifest - What's in the directory? + +In the top level of the pFUnit distribution you will see the following +files. + +CMakeLists.txt - Initial support for cmake-based builds. + +COPYRIGHT - Contains information pertaining to the use and +distribution of pFUnit. + +Examples - Contains examples of how to use pFUnit once it is +installed. + +GNUmakefile - The top level makefile for building and installing +pFUnit. + +LICENSE - The NASA Open Source Agreement for GSC-15,137-1 F-UNIT, also +known as pFUnit. + +README-INSTALL - Basic documentation on pFUnit installation and use. + +bin - Executables used to construct and perform unit tests. + +include - Files to be included into makefiles or source, including use +code. + +source - Source code and scripts of the pFUnit library and framework. + +tests - Source code for unit testing pFUnit itself. + +tools - Tools used to help develop, build, and install pFUnit. + +VERSION - Contains a string describing the current version of the framework. + +\section sec_Configuration Configuration +Little needs to be done to configure pFUnit for the build, however +there are several environment variables on which the package depends. + +`F90_VENDOR` - is set to include the correct makefile in $(TOP_DIR)/include, +i.e. GNU, Intel, NAG, or PGI. Case insensitive file systems may cause +some confusion from time-to-time. + +`F90` - is set to the Fortran compiler being used: e.g. ifort for Intel, +gfortran for GNU. + +`COMPILER` - is set according to `F90_VENDOR` and is automatically set in +the top level makefile. + +For MPI-based unit testing, your setup may require the following as well. + +`MPIF90`\code +$ export MPIF90=mpif90\endcode + +As a convenience for working with multiple MPI configurations, you may +also set the following. + +`MPIRUN`\code +$ export MPIRUN=/some.path/mpirun\endcode + +PFUNIT_MAX_ARRAY_RANK + +`PFUNIT_MAX_ARRAY_RANK` - controls the maximum size of the arrays asserts are +defined over. If PFUNIT_MAX_ARRAY_RANK is not set, the default is 5 and pFUnit's assertions will be able to handle arrays up to rank 5, i.e. A(:,:,:,:,:). PFUNIT_MAX_ARRAY_RANK and MAX_RANK do not refer to MPI ranks (process id within a group). Example:\code +$ export PFUNIT_MAX_ARRAY_RANK=5\endcode + +`PFUNIT_MAX_RANK` is a deprecated way to set maximum rank and is to be removed in version 4. + + +`DOXYGEN` - To generate documentation, set DOXYGEN to the desired +executable. NOTE: Doxygen Version 1.8.5 does not respect CamelCase +names from Fortran source code by currently converting all to +lowercase. It does this to get HTML links correct for references in +the source code that also do not respect the CamelCase convention. +The Fortran standard specifies case insensitivity. Doxygen 1.7.x +seems to better respect CamelCase. +\code +$ export DOXYGEN=/opt/local/share/doxygen/doxygen-1.7.6/bin/doxygen\endcode + +\section sec_Building Building pFUnit +\subsection sec_BuildingPFUNITSerial Building pFUnit for testing serial codes (Non-MPI) + +1. Change to the directory into which pFUnit has been placed. +2. Set the environment variables (for example in bash): +\code +$ export F90=gfortran-mp-4.8 +$ export F90_VENDOR=GNU\endcode +3. To build pFUnit for unit testing of serial codes, execute make. +The unit tests for pFUnit itself will run automatically. +\code +$ make tests\endcode +3.1 Occasionally on the first run through, one will get a spurious +(runtime) error, for example in the unix process component. +\code +Re-execute "make tests" to check again.\endcode +4. At this point the pFUnit object library is in the source directory, +along with a large number of Fortran module files. + +\subsection sec_BuildingPFUNITMPI Building pFUnit for testing parallel codes (MPI) + +To build pFUnit for unit testing MPI-based codes, be sure that the +environment is properly set up for the MPI implementation you are +using. Depending on your local environment, you may need execute the +build within a batch or other job queing system, e.g. an interactive +batch job under PBS. The steps for building pFUnit start out the same +as for the serial case above, but add MPI=YES to the environment to +switch on MPI support. The MPI-based unit tests for pFUnit itself +will run automatically. Again, occasionally a spurious (runtime) +error may appear on the first execution. + +3. Execute make as follows. +\code +$ make tests MPI=YES \endcode + +4. At this point an MPI-enabled pFUnit object library is in the source +directory, along with a large number of Fortran module files. + +Also, one may get some harmless "no symbols" warnings when the pFUnit library is constructed. + +\subsection sec_BuildingPFUNITOPENMP OPENMP + +Initial (limited) support for OPENMP has been implemented. At this +writing, a basic functionality is available. + +The process for building pFUnit for testing OPENMP-based codes is +similar to that for other paradigms. + +3. To compile for OPENMP support execute make as follows. +\code +$ make tests OPENMP=YES\endcode + +4. At this point the OPENMP-enabled pFUnit is ready to be installed. + +\subsection sec_BuildingPFUNITCleaning Cleaning + +To clean the pFUnit build directory for the space or to rebuild there +are two options. + +1. Make clean to remove object files and other intermediate products. +\code +$ make clean\endcode + +2. Make distclean to remove libraries and other more final products. +\code +$ make distclean\endcode + +3. Some directories support a `make src_clean` to remove intermediate +products in subdirectories. + +\subsection sec_BuildingPFUNITDocumentation Documentation + +A start at documentation for pFUnit is in the documentation directory. +Doxygen is our primary +documentation tool. To make the documentation, which will be +generated in the documentation directory, please invoke the following +from the top level of your pFUnit distribution. + +\code +$ make documentation\endcode + +Or to make a reference manual. + +\code +$ make documentation/pFUnit2-ReferenceManual.pdf\endcode + +To select a specific version of Doxygen, please set the DOXYGEN +environment variable as in \ref sec_Configuration. You may wish to do +this if your code uses CamelCase names as current versions of Doxygen +(1.8.5) do not respect this convention for Fortran. + +\subsection sec_BuildingPFUNITCMAKE CMAKE + +Initial support for CMAKE has been implemented. At this +writing, a basic functionality is available. + +3. The process for building pFUnit using cmake is as follows. In the +top directory of the distribution make a new directory to support the +build, then change to that directory and run cmake (pointing back to +the source) to generate the required makefiles. +\code +$ mkdir build +$ cd build +$ # e.g. cmake -DMPI=YES -DOPENMP=NO -DINSTALL_PATH= +$ cmake -DMPI=NO .. +$ make tests\endcode + +One may also set the environment variable PFUNIT instead of setting +INSTALL_PATH on the cmake command line as given above. + +If your MPI installation does not provide mpirun, you may try to set +-DMPI_USE_MPIEXEC=YES to tell CMake to use its FindMPI function to +find out how to execute the tests. + +4. If the build is successful, then at this point make install should work. + +\section sec_Installation Installation +\subsection sec_InstallationSerial Installation - Serial + +To install pFUnit for regular use, set INSTALL_DIR to the location in +which to place pFUnit. This can be done on the make command line. +For example, after compiling pFUnit for serial use (MPI absent or +MPI=NO), please try. +\code +$ # In the top of the pFUnit build directory. +$ make install INSTALL_DIR=/opt/pfunit/pfunit-serial\endcode + +Note: you may need special priveleges to install in some locations, +e.g. via sudo. + +To test the installation set PFUNIT to INSTALL_DIR, then change the +working directory to Examples in pFUnit distribution and execute +"make," which will run a number of examples. These include some +expected (intentional) failures. +\code +$ # In the top pFUnit build directory... +$ export PFUNIT=/opt/pfunit/pfunit-serial +$ cd Examples +$ make\endcode + +\subsection sec_InstallationMPI Installation - MPI + +For installing an MPI-enabled pFUnit library, change to the top of the +distribution and execute make with MPI=YES. You may need to "make +distclean" first. After compilation and pFUnit passes its self-tests, +then installation proceeds as for the serial case above. +\code +$ make install INSTALL_DIR=/opt/pfunit/pfunit-parallel\endcode + +To test, set PFUNIT and go into Examples/MPI_Halo directory. +\code +$ # In the top pFUnit build directory... +$ export PFUNIT=/opt/pfunit/pfunit-parallel +$ # The variable MPIF90 must be set to the appropriate build script. +$ export MPIF90=mpif90 +$ cd Examples/MPI_Halo +$ make\endcode + +This will compile and run a set of parallel examples that includes +intentional failures. To run all of the examples try executing +"make MPI=YES" in the Examples directory. + +\subsection sec_InstallationOPENMP Installation - OPENMP + +At this time the OPENMP version of pFUnit can be installed in the same +way as for the serial or MPI-parallel codes. OPENMP support, tests, +and examples are limited as of this writing. + +\subsection sec_InstallationDefaultDirectory Installation - DEFAULT DIRECTORY + +If INSTALL_DIR is not set, "make install" will attempt to install +pFUnit into the top build directory. This will create directories +such as lib and mod in the top level of the build directory and will +overwrite the include/base.mk with include/base-install.mk. If this +is not desired, then "make develop" will put back the original +base.mk, which is the file to be used for development and building +pFUnit. In general, we recommend installing to a directory that is not also the +build directory. + +*/ diff --git a/documentation/pages/known-installations-and-versions.dox b/documentation/pages/known-installations-and-versions.dox new file mode 100644 index 00000000..4b5a860b --- /dev/null +++ b/documentation/pages/known-installations-and-versions.dox @@ -0,0 +1,14 @@ + +/*! + +\page page_KnownInstallationsAndVersions Known Installations & Versions + +master - The current release. + +development - The cutting edge of pFUnit development. + +mock_services - Experimental support for mocking. + +pfunit_2.1.0 - A feature freeze prior to a major upgrade of the preprocessor. + +*/ diff --git a/documentation/pages/platform-specific-notes.dox b/documentation/pages/platform-specific-notes.dox new file mode 100644 index 00000000..de9e2013 --- /dev/null +++ b/documentation/pages/platform-specific-notes.dox @@ -0,0 +1,25 @@ + +/*! + +\page page_PlatformSpecific Platform Specific Notes + +\section sec_MacOSX Mac OSX + +The MacPorts package management system is a convenient way to install +and maintain many packages, including gcc which includes gfortran. + +\section sec_WindowsCYGWIN Windows/CYGWIN + +User contributed code for Windows/CYGWIN has been added, but is +currently not tested and supported by the pFUnit team. At this +writing, 2013-1031, serial Examples and MPI are not known to be +supported. Please contact us if you wish to either contribute or +otherwise discuss this port. + +\section sec_Intel13 Intel Fortran Version 13: -DINTEL_13 +To make pFUnit work with Intel Fortran Version 13, please ensure that +-DINTEL_13 is passed to the compiler when building or +using pFUnit. In the build process for pFUnit, this is added to the +make variables CPPFLAGS and FPPFLAGS. + +*/ diff --git a/documentation/pages/revision-notes.dox b/documentation/pages/revision-notes.dox new file mode 100644 index 00000000..12bb3416 --- /dev/null +++ b/documentation/pages/revision-notes.dox @@ -0,0 +1,23 @@ + +/*! + +\page page_RevisionNotes Revision Notes + + + +*/ diff --git a/documentation/pages/the-preprocessor.dox b/documentation/pages/the-preprocessor.dox new file mode 100644 index 00000000..8c7f4f7f --- /dev/null +++ b/documentation/pages/the-preprocessor.dox @@ -0,0 +1,226 @@ + +/*! + +\page page_funitproc The Preprocessor - funitproc + +Overview of Preprocessor (funitproc) + + + +/////////////////////////////////////////////////////////////////////// +\section sec_UsingThePreprocessor Using The Preprocessor + +How to write tests using the ".pf" files. We expect this to be the +main way people write pFUnit-based tests. Please see the Examples +directory for a wide range of examples. The .pf files themselves are +generally to be found in an example's "tests" subdirectory. + +\subsection ss_Configuration Configuration - testSuites.inc + +The include file "testSuites.inc" tells the preprocessor to generate +code for TestSuites listed therein. The suite names are based on the +TestCases provided in the preprocessor input file or the name of the +preprocessor input file (.pf) itself. For example, if no module is defined +in a .pf file, i.e. the preprocessor will define the module, one +can set up a "testSuites.inc" as follows. +\code +! To load "exampleTestsNoModule.pf". +ADD_TEST_SUITE(exampleTestsNoModule_suite) +\endcode + +For a .pf file that contains a module associated with a test suite the +syntax is as follows. + +\code +! To load "exampleTests.pf" implementing the module exampleTests_mod. +ADD_TEST_SUITE(exampleTests_mod_suite) +\endcode + +\subsection ss_Invocation Invocation + +To run the preprocessor on on a preprocessor input file "exampleTests.pf", invoke: + +\code +$ ${PFUNIT}/bin/funitproc exampleTests.pf exampleTests.F90 +\endcode + +A convenient GNUmakefile rule is as follows. + +\code +%.F90: %.pf + $(PFUNIT)/bin/funitproc $< $@ +\endcode + +\subsection ss_PreprocessorInput Preprocessor Input File (.pf) + +The preprocessor input file is a Fortran free format file that +contains subroutines, including those implementing the suite of tests, +or a module with the tests, TestCases, and support for parameters. +The preprocessor reads and parses this file producing a fortran file +implementing the tests, automating some boilerplate code. Embedded +"@" directives inform the preprocessor about information needed to +generate the test suite. If the .pf file does not implement a module +providing a test suite, the preprocessor will use the name of .pf file +referred to by "testSuites.inc". Currently only one test suite per +.pf file is allowed, a limitation of the current implementation of the +parser. + +Many example .pf files may be found in the examples' +"tests" subdirectories in the Examples directory. + +Below we present the most commonly used directives first, but in a .pf +file using all of these capabilities, the most common order is as +follows. + + + +\section ss_Directives Directives + +Preprocessor "@" directives, which in keeping with Fortran style are +not case sensitive, instruct the preprocessor how to interpret parts +of the code relevant to the generation of the test suite. The most +important directives follow. + +\subsection s3_atTest @Test + +This directive is used to indicate a test routine to the preprocessor, +which then includes it in the test suite. There may be multiple +tests in the .pf file, each annotated by the \@Test directive. + +\@Test also supports MPI-parallel tests (see \ref s3_atMPITest ). + +An example, from Examples/Fixture: + +\code +@Test + subroutine testBracketInterior(this) + class (Test_LinearInterpolator), intent(inout) :: this + @assertEqual([3,4], this%interpolator%getBracket(at=4.)) + end subroutine testBracketInterior + +@Test + subroutine testInterpolateAtNode(this) + class (Test_LinearInterpolator), intent(inout) :: this + @assertEqual(2., this%interpolator%interpolate(at=3.)) + end subroutine testInterpolateAtNode +\endcode + + +\subsection s3_atMPITest @MPITest + +\ref s3_atMPITest is deprecated as \@Test now handles this case. + +This directive indicates an MPI parallel test to the preprocessor, +which then includes it in an MPI enabled test suite. The directive +takes a single argument, the requested number of MPI processes to run. +The syntax, exemplified by one of the tests from Examples/MPI_Halo: + +\code +@Test( npes=[1,2,3]) +subroutine testHaloInterior(this) + use Halo_mod + use pfunit_mod + implicit none + class (MpiTestMethod) :: this + + integer, parameter :: N = 2 + real :: a(N,0:N+1) + integer :: p + + p = this%getProcessRank() + a(:,1:N) = p + a(:,0) = -1 + a(:,N+1) = -1 + + call haloFill(a, this%getMpiCommunicator()) + + @assertEqual(real(p), a(1,1)) + @assertEqual(real(p), a(2,1)) + @assertEqual(real(p), a(1,2)) + @assertEqual(real(p), a(2,2)) + +end subroutine testHaloInterior +\endcode + +\subsection s3_atAssert @Assert + +The \@Assert directives are expanded into calls to similarly named +pFUnit library routines. The syntax for the directives follows the +pattern for \@assertEqual below. + +\code +@assertEqual(expected,found,'An identifying or explanatory message.') +\endcode + +The preprocessor will automatically add information about source +location (file & line number) to the call emitted to the test suite +code. It also adds the check for exceptions. + +For more information about \@assert directives, please refer to the \ref page_Assert. + +\subsection s3_atParameters @Parameters + +The \@Parameter directive indicates the declaration of the +parameterized type used to generate the iteration over the multiple +parameter values. It also identifies the names of the parameters to +be iterated over. The preprocessor extracts type information from the +declaration of the parameter type collection that immediately follows +the directive. This directive will set up the iteration. To define +the parameter values per iteration the getParameters +method of the abstract ParameterizedTest must be implemented. For +example: + +\code + @Parameters = [p1,p2] + type, extends(AbstractTestParameter) :: exampleCase + integer :: i + real :: x + end type exampleCase +\endcode + +\subsection s3_atTestCase @TestCase + +This directive identifies to the preprocessor the TestCase +declaration. The type declared at this point extends TestCase (or its +extension), which includes setting methods such as the following: +setUp, tearDown, runMethod, userMethod. For the extension +MPITestCase, as with ParameterizedTestCase, you have the option +(requirement if parameters are used) to set getParameters and +getParameterString. For example: + +\code + @TestCase + type, extends(MPITestCase) :: Test_Parameters + integer :: p1, p2 + procedure(runMethod), pointer :: userMethod => null() + contains + procedure, nopass :: getParameters + procedure :: getParameterString => getParameterString_ + procedure :: runMethod + end type Test_Parameters +\endcode + +*/ diff --git a/documentation/pages/usage.dox b/documentation/pages/usage.dox new file mode 100644 index 00000000..63e3f88c --- /dev/null +++ b/documentation/pages/usage.dox @@ -0,0 +1,196 @@ + +/*! + +\page page_Usage Usage + +\li \ref sec_UsageConfiguration +\li \ref sec_CmakeIntegration +\li \ref sec_UsageHelloWorld +\li \ref sec_UsagePreprocessor +\li \ref sec_UsageExecutingTheTest + +\section sec_UsageConfiguration Usage - Configuration + +For regular use, after installation, the same compiler/MPI development +configuration that was used to build pFUnit should be used. Once the +environment variables and paths associated with the environment are +set, to configure pFUnit, please set the following. + +`PFUNIT` - set to the directory into which pFUnit was installed. + +`F90_VENDOR` - set to Intel, GNU, NAG, or PGI accordingly. + +\section sec_CmakeIntegration Integrating with CMake + +Integrating with CMake can be achieved once you have a local version of pFUnit installed with the following code. + +\code{cmake} +# Include pFUnit libraries and CMake functions within your project +find_package(PFUNIT REQUIRED) + +# Enable ctest +enable_testing() + +# Create library for src code +file(GLOB PROJ_SRC_FILES "${PROJECT_SOURCE_DIR}/src/*.f90") +add_library (src_lib STATIC ${PROJ_SRC_FILES}) + +# List all .pf test files +file(GLOB + test_srcs + "${PROJECT_SOURCE_DIR}/test/*.pf" +) + +# Filter all tests to only the ones desired for this ctest test +set(specific_test_files ${test_srcs}) +list(FILTER specific_test_files INCLUDE REGEX ".*test_something_*.pf") + +add_pfunit_ctest (test_something_specific # Give your test a name + TEST_SOURCES ${specific_test_files} # Specify the .pf files for this test + LINK_LIBRARIES src_lib # Link to your src application library + ) +\endcode + +To include the pFUnit library within the CMake project, we have added the following to the CMakeLists.txt + +\code{cmake} +find_package(PFUNIT REQUIRED) +\endcode + +This will search the CMAKE_PREFIX_PATH for the pFUnit libraries. Therefore, you need to add the pFUnit installed libraries +to this path. To do this, build your project with the following command, setting any custom CMake flags as needed. + +\code{.sh} +cmake -B build -DCMAKE_PREFIX_PATH=$PFUNIT_INSTALLED_PATH +\endcode + +The ctest test itelf is added via the call to the CMake fucntion provided by pFUnit + +\code{cmake} +add_pfunit_ctest (test_something_specific # Give your test a name + TEST_SOURCES ${specific_test_files} # Specify the .pf files for this test + LINK_LIBRARIES src_lib # Link to your src application library + ) +\endcode + +\subsection sec_CmakeIntegrationParallel Enabling MPI parallel testing via CMake + +To enable building a parallel pFUnit test with CMake and ctest you must add one extra input into +the `add_pfunit_ctest` function - `MAX_PES` + +\code{cmake} +add_pfunit_ctest (test_something_specific # Give your test a name + TEST_SOURCES ${specific_test_files} # Specify the .pf files for this test + LINK_LIBRARIES src_lib # Link to your src application library + MAX_PES # Set the maximum number of allowed MPI ranks for this test + ) +\endcode + +\section sec_UsageHelloWorld Usage - Hello World + +For an example of a simple usage of pFUnit, see Examples/Simple/tests. + +The simplest way to write a test is to write a preprocessor input file (extension ".pf"), which is a Fortran free format file with preprocessor directives added. An example from "helloWorld.pf" follows. +\code{.f90} +! from helloWorld.pf +@test +subroutine testHelloWorld() + use pfunit_mod + implicit none + @assertEqual("Hello World!","Hello World!") +end subroutine testHelloWorld +\endcode + +One then instructs the preprocessor to construct a suite to execute these tests via the "testSuites.inc" file as follows. +\code +! from testSuites.inc +ADD_TEST_SUITE(helloWorld_suite) +\endcode + +At this point, one can invoke the preprocessor to generate a Fortran file that when compiled and linked with pFUnit will execute the tests. For more information please see \ref page_funitproc or try out the examples in Example/Simple. + +\section sec_UsagePreprocessor Usage - Preprocessor +Please see \ref page_funitproc. + +\section sec_UsageExecutingTheTest Compiling and Executing The Test + +An example of a GNU make rule for for the final step of compiling a test follows. + +\code +# This step presumes "include $(PFUNIT)/include/base.mk" earlier in the makefile. +tests.x: testSuites.inc myTests.pf + $(F90) -o $@ -I$(PFUNIT)/mod -I$(PFUNIT)/include \ + $(PFUNIT)/include/driver.F90 \ + ./*$(OBJ_EXT) $(LIBS) $(FFLAGS) +\endcode + +To execute the tests, one invokes "./tests.x" with the appropriate command line options (see below). + +In some cases, since include/driver.F90 is "implicit none," it may be +necessary to insert a "use" clause to identify external suite-wide +fixture code to the compiler. As a convenience, the CPP macro +PFUNIT_EXTRA_USAGE can be set to a module of fixture code via a +compiler command line argument turning on a "use PFUNIT_EXTRA_USAGE" +line at the beginning of include/driver.F90. + +\section ss_UsageExecutingTheTestParallel - Compiling and Executing the Tests (MPI PARALLEL) + +One invokes MPI-based parallel tests according to the MPI framework being used. For example: + +\code +$ mpirun -np 4 tests.x\endcode + + +\section ss_CommandLineOptions Command Line Options + +The executable test program provides several command line options, +when "include/driver.F90" is used, as it is automatically when using +the PFUNIT preprocessor. + + + + + + + + + + + +
-v or -verbose Verbose execution.
-d or -debug Provide debugging information.
-h Print help message.
-o \ Direct pFUnit messages to a file. +
-robust Use the robust runner. Runs tests as processes so failures do not halt testing.
-max-timeout-duration Limit detection time for robust runner.
-max-launch-duration Limit detection time for robust runner.
-skip \Use the subset runner, which runs a subset of the tests in a suite.
-xml \Generate XML output in JUnit +compatible format, write it to given file. This XML output can be used +in integration with e.g. Jenkins. To ensure the XML file is written +correctly, it is recommended to also use the -robust flag.
-name \Give the set of tests an identifying +name, which is used in the XML output.
+ +An example from Examples/Robust: + +\code +$ ./tests.x -robust\endcode + +\subsection ss_XML XML output + +To output JUnit XML, execute tests with the -xml flag: +\code +$ ./tests.x -robust -xml test.xml -name my_suite_name\endcode + +This creates a file named test.xml. As an example, the output may look like this: + +\code + + + + + + + + + +\endcode + +Output explained: The test suite took 2.1020 seconds to execute. One +test (test_addition) succeeded, one (test_division) crashed for some +reason, and one test (test_foo) failed at line 24 of test_other.pf. + +*/ diff --git a/src/funit/asserts/AssertBasic.F90 b/src/funit/asserts/AssertBasic.F90 index d8800bea..27f0f062 100644 --- a/src/funit/asserts/AssertBasic.F90 +++ b/src/funit/asserts/AssertBasic.F90 @@ -13,7 +13,7 @@ !! @date !! 07 Nov 2013 !! -!! @note For assertions on strings whitespace may or may not be +!! For assertions on strings whitespace may or may not be !! significant to a test. We now have several options for dealing !! with whitespace via the optional argument !! Whitespace. These options are