Skip to content

Commit f58da3b

Browse files
authored
Merge pull request #494 from awvwgk/test
Add testing module to allow better structuring of test suites
2 parents ac80d30 + d2e0fe3 commit f58da3b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+10569
-6861
lines changed

Diff for: ci/fpm-deployment.sh

+1-2
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ include=(
2424
prune=(
2525
"$destdir/test/test_always_fail.f90"
2626
"$destdir/test/test_always_skip.f90"
27-
"$destdir/test/test_mean_f03.f90"
2827
"$destdir/src/common.f90"
2928
"$destdir/src/f18estop.f90"
3029
)
@@ -43,7 +42,7 @@ find src/tests -name "*.dat" -exec cp {} "$destdir/" \;
4342
# Include additional files
4443
cp "${include[@]}" "$destdir/"
4544

46-
# Source file workarounds for fpm
45+
# Source file workarounds for fpm; ignore missing files
4746
rm "${prune[@]}"
4847

4948
# List stdlib-fpm package contents

Diff for: ci/fpm.toml

+3
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,6 @@ license = "MIT"
44
author = "stdlib contributors"
55
maintainer = "@fortran-lang/stdlib"
66
copyright = "2019-2021 stdlib contributors"
7+
8+
[dev-dependencies]
9+
test-drive.git = "https://github.com/fortran-lang/test-drive"

Diff for: config/CMakeLists.txt

+3
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ if(NOT DEFINED CMAKE_INSTALL_MODULEDIR)
1010
)
1111
endif()
1212

13+
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
14+
set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}" PARENT_SCOPE)
15+
1316
# Export a pkg-config file
1417
configure_file(
1518
"${CMAKE_CURRENT_SOURCE_DIR}/template.pc"

Diff for: config/cmake/Findtest-drive.cmake

+178
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
# SPDX-Identifier: MIT
2+
3+
#[[.rst:
4+
Find test-drive
5+
---------------
6+
7+
Makes the test-drive project available.
8+
9+
Imported Targets
10+
^^^^^^^^^^^^^^^^
11+
12+
This module provides the following imported target, if found:
13+
14+
``test-drive::test-drive``
15+
The test-drive library
16+
17+
18+
Result Variables
19+
^^^^^^^^^^^^^^^^
20+
21+
This module will define the following variables:
22+
23+
``TEST_DRIVE_FOUND``
24+
True if the test-drive library is available
25+
26+
``TEST_DRIVE_SOURCE_DIR``
27+
Path to the source directory of the test-drive project,
28+
only set if the project is included as source.
29+
30+
``TEST_DRIVE_BINARY_DIR``
31+
Path to the binary directory of the test-drive project,
32+
only set if the project is included as source.
33+
34+
Cache variables
35+
^^^^^^^^^^^^^^^
36+
37+
The following cache variables may be set to influence the library detection:
38+
39+
``TEST_DRIVE_FIND_METHOD``
40+
Methods to find or make the project available. Available methods are
41+
- ``cmake``: Try to find via CMake config file
42+
- ``pkgconf``: Try to find via pkg-config file
43+
- ``subproject``: Use source in subprojects directory
44+
- ``fetch``: Fetch the source from upstream
45+
46+
``TEST_DRIVE_DIR``
47+
Used for searching the CMake config file
48+
49+
``TEST_DRIVE_SUBPROJECT``
50+
Directory to find the test-drive subproject, relative to the project root
51+
52+
#]]
53+
54+
set(_lib "test-drive")
55+
set(_pkg "TEST_DRIVE")
56+
set(_url "https://github.com/fortran-lang/test-drive")
57+
58+
if(NOT DEFINED "${_pkg}_FIND_METHOD")
59+
if(DEFINED "${PROJECT_NAME}-dependency-method")
60+
set("${_pkg}_FIND_METHOD" "${${PROJECT_NAME}-dependency-method}")
61+
else()
62+
set("${_pkg}_FIND_METHOD" "cmake" "pkgconf" "subproject" "fetch")
63+
endif()
64+
set("_${_pkg}_FIND_METHOD")
65+
endif()
66+
67+
foreach(method ${${_pkg}_FIND_METHOD})
68+
if(TARGET "${_lib}::${_lib}")
69+
break()
70+
endif()
71+
72+
if("${method}" STREQUAL "cmake")
73+
message(STATUS "${_lib}: Find installed package")
74+
if(DEFINED "${_pkg}_DIR")
75+
set("_${_pkg}_DIR")
76+
set("${_lib}_DIR" "${_pkg}_DIR")
77+
endif()
78+
find_package("${_lib}" CONFIG QUIET)
79+
if("${_lib}_FOUND")
80+
message(STATUS "${_lib}: Found installed package")
81+
break()
82+
endif()
83+
endif()
84+
85+
if("${method}" STREQUAL "pkgconf")
86+
find_package(PkgConfig QUIET)
87+
pkg_check_modules("${_pkg}" QUIET "${_lib}")
88+
if("${_pkg}_FOUND")
89+
message(STATUS "Found ${_lib} via pkg-config")
90+
91+
add_library("${_lib}::${_lib}" INTERFACE IMPORTED)
92+
target_link_libraries(
93+
"${_lib}::${_lib}"
94+
INTERFACE
95+
"${${_pkg}_LINK_LIBRARIES}"
96+
)
97+
target_include_directories(
98+
"${_lib}::${_lib}"
99+
INTERFACE
100+
"${${_pkg}_INCLUDE_DIRS}"
101+
)
102+
103+
break()
104+
endif()
105+
endif()
106+
107+
if("${method}" STREQUAL "subproject")
108+
if(NOT DEFINED "${_pkg}_SUBPROJECT")
109+
set("_${_pkg}_SUBPROJECT")
110+
set("${_pkg}_SUBPROJECT" "subprojects/${_lib}")
111+
endif()
112+
set("${_pkg}_SOURCE_DIR" "${PROJECT_SOURCE_DIR}/${${_pkg}_SUBPROJECT}")
113+
set("${_pkg}_BINARY_DIR" "${PROJECT_BINARY_DIR}/${${_pkg}_SUBPROJECT}")
114+
if(EXISTS "${${_pkg}_SOURCE_DIR}/CMakeLists.txt")
115+
message(STATUS "Include ${_lib} from ${${_pkg}_SUBPROJECT}")
116+
add_subdirectory(
117+
"${${_pkg}_SOURCE_DIR}"
118+
"${${_pkg}_BINARY_DIR}"
119+
)
120+
121+
add_library("${_lib}::${_lib}" INTERFACE IMPORTED)
122+
target_link_libraries("${_lib}::${_lib}" INTERFACE "${_lib}")
123+
124+
# We need the module directory in the subproject before we finish the configure stage
125+
if(NOT EXISTS "${${_pkg}_BINARY_DIR}/include")
126+
make_directory("${${_pkg}_BINARY_DIR}/include")
127+
endif()
128+
129+
break()
130+
endif()
131+
endif()
132+
133+
if("${method}" STREQUAL "fetch")
134+
message(STATUS "Retrieving ${_lib} from ${_url}")
135+
include(FetchContent)
136+
FetchContent_Declare(
137+
"${_lib}"
138+
GIT_REPOSITORY "${_url}"
139+
GIT_TAG "HEAD"
140+
)
141+
FetchContent_MakeAvailable("${_lib}")
142+
143+
add_library("${_lib}::${_lib}" INTERFACE IMPORTED)
144+
target_link_libraries("${_lib}::${_lib}" INTERFACE "${_lib}")
145+
146+
# We need the module directory in the subproject before we finish the configure stage
147+
FetchContent_GetProperties("${_lib}" SOURCE_DIR "${_pkg}_SOURCE_DIR")
148+
FetchContent_GetProperties("${_lib}" BINARY_DIR "${_pkg}_BINARY_DIR")
149+
if(NOT EXISTS "${${_pkg}_BINARY_DIR}/include")
150+
make_directory("${${_pkg}_BINARY_DIR}/include")
151+
endif()
152+
153+
break()
154+
endif()
155+
156+
endforeach()
157+
158+
if(TARGET "${_lib}::${_lib}")
159+
set("${_pkg}_FOUND" TRUE)
160+
else()
161+
set("${_pkg}_FOUND" FALSE)
162+
endif()
163+
164+
if(DEFINED "_${_pkg}_SUBPROJECT")
165+
unset("${_pkg}_SUBPROJECT")
166+
unset("_${_pkg}_SUBPROJECT")
167+
endif()
168+
if(DEFINED "_${_pkg}_DIR")
169+
unset("${_lib}_DIR")
170+
unset("_${_pkg}_DIR")
171+
endif()
172+
if(DEFINED "_${_pkg}_FIND_METHOD")
173+
unset("${_pkg}_FIND_METHOD")
174+
unset("_${_pkg}_FIND_METHOD")
175+
endif()
176+
unset(_lib)
177+
unset(_pkg)
178+
unset(_url)

Diff for: src/stdlib_io.fypp

+36-21
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,16 @@ module stdlib_io
1919
! Private API that is exposed so that we can test it in tests
2020
public :: parse_mode
2121

22+
! Format strings with edit descriptors for each type and kind
23+
character(*), parameter :: &
24+
FMT_INT = '(*(i0,1x))', &
25+
FMT_REAL_SP = '(*(es15.8e2,1x))', &
26+
FMT_REAL_DP = '(*(es24.16e3,1x))', &
27+
FMT_REAL_QP = '(*(es44.35e4,1x))', &
28+
FMT_COMPLEX_SP = '(*(es15.8e2,1x,es15.8e2))', &
29+
FMT_COMPLEX_DP = '(*(es24.16e3,1x,es24.16e3))', &
30+
FMT_COMPLEX_QP = '(*(es44.35e4,1x,es44.35e4))'
31+
2232
interface loadtxt
2333
!! version: experimental
2434
!!
@@ -78,13 +88,22 @@ contains
7888

7989
! determine number of columns
8090
ncol = number_of_columns(s)
91+
#:if 'complex' in t1
92+
ncol = ncol / 2
93+
#:endif
8194

8295
! determine number or rows
83-
nrow = number_of_rows_numeric(s)
96+
nrow = number_of_rows(s)
8497

8598
allocate(d(nrow, ncol))
8699
do i = 1, nrow
87-
read(s, *) d(i, :)
100+
#:if 'real' in t1
101+
read(s, FMT_REAL_${k1}$) d(i, :)
102+
#:elif 'complex' in t1
103+
read(s, FMT_COMPLEX_${k1}$) d(i, :)
104+
#:else
105+
read(s, *) d(i, :)
106+
#:endif
88107
end do
89108
close(s)
90109

@@ -116,7 +135,15 @@ contains
116135
integer :: s, i
117136
s = open(filename, "w")
118137
do i = 1, size(d, 1)
119-
write(s, *) d(i, :)
138+
#:if 'real' in t1
139+
write(s, FMT_REAL_${k1}$) d(i, :)
140+
#:elif 'complex' in t1
141+
write(s, FMT_COMPLEX_${k1}$) d(i, :)
142+
#:elif 'integer' in t1
143+
write(s, FMT_INT) d(i, :)
144+
#:else
145+
write(s, *) d(i, :)
146+
#:endif
120147
end do
121148
close(s)
122149
end subroutine savetxt_${t1[0]}$${k1}$
@@ -147,36 +174,24 @@ contains
147174
end function number_of_columns
148175

149176

150-
integer function number_of_rows_numeric(s) result(nrows)
177+
integer function number_of_rows(s) result(nrows)
151178
!! version: experimental
152179
!!
153-
!! determine number or rows
154-
integer,intent(in)::s
180+
!! Determine the number or rows in a file
181+
integer, intent(in)::s
155182
integer :: ios
156183

157-
real :: r
158-
complex :: z
159-
160184
rewind(s)
161185
nrows = 0
162186
do
163-
read(s, *, iostat=ios) r
187+
read(s, *, iostat=ios)
164188
if (ios /= 0) exit
165189
nrows = nrows + 1
166190
end do
167191

168192
rewind(s)
169193

170-
! If there are no rows of real numbers, it may be that they are complex
171-
if( nrows == 0) then
172-
do
173-
read(s, *, iostat=ios) z
174-
if (ios /= 0) exit
175-
nrows = nrows + 1
176-
end do
177-
rewind(s)
178-
end if
179-
end function number_of_rows_numeric
194+
end function number_of_rows
180195

181196

182197
integer function open(filename, mode, iostat) result(u)
@@ -314,4 +329,4 @@ contains
314329

315330
end function parse_mode
316331

317-
end module
332+
end module stdlib_io

Diff for: src/tests/CMakeLists.txt

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
1+
if (NOT TARGET "test-drive::test-drive")
2+
find_package("test-drive" REQUIRED)
3+
endif()
4+
15
macro(ADDTEST name)
26
add_executable(test_${name} test_${name}.f90)
3-
target_link_libraries(test_${name} ${PROJECT_NAME})
7+
target_link_libraries(test_${name} "${PROJECT_NAME}" "test-drive::test-drive")
48
add_test(NAME ${name}
59
COMMAND $<TARGET_FILE:test_${name}> ${CMAKE_CURRENT_BINARY_DIR}
610
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})

Diff for: src/tests/Makefile.manual

+21-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,17 @@
11
.PHONY: all clean test
22

3-
all test clean:
3+
LIB = libstdlib-testing.a
4+
SRC = testdrive.F90
5+
OBJS = $(SRC:.F90=.o)
6+
MODS = $(OBJS:.o=.mod)
7+
FETCH = curl -L
8+
9+
all test:: $(LIB)
10+
11+
testdrive.F90:
12+
$(FETCH) https://github.com/fortran-lang/test-drive/raw/main/src/testdrive.F90 > $@
13+
14+
all test clean::
415
$(MAKE) -f Makefile.manual --directory=ascii $@
516
$(MAKE) -f Makefile.manual --directory=bitsets $@
617
$(MAKE) -f Makefile.manual --directory=io $@
@@ -13,3 +24,12 @@ all test clean:
1324
$(MAKE) -f Makefile.manual --directory=math $@
1425
$(MAKE) -f Makefile.manual --directory=stringlist $@
1526
$(MAKE) -f Makefile.manual --directory=linalg $@
27+
28+
$(LIB): $(OBJS)
29+
ar rcs $@ $^
30+
31+
clean::
32+
$(RM) $(LIB) $(OBJS) $(MODS) $(SRCGEN)
33+
34+
%.o: %.F90
35+
$(FC) $(FFLAGS) -I.. -c $<

Diff for: src/tests/Makefile.manual.test.mk

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# Common Makefile rules that are included from each test subdirectory's
22
# Makefile
33

4-
CPPFLAGS += -I../..
5-
LDFLAGS += -L../.. -lstdlib
4+
CPPFLAGS += -I../.. -I..
5+
LDFLAGS += -L../.. -L.. -lstdlib-testing -lstdlib
66

77
OBJS = $(PROGS_SRC:.f90=.o)
88
PROGS = $(OBJS:.o=)

0 commit comments

Comments
 (0)