!******************************************************************************!
! Test the DataFile library.
!
! Arguments:
!   in  - in file name
!   out - out file name
!
! Issue:   NXM-1093 TRUNCATE flag not handled properly in DataFile.open()
! Issue:   NXM-1934 DATAFILE: getComment() does not work when reading a file
! Issue:   NXM-2015 MA.getDataFile would warn or error when hcbin have NOT been opened
! Issue:   NXM-2087 DATAFILE: Should use TRUNCATE by default (via ENV.IOOPTIONS for 2.9.1)
! Issue:   NXM-2247 WAVEFORM / DataFile output over existing file in RAM AUX does not honor protect flag
! Issue:   NXM-2384 DataFile: calling setSubRecords(..) with empty String
! Issue:   NXM-2424 DATAFILE / PIPE: Can't pipe type 6000 files the same way as type 3000 files
! Issue:   NXM-2583 DataFile: Read time from Platinum files
! Issue:   NXM-2748 Missing BaseFile.hashCode() and DataFile.hashCode() methods
! Issue:   NXM-3009 Setting Keywords in Pipe
! Issue:   NXM-3894 12-bit integer Midas Data Type needed
! Issue:   NXM-4009 DS= File qualifier broken, others should work and be tested
! Since:   NeXtMidas 2.7.3
! Author:  J Bauer / Neon Ngo
!******************************************************************************!
startmacro fn:in["nxm.sys.dat.apenny.prm"] fn:out["testnxm2015.tmp"]
  switch INTERACTIVE interAct GET DEF=TRUE  SDEF=TRUE  ! for normal interactive test(s)
  switch BASELINE    baseline GET DEF=FALSE SDEF=TRUE  ! for defects or more obscure test case(s)

  call setDatDir
  invoke inPath in.toString()
  invoke inPath inPath.replace("^{datDir}",^{datDir})
  new nxm.sys.lib.FileName(inPath) in

  call testGetComment               ! NXM-1934
  call test_truncate                ! NXM-1093, NXM-2015
  call test_overwrite_protected     ! NXM-2247
  call test_clear_subrecords        ! NXM-2384
  call test_piping_6000_file        ! NXM-2424
  call test_platunim_time           ! NXM-2583
  call test_hashcode_contract       ! NXM-2748
  call test_setting_keyword_in_pipe ! NXM-3009
  call test_overwrite_datastart     ! NXM-4009

  ! Allow most of the tests to run in a thinned NeXtMidas by skipping only ones needing missing dependencies - 4.0.0
  invoke gcontrolExists reg.shell.M.dictionary.isDictionaryEntry(GCONTROL)
  invoke noopExists     reg.shell.M.dictionary.isDictionaryEntry(NOOP)

  if gcontrolExists AND noopExists then
    ! interactive test case for NXM-2015
    if interAct then
      res part1_instr "*PART 1*\n&
                       1) You should see a warning that headers cannot be propagated from &
                       input file to output file\n\n&
                       2) Click 'PART_2' button to go to part 2 of this test"

      res part2_instr "*PART 2*\n&
                       You should see:\n&
                       1) an INFO about not having full PLATINUM VER=2.0 support,\n\n&
                       2) a warning about fixing TimeCode+TC_PREC, and \n\n&
                       3) the STATUS listing for a Platinum file in the bottom shell &
                       where the Start time is listed as &
                       '2012:11:10::09:08:07.654321012300 (TimeLine)'."

      invoke OUTPUT=nxm.sys.lib.DataFile.OUTPUT
      invoke hcbin=this.args.getDataFile("IN")

      noop ^{datDir}.test3000.prm ram:testfile
      pipe on
        panel/setup/controls=gc
        gcontrol label macro "MACRO"
        gcontrol menu main "Exit with Status = " "PASS,FAIL" /tleft
        gcontrol text idtext "INSTRUCTIONS" "^part1_instr" 24 20 /title
        gcontrol button test_section "Test Section" "PART_1,PART_2" "PART_1"

        set gc.main.itemcolors {PASS=GREEN,FAIL=RED}

        shellgui/id=SHELL1/attach
        say "*"
        say "**** PART 1 ************
        say "*"
        say "calling MA.getDataFile("OUT",hcbin,OUTPUT) ..."
        res hcbout this.args.getDataFile("OUT",hcbin,OUTPUT)
      pipe off
    endif

    %test_datafile_j_12-bit/INTERACTIVE=^interAct          ! NXM-3894 'J' 12-bit
    %test_datafile_j_12-bit/INTERACTIVE=^interAct/NONATIVE ! NXM-3894 'J' 12-bit
  endif

  %test_data_unsigned/INTERACTIVE=^interAct ! NXM-3021 Test unsigned data types 'U' and 'V'
  %test_data_256ascii                       ! NXM-3570 'Z' 256 ASCII character type
  %test_datafile_256ascii                   ! NXM-3570 'Z' 256 ASCII character type
endmacro

!******************************************************************************!
procedure  processMessage m:msg
  if msg.name eqs "MAIN" then
    assert/text="^reg.main.name: user indicated tests" msg.data eqss "PASS"
    pipe stop
  elseif msg.name eqs "TEST_SECTION" then
    if msg.data eqs "PART_2" then
      res gc.idtext.value part2_instr
      say "*"
      say "**** PART 2 ************
      say "*"
      say "nM> STATUS nxm.sys.test.testplat1001.cdif"
      STATUS nxm.sys.test.testplat1001.cdif
    else
      !message func=sendw id=TD ,,CLEAR,,
      res gc.idtext.value part1_instr
      say "*"
      say "**** PART 1 ************
      say "*"
      say "calling MA.getDataFile("OUT",hcbin,OUTPUT) ..."
      res hcbout this.args.getDataFile("OUT",hcbin,OUTPUT)
    endif
  endif
return

!******************************************************************************!
procedure  processException m:emsg
  if emsg.name eqs "ERROR" AND "Output is protected" SUBS emsg.data.message then
    res z:gotExceptionForNxm2247 true
    assert/text="^reg.main.name: Should get ERROR for overwriting protected file" TRUE
  else
    assert/text="^reg.main.name: Unexpected exception: ^emsg.data" FALSE
  endif
return

!******************************************************************************!
! Set the dat directory
!******************************************************************************!
procedure setDatDir
  invoke nxmMajor env.nmversion.subString(0,1)
  invoke major java.lang.Integer.valueOf(nxmMajor)
  if major GE 4 then
    invoke s:datDir           nxm.sys.test.DatLocator.getDatDirLocation()
    invoke s:datDirSlash      nxm.sys.test.DatLocator.getDatDirSlashLocation()
    invoke z:sysDatFull       nxm.sys.test.DatLocator.sysDatFull()
    invoke z:sysTestDatExists nxm.sys.test.DatLocator.sysTestDatExists()
  else
    set s:datDir           "nxm.sys.dat"
    set s:datDirSlash      "nxm/sys/dat"
    set z:sysDatFull       true
    set z:sysTestDatExists false
  endif
return

!******************************************************************************!
! Tests getting the comment from a file through the macro language (NXM-1934)
procedure testGetComment
  res fname "nxm.sys.test.listtemplate.tmp"
  res expectedComment "X-DataList template file"

  file open myFile "^fname"
  res comment myFile.comment

  assert/text="^reg.main.name: getComment"      comment EQS expectedComment

  file close myFile
return

!******************************************************************************!
! Tests opening an output file with the TRUNCATE flag qualifier
! Test NXM-1093 TRUNCATE flag not handled properly in DataFile.open()
! Test NXM-2087 DataFile: Should use TRUNCATE by default (via ENV)
procedure test_truncate
  set fname     "test_datafile_trunc.tmp"
  set fname_tmp "test_datafile_trunc_tmp.tmp"

  ! remove any existing (highly unlikely)
  erase/warn=no fname
  erase/warn=no fname_tmp

  ! first make a larger file
  waveform fname elem=50k
  status   fname{fg=raw} size=size_big

  ! get the size for the eventual smaller file by using a dummy test file
  waveform fname_tmp elem=1k
  status   fname_tmp{fg=raw} size=size_small

  env get IOOptions origIOOptions
  env set IOOptions -TruncateBLUE

  waveform fname elem=1k
  status   fname{fg=raw} size=fsize
  assert/text="^reg.main.name: No truncate (flag) file size= ^fsize" ^fsize eq size_big

  waveform fname{flags=truncate} elem=1k
  status   fname{fg=raw} size=fsize
  assert/text="^reg.main.name: With truncate (flag) file size= ^fsize" ^fsize eq size_small

  ! test case for NXM-2015 BLUE Files should truncate by default (via ENV setting)
  waveform fname elem=50k   ! create big file again
  env set IOOptions +TruncateBLUE
  waveform fname elem=1k
  status   fname{fg=raw} size=fsize2
  assert/text="^reg.main.name: With truncate (TruncateBLUE env) file size= ^fsize2" ^fsize2 eq size_small

  ! restore IOOptions settings
  env set IOOptions origIOOptions

  ! cleanup files
  erase/warn=no fname
  erase/warn=no fname_tmp

return

!******************************************************************************!
! Tests overwriting a protected file in the RAM AUX.
! Test NXM-2247 WAVEFORM / DataFile output over existing file in RAM AUX does not honor protect flag
procedure test_overwrite_protected
  res testfile "ram:ramfile"
  waveform testfile
  file protect testfile

  res z:gotExceptionForNxm2247 false
  ! the below should cause an exception since file in RAM should be protected
  waveform testfile
  assert/text="^reg.main.name: Overwrite protected file in RAM AUX" gotExceptionForNxm2247 isTrue

  ! cleanup
  file unprotect testfile
  erase/warn=no testfile
return

!******************************************************************************!
! Tests clearing out subrecords (NXM-2384)
procedure test_clear_subrecords
  set testfile "ram:mytest3000"
  noop ^{datDir}.test3000.prm testfile
  file open/d mytag testfile
  res startRecs mytag.recordDefCount
  file close mytag

  file/d open mynewtag testfile
  invoke ,, mynewtag.setSubRecords("")
  invoke endRecs mynewtag.getRecordDefCount()
  file close mynewtag

  assert/text="^reg.main.name: Clear defined subrecords" endRecs eq 0

  erase/warn=no testfile
return

!******************************************************************************!
! Tests piping a type 6000 file (NXM-2424)
procedure test_piping_6000_file
  rem myNumSubRecs mySubRecord1
  pipe on
    waveform _my6000pipe{type=6000,sr=(DATA/SF)} form=SF elem=64k
    status _my6000pipe nsr=myNumSubRecs sr(1)=mySubRecord1
    assert/text="^reg.main.name: piping type 6000 file - num subrecords" myNumSubRecs eq 1
    assert/text="^reg.main.name: piping type 6000 file - sr(1).name"   mySubRecord1.name   eqs "DATA"
    assert/text="^reg.main.name: piping type 6000 file - sr(1).format" mySubRecord1.format eqs "SF"
  pipe off
return

!******************************************************************************!
! Tests reading Platinum time values (NXM-2583)
procedure test_platunim_time
  info "Will see 3 warnings (each) about a BLUE VER=2.0 file and fixing TimeCode+TC_PREC..."
  timex  INFILE=nxm.sys.test.testplat1001.cdif time
  status nxm.sys.test.testplat1001.cdif timecode=timecode
  key    nxm.sys.test.testplat1001.cdif GET TC_PREC tc_prec

  invoke timeStr time.toString(12)
  assert/text="^reg.main.name: Got proper Platinum time"     timeStr  EQS "2012:11:10::09:08:07.654321012300"
  assert/text="^reg.main.name: Got proper Platinum timecode" timecode EQ  1.983690487654321E9
  assert/text="^reg.main.name: Got proper Platinum TC_PREC"  tc_prec  EQ  0.000000012300
return

!******************************************************************************!
! Tests HashcodeContract (NXM-2748)
procedure test_hashcode_contract
  waveform ram:testf1 elem=4k
  waveform ram:testf2 elem=8k
  waveform ram:testf3 elem=8k
  
  assert/text="^reg.main.name: Files of Different Size Not Equal"          FILE(ram:testf1)          NOEQ FILE(ram:testf2)
  assert/text="^reg.main.name: Files of Different Size Hashcode Not Equal" FILE(ram:testf1).hashcode  NEQ FILE(ram:testf2).hashcode
  assert/text="^reg.main.name: Files of Same Size Equal"                   FILE(ram:testf2)           OEQ FILE(ram:testf3)
  assert/text="^reg.main.name: Files of Same Size Hashcode Equal"          FILE(ram:testf2).hashcode   EQ FILE(ram:testf3).hashcode
return

!******************************************************************************!
! Tests setting keyword in pipe
procedure test_setting_keyword_in_pipe
  res D:exp6456 6.456
  res I:exp2    2
  res S:expmain "YES!"
  waveform waveoutsidepipe.tmp{AUX=RAM,EXTKW="D:KEY6456=6.456,I:MY2=2",MAINKW="MAINKW=NO!"}
  pipe on
    waveform _wavekey{EXTKW="D:KEY6456=6.456,I:MY2=2",MAINKW="MAINKW=YES!"}
    noop _wavekey wave_with_keywords.tmp{AUX=RAM}
    noop waveoutsidepipe.tmp{AUX=RAM,MAINKW="MAINKW=YES!"} _wavekey2
    noop _wavekey2 wave_with_keywords2.tmp{AUX=RAM}
  pipe off
  keyword wave_with_keywords.tmp{AUX=RAM} GET key6456 val6456
  keyword wave_with_keywords.tmp{AUX=RAM} GET my2 val2
  keyword wave_with_keywords.tmp{AUX=RAM} GET MAINKW valmain
  keyword wave_with_keywords2.tmp GET MAINKW valmain2
  assert/text="^reg.main.name: Setting Keyword in pipe 1st keyword" val6456 EQ exp6456
  assert/text="^reg.main.name: Setting Keyword in pipe 2nd keyword" val2 EQ exp2
  assert/text="^reg.main.name: Setting Keyword in pipe Main keyword" valmain EQS expmain
  assert/text="^reg.main.name: Replacing Keyword in pipe Main keyword" valmain2 EQS expmain
  
return

!******************************************************************************!
! Tests overwriting the start position of Data (in bytes)
!******************************************************************************!
procedure test_overwrite_datastart
  res testFileDefaultDS "testFileDefaultDataStart{AUX=RAM}"
  headermod/create testFileDefaultDS
  status testFileDefaultDS datastart=dsVal
  assert/text="^reg.main.name: Data start value should be 512.0" dsVal EQ 512.0

  res testFileNewDS "testFileNewDataStart{AUX=RAM,DS=2048.0}"
  headermod/create testFileNewDS
  status testFileNewDS datastart=dsVal
  assert/text="^reg.main.name: Data start value should be 2048.0" dsVal EQ 2048.0
return