Skip to content

Commit 3ad6594

Browse files
committed
replace cli_test test
1 parent 607bd56 commit 3ad6594

File tree

1 file changed

+232
-0
lines changed

1 file changed

+232
-0
lines changed

fpm/test/cli_test/cli_test.f90

Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
program main
2+
3+
! for each set of command options, call this command recursively which will print the resulting parameters with a
4+
! given test command CMD from the TEST() array.
5+
!
6+
! Then read the expected values as a NAMELIST group from the test array and compare the expected
7+
! results with the actual results.
8+
!
9+
! the PARSE() subroutine is a copy of the app/main.f90 program except it creates and writes a NAMELIST file instead
10+
! of actually calling the subcommands.
11+
!
12+
! The program will exit with a non-zero status if any of the tests fail
13+
14+
use, intrinsic :: iso_fortran_env, only : compiler_version, compiler_options
15+
implicit none
16+
17+
! convenient arbitrary sizes for test
18+
19+
! assuming no name over 15 characters to make output have shorter lines
20+
character(len=15),allocatable :: name(:),act_name(:) ; namelist/act_cli/act_name
21+
integer,parameter :: max_names=10
22+
23+
character(len=:),allocatable :: command
24+
character(len=:),allocatable :: cmd
25+
integer :: cstat, estat
26+
integer :: act_cstat, act_estat
27+
integer :: i, ios
28+
logical :: w_e,act_w_e ; namelist/act_cli/act_w_e
29+
logical :: w_t,act_w_t ; namelist/act_cli/act_w_t
30+
31+
logical :: release,act_release ; namelist/act_cli/act_release
32+
character(len=:),allocatable :: args,act_args ; namelist/act_cli/act_args
33+
namelist/expected/cmd,cstat,estat,w_e,w_t,name,release,args
34+
integer :: lun
35+
logical,allocatable :: tally(:)
36+
logical,allocatable :: subtally(:)
37+
character(len=256) :: message
38+
39+
! table of arguments to pass to program and expected non-default values for that execution in NAMELIST group format
40+
character(len=*),parameter :: tests(*)= [ character(len=256) :: &
41+
42+
'CMD="new", ESTAT=1,', &
43+
'CMD="new -unknown", ESTAT=2,', &
44+
'CMD="new my_project another yet_another -with-test", ESTAT=2,', &
45+
'CMD="new my_project --with-executable", W_E=T, NAME="my_project",', &
46+
'CMD="new my_project --with-executable -with-test", W_E=T,W_T=T, NAME="my_project",', &
47+
'CMD="new my_project -with-test", W_T=T, NAME="my_project",', &
48+
'CMD="new my_project", NAME="my_project",', &
49+
50+
'CMD="run", ', &
51+
'CMD="run my_project", NAME="my_project", ', &
52+
'CMD="run proj1 p2 project3", NAME="proj1","p2","project3", ', &
53+
'CMD="run proj1 p2 project3 --release", NAME="proj1","p2","project3",RELEASE=T,', &
54+
'CMD="run proj1 p2 project3 --release -- arg1 -x ""and a long one""", &
55+
&NAME="proj1","p2","project3",RELEASE=T ARGS="""arg1"" -x ""and a long one""", ', &
56+
57+
'CMD="test", ', &
58+
'CMD="test my_project", NAME="my_project", ', &
59+
'CMD="test proj1 p2 project3", NAME="proj1","p2","project3", ', &
60+
'CMD="test proj1 p2 project3 --release", NAME="proj1","p2","project3",RELEASE=T,', &
61+
'CMD="test proj1 p2 project3 --release -- arg1 -x ""and a long one""", &
62+
&NAME="proj1","p2","project3",RELEASE=T ARGS="""arg1"" -x ""and a long one""", ', &
63+
64+
'CMD="build", NAME= RELEASE=F,ARGS="",', &
65+
'CMD="build --release", NAME= RELEASE=T,ARGS="",', &
66+
' ' ]
67+
character(len=256) :: readme(3)
68+
69+
readme(1)='&EXPECTED' ! top and bottom line for a NAMELIST group read from TEST() used to set the expected values
70+
readme(3)=' /'
71+
tally=[logical ::] ! an array that tabulates the command test results as pass or fail.
72+
73+
if(command_argument_count().eq.0)then ! assume if called with no arguments to do the tests. This means you cannot
74+
! have a test of no parameters. Could improve on this.
75+
! if called with parameters assume this is a test and call the routine to
76+
! parse the resulting values after calling the CLI command line parser
77+
! and write the NAMELIST group so it can be read and tested against the
78+
! expected results
79+
write(*,*)'start tests of the CLI command line parser'
80+
command=repeat(' ',4096)
81+
call get_command_argument(0,command)
82+
command=trim(command)
83+
write(*,*)'command=',command
84+
85+
do i=1,size(tests)
86+
if(tests(i).eq.' ')then
87+
open(file='_test_cli',newunit=lun,delim='quote')
88+
close(unit=lun,status='delete')
89+
exit
90+
endif
91+
! blank out name group EXPECTED
92+
name=[(repeat(' ',len(name)),i=1,max_names)] ! the words on the command line sans the subcommand name
93+
release=.false. ! --release
94+
w_e=.false. ! --with-executable
95+
w_t=.false. ! --with-test
96+
args=repeat(' ',132) ! -- ARGS
97+
cmd=repeat(' ',132) ! the command line arguments to test
98+
cstat=0 ! status values from EXECUTE_COMMAND_LINE()
99+
estat=0
100+
readme(2)=' '//tests(i) ! select command options to test for CMD and set nondefault expected values
101+
read(readme,nml=expected)
102+
103+
write(*,'(*(g0))')'START: TEST ',i,' CMD=',trim(cmd)
104+
! call this program which will crack command line and write results to scratch file _test_cli
105+
call execute_command_line(command//' '//trim(cmd),cmdstat=act_cstat,exitstat=act_estat)
106+
if(cstat.eq.act_cstat.and.estat.eq.act_estat)then
107+
if(estat.eq.0)then
108+
open(file='_test_cli',newunit=lun,delim='quote')
109+
act_name=[(repeat(' ',len(act_name)),i=1,max_names)]
110+
act_release=.false.
111+
act_w_e=.false.
112+
act_w_t=.false.
113+
act_args=repeat(' ',132)
114+
read(lun,nml=act_cli,iostat=ios,iomsg=message)
115+
if(ios.ne.0)then
116+
write(*,'(a)')'ERROR:',trim(message)
117+
endif
118+
close(unit=lun)
119+
! compare results to expected values
120+
subtally=[logical ::]
121+
call test_test('NAME',all(act_name.eq.name))
122+
call test_test('RELEASE',act_release.eqv.release)
123+
call test_test('WITH_EXPECTED',act_w_e.eqv.w_e)
124+
call test_test('WITH_TESTED',act_w_t.eqv.w_t)
125+
call test_test('WITH_TEST',act_w_t.eqv.w_t)
126+
call test_test('ARGS',act_args.eq.args)
127+
if(all(subtally))then
128+
write(*,'(*(g0))')'PASSED: TEST ',i,' STATUS: expected ',cstat,' ',estat,' actual ',act_cstat,' ',act_estat,&
129+
& ' for [',trim(cmd),']'
130+
tally=[tally,.true.]
131+
else
132+
write(*,'(*(g0))')'FAILED: TEST ',i,' STATUS: expected ',cstat,' ',estat,' actual ',act_cstat,' ',act_estat,&
133+
& ' for [',trim(cmd),']'
134+
print '(4a)', &
135+
'This file was compiled by ', &
136+
compiler_version(), &
137+
' using the options ', &
138+
compiler_options()
139+
write(*,nml=act_cli,delim='quote')
140+
tally=[tally,.false.]
141+
endif
142+
else
143+
write(*,'(*(g0))')'PASSED: TEST ',i,' EXPECTED BAD STATUS: expected ',cstat,' ',estat, &
144+
' actual ',act_cstat,' ',act_estat,' for [',trim(cmd),']'
145+
tally=[tally,.true.]
146+
endif
147+
else
148+
write(*,'(*(g0))')'FAILED: TEST ',i,'BAD STATUS: expected ',cstat,' ',estat,' actual ',act_cstat,' ',act_estat,&
149+
' for [',trim(cmd),']'
150+
tally=[tally,.false.]
151+
endif
152+
enddo
153+
! write up total results and if anything failed exit with a non-zero status
154+
write(*,'(*(g0))')'TALLY;',tally
155+
if(all(tally))then
156+
write(*,'(*(g0))')'PASSED: all ',count(tally),' tests passed '
157+
else
158+
write(*,*)'FAILED: PASSED=',count(tally),' FAILED=',count(.not.tally)
159+
stop 4
160+
endif
161+
else
162+
! call this program with arguments
163+
!=============================================
164+
debugit: block
165+
integer :: j, ilen
166+
character(len=256) :: big_argument
167+
write(*,*)'arguments seen directly by program'
168+
do j=1,command_argument_count()
169+
call get_command_argument(number=j,value=big_argument,length=ilen)
170+
write(*,'(*(g0))')j,'[',big_argument(:ilen),']'
171+
enddo
172+
end block debugit
173+
!=============================================
174+
call parse()
175+
endif
176+
177+
contains
178+
179+
subroutine test_test(name,tst)
180+
character(len=*) :: name
181+
logical,intent(in) :: tst
182+
!!write(*,'(*(g0,1x))')' SUBTEST ',name,' ',merge('PASSED','FAILED',tst)
183+
subtally=[subtally,tst]
184+
end subroutine test_test
185+
186+
subroutine parse()
187+
! all the extended types for settings from the main program
188+
use fpm_command_line, only: &
189+
fpm_cmd_settings, &
190+
fpm_new_settings, &
191+
fpm_build_settings, &
192+
fpm_run_settings, &
193+
fpm_test_settings, &
194+
fpm_install_settings, &
195+
get_command_line_settings
196+
use fpm, only: cmd_build, cmd_install, cmd_new, cmd_run, cmd_test
197+
class(fpm_cmd_settings), allocatable :: cmd_settings
198+
! duplicates the calls as seen in the main program for fpm
199+
call get_command_line_settings(cmd_settings)
200+
201+
allocate (character(len=len(name)) :: act_name(0) )
202+
act_args=''
203+
act_w_e=.false.
204+
act_w_t=.false.
205+
act_release=.false.
206+
207+
select type(settings=>cmd_settings)
208+
type is (fpm_new_settings)
209+
act_w_e=settings%with_executable
210+
act_w_t=settings%with_test
211+
act_name=[trim(settings%name)]
212+
type is (fpm_build_settings)
213+
act_release=settings%release
214+
type is (fpm_run_settings)
215+
act_release=settings%release
216+
act_name=settings%name
217+
act_args=settings%args
218+
type is (fpm_test_settings)
219+
act_release=settings%release
220+
act_name=settings%name
221+
act_args=settings%args
222+
type is (fpm_install_settings)
223+
end select
224+
225+
open(file='_test_cli',newunit=lun,delim='quote')
226+
write(lun,nml=act_cli,delim='quote')
227+
!!write(*,nml=act_cli)
228+
close(unit=lun)
229+
230+
end subroutine parse
231+
232+
end program main

0 commit comments

Comments
 (0)