Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add test_description_t tests simplify derived type #27

Merged
merged 4 commits into from
Dec 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [macos-12, ubuntu-24.04]
os: [macos-13, ubuntu-24.04]

steps:
- name: Checkout code
Expand Down
16 changes: 13 additions & 3 deletions src/julienne/julienne_test_result_m.f90
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@ module julienne_test_result_m
type test_result_t
!! Encapsulate test descriptions and outcomes
private
type(string_t) description_
character(len=:), allocatable :: description_
logical passed_
contains
procedure :: characterize
procedure :: passed
procedure :: description_contains
generic :: description_contains => description_contains_string, description_contains_characters
procedure, private :: description_contains_string
procedure, private :: description_contains_characters
end type

interface test_result_t
Expand Down Expand Up @@ -55,14 +57,22 @@ impure elemental module function passed(self) result(test_passed)
logical test_passed
end function

elemental module function description_contains(self, substring) result(substring_found)
elemental module function description_contains_string(self, substring) result(substring_found)
!! The result is true if and only if the test description contains the substring
implicit none
class(test_result_t), intent(in) :: self
type(string_t), intent(in) :: substring
logical substring_found
end function

elemental module function description_contains_characters(self, substring) result(substring_found)
!! The result is true if and only if the test description contains the substring
implicit none
class(test_result_t), intent(in) :: self
character(len=*), intent(in) :: substring
logical substring_found
end function

end interface

end module julienne_test_result_m
10 changes: 7 additions & 3 deletions src/julienne/julienne_test_result_s.f90
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,20 @@
end procedure

module procedure characterize
characterization = trim(merge("passes on ", "FAILS on ", self%passed_)) // " " // trim(self%description_%string()) // "."
characterization = trim(merge("passes on ", "FAILS on ", self%passed_)) // " " // trim(self%description_) // "."
end procedure

module procedure passed
test_passed = self%passed_
call co_all(test_passed)
end procedure

module procedure description_contains
substring_found = index(self%description_%string(), substring%string()) /= 0
module procedure description_contains_string
substring_found = index(self%description_, substring%string()) /= 0
end procedure

module procedure description_contains_characters
substring_found = index(self%description_, substring) /= 0
end procedure

end submodule julienne_test_result_s
95 changes: 87 additions & 8 deletions test/test_description_test.F90
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,14 @@

module test_description_test_m
!! Verify test_description_t object behavior
use julienne_m, only : string_t, test_result_t, test_description_t, test_t, test_description_substring
use julienne_m, only : &
string_t &
,test_result_t &
,test_description_t &
,test_t &
,test_description_substring &
,vector_test_description_t &
,vector_function_strategy_t
#if ! HAVE_PROCEDURE_ACTUAL_FOR_POINTER_DUMMY
use julienne_m, only : test_function_i
#endif
Expand All @@ -20,6 +27,11 @@ module test_description_test_m
procedure, nopass :: results
end type

type, extends(vector_function_strategy_t) :: substring_search_test_function_t
contains
procedure, nopass :: vector_function => check_substring_search
end type

contains

pure function subject() result(specimen)
Expand All @@ -28,28 +40,63 @@ pure function subject() result(specimen)
end function

function results() result(test_results)
type(test_result_t), allocatable :: test_results(:)
type(test_description_t), allocatable :: test_descriptions(:)
type(test_result_t), allocatable :: test_results(:), vector_test_results(:)
type(test_description_t), allocatable :: scalar_test_descriptions(:)
type(vector_test_description_t), allocatable :: vector_test_descriptions(:)
type(substring_search_test_function_t) substring_search_test_function

#if HAVE_PROCEDURE_ACTUAL_FOR_POINTER_DUMMY
test_descriptions = [ &
scalar_test_descriptions = [ &
test_description_t("identical construction from string_t or character arguments", check_character_constructor) &
]
#else
! Work around missing Fortran 2008 feature: associating a procedure actual argument with a procedure pointer dummy argument:
procedure(test_function_i), pointer :: check_character_ptr
check_character_ptr => check_character_constructor
test_descriptions = [ &
scalar_test_descriptions = [ &
test_description_t("identical construction from string_t or character arguments", check_character_ptr) &
]
#endif

vector_test_descriptions = [ &
vector_test_description_t( &
[ string_t("finding a string_t substring in a test description") &
,string_t("finding an assumed-length character substring in a test description") &
,string_t("not finding a missing string_t substring in a test description") &
,string_t("not finding a missing assumed-length character substring in a test description") &
], substring_search_test_function &
) &
]

associate( &
substring_in_subject => index(subject(), test_description_substring) /= 0, &
substring_in_description => test_descriptions%contains_text(string_t(test_description_substring)) &
substring_in_description => scalar_test_descriptions%contains_text(string_t(test_description_substring)), &
num_vector_tests => size(vector_test_descriptions) &
)
test_descriptions = pack(test_descriptions, substring_in_subject .or. substring_in_description)
scalar_test_descriptions = pack(scalar_test_descriptions, substring_in_subject .or. substring_in_description)

block
integer i

associate( &
substring_in_description_vector => &
[(any(vector_test_descriptions(i)%contains_text(test_description_substring)), i=1,num_vector_tests)] &
)
if (substring_in_subject) then
vector_test_results = [(vector_test_descriptions(i)%run(), i=1,num_vector_tests)]
else if (any(substring_in_description_vector)) then
vector_test_descriptions = pack(vector_test_descriptions, substring_in_description_vector)
vector_test_results = [(vector_test_descriptions(i)%run(), i=1,size(vector_test_descriptions))]
vector_test_results = &
pack(vector_test_results, vector_test_results%description_contains(string_t(test_description_substring)))
else
vector_test_results = [test_result_t::]
end if
test_results = [scalar_test_descriptions%run(), vector_test_results]
end associate
end block
end associate
test_results = test_descriptions%run()

end function

function check_character_constructor() result(passed)
Expand All @@ -67,4 +114,36 @@ logical function tautology()
end function
end function

function check_substring_search() result(tests_pass)
logical, allocatable :: tests_pass(:)
type(test_description_t), allocatable :: test_descriptions(:)

#if ! HAVE_PROCEDURE_ACTUAL_FOR_POINTER_DUMMY

procedure(test_function_i), pointer :: null_ptr
null_ptr => null()

test_descriptions = [ &
test_description_t("an example substring" , null_ptr) &
,test_description_t("another example substring", null_ptr) &
,test_description_t("moving right along" , null_ptr) &
,test_description_t("nothing to see here" , null_ptr) &
]
#else

test_descriptions = [ &
test_description_t("an example substring" , null()) &
,test_description_t("another example substring", null()) &
,test_description_t("moving right along" , null()) &
,test_description_t("nothing to see here" , null()) &
]
#endif
tests_pass = [ &
test_descriptions(1)%contains_text(string_t("example") ) &
, test_descriptions(2)%contains_text( "example" ) &
,.not. test_descriptions(3)%contains_text(string_t("missing string")) &
,.not. test_descriptions(4)%contains_text( "missing string" ) &
]
end function

end module test_description_test_m
Loading