!= dc_histnml モジュールのテストプログラム
!
!= Test program for "dc_histnml"
!
! Authors::   Yasuhiro MORIKAWA
! Version::   $Id: dc_histnml_test.f90,v 1.8 2007/12/16 12:25:38 morikawa Exp $
! Tag Name::  $Name: gt4f90io-20080210 $
! Copyright:: Copyright (C) GFD Dennou Club, 2007. All rights reserved.
! License::   See COPYRIGHT[link:../../COPYRIGHT]
!
! <b>Note that Japanese and English are described in parallel.</b>
!
! dc_histnml モジュールの動作テストを行うためのプログラムです.
! このプログラムがコンパイルできること, および実行時に
! プログラムが正常終了することを確認してください.
!
! This program checks the operation of "dc_histnml" module.
! Confirm compilation and execution of this program.
!

program dc_histnml_test
  use dc_histnml, only: DCHSTNML, Create, Close, &
    & PutLine, initialized, Add, Delete, Inquire, &
    & output_step, output_valid, names, ResetDefault
  use dc_test, only: AssertEqual, AssertGreaterThan, AssertLessThan
  use dc_types, only: DP, STRING, TOKEN
  use dc_string, only: StoA, PutLine
  use dc_args, only: ARGS, Open, HelpMsg, Option, Debug, Help, Strict, Close
  use dc_date_types, only: DC_DIFFTIME
  use dc_date, only: Create, operator(*)
  implicit none

  !-------------------------------------------------------------------
  !  実験の表題, モデルの名称, 所属機関名
  !  Title of a experiment, name of model, sub-organ
  !-------------------------------------------------------------------
  character(*), parameter:: title = &
    & 'dc_histnml_test $Name: gt4f90io-20080210 $ :: ' // &
    & 'Test program of "dc_histnml" module'
  character(*), parameter:: source = &
    & 'gtool4 project ' // &
    & '(See http://www.gfd-dennou.org/library/gtool4)'
  character(*), parameter:: institution = &
    & 'GFD Dennou Club (See http://www.gfd-dennou.org)'


  !-------------------------------------------------------------------
  !  作業変数
  !  Work variables
  !-------------------------------------------------------------------
  type(ARGS):: arg            ! コマンドライン引数. 
                              ! Command line arguments
  logical:: OPT_namelist      ! -N, --namelist オプションの有無. 
                              ! Existence of '-N', '--namelist' option
  character(STRING):: VAL_namelist
                              ! -N, --namelist オプションの値. 
                              ! Value of '-N', '--namelist' option

  type(DCHSTNML):: hstnml00, hstnml01, hstnml02, hstnml03, hstnml04
  type(DCHSTNML):: hstnml05, hstnml06, hstnml07, hstnml08
  logical:: err
  type(DC_DIFFTIME):: interval_time
  character(STRING):: file
                              ! ヒストリデータのファイル名. 
                              ! History data filenames
  real(DP):: interval_value
                              ! ヒストリデータの出力間隔の数値. 
                              ! Numerical value for interval of history data output
  character(TOKEN):: interval_unit
                              ! ヒストリデータの出力間隔の単位. 
                              ! Unit for interval of history data output
  character(TOKEN):: precision
                              ! ヒストリデータの精度. 
                              ! Precision of history data
  logical:: average
                              ! 出力データの平均化フラグ. 
                              ! Flag for average of output data.
  character(STRING):: fileprefix
                              ! ヒストリデータのファイル名の接頭詞. 
                              ! Prefixes of history data filenames
  character(STRING):: varnames
                              ! 変数名リスト
                              ! List of variables


!!$  character(*), parameter:: subname = 'dc_histnml_test'
continue

  !-------------------------------------------------------------------
  !  コマンドライン引数の処理
  !  Command line arguments handling
  !-------------------------------------------------------------------
  call Open( arg )
  call HelpMsg( arg, 'Title', title )
  call HelpMsg( arg, 'Usage', &
    & './dc_histnml_test [Options]' )
  call HelpMsg( arg, 'Source', source )
  call HelpMsg( arg, 'Institution', institution )
  call Option( arg, StoA('-N', '--namelist'), &
    & OPT_namelist, VAL_namelist, help = 'NAMELIST filename' )
  call Debug( arg ) ; call Help( arg ) ; call Strict( arg, severe = .true. )
  call Close( arg )

  !-------------------------------------------------------------------
  !  基本の初期設定, 終了処理テスト
  !  Basic initialization and termination test
  !-------------------------------------------------------------------
  call Create( hstnml = hstnml00 ) ! (inout)
  call AssertEqual( 'basic initialization test 1', &
    & answer = .true., check = initialized(hstnml00) )
  call PutLine( hstnml = hstnml00 ) ! (in)

  call Close( hstnml = hstnml00 ) ! (inout)
  call AssertEqual( 'basic termination test 1', &
    & answer = .false., check = initialized(hstnml00) )
  call PutLine( hstnml = hstnml00 ) ! (in)

  call Create( hstnml = hstnml00, & ! (inout)
    & interval_value = 3.0_DP, &    ! (in)
    & interval_unit = 'min', &      ! (in)
    & precision = 'double', &       ! (in)
    & average = .false. )           ! (in)
  call AssertEqual( 'basic initialization test 2', &
    & answer = .true., check = initialized(hstnml00) )
  call PutLine( hstnml = hstnml00 ) ! (in)

  call Close( hstnml = hstnml00 ) ! (inout)
  call AssertEqual( 'basic termination test 2', &
    & answer = .false., check = initialized(hstnml00) )
  call PutLine( hstnml = hstnml00 ) ! (in)


  !-------------------------------------------------------------------
  !  重複初期設定に関するエラー処理のテスト
  !  Error handling related to duplicated initialization test
  !-------------------------------------------------------------------
  call Create( hstnml = hstnml00 ) ! (inout)
  call Create( hstnml = hstnml00, & ! (inout)
    & err = err )                             ! (out)
  call AssertEqual( 'error handling related to duplicated initialization test 1', &
    & answer = .true., check = err )
  call PutLine( hstnml = hstnml00 ) ! (in)
  call Close( hstnml = hstnml00 ) ! (inout)


  !-------------------------------------------------------------------
  !  終了処理に関するエラー処理のテスト
  !  Error handling related to termination test
  !-------------------------------------------------------------------
  call Close( hstnml = hstnml00, & ! (inout)
    & err = err )
  call AssertEqual( 'error handling related to termination test 1', &
    & answer = .true., check = err )

  !-------------------------------------------------------------------
  !  終了処理のテスト
  !  Termination test
  !-------------------------------------------------------------------
  call Create( hstnml = hstnml01, & ! (inout)
    & interval_value = 3.0_DP, &    ! (in)
    & interval_unit = 'min' )       ! (in)

  call Add( hstnml = hstnml01, & ! (inout)
    & name = 'Data1' )           ! (in)
  call Add( hstnml = hstnml01, & ! (inout)
    & name = 'Data2' )           ! (in)
  call Add( hstnml = hstnml01, & ! (inout)
    & name = 'Data3' )           ! (in)
  call Add( hstnml = hstnml01, & ! (inout)
    & name = 'Data4' )           ! (in)
  call Add( hstnml = hstnml01, & ! (inout)
    & name = 'Data5' )           ! (in)

  call PutLine( hstnml = hstnml01 ) ! (in)

  call Close( hstnml = hstnml01 ) ! (inout)

  !-------------------------------------------------------------------
  !  無効な値に関するエラー処理のテスト
  !  Error handling related to invalid values test
  !-------------------------------------------------------------------
  call Create( hstnml = hstnml02, & ! (inout)
    & interval_value = 3.0_DP, &    ! (in)
    & interval_unit = 'hogehoge', & ! (in)
    & precision = 'double', &       ! (in)
    & average = .false., &          ! (in)
    & err = err )                   ! (out)
  call PutLine( hstnml = hstnml02 ) ! (in)
  call AssertEqual( 'error handling related to invalid values test 1', &
    & answer = .true., check = err )

  call Create( hstnml = hstnml02, & ! (inout)
    & interval_value = 3.0_DP, &    ! (in)
    & interval_unit = 'hour', &     ! (in)
    & precision = 'double', &       ! (in)
    & average = .false. )           ! (in)
  call PutLine( hstnml = hstnml02 ) ! (in)

  call Add( hstnml = hstnml02, & ! (inout)
    & name = 'Data1', &          ! (in)
    & interval_value = 3.0_DP, & ! (in)
    & interval_unit = 'foo', &   ! (in)
    & err = err )                ! (out)
  call PutLine( hstnml = hstnml02 ) ! (in)
  call AssertEqual( 'error handling related to invalid values test 2', &
    & answer = .true., check = err )

  call Close( hstnml = hstnml02 ) ! (inout)

  !-------------------------------------------------------------------
  !  データ操作のテスト
  !  Data handling test
  !-------------------------------------------------------------------
  call Create( hstnml = hstnml03, & ! (inout)
    & interval_value = 30.0_DP, &   ! (in)
    & interval_unit = 'min' )       ! (in)

  call Inquire( hstnml = hstnml03, &     ! (in)
    & name = '', &                       ! (in)
    & file = file, &                     ! (out)
    & interval_value = interval_value, & ! (out)
    & interval_unit = interval_unit, &   ! (out)
    & precision = precision, &           ! (out)
    & average = average )                ! (out)

  call AssertEqual( 'data handling test 1-1', &
    & answer = '', check = file )
  call AssertEqual( 'data handling test 1-2', &
    & answer = 30.0_DP, check = interval_value, &
    & significant_digits = 7, ignore_digits = -6 )
  call AssertEqual( 'data handling test 1-3', &
    & answer = 'min', check = interval_unit )
  call AssertEqual( 'data handling test 1-4', &
    & answer = 'float', check = precision )
  call AssertEqual( 'data handling test 1-5', &
    & answer = .false., check = average )

  call Add( hstnml = hstnml03, & ! (inout)
    & interval_value = 3.0_DP, & ! (in)
    & interval_unit = 'min', &   ! (in)
    & precision = 'double' )     ! (in)

  call PutLine( hstnml = hstnml03 ) ! (in)

  call Add( hstnml = hstnml03, &  ! (inout)
    & name = 'Data1', &           ! (in)
    & precision = 'double' )      ! (in)

  call PutLine( hstnml = hstnml03 ) ! (in)

  call Add( hstnml = hstnml03, & ! (inout)
    & name = 'Data2', &          ! (in)
    & file = 'Data2.nc', &       ! (in)
    & interval_value = 5.0_DP, & ! (in)
    & interval_unit = 'hour' )   ! (in)

  call PutLine( hstnml = hstnml03 ) ! (in)

  call Add( hstnml = hstnml03, & ! (inout)
    & name = 'Data3', &          ! (in)
    & interval_value = -1.0_DP ) ! (in)

  call PutLine( hstnml = hstnml03 ) ! (in)

  call Inquire( hstnml = hstnml03, &     ! (in)
    & name = 'Data2', &                  ! (in)
    & file = file, &                     ! (out)
    & interval_value = interval_value, & ! (out)
    & interval_unit = interval_unit, &   ! (out)
    & precision = precision, &           ! (out)
    & average = average )                ! (out)

  call AssertEqual( 'data handling test 2-1', &
    & answer = 'Data2.nc', check = file )
  call AssertEqual( 'data handling test 2-2', &
    & answer = 5.0_DP, check = interval_value, &
    & significant_digits = 7, ignore_digits = -6 )
  call AssertEqual( 'data handling test 2-3', &
    & answer = 'hour', check = interval_unit )
  call AssertEqual( 'data handling test 2-4', &
    & answer = 'double', check = precision )
  call AssertEqual( 'data handling test 2-5', &
    & answer = .false., check = average )

  call Delete( hstnml = hstnml03, & ! (inout)
    & name = 'Data2' )              ! (in)

  call PutLine( hstnml = hstnml03 ) ! (in)

  call Inquire( hstnml = hstnml03, &     ! (in)
    & name = 'Data2', &                  ! (in)
    & file = file, &                     ! (out)
    & interval_value = interval_value, & ! (out)
    & interval_unit = interval_unit, &   ! (out)
    & precision = precision, &           ! (out)
    & average = average, &               ! (out)
    & err = err )                        ! (out)

  call AssertEqual( 'data handling test 3-1', &
    & answer = .true., check = err )


  call Inquire( hstnml = hstnml03, &     ! (in)
    & name = 'Data1', &                  ! (in)
    & interval_value = interval_value, & ! (out)
    & interval_unit = interval_unit, &   ! (out)
    & precision = precision, &           ! (out)
    & average = average )                ! (out)

  call AssertEqual( 'data handling test 2-2', &
    & answer = 3.0_DP, check = interval_value, &
    & significant_digits = 7, ignore_digits = -6 )
  call AssertEqual( 'data handling test 2-3', &
    & answer = 'min', check = interval_unit )
  call AssertEqual( 'data handling test 2-4', &
    & answer = 'double', check = precision )
  call AssertEqual( 'data handling test 2-5', &
    & answer = .false., check = average )

  call Add( hstnml = hstnml03, & ! (inout)
    & interval_value = 1.0_DP, & ! (in)
    & interval_unit = 'day', &   ! (in)
    & precision = 'float', &     ! (in)
    & average = .true. )         ! (in)

  call Inquire( hstnml = hstnml03, &     ! (in)
    & name = 'Data1', &                  ! (in)
    & interval_value = interval_value, & ! (out)
    & interval_unit = interval_unit, &   ! (out)
    & precision = precision, &           ! (out)
    & average = average )                ! (out)

  call AssertEqual( 'data handling test 2-2', &
    & answer = 1.0_DP, check = interval_value, &
    & significant_digits = 7, ignore_digits = -6 )
  call AssertEqual( 'data handling test 2-3', &
    & answer = 'day', check = interval_unit )
  call AssertEqual( 'data handling test 2-4', &
    & answer = 'double', check = precision )
  call AssertEqual( 'data handling test 2-5', &
    & answer = .true., check = average )


  call AssertEqual( 'data handling test 4-1', &
    & answer = .true., &
    & check = output_valid( hstnml = hstnml03, name = '' ) )

  call AssertEqual( 'data handling test 4-2', &
    & answer = .true., &
    & check = output_valid( hstnml = hstnml03, name = 'Data1' ) )

  call AssertEqual( 'data handling test 4-3', &
    & answer = .false., &
    & check = output_valid( hstnml = hstnml03, name = 'Data2' ) )

  call AssertEqual( 'data handling test 4-4', &
    & answer = .false., &
    & check = output_valid( hstnml = hstnml03, name = 'Data3' ) )

  call Close( hstnml = hstnml03 ) ! (inout)

  !-------------------------------------------------------------------
  !  出力ステップ問い合わせのテスト
  !  Inquire output step test
  !-------------------------------------------------------------------
  call Create( hstnml = hstnml04, & ! (inout)
    & interval_value = 30.0_DP, &   ! (in)
    & interval_unit = 'min' )       ! (in)

  call Add( hstnml = hstnml04, &  ! (inout)
    & name = 'Data1', &           ! (in)
    & file = 'Data1.nc', &        ! (in)
    & interval_value = 1.0_DP, &  ! (in)
    & interval_unit = 'hour' )    ! (in)

  call Add( hstnml = hstnml04, & ! (inout)
    & name = 'Data2', &          ! (in)
    & file = 'Data2.nc', &       ! (in)
    & interval_value = -1.0_DP ) ! (in)

  call Create( &
    & diff = interval_time, & ! (out)
    & value = 6.0_DP, &       ! (in)
    & unit = 'sec' )          ! (in)

  call AssertEqual( 'inquire output step test 1-1', &
    & answer = .false., &
    & check = output_step( hstnml = hstnml04, name = 'Data2', time = interval_time ) )

  call AssertEqual( 'inquire output step test 1-2', &
    & answer = .false., &
    & check = output_step( hstnml = hstnml04, name = '', time = interval_time ) )

  call AssertEqual( 'inquire output step test 1-3', &
    & answer = .true., &
    & check = output_step( hstnml = hstnml04, name = '', time = interval_time * 300 ) )

  call AssertEqual( 'inquire output step test 1-4', &
    & answer = .false., &
    & check = output_step( hstnml = hstnml04, name = 'Data1', time = interval_time * 300 ) )

  call AssertEqual( 'inquire output step test 1-5', &
    & answer = .true., &
    & check = output_step( hstnml = hstnml04, name = 'Data1', time = interval_time * 600 ) )

  call Close( hstnml = hstnml04 ) ! (inout)

  !-------------------------------------------------------------------
  !  fileprefix テスト
  !  fileprefix test
  !-------------------------------------------------------------------
  call Create( hstnml = hstnml05, & ! (inout)
    & interval_value = 30.0_DP, &   ! (in)
    & interval_unit = 'min', &      ! (in)
    & fileprefix = 'hoge/' )        ! (in)

  call Add( hstnml = hstnml05, & ! (inout)
    & name = 'Data1' )           ! (in)

  call PutLine( hstnml = hstnml05 ) ! (in)

  call Inquire( hstnml = hstnml05, &     ! (in)
    & name = '', &                       ! (in)
    & file = file, &                     ! (out)
    & fileprefix = fileprefix )          ! (out)

  call AssertEqual( 'fileprefix test 1-1', &
    & answer = '', check = file )
  call AssertEqual( 'fileprefix test 1-2', &
    & answer = 'hoge/', check = fileprefix )

  call Inquire( hstnml = hstnml05, &     ! (in)
    & name = '  Data1', &                ! (in)
    & file = file, &                     ! (out)
    & fileprefix = fileprefix )          ! (out)

  call AssertEqual( 'fileprefix test 2-1', &
    & answer = 'hoge/Data1.nc', check = file )
  call AssertEqual( 'fileprefix test 2-2', &
    & answer = 'hoge/', check = fileprefix )

  call Add( hstnml = hstnml05, & ! (inout)
    & name = '', &               ! (in)
    & fileprefix = 'foo/bar_' )  ! (in)

  call Inquire( hstnml = hstnml05, &     ! (in)
    & name = '', &                       ! (in)
    & file = file, &                     ! (out)
    & fileprefix = fileprefix )          ! (out)

  call AssertEqual( 'fileprefix test 3-1', &
    & answer = '', check = file )
  call AssertEqual( 'fileprefix test 3-2', &
    & answer = 'foo/bar_', check = fileprefix )

  call Inquire( hstnml = hstnml05, &     ! (in)
    & name = 'Data1', &                  ! (in)
    & file = file, &                     ! (out)
    & fileprefix = fileprefix )          ! (out)

  call AssertEqual( 'fileprefix test 4-1', &
    & answer = 'foo/bar_Data1.nc', check = file )
  call AssertEqual( 'fileprefix test 4-2', &
    & answer = 'foo/bar_', check = fileprefix )

  !-------------------------------------------------------------------
  !  names テスト
  !  "names" test
  !-------------------------------------------------------------------
  varnames = names( hstnml06 )

  call AssertEqual( '"names" test 1-1', &
    & answer = '', check = varnames )

  call Create( hstnml = hstnml06, & ! (inout)
    & interval_value = 3.0_DP, &    ! (in)
    & interval_unit = 'min' )       ! (in)

  call Add( hstnml = hstnml06, & ! (inout)
    & name = 'Data1' )           ! (in)
  call Add( hstnml = hstnml06, & ! (inout)
    & name = 'Data2' )           ! (in)
  call Add( hstnml = hstnml06, & ! (inout)
    & name = 'Data3' )           ! (in)
  call Add( hstnml = hstnml06, & ! (inout)
    & name = 'Data4' )           ! (in)
  call Add( hstnml = hstnml06, & ! (inout)
    & name = 'Data5' )           ! (in)

  call Delete( hstnml = hstnml06, & ! (inout)
    & name = 'Data3' )              ! (in)

  call PutLine( hstnml = hstnml06 ) ! (in)

  varnames = names( hstnml06 )

  call AssertEqual( '"names" test 1-2', &
    & answer = 'Data1,Data2,Data4,Data5', check = varnames )

  call Close( hstnml = hstnml06 ) ! (inout)

  !-------------------------------------------------------------------
  !  ResetDefault テスト
  !  "ResetDefault" test
  !-------------------------------------------------------------------
  call Create( hstnml = hstnml07, & ! (inout)
    & interval_value = 3.0_DP, &    ! (in)
    & interval_unit = 'min' )       ! (in)

  call Add( hstnml = hstnml07, & ! (inout)
    & name = 'Data1' )           ! (in)
  call Add( hstnml = hstnml07, & ! (inout)
    & name = 'Data2' )           ! (in)

  call PutLine( hstnml = hstnml07 ) ! (in)

  call ResetDefault( hstnml = hstnml07 ) ! (inout)

  call PutLine( hstnml = hstnml07 ) ! (in)

  varnames = names( hstnml07 )

  call AssertEqual( '"ResetDefault" test 1-1', &
    & answer = '', check = varnames )

  call AssertEqual( '"ResetDefault" test 1-2', &
    & answer = .true., check = initialized( hstnml07 ) )

  call Inquire( hstnml = hstnml07, &     ! (in)
    & name = '', &                       ! (in)
    & interval_value = interval_value, & ! (in)
    & interval_unit = interval_unit )    ! (in)

  call AssertEqual( '"ResetDefault" test 1-3', &
    & answer = 3.0_DP, check = interval_value )
  call AssertEqual( '"ResetDefault" test 1-4', &
    & answer = 'min', check = interval_unit )

  call Close( hstnml = hstnml07 ) ! (inout)

  !-------------------------------------------------------------------
  !  複数変数操作テスト
  !  Multiple variables handling test
  !-------------------------------------------------------------------
  call Create( hstnml = hstnml08, & ! (inout)
    & interval_value = 3.0_DP, &    ! (in)
    & interval_unit = 'min' )       ! (in)

  call Add( hstnml = hstnml08, &             ! (inout)
    & name = 'Data1, Data2, Data3, Data4', & ! (in)
    & file = 'multi.nc', &                   ! (in)
    & interval_value = 2.0_DP, &             ! (in)
    & interval_unit = 'hour' )               ! (in)

  call Add( hstnml = hstnml08, & ! (inout)
    & precision = 'double' )     ! (in)

  call PutLine( hstnml = hstnml08 ) ! (in)

  varnames = names( hstnml08 )

  call AssertEqual( 'multiple variables handling test 1-1', &
    & answer = 'Data1,Data2,Data3,Data4', check = varnames )

  call Delete( hstnml = hstnml08, & ! (inout)
    & name = 'Data2, Data3' )        ! (in)

  call PutLine( hstnml = hstnml08 ) ! (in)

  varnames = names( hstnml08 )

  call AssertEqual( 'multiple variables handling test 1-1', &
    & answer = 'Data1,Data4', check = varnames )

  call Close( hstnml = hstnml08 ) ! (inout)


end program dc_histnml_test
