diff --git a/README.md b/README.md index 8b4decd69..9fb3ad678 100644 --- a/README.md +++ b/README.md @@ -156,7 +156,8 @@ Getting Started --------------- ### Writing Assertions To write a Julienne assertion, insert a function-like preprocessor macro -`call_julienne_assert` on a single line as in the following program: +`call_julienne_assert` on a single line as in each of the two macro +invocations below: ```fortran #include "julienne-assertion-macros.h" program main @@ -164,14 +165,24 @@ program main implicit none real, parameter :: x=1., y=2., tolerance=3. call_julienne_assert(x .approximates. y .within. tolerance) + call_julienne_assert(abs(x-y) < tolerance) end program ``` -where inserting `-DASSERTIONS` in a compile command will expand the macro to +where inserting `-DASSERTIONS` in a compile command will expand the macros to ```fortran - call call_julienne_assert_(x .approximates. y .within. tolerance) + call call_julienne_assert_(x .approximates. y .within. tolerance, __FILE__, __LINE__) + call call_julienne_assert_(allocated(a), __FILE__, __LINE__) ``` -and where dots (`.`) delimit Julienne operators and the parenthetical expression -evaluates to a Julienne `test_diagnosis_t` object. +and where dots (`.`) delimit Julienne operators. The above expression containing +Julienne operators evaluates to a Julienne `test_diagnosis_t` object, whereas +expression `allocated(a)` on the subsequent line evaluates to a `logical` value. +If an assertion containing a Julienne expression fails, Julienne inserts diagnostic +information into the stop code in an ultimate `error stop`. If an expression +evaluates to a `logical` value of `false.`, the error stop code will contain a +literal copy of the expression (e.g., `allocated(a)`). In either case, Julienne +also inserts the file and line number into the stop code using via the `__FILE__` +and `__LINE__` macros, respectively. Most compilers write the resulting stop code +to `error_unit`. ### Writing Unit Tests Writing tests using Julienne involves constructing a test-description array, diff --git a/fpm.toml b/fpm.toml index a2d5f1dd2..251ef84ee 100644 --- a/fpm.toml +++ b/fpm.toml @@ -1,7 +1,7 @@ name = "julienne" [dependencies] -assert = {git = "https://github.com/berkeleylab/assert", tag = "3.0.0"} +assert = {git = "https://github.com/berkeleylab/assert", tag = "3.0.2"} [install] library = true diff --git a/src/julienne/julienne_assert_m.f90 b/src/julienne/julienne_assert_m.f90 new file mode 100644 index 000000000..8fe2570ae --- /dev/null +++ b/src/julienne/julienne_assert_m.f90 @@ -0,0 +1,53 @@ +! Copyright (c) 2024-2025, The Regents of the University of California and Sourcery Institute +! Terms of use are as specified in LICENSE.txt + +module julienne_assert_m + !! Define interfaces for writing assertions + use julienne_test_diagnosis_m, only : test_diagnosis_t + implicit none + + private + public :: call_julienne_assert_ + public :: julienne_assert + + interface call_julienne_assert_ + + pure module subroutine julienne_assert(test_diagnosis, file, line) + !! This subroutine wraps the Assert library's `assert` subroutine. + !! + !! Use Cases + !! --------- + !! 1. Invoke julienne_assert via the generic interface `call_julienne_assert` to + !! facilitate complete removal when compiling without the flag `-DASSERTIONS`. + !! 2. Invoke julienne_assert via direct procedure call to guarantee execution. + !! + !! Usage + !! ----- + !! Make the only actual argument an expression containing `test_diagnosis_t` defined + !! operations, such as `x .approximates. y .within. tolerance`. The expression + !! result will be a `test_diagnosis_t` object on which `julienne_assert` will invoke + !! the `diagnostics_string()` type-bound procedure, the result of which julienne_assert + !! will include in the stop code of an `error stop` if the expresssion is untrue. + !! The resulting stop code will contain such information as the operand values and + !! roles (expected value, actual value, tolerance value). In use case 1, compiling + !! with `-DASSERTIONS` will cause the preprocessor to insert the corresponding + !! invocations's line number and the encompassing file's name as the `file` and `line` + !! arguments, respectively, which `julienne_assert` will include in the stop code. + !! Most compilers will write the stop code to `error_unit`. + !! + !! If a literal reproduction of the test expression suffices, such as when the + !! expression is `allocated(a)`, then instead invoke the Assert library's `assert` + !! subroutine by that library's `call_assert` macro or by direct call. + !! When invoking via the macro, make the only actual argument, `assertion`, a + !! `logical` expression. Then if compiling with `-DASSERTIONS` and if the assertion + !! evaluates to `.false.`, the stop code will include the text of the expression + !! argument, the file name, and the line number of the `call_assert` macro invocation. + implicit none + type(test_diagnosis_t), intent(in) :: test_diagnosis + character(len=*), intent(in), optional :: file + integer, intent(in), optional :: line + end subroutine + + end interface + +end module julienne_assert_m diff --git a/src/julienne/julienne_assert_s.f90 b/src/julienne/julienne_assert_s.f90 new file mode 100644 index 000000000..a3380069e --- /dev/null +++ b/src/julienne/julienne_assert_s.f90 @@ -0,0 +1,19 @@ +! Copyright (c) 2024-2025, The Regents of the University of California and Sourcery Institute +! Terms of use are as specified in LICENSE.txt + +submodule(julienne_assert_m) julienne_assert_s + use assert_m, only : assert_always + use julienne_m, only : string_t + implicit none + +contains + + module procedure julienne_assert + character(len=:), allocatable :: diagnostics_string + diagnostics_string = test_diagnosis%diagnostics_string() + if (present(file)) diagnostics_string = diagnostics_string // " in file " // file + if (present(line)) diagnostics_string = diagnostics_string // " at line " // string_t(line) + call assert_always(test_diagnosis%test_passed(), diagnostics_string) + end procedure + +end submodule julienne_assert_s diff --git a/src/julienne/julienne_bin_s.F90 b/src/julienne/julienne_bin_s.F90 index 094352195..a9be91e13 100644 --- a/src/julienne/julienne_bin_s.F90 +++ b/src/julienne/julienne_bin_s.F90 @@ -1,17 +1,17 @@ ! Copyright (c) 2024-2025, The Regents of the University of California and Sourcery Institute ! Terms of use are as specified in LICENSE.txt -#include "assert_macros.h" +#include "julienne-assert-macros.h" submodule(julienne_bin_m) julienne_bin_s - use assert_m + use julienne_m, only : call_julienne_assert_, operator(.isAtLeast.) implicit none contains module procedure construct - call_assert(num_items>=num_bins) + call_julienne_assert(num_items .isAtLeast. num_bins) associate( remainder => mod(num_items, num_bins), items_per_bin => num_items/num_bins) diff --git a/src/julienne/julienne_command_line_m.f90 b/src/julienne/julienne_command_line_m.f90 index 5c13d1276..c555d7e0d 100644 --- a/src/julienne/julienne_command_line_m.f90 +++ b/src/julienne/julienne_command_line_m.f90 @@ -1,5 +1,6 @@ ! Copyright (c) 2024-2025, The Regents of the University of California and Sourcery Institute ! Terms of use are as specified in LICENSE.txt + module julienne_command_line_m !! return command line argument information implicit none diff --git a/src/julienne/julienne_command_line_s.f90 b/src/julienne/julienne_command_line_s.f90 index ddffdcc59..5413b87dd 100644 --- a/src/julienne/julienne_command_line_s.f90 +++ b/src/julienne/julienne_command_line_s.f90 @@ -1,5 +1,6 @@ ! Copyright (c) 2024-2025, The Regents of the University of California and Sourcery Institute ! Terms of use are as specified in LICENSE.txt + submodule(julienne_command_line_m) julienne_command_line_s implicit none diff --git a/src/julienne/julienne_file_m.f90 b/src/julienne/julienne_file_m.f90 index 1fae2a5cf..7a113638b 100644 --- a/src/julienne/julienne_file_m.f90 +++ b/src/julienne/julienne_file_m.f90 @@ -1,5 +1,6 @@ ! Copyright (c) 2024-2025, The Regents of the University of California and Sourcery Institute ! Terms of use are as specified in LICENSE.txt + module julienne_file_m !! A representation of a file as an object use julienne_string_m, only : string_t diff --git a/src/julienne/julienne_formats_m.F90 b/src/julienne/julienne_formats_m.F90 index 386b8d08f..345201516 100644 --- a/src/julienne/julienne_formats_m.F90 +++ b/src/julienne/julienne_formats_m.F90 @@ -1,5 +1,6 @@ ! Copyright (c) 2024-2025, The Regents of the University of California and Sourcery Institute ! Terms of use are as specified in LICENSE.txt + module julienne_formats_m !! Useful strings for formatting `print` and `write` statements implicit none diff --git a/src/julienne/julienne_formats_s.F90 b/src/julienne/julienne_formats_s.F90 index 62adb6680..f2f3ac3d3 100644 --- a/src/julienne/julienne_formats_s.F90 +++ b/src/julienne/julienne_formats_s.F90 @@ -1,5 +1,6 @@ ! Copyright (c) 2024-2025, The Regents of the University of California and Sourcery Institute ! Terms of use are as specified in LICENSE.txt + submodule(julienne_formats_m) julienne_formats_s !! Construct separated-value formats implicit none diff --git a/src/julienne/julienne_github_ci_m.f90 b/src/julienne/julienne_github_ci_m.f90 index 466085dc7..c43c7b8da 100644 --- a/src/julienne/julienne_github_ci_m.f90 +++ b/src/julienne/julienne_github_ci_m.f90 @@ -1,5 +1,6 @@ ! Copyright (c) 2024-2025, The Regents of the University of California and Sourcery Institute ! Terms of use are as specified in LICENSE.txt + module julienne_github_ci_m !! Detect whether a program is running in GitHub Continuous Integration (CI) implicit none diff --git a/src/julienne/julienne_github_ci_s.f90 b/src/julienne/julienne_github_ci_s.f90 index 893ee1824..37eedb17d 100644 --- a/src/julienne/julienne_github_ci_s.f90 +++ b/src/julienne/julienne_github_ci_s.f90 @@ -1,5 +1,6 @@ ! Copyright (c) 2024-2025, The Regents of the University of California and Sourcery Institute ! Terms of use are as specified in LICENSE.txt + submodule(julienne_github_ci_m) julienne_github_ci_s implicit none diff --git a/src/julienne/julienne_string_m.f90 b/src/julienne/julienne_string_m.f90 index ed5c4a5fb..6742273af 100644 --- a/src/julienne/julienne_string_m.f90 +++ b/src/julienne/julienne_string_m.f90 @@ -1,5 +1,6 @@ ! Copyright (c) 2024-2025, The Regents of the University of California and Sourcery Institute ! Terms of use are as specified in LICENSE.txt + module julienne_string_m use iso_c_binding, only : c_bool implicit none diff --git a/src/julienne/julienne_string_s.F90 b/src/julienne/julienne_string_s.F90 index 77306e7a5..f5323805c 100644 --- a/src/julienne/julienne_string_s.F90 +++ b/src/julienne/julienne_string_s.F90 @@ -1,9 +1,12 @@ ! Copyright (c) 2024-2025, The Regents of the University of California and Sourcery Institute ! Terms of use are as specified in LICENSE.txt + +#include "julienne-assert-macros.h" #include "assert_macros.h" submodule(julienne_string_m) julienne_string_s use assert_m + use julienne_m, only : call_julienne_assert_, operator(.equalsExpected.) implicit none integer, parameter :: integer_width_supremum = 11, default_real_width_supremum = 20, double_precision_width_supremum = 25 @@ -185,7 +188,7 @@ module procedure get_real character(len=:), allocatable :: raw_line, string_value - call_assert(key==self%get_json_key()) + call_julienne_assert(self%get_json_key() .equalsExpected. key) raw_line = self%string() associate(text_after_colon => raw_line(index(raw_line, ':')+1:)) @@ -204,7 +207,7 @@ module procedure get_double_precision character(len=:), allocatable :: raw_line, string_value - call_assert(key==self%get_json_key()) + call_julienne_assert(self%get_json_key() .equalsExpected. key) raw_line = self%string() associate(text_after_colon => raw_line(index(raw_line, ':')+1:)) @@ -247,7 +250,7 @@ character(len=:), allocatable :: raw_line integer i, comma, opening_quotes, closing_quotes - call_assert(key==self%get_json_key()) + call_julienne_assert(self%get_json_key() .equalsExpected. key) raw_line = self%string() @@ -275,7 +278,7 @@ character(len=:), allocatable :: raw_line - call_assert(key==self%get_json_key()) + call_julienne_assert(self%get_json_key() .equalsExpected. key) raw_line = self%string() associate(text_after_colon => raw_line(index(raw_line, ':')+1:)) @@ -299,7 +302,7 @@ module procedure get_logical character(len=:), allocatable :: raw_line, string_value - call_assert(key==self%get_json_key()) + call_julienne_assert(self%get_json_key() .equalsExpected. key) raw_line = self%string() associate(text_after_colon => raw_line(index(raw_line, ':')+1:)) @@ -309,7 +312,7 @@ else string_value = trim(adjustl((text_after_colon(:trailing_comma-1)))) end if - call_assert(string_value=="true" .or. string_value=="false") + call_assert(any(string_value==['true ', 'false'])) value_ = string_value == "true" end associate end associate @@ -319,7 +322,7 @@ module procedure get_integer character(len=:), allocatable :: raw_line, string_value - call_assert(key==self%get_json_key()) + call_julienne_assert(self%get_json_key() .equalsExpected. key) raw_line = self%string() associate(text_after_colon => raw_line(index(raw_line, ':')+1:)) @@ -360,7 +363,7 @@ real, allocatable :: real_array(:) integer i - call_assert(key==self%get_json_key()) + call_julienne_assert(self%get_json_key() .equalsExpected. key) raw_line = self%string() associate(colon => index(raw_line, ":")) @@ -384,7 +387,7 @@ double precision, allocatable :: double_precision_array(:) integer i - call_assert(key==self%get_json_key()) + call_julienne_assert(self%get_json_key() .equalsExpected. key) raw_line = self%string() associate(colon => index(raw_line, ":")) diff --git a/src/julienne/julienne_test_description_m.f90 b/src/julienne/julienne_test_description_m.f90 index 432ad7201..29deb2d16 100644 --- a/src/julienne/julienne_test_description_m.f90 +++ b/src/julienne/julienne_test_description_m.f90 @@ -1,5 +1,6 @@ ! Copyright (c) 2024-2025, The Regents of the University of California and Sourcery Institute ! Terms of use are as specified in LICENSE.txt + module julienne_test_description_m !! Define an abstraction for describing test intentions and test functions use julienne_string_m, only : string_t diff --git a/src/julienne/julienne_test_description_s.F90 b/src/julienne/julienne_test_description_s.F90 index 45c3dffbd..5f0ed2328 100644 --- a/src/julienne/julienne_test_description_s.F90 +++ b/src/julienne/julienne_test_description_s.F90 @@ -1,10 +1,12 @@ ! Copyright (c) 20242-2025, The Regents of the University of California and Sourcery Institute ! Terms of use are as specified in LICENSE.txt +#include "julienne-assert-macros.h" #include "assert_macros.h" submodule(julienne_test_description_m) julienne_test_description_s use assert_m + use julienne_m, only : call_julienne_assert_ implicit none contains diff --git a/src/julienne/julienne_test_diagnosis_m.F90 b/src/julienne/julienne_test_diagnosis_m.F90 index fe1e7a642..901866a84 100644 --- a/src/julienne/julienne_test_diagnosis_m.F90 +++ b/src/julienne/julienne_test_diagnosis_m.F90 @@ -4,15 +4,12 @@ #include "language-support.F90" module julienne_test_diagnosis_m - !! Define abstractions, defined operations, and procedures for writing correctness checks in - !! the form of assertions and tests. + !! Define abstractions, defined operations, and procedures for writing correctness checks use julienne_string_m, only : string_t implicit none private public :: test_diagnosis_t - public :: call_julienne_assert_ - public :: julienne_assert public :: operator(.all.) public :: operator(.and.) public :: operator(.also.) @@ -33,7 +30,7 @@ module julienne_test_diagnosis_m type test_diagnosis_t !! Encapsulate test outcome and diagnostic information private - logical test_passed_ + logical :: test_passed_ = .false. character(len=:), allocatable :: diagnostics_string_ contains procedure test_passed @@ -57,20 +54,6 @@ module julienne_test_diagnosis_m end type #endif - interface call_julienne_assert_ - - pure module subroutine julienne_assert(test_diagnosis, file, line) - !! Use cases: - !! 1. When invoked via the generic interface, the preprocessor passes the 'file' and 'line' dummy arguments automatically. - !! 2. When invoked directly, there is 1 argument: an expression containing defined operations such as 1 .equalsExpected. 1 - implicit none - type(test_diagnosis_t), intent(in) :: test_diagnosis - character(len=*), intent(in), optional :: file - integer, intent(in), optional :: line - end subroutine - - end interface - interface operator(.all.) #ifndef __GFORTRAN__ diff --git a/src/julienne/julienne_test_diagnosis_s.F90 b/src/julienne/julienne_test_diagnosis_s.F90 index 249fb974c..241a032b9 100644 --- a/src/julienne/julienne_test_diagnosis_s.F90 +++ b/src/julienne/julienne_test_diagnosis_s.F90 @@ -6,7 +6,7 @@ submodule(julienne_test_diagnosis_m) julienne_test_diagnosis_s use assert_m - use julienne_string_m, only : operator(.csv.), operator(.cat.) + use julienne_m, only : operator(.cat.) implicit none contains @@ -541,12 +541,4 @@ pure function aggregate_vector_diagnosis(diagnoses) result(diagnosis) string_ = string_t(self%diagnostics_string_) end procedure - module procedure julienne_assert - character(len=:), allocatable :: diagnostics_string - diagnostics_string = test_diagnosis%diagnostics_string_ - if (present(file)) diagnostics_string = diagnostics_string // " in file " // file - if (present(line)) diagnostics_string = diagnostics_string // " at line " // string_t(line) - call assert_always(test_diagnosis%test_passed_, diagnostics_string) - end procedure - end submodule julienne_test_diagnosis_s diff --git a/src/julienne/julienne_test_result_m.f90 b/src/julienne/julienne_test_result_m.f90 index dcca9e018..bbb48ece1 100644 --- a/src/julienne/julienne_test_result_m.f90 +++ b/src/julienne/julienne_test_result_m.f90 @@ -1,5 +1,6 @@ ! Copyright (c) 2024-2025, The Regents of the University of California and Sourcery Institute ! Terms of use are as specified in LICENSE.txt + module julienne_test_result_m !! Define an abstraction for describing test intentions and results use julienne_string_m, only : string_t diff --git a/src/julienne/julienne_test_result_s.f90 b/src/julienne/julienne_test_result_s.f90 index 166529109..7ab620c41 100644 --- a/src/julienne/julienne_test_result_s.f90 +++ b/src/julienne/julienne_test_result_s.f90 @@ -1,5 +1,6 @@ ! Copyright (c) 2024-2025, The Regents of the University of California and Sourcery Institute ! Terms of use are as specified in LICENSE.txt + submodule(julienne_test_result_m) julienne_test_result_s use julienne_user_defined_collectives_m, only : co_all implicit none diff --git a/src/julienne/julienne_user_defined_collectives_m.f90 b/src/julienne/julienne_user_defined_collectives_m.f90 index 2c8da12da..57973a3e7 100644 --- a/src/julienne/julienne_user_defined_collectives_m.f90 +++ b/src/julienne/julienne_user_defined_collectives_m.f90 @@ -4,6 +4,7 @@ ! "Multi-Dimensional Physics Implementation into Fuel Analysis under Steady-state and Transients (FAST)", ! contract # NRC-HQ-60-17-C-0007 ! + module julienne_user_defined_collectives_m !! User-defined collective subroutines. implicit none diff --git a/src/julienne/julienne_vector_test_description_m.F90 b/src/julienne/julienne_vector_test_description_m.F90 index d3ac452eb..4d3da0a7a 100644 --- a/src/julienne/julienne_vector_test_description_m.F90 +++ b/src/julienne/julienne_vector_test_description_m.F90 @@ -1,5 +1,6 @@ ! Copyright (c) 2024-2025, The Regents of the University of California and Sourcery Institute ! Terms of use are as specified in LICENSE.txt + module julienne_vector_test_description_m !! Define an abstraction for describing test intentions and array-valued test functions use julienne_string_m, only : string_t diff --git a/src/julienne/julienne_vector_test_description_s.F90 b/src/julienne/julienne_vector_test_description_s.F90 index fd091d79b..307593f14 100644 --- a/src/julienne/julienne_vector_test_description_s.F90 +++ b/src/julienne/julienne_vector_test_description_s.F90 @@ -1,9 +1,11 @@ ! Copyright (c) 2024-2025, The Regents of the University of California and Sourcery Institute ! Terms of use are as specified in LICENSE.txt +#include "julienne-assert-macros.h" #include "assert_macros.h" submodule(julienne_vector_test_description_m) julienne_vector_test_description_s + use julienne_m, only : call_julienne_assert_, operator(.equalsExpected.) use assert_m implicit none @@ -45,7 +47,7 @@ module function construct_from_strings(descriptions, vector_diagnosis_function) associate(diagnoses => self%vector_diagnosis_function_()) #if defined(ASSERTIONS) associate(num_descriptions => size(self%descriptions_), num_results => size(diagnoses)) - call_assert(num_descriptions == num_results) + call_julienne_assert(num_descriptions .equalsExpected. num_results) end associate #endif test_results = test_result_t(self%descriptions_, diagnoses) diff --git a/src/julienne_m.f90 b/src/julienne_m.f90 index cd232fa14..1540f6556 100644 --- a/src/julienne_m.f90 +++ b/src/julienne_m.f90 @@ -1,17 +1,24 @@ ! Copyright (c) 2024-2025, The Regents of the University of California and Sourcery Institute ! Terms of use are as specified in LICENSE.txt + module julienne_m !! Global aggregation of all public entities + use julienne_assert_m, only : call_julienne_assert_, julienne_assert use julienne_bin_m, only : bin_t use julienne_command_line_m, only : command_line_t use julienne_file_m, only : file_t use julienne_formats_m, only : separated_values, csv use julienne_github_ci_m, only : github_ci + use julienne_string_m, only : & + string_t & + ,array_of_strings & + ,operator(.cat.) & + ,operator(.csv.) & + ,operator(.separatedBy.) & ! same as operator(.sv.) + ,operator(.sv.) use julienne_test_description_m, only : test_description_t, diagnosis_function_i use julienne_test_diagnosis_m, only : & test_diagnosis_t & - ,call_julienne_assert_ & - ,julienne_assert & ,operator(.all.) & ,operator(.and.) & ,operator(.also.) & @@ -28,13 +35,6 @@ module julienne_m ,operator(.within.) & ,operator(.withinFraction.) & ,operator(.withinPercentage.) - use julienne_string_m, only : & - string_t & - ,array_of_strings & - ,operator(.cat.) & - ,operator(.csv.) & - ,operator(.separatedBy.) & ! same as operator(.sv.) - ,operator(.sv.) use julienne_test_m, only : test_t, test_description_substring use julienne_test_result_m, only : test_result_t diff --git a/test/false-assertion.F90 b/test/false-assertion.F90 deleted file mode 100644 index 1fc4cbe12..000000000 --- a/test/false-assertion.F90 +++ /dev/null @@ -1,18 +0,0 @@ -! Copyright (c) 2024-2025, The Regents of the University of California and Sourcery Institute -! Terms of use are as specified in LICENSE.txt - -program false_assertion - !! Test an assertion that is hardwired to fail by directly calling julienne_assert - !! with a false test_diagnosis_t expression. - -#ifdef RUN_FALSE_ASSERTIONS - - use julienne_m, only : operator(.equalsExpected.), julienne_assert - implicit none - - call julienne_assert(1 .equalsExpected. 2) - -#endif - -end program - diff --git a/test/modules/assert_test_m.F90 b/test/modules/assert_test_m.F90 index f4acae7f4..5933b469a 100644 --- a/test/modules/assert_test_m.F90 +++ b/test/modules/assert_test_m.F90 @@ -3,12 +3,15 @@ #include "language-support.F90" #include "julienne-assert-macros.h" +#include "assert_macros.h" module assert_test_m - !! Test Julienne's assert generic interface - + !! Test Julienne's call_julienne_assert generic interface + use assert_m ! Import call_assert macro use julienne_m, only : & call_julienne_assert_ & + ,julienne_assert & + ,operator(.equalsExpected.) & ,test_diagnosis_t & ,test_t & ,test_description_t & @@ -31,7 +34,7 @@ module assert_test_m pure function subject() result(specimen) character(len=:), allocatable :: specimen - specimen = "The call_julienne_assert macro" + specimen = "The julienne_assert subroutine" end function #if HAVE_PROCEDURE_ACTUAL_FOR_POINTER_DUMMY @@ -40,7 +43,9 @@ function results() result(test_results) type(test_result_t), allocatable :: test_results(:) associate(descriptions => [ & - test_description_t("invocation with an expression containing Julienne operators", check_macro_with_expression) & + test_description_t("invocation via the call_julienne_assert macro", check_call_julienne_assert_macro) & + ,test_description_t("invocation via direct call", check_julienne_assert_call) & + ,test_description_t("invocation removal after undefining the ASSERTIONS macro", check_macro_removal) & ]) associate(substring_in_subject => index(subject(), test_description_substring) /= 0) associate(substring_in_test_diagnosis => descriptions%contains_text(test_description_substring)) @@ -61,10 +66,13 @@ function results() result(test_results) type(test_result_t), allocatable :: test_results(:) type(test_description_t), allocatable :: descriptions(:) procedure(diagnosis_function_i), pointer :: & - check_macro_with_expression_ptr => check_macro_with_expression - + check_call_julienne_assert_macro_ptr => check_call_julienne_assert_macro & + ,check_julienne_assert_call_ptr => check_julienne_assert_call & + ,check_macro_removal_ptr => check_macro_removal descriptions = [ & - test_description_t("invocation via macro with an expression containing Julienne operators", check_macro_with_expression_ptr)& + test_description_t("invoking the call_julienne_assert macro", check_call_julienne_assert_macro_ptr) & + ,test_description_t("directly calling julienne_assert", check_julienne_assert_call_ptr) & + ,test_description_t("removal when the ASSERTIONS macro is defined as 0", check_macro_removal_ptr) & ] block @@ -81,10 +89,24 @@ function results() result(test_results) #endif - function check_macro_with_expression() result(test_diagnosis) + function check_call_julienne_assert_macro() result(test_diagnosis) type(test_diagnosis_t) test_diagnosis call_julienne_assert(1. .approximates. 2. .within. 3.) - test_diagnosis = test_diagnosis_t(.true., "") + test_diagnosis = test_diagnosis_t(test_passed=.true., diagnostics_string="") + end function + + function check_julienne_assert_call() result(test_diagnosis) + type(test_diagnosis_t) test_diagnosis + call julienne_assert(1. .approximates. 2. .within. 3.) + test_diagnosis = test_diagnosis_t(test_passed=.true., diagnostics_string="") + end function + + function check_macro_removal() result(test_diagnosis) + type(test_diagnosis_t) test_diagnosis +#undef ASSERTIONS +#include "julienne-assert-macros.h" + call_julienne_assert(5 .equalsExpected. 9) + test_diagnosis = test_diagnosis_t(test_passed=.true., diagnostics_string="") end function end module assert_test_m diff --git a/test/test-julienne_assert-intentional-failure.F90 b/test/test-julienne_assert-intentional-failure.F90 new file mode 100644 index 000000000..1b30dda14 --- /dev/null +++ b/test/test-julienne_assert-intentional-failure.F90 @@ -0,0 +1,26 @@ +! Copyright (c) 2024-2025, The Regents of the University of California and Sourcery Institute +! Terms of use are as specified in LICENSE.txt + +#include "julienne-assert-macros.h" + +program test_julienne_assert_intentional_failure + !! Conditionally test an assertion that is hardwired to fail. + +#ifdef RUN_FALSE_ASSERTIONS + + use julienne_m, only : operator(.equalsExpected.), call_julienne_assert_ + implicit none + print '(a)', new_line('') // 'Test julienne_assert intentional failure: ' // new_line('') + call_julienne_assert(1 .equalsExpected. 2) + +#else + + print * + print '(a)', 'Skipping the test in ' // __FILE__ // '.' + print '(a)', 'Add the following to your fpm command to test assertion failure: --flag "-DASSERTIONS -DRUN_FALSE_ASSERTIONS"' + print * + +#endif + +end program +