File: dealloc_01.f90

package info (click to toggle)
lfortran 0.45.0-1
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 46,332 kB
  • sloc: cpp: 137,068; f90: 51,260; python: 6,444; ansic: 4,277; yacc: 2,285; fortran: 806; sh: 524; makefile: 30; javascript: 15
file content (187 lines) | stat: -rw-r--r-- 5,993 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
module dealloc_01_testdrive
  use, intrinsic :: iso_fortran_env, only : error_unit
  implicit none
  private

  public :: run_testsuite, new_unittest, unittest_type, testsuite_type, &
      error_type, skip_test

  integer, parameter :: success = 0, fatal = 1, skipped = 77

  type :: error_type
    integer :: stat = success
    character(len=:), allocatable :: message
  end type error_type

  abstract interface
    subroutine test_interface(error)
      import :: error_type
      type(error_type), allocatable, intent(out) :: error
    end subroutine test_interface
  end interface

  type :: unittest_type
    character(len=:), allocatable :: name
    procedure(test_interface), pointer, nopass :: test => null()
    logical :: should_fail = .false.
  end type unittest_type

  abstract interface
    subroutine collect_interface(testsuite)
      import :: unittest_type
      type(unittest_type), allocatable, intent(out) :: testsuite(:)
    end subroutine collect_interface
  end interface

  type :: testsuite_type
    character(len=:), allocatable :: name
    procedure(collect_interface), pointer, nopass :: collect => null()
  end type testsuite_type

  character(len=*), parameter :: fmt = '(1x, *(1x, a))'

contains

  recursive subroutine run_testsuite(collect, unit, stat, parallel)
    procedure(collect_interface) :: collect
    integer, intent(in) :: unit
    integer, intent(inout) :: stat
    logical, intent(in), optional :: parallel
    type(unittest_type), allocatable :: testsuite(:)
    integer :: it
    logical :: parallel_
    parallel_ = .true.
    if(present(parallel)) parallel_ = parallel
    call collect(testsuite)
    do it = 1, size(testsuite)
      write(unit, '(1x, 3(1x, a), 1x, "(", i0, "/", i0, ")")') &
        & "Starting", testsuite(it)%name, "...", it, size(testsuite)
      call run_unittest(testsuite(it), unit, stat)
    end do
  end subroutine run_testsuite

  recursive subroutine run_unittest(test_var, unit, stat)
    type(unittest_type), intent(in) :: test_var
    integer, intent(in) :: unit
    integer, intent(inout) :: stat
    type(error_type), allocatable :: error
    character(len=:), allocatable :: message
    call test_var%test(error)
    if (.not.test_skipped(error)) then
      if (allocated(error) .neqv. test_var%should_fail) stat = stat + 1
    end if
    call make_output(message, test_var, error)
    write(unit, '(a)') message
  end subroutine run_unittest

  pure function test_skipped(error) result(is_skipped)
    type(error_type), intent(in), optional :: error
    logical :: is_skipped
    is_skipped = .false.
    if (present(error)) then
      is_skipped = error%stat == skipped
    end if
  end function test_skipped

  pure subroutine make_output(output, test, error)
    character(len=:), allocatable, intent(out) :: output
    type(unittest_type), intent(in) :: test
    type(error_type), intent(in), optional :: error
    character(len=:), allocatable :: label
    character(len=*), parameter :: indent = "       " // "..." // " "
    if (test_skipped(error)) then
      output = indent // test%name // " [SKIPPED]" &
        & // new_line("a") // "  Message: " // error%message
      return
    end if
    if (present(error) .neqv. test%should_fail) then
      if (test%should_fail) then
        label = " [UNEXPECTED PASS]"
      else
        label = " [FAILED]"
      end if
    else
      if (test%should_fail) then
        label = " [EXPECTED FAIL]"
      else
        label = " [PASSED]"
      end if
    end if
    output = indent // test%name // label
    if (present(error)) then
      output = output // new_line("a") // "  Message: " // error%message
    end if
  end subroutine make_output

  function new_unittest(name, test, should_fail) result(self)
    character(len=*), intent(in) :: name
    procedure(test_interface) :: test
    logical, intent(in), optional :: should_fail
    type(unittest_type) :: self
    self%name = name
    self%test => test
    if (present(should_fail)) self%should_fail = should_fail
  end function new_unittest

  subroutine test_failed(error, message, more, and_more)
    type(error_type), allocatable, intent(out) :: error
    character(len=*), intent(in) :: message
    character(len=*), intent(in), optional :: more
    character(len=*), intent(in), optional :: and_more
    character(len=*), parameter :: skip = new_line("a") // "           "
    allocate(error)
    error%stat = fatal
    error%message = message
    if (present(more)) then
      error%message = error%message // skip // more
    end if
    if (present(and_more)) then
      error%message = error%message // skip // and_more
    end if

  end subroutine test_failed

  subroutine skip_test(error, message, more, and_more)
    type(error_type), allocatable, intent(out) :: error
    character(len=*), intent(in) :: message
    character(len=*), intent(in), optional :: more
    character(len=*), intent(in), optional :: and_more
    call test_failed(error, message, more, and_more)
    error%stat = skipped
  end subroutine skip_test

end module

module dealloc_01_linalg
use dealloc_01_testdrive, only : new_unittest, unittest_type, error_type, skip_test
implicit none

contains

    subroutine collect_linalg(testsuite)
    type(unittest_type), allocatable, intent(out) :: testsuite(:)
    testsuite = [ &
        new_unittest("diag_rqp", test_diag_rqp) &
        ]
    end subroutine collect_linalg

    subroutine test_diag_rqp(error)
    type(error_type), allocatable, intent(out) :: error
    call skip_test(error, "Quadruple precision is not enabled")
    end subroutine test_diag_rqp

end module


program dealloc_01
use, intrinsic :: iso_fortran_env, only : error_unit
use dealloc_01_testdrive, only : run_testsuite, testsuite_type
use dealloc_01_linalg, only : collect_linalg
implicit none
integer :: stat
type(testsuite_type), allocatable :: testsuites(:)
stat = 0
call run_testsuite(collect_linalg, error_unit, stat)
print *, "stat: ", stat
if (stat > 0) error stop
end program