Skip to content

Commit c7b1a3d

Browse files
committed
harmonize tests with h5fortran. add rank check on read
1 parent 85e9134 commit c7b1a3d

File tree

12 files changed

+293
-393
lines changed

12 files changed

+293
-393
lines changed

src/CMakeLists.txt

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,22 @@ endif()
77
configure_file(pathlib.in.f90 pathlib.f90)
88

99
set(reader_template "
10-
integer :: varid, ier
10+
integer :: varid, ier, drank
11+
1112
1213
if(.not.self%is_open) error stop 'ERROR:nc4fortran:reader file handle not open'
1314
1415
ier = nf90_inq_varid(self%ncid, dname, varid)
1516
17+
if(ier == NF90_NOERR) then
18+
ier = nf90_inquire_variable(self%ncid, varid, ndims=drank)
19+
if(drank /= rank(value)) then
20+
ier = NF90_EDIMSIZE
21+
write(stderr,*) 'ERROR: ' // dname // ' rank ', drank, ' /= variable rank ',rank(value)
22+
return
23+
endif
24+
endif
25+
1626
if(ier == NF90_NOERR) then
1727
select type (value)
1828
type is (real(real64))

src/interface.f90

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ module nc4fortran
55

66
use netcdf, only : nf90_create, nf90_open, NF90_WRITE, NF90_CLOBBER, NF90_NETCDF4, NF90_MAX_NAME, &
77
NF90_NOERR, NF90_EHDFERR, NF90_EBADNAME, NF90_EBADDIM, NF90_EBADTYPE, NF90_EBADGRPID, NF90_ENOTNC, NF90_ENOTVAR, &
8-
NF90_ECHAR, NF90_EEDGE, NF90_ENAMEINUSE, NF90_EBADID, NF90_EINDEFINE, NF90_NOWRITE, &
8+
NF90_ECHAR, NF90_EEDGE, NF90_ENAMEINUSE, NF90_EBADID, NF90_EINDEFINE, NF90_NOWRITE, NF90_EDIMSIZE, &
99
nf90_open, nf90_close, nf90_estride, nf90_inq_varid, nf90_inq_dimid, nf90_inquire_dimension, &
1010
nf90_def_dim, nf90_def_var, nf90_get_var, nf90_put_var, &
1111
nf90_inq_libvers, nf90_sync
@@ -391,6 +391,8 @@ logical function check_error(code, dname)
391391
m = 'ERROR: ' // dname // ' Name contains illegal characters.'
392392
case (NF90_EBADTYPE)
393393
m = 'ERROR: ' // dname // ' specified type is not a valid netCDF type'
394+
case (NF90_EDIMSIZE)
395+
m = 'ERROR: ' // dname // ' bad dimension size'
394396
case (NF90_EBADDIM)
395397
m = 'ERROR: ' // dname // ' invalid dimension ID or Name'
396398
case (NF90_EBADGRPID)

src/tests/CMakeLists.txt

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,40 @@
1-
set(tmpdir ${CMAKE_CURRENT_BINARY_DIR})
2-
3-
add_executable(test_io test_io.f90)
4-
target_link_libraries(test_io nc4fortran::nc4fortran)
1+
add_executable(test_array test_array.f90)
2+
target_link_libraries(test_array nc4fortran::nc4fortran)
53
if(CMAKE_Fortran_COMPILER_ID STREQUAL GNU)
6-
target_compile_options(test_io PRIVATE -Wno-compare-reals)
4+
target_compile_options(test_array PRIVATE -Wno-compare-reals)
75
endif()
8-
add_test(NAME nc4fortran:readwrite COMMAND $<TARGET_FILE:test_io> ${CMAKE_CURRENT_BINARY_DIR})
6+
add_test(NAME nc4fortran:array COMMAND $<TARGET_FILE:test_array>
7+
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
98

10-
add_executable(test_attr test_attr.f90)
11-
target_link_libraries(test_attr nc4fortran::nc4fortran)
12-
add_test(NAME nc4fortran:attributes COMMAND $<TARGET_FILE:test_attr> ${CMAKE_CURRENT_BINARY_DIR})
9+
add_executable(test_attributes test_attributes.f90)
10+
target_link_libraries(test_attributes nc4fortran::nc4fortran)
1311
if(${CMAKE_Fortran_COMPILER_ID} STREQUAL GNU)
14-
target_compile_options(test_attr PRIVATE -Wno-compare-reals)
12+
target_compile_options(test_attributes PRIVATE -Wno-compare-reals)
1513
endif()
14+
add_test(NAME nc4fortran:attributes COMMAND $<TARGET_FILE:test_attributes>
15+
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
1616

17-
add_executable(test_errors test_errors.f90)
18-
target_link_libraries(test_errors nc4fortran::nc4fortran)
19-
add_test(NAME nc4fortran:errors COMMAND $<TARGET_FILE:test_errors> ${CMAKE_CURRENT_BINARY_DIR})
17+
add_executable(test_error test_error.f90)
18+
target_link_libraries(test_error nc4fortran::nc4fortran)
19+
add_test(NAME nc4fortran:error COMMAND $<TARGET_FILE:test_error>
20+
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
2021

2122
add_executable(test_exist test_exist.f90)
2223
target_link_libraries(test_exist PRIVATE nc4fortran::nc4fortran)
23-
add_test(NAME nc4fortran:test_exist COMMAND $<TARGET_FILE:test_exist> ${tmpdir})
24+
add_test(NAME nc4fortran:test_exist COMMAND $<TARGET_FILE:test_exist>
25+
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
26+
27+
add_executable(test_scalar test_scalar.f90)
28+
target_link_libraries(test_scalar PRIVATE nc4fortran::nc4fortran)
29+
add_test(NAME nc4fortran:test_scalar COMMAND $<TARGET_FILE:test_scalar>
30+
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
2431

2532
add_executable(test_string test_string.f90)
2633
target_link_libraries(test_string nc4fortran::nc4fortran)
27-
add_test(NAME nc4fortran:test_string COMMAND $<TARGET_FILE:test_string> ${tmpdir})
34+
add_test(NAME nc4fortran:test_string COMMAND $<TARGET_FILE:test_string>
35+
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
2836

2937
add_executable(test_shape test_shape.f90)
3038
target_link_libraries(test_shape PRIVATE nc4fortran::nc4fortran)
31-
add_test(NAME nc4fortran:shape_check COMMAND $<TARGET_FILE:test_shape> ${tmpdir})
39+
add_test(NAME nc4fortran:shape_check COMMAND $<TARGET_FILE:test_shape>
40+
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})

src/tests/meson.build

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@ test_io = executable('test_io', 'test_io.f90',
33
dependencies: netcdf_interface)
44
test('ReadWrite', test_io, args: meson.current_build_dir(), timeout: 10, suite: 'nc4basic')
55

6-
test_attr = executable('test_attr', 'test_attr.f90',
6+
test_attr = executable('test_attributes', 'test_attributes.f90',
77
fortran_args: quiet,
88
dependencies: netcdf_interface)
99
test('attributes', test_attr, args: meson.current_build_dir(), timeout: 10, suite: 'nc4basic')
1010

11-
test_errors = executable('test_errors', 'test_errors.f90',
11+
test_error = executable('test_error', 'test_error.f90',
1212
fortran_args: quiet,
1313
dependencies: netcdf_interface)
14-
test('errors', test_errors, args: meson.current_build_dir(), timeout: 10, suite: 'nc4basic')
14+
test('errors', test_error, args: meson.current_build_dir(), timeout: 10, suite: 'nc4basic')
1515

1616
test_exist = executable('test_exist', 'test_exist.f90',
1717
fortran_args: quiet,

src/tests/test_array.f90

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
program array_test
2+
3+
use, intrinsic:: iso_fortran_env, only: int64, int32, real32, real64, stderr=>error_unit
4+
use, intrinsic:: ieee_arithmetic, only: ieee_value, ieee_quiet_nan, ieee_is_nan
5+
use nc4fortran, only : netcdf_file
6+
7+
implicit none (type, external)
8+
9+
real(real32) :: nan
10+
11+
call test_basic_array()
12+
print *,'PASSED: array write'
13+
14+
contains
15+
16+
subroutine test_basic_array()
17+
18+
type(netcdf_file) :: h
19+
integer, allocatable :: dims(:)
20+
character(*), parameter :: filename = 'test_array.nc'
21+
22+
integer(int32), dimension(4) :: i1, i1t
23+
integer(int32), dimension(4,4) :: i2, i2t
24+
integer(int64), dimension(4,4) :: i2t64
25+
real(real32), allocatable :: rr2(:,:)
26+
real(real32) :: nant, r1(4), r2(4,4), B(6,6)
27+
integer :: i, ierr
28+
integer(int32) :: i2_8(8,8)
29+
30+
nan = ieee_value(1.0, ieee_quiet_nan)
31+
32+
do i = 1,size(i1)
33+
i1(i) = i
34+
enddo
35+
36+
i2(1,:) = i1
37+
do i = 1,size(i2,2)
38+
i2(i,:) = i2(1,:) * i
39+
enddo
40+
41+
r1 = i1
42+
r2 = i2
43+
44+
call h%initialize(filename, status='replace', comp_lvl=1)
45+
46+
call h%write('int32-1d', i1)
47+
call h%write('int32-2d', i2, ['x', 'y'])
48+
call h%write('int64-2d', int(i2, int64))
49+
call h%write('real32-2d', r2)
50+
call h%write('nan', nan)
51+
52+
!> test writing wrong size
53+
call h%write('int32-1d', [-1], ierr=ierr)
54+
if(ierr==0) error stop 'test_write_array: did not error for write array shape mismatch'
55+
56+
!> test writing wrong rank
57+
call h%write('int32-1d', i2, ierr=ierr)
58+
if(ierr==0) error stop 'test_write_array: did not error for write array rank mismatch'
59+
60+
call h%finalize()
61+
62+
!! read
63+
call h%initialize(filename, status='old', action='r')
64+
65+
!> int32
66+
call h%read('int32-1d', i1t)
67+
if (.not.all(i1==i1t)) error stop 'read 1-d int32: does not match write'
68+
69+
call h%read('int32-2d',i2t)
70+
if (.not.all(i2==i2t)) error stop 'read 2-D: int32 does not match write'
71+
72+
call h%read('int64-2d',i2t64)
73+
if (.not.all(i2==i2t64)) error stop 'read 2-D: int64 does not match write'
74+
75+
!> verify reading into larger array
76+
i2_8 = 0
77+
call h%read('int32-2d', i2_8(2:5,3:6))
78+
if (.not.all(i2_8(2:5,3:6) == i2)) error stop 'read into larger array fail'
79+
80+
!> check error for reading array dimension mismatch
81+
82+
!> check that 1D disk into 2D raises error
83+
call h%read('int32-1d', i2, ierr)
84+
if (ierr==0) error stop 'failed to error on read rank mismatch'
85+
86+
!> real
87+
call h%shape('real32-2d',dims)
88+
allocate(rr2(dims(1), dims(2)))
89+
call h%read('real32-2d',rr2)
90+
if (.not.all(r2 == rr2)) error stop 'real 2-D: read does not match write'
91+
print *,'read large'
92+
! check read into a variable slice
93+
call h%read('real32-2d', B(2:5,3:6))
94+
if(.not.all(B(2:5,3:6) == r2)) error stop 'real 2D: reading into variable slice'
95+
96+
call h%read('nan',nant)
97+
if (.not.ieee_is_nan(nant)) error stop 'failed storing or reading NaN'
98+
99+
call h%finalize()
100+
101+
end subroutine test_basic_array
102+
103+
104+
end program

src/tests/test_attr.f90 renamed to src/tests/test_attributes.f90

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,7 @@ program test_attr
55

66
implicit none (type, external)
77

8-
character(:), allocatable :: path, filename
9-
character(1024) :: argv
10-
11-
12-
if(command_argument_count() /= 1) error stop 'input temp path'
13-
call get_command_argument(1, argv)
14-
path = trim(argv)
15-
16-
filename = path // '/test_attr.nc'
17-
8+
character(*), parameter :: filename = 'test_attr.h5'
189

1910
call test_write_attributes(filename)
2011
print *,'PASSED: write attributes'
@@ -76,5 +67,4 @@ subroutine test_read_attributes(path)
7667

7768
end subroutine test_read_attributes
7869

79-
8070
end program

src/tests/test_error.f90

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
program test_errors
2+
use, intrinsic:: iso_fortran_env, only: int64, int32, real32, real64, stderr=>error_unit
3+
use nc4fortran, only: netcdf_file, NF90_NOERR
4+
5+
implicit none (type, external)
6+
7+
call test_nonexist_old_file()
8+
print *, 'OK: non-existing old file'
9+
call test_nonexist_unknown_file()
10+
print *, 'OK: non-existing unknown file'
11+
call test_nonnetcdf_file()
12+
print *, 'OK: non-NetCDF file'
13+
call test_nonexist_variable()
14+
print *, 'OK: non-existing variable'
15+
call test_wrong_type()
16+
print *, "OK: wrong type read"
17+
call test_unknown_write()
18+
print *, 'OK: unknown write'
19+
call test_unknown_read()
20+
print *, 'OK: unknown read'
21+
22+
contains
23+
24+
25+
subroutine test_nonexist_old_file()
26+
integer :: ierr
27+
type(netcdf_file) :: h
28+
29+
call h%initialize('not-exist.nc', ierr, status='old', action='read')
30+
if (ierr==NF90_NOERR) error stop 'should have had ierr/=0 on non-existing old file'
31+
end subroutine test_nonexist_old_file
32+
33+
34+
subroutine test_nonexist_unknown_file()
35+
integer :: ierr
36+
type(netcdf_file) :: h
37+
38+
call h%initialize('not-exist.nc', ierr, status='unknown', action='read')
39+
if (ierr==NF90_NOERR) error stop 'should have had ierr/=0 on non-existing unknown read file'
40+
end subroutine test_nonexist_unknown_file
41+
42+
43+
subroutine test_nonnetcdf_file()
44+
integer :: u,ierr
45+
type(netcdf_file) :: h
46+
character(*), parameter :: filename = 'bad.nc'
47+
48+
! create or replace zero-length file, could be any size, just not a valid NetCDF file
49+
open(newunit=u, file=filename, status='replace', action='write')
50+
close(u)
51+
52+
call h%initialize(filename, ierr, status='old', action='read')
53+
if (ierr==NF90_NOERR) error stop 'should have had ierr/=0 on invalid NetCDF file'
54+
end subroutine test_nonnetcdf_file
55+
56+
57+
subroutine test_nonexist_variable()
58+
integer :: u,ierr
59+
type(netcdf_file) :: h
60+
character(*), parameter :: filename = 'bad.nc'
61+
62+
call h%initialize(filename, status='replace')
63+
call h%read('/not-exist', u, ierr)
64+
if (ierr==NF90_NOERR) error stop 'test_nonexist_variable: should have ierr/=0 on non-exist variable'
65+
call h%finalize()
66+
end subroutine test_nonexist_variable
67+
68+
69+
subroutine test_wrong_type()
70+
integer :: u
71+
type(netcdf_file) :: h
72+
character(*), parameter :: filename = 'bad.nc'
73+
74+
call h%initialize(filename, status='replace')
75+
call h%write('real32', 42.)
76+
call h%finalize()
77+
78+
call h%initialize(filename, status='old', action='read')
79+
call h%read('real32', u)
80+
if (u /= 42) error stop 'test_wrong_type: did not coerce real to integer'
81+
call h%finalize()
82+
83+
end subroutine test_wrong_type
84+
85+
86+
subroutine test_unknown_write()
87+
integer :: ierr
88+
type(netcdf_file) :: h
89+
character(*), parameter :: filename = 'bad.nc'
90+
complex :: x
91+
92+
x = (1, -1)
93+
94+
call h%initialize(filename, ierr, status='replace')
95+
call h%write('/complex', x, ierr)
96+
if(ierr==NF90_NOERR) error stop 'test_unknown_write: writing unknown type variable'
97+
end subroutine test_unknown_write
98+
99+
100+
subroutine test_unknown_read()
101+
integer :: ierr
102+
type(netcdf_file) :: h
103+
character(*), parameter :: filename = 'bad.nc'
104+
complex :: x
105+
106+
x = (1, -1)
107+
108+
call h%initialize(filename, status='unknown', action='readwrite')
109+
call h%read('/complex', x, ierr)
110+
if(ierr==NF90_NOERR) error stop 'test_unknown_read: reading unknown type variable'
111+
end subroutine test_unknown_read
112+
113+
end program

0 commit comments

Comments
 (0)