!******************************************************************************!
! Macro for testing the 256 ASCII character type
! Tests:
! - T1000 creation and reading of file with type 'Z' 256 ASCII data
! - T3000 creation and reading of file with type 'Z' 256 ASCII data
! - T5000 using setData and writeDataTable with type 'Z' 256 ASCII data
! - Z result in table becomes Boolean
! - Z Data in table becomes String
! - T3000 altering of record with 'Z' 256 ASCII field w/ table
! - T3000 update of Z field where value is too short
! - T3000 update of Z field where value is too long
! - T3000 adding of record with 'Z' 256 ASCII field w/ table
!
! Arguments: None
!
! @bug      NXM-3570 'Z' for 256 ASCII DataType
! @since    3.9.4
! @author:  Jeanette McCall
!******************************************************************************!
startmacro s:func[""] s:rootIn[""]
  switch INTERACTIVE interAct GET DEF=TRUE  SDEF=TRUE
  switch BASELINE    baseline GET DEF=FALSE SDEF=TRUE
  switch DEBUG       debug    GET DEF=true  SDEF=TRUE
  set OperatingSystem ENV GET OSNAME
  set z:exceptionExpected false
  set num_A_notes 10

  if rootIn EQS "" AND baseline isTRUE then
    set s:root "http://nextmidas.com/nm/"
  else
    set s:root "^rootIn"
  endif
  info "r00t = ^root"

  call test_create_a_notes
  call test_create_z_notes
  if func NEQS "" then
    call test_^{func}
  else

    ! create 1000 with 'Z' type data
    call test_create_1000
  
    set testfile "test_file_command_3000"
    call createTestFile3000 "^testfile"
    call test_create_3000   "^testfile"
  
    assert/text="^reg.main.name: get type-3000 row, table exists?"/stat=tempStatus "^testfile" FEXISTS
    if tempStatus NEQS "PASS" then
      WARNING "^testfile does not exist, bypassing other type-3000 tests"
    else
      call test_setDataTable      "^testfile"  ! Type 3000, 5000, 6000, ListFile
      call test_alterRecord_3000  "^testfile"
      call test_addRecord_3000    "^testfile"
      erase testfile
    endif

    call test_time_from_Z

  endif
endmacro


!******************************************************************************!
! Main process message for this macro. Should be right after the 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
  else
    say "Unhandled message name: ^msg.name from fid: ^msg.fid data: ^msg.data"
  endif
return

!******************************************************************************!
! If an unexpected exception is caught, mark test as failed, unless it is expected
!******************************************************************************!
procedure  processException m:emsg
  if exceptionExpected isTRUE AND emsg.name eqs "ERROR" AND "Use DETACH/F modifier to overwrite existing file" SUBS emsg.data.message then
    res z:gotExceptionForDetach true
    set z:exceptionExpected     false
  else
    assert/text="^reg.main.name: (exceptionExpected=^exceptionExpected) Unexpected exception: ^emsg.data" FALSE
    if "Trace" SUBS ENV.DEBUG then invoke ,, emsg.data.printStackTrace()
  endif
return


!******************************************************************************!
procedure test_create_1000

  result myErr ""
  result testfile "test_file_command_1000"
  result L:nels 10
  !
  ! Test NEW type 1000 file
  !
  res typechar Z
  res modechar 4
  file open/d/n tag testfile
  res modetype ^{modechar}^{typechar}
  res modetypestr modetype.toString()
  invoke ,, tag.setFormat(modetypestr)
  res mynote ^{note_^{typechar}^{modechar}}
  res mydata mynote.toString()
  forall #=1:^nels res tag.setdata(#-) mydata
  file close tag
  status testfile size=size
  if size eq nels then
    file open/d tag testfile
    do i 1 nels
      res x tag.getdata(^i-)
      if x neqs mydata then
        result myErr "data not correct"
        break
      endif
    enddo
    file close tag
  else
    result myErr "size not correct"
  endif
  erase testfile
  
  assert/text="^reg.main.name: CREATE1000 ^myErr" myErr eqs ""

return

!******************************************************************************!
procedure createTestFile3000 fn:testfile
  if "^testfile" FEXISTS erase "^testfile"
  result truth {}
  result L:truth.nels 2
  result truth.numSubRecs 5

  file open/d/n tag testfile{SR=(BYTE/SB,INT/SI,LONG/SL,DBLE/SD,ZTYP/7Z)}
  do i 0 truth.nels-1
    res tag.setdata(i,BYTE) 1
    res tag.setdata(i,INT)  2
    res tag.setdata(i,LONG) 3
    res tag.setdata(i,DBLE) 4
    res tag.setdata(i,ZTYP) ^note_z7
  enddo

  file close tag

return

!******************************************************************************!
procedure test_create_3000 fn:testfile
  !
  !  Test NEW non-homogeneous TYPE 3000 file
  !
  result myErr ""
  !
  status testfile size=size nsr=numsubrecs
  if size eq truth.nels then
    if numsubrecs eq truth.numSubRecs then
      file open/d tag testfile
      do i 1 truth.nels
        result elem i-1
        ! Test the numeric value(s)
        do j 1 numsubrecs
          ! Record names are indexed from 0!
          !
          result L:recindex j-1
          res recname tag.getrecname(recindex)
          res x tag.getdata(elem,^{recname})
          if j LT numsubrecs then
            if x neq j then
              result myErr " ^myKey, data, elem = ^i, subrec = ^j"
              goto LAB_CREATE3000
            endif
          else
            ! Z 256 ASCII compare
            if x neqs ^note_z7 then
              result myErr "^macroName: ^myKey, Z 256 ASCII data, elem = ^i, &
                           subrec = ^j"
              goto LAB_CREATE3000
            endif
          endif
        enddo
        ! Now test the ascii value(s)
      enddo
      file close tag
    else
      result myErr "num subrecords not correct"
    endif
  else
    result myErr "size ^size NE truth.nels ^truth.nels"
  endif
  
  label LAB_CREATE3000
  assert/text="^reg.main.name: CREATE3000 ^myErr" myErr eqs ""

return

!******************************************************************************!
procedure test_setDataTable fn:testfile
  set numElem 4 ! only use first 4, since the basics are tested in test_file
  set note64 123456789O12345678901234567890123456789012345678901234567890123
  res note "A^{note64}B^{note64}C^{note64}D^{note64}"
  set t:ellipse5000_data {}
  set t:ellipse5000_data.0 {POS=(0.0,0.0,45.0),ELPS=(300000.0,70000.0,0.0),NAME="TONY",NOTE=^note}
  set t:ellipse5000_data.1 {POS=(0.0,0.0,45.0),ELPS=(300000.0,70000.0,15.0),NAME="TONY",NOTE=^note}
  set t:ellipse5000_data.2 {POS=(0.0,0.0,45.0),ELPS=(300000.0,70000.0,30.0),NAME="TONY",NOTE=^note}
  set t:ellipse5000_data.3 {POS=(0.0,0.0,45.0),ELPS=(300000.0,70000.0,45.0),NAME="TONY",NOTE=^note}
  set t:ellipse5000_data.4 {POS=(0.0,15.0,60.0),ELPS=(300000.0,70000.0,60.0),NAME="TONY5",NOTE=^note}
  set t:ellipse5000_data.5 {POS=(0.0,15.0,75.0),ELPS=(300000.0,70000.0,75.0),NAME="TONY6",NOTE=^note}
  set t:ellipse5000_data.6 {POS=(0.0,15.0,90.0),ELPS=(300000.0,70000.0,90.0),NAME="TONY7",NOTE=^note}
  set t:ellipse5000_data.7 {POS=(0.0,15.0,105.0),ELPS=(300000.0,70000.0,105.0),NAME="TONY8",NOTE=^note}
  set t:ellipse5000_data.8 {POS=(0.0,60.0,0.0),ELPS=(300000.0,70000.0,45.0),NAME="TONY9",NOTE=^note}

  !!!!!!!!!!! setData tests !!!!!!!!!!!

  file open/n out ram:temp_ellipse5000{COMPONENTS=(POS/VD,ELPS/VD,NAME/9A,NOTE/1Z),SIZE=9}
    ! Do evens in order then odds in reverse order to prove that we have random-access into the
    ! file when using getDataTable(..)
    do i 0 numElem 2
      invoke ,, out.setData(^i,ellipse5000_data.^i)
    enddo
    calc highestOdd numElem 1 -
    do i ^highestOdd 1 -2
      invoke ,, out.setData(^i,ellipse5000_data.^i)
    enddo
  file close out

  file open in ram:temp_ellipse5000
  do i 0 numElem 1
    set    expected ellipse5000_data.^i
    set    actual   {}
    invoke numRead  in.readDataTable(actual)

    if i EQ 0 then
      ! test that when placed in Table the 256ASCII Data type becomes a string
      ! and a Z: result becomes a z: Boolean object
      table mycopy create
      table mycopy setkey newnote ^{actual.note}
      res z:myboolean true
      table mycopy setkey mybool myboolean
      assert/text="^reg.main.name: 'Z' result in table becomes Boolean" mycopy.mybool INSTANCEOF java.lang.Boolean
      assert/text="^reg.main.name: 'Z' Data in table becomes String" mycopy.newnote INSTANCEOF java.lang.String
    endif

    assert/text="^reg.main.name: T5000 setData(..) at ^i (numRead)" numRead          eq      1
    assert/text="^reg.main.name: T5000 setData(..) at ^i (getSize)" expected.getSize eq      actual.getSize
    assert/text="^reg.main.name: T5000 setData(..) at ^i (POS)"     expected.POS     eq/s/v  actual.POS
    assert/text="^reg.main.name: T5000 setData(..) at ^i (ELPS)"    expected.ELPS    eq/s/v  actual.ELPS
    assert/text="^reg.main.name: T5000 setData(..) at ^i (NAME)"    expected.NAME    eqs     actual.NAME
    assert/text="^reg.main.name: T5000 setData(..) at ^i (NOTE)"    expected.NOTE    eqs     ^note
  enddo
  set    actual   {}
  invoke numRead  in.readDataTable(actual)
  assert/text="^reg.main.name: T5000 setData(..) at ^i (EndOfFile)" numRead eq -1
  file close in

  !!!!!!!!!!! writeDataTable tests !!!!!!!!!!!

  file open/n out ram:test_ellipse5000{COMPONENTS=(POS/VD,ELPS/VD,NAME/9A,NOTE/1Z),SIZE=9}
    ! Do evens in order then odds in reverse order to prove that we have random-access into the
    ! file when using getDataTable(..)
    do i 0 numElem 1
      invoke ,, out.writeDataTable(ellipse5000_data.^i)
    enddo
  file close out

  file open in ram:test_ellipse5000
    do i 0 numElem 1
      set    expected ellipse5000_data.^i
      set    actual   {}
      invoke numRead  in.readDataTable(actual)

      assert/text="^reg.main.name: T5000 writeDataTable(..) at ^i (numRead)" numRead          eq      1
      assert/text="^reg.main.name: T5000 writeDataTable(..) at ^i (getSize)" expected.getSize eq      actual.getSize
      assert/text="^reg.main.name: T5000 writeDataTable(..) at ^i (POS)"     expected.POS     eq/s/v  actual.POS
      assert/text="^reg.main.name: T5000 writeDataTable(..) at ^i (ELPS)"    expected.ELPS    eq/s/v  actual.ELPS
      assert/text="^reg.main.name: T5000 writeDataTable(..) at ^i (NAME)"    expected.NAME    eqs     actual.NAME
      assert/text="^reg.main.name: T5000 writeDataTable(..) at ^i (1Z:NOTE)"    expected.NOTE    eqs     ^note
    enddo
    set    actual   {}
    invoke numRead  in.readDataTable(actual)
    assert/text="^reg.main.name: T5000 writeDataTable(..) at ^i (EndOfFile)" numRead eq -1
  file close in

  keyword ram:temp_ellipse5000 get name=VER value=blueVer
  assert/text="^reg.main.name: T5000 with 'Z' 256 ASCII type is VER 1.2" blueVer EQS "1.2"
return

!******************************************************************************!
!  Test altering a type-3000 record with a table
procedure test_alterRecord_3000 fn:testfile
  if table REXISTS rem table
  res alt_note NEW_NEW_^{last7}^{all8}^{all8}^{all8}
  res altZTyp ^{note_z6}^{alt_note}
  result t:tableTrue {BYTE=11,INT=12,LONG=13,DBLE=14,zTYP=^altZTyp}

  ! Alter the record in the file
  file open/d/w tag testfile
    result tag.setData(1) ^tableTrue
  file close tag

  ! Read the new record from the file
  file open/d tag testfile
    result table tag.getDataTable(1)
  file close tag

  result allPass "TRUE"
  result s:myMsg "T3000 alter record w/ table containing long string for 7Z field"
  result L:entry 1
  foreach key INTABLE tableTrue
    result tempStatus "PASS"
    if entry NEQ truth.numSubRecs
      if table.^{key} NEQ tableTrue.^{key} then
        result tempStatus "FAIL"
      endif
    else
      if "^{table.^{key}}" NEQS "^{tableTrue.^{key}}" then
        result tempStatus "FAIL"
      endif
    endif
    if tempStatus isFalse then
      result S:allPass "FALSE"
      result S:myMsg "T3000 alter record, &
                      ^key; ^{table.^{key}} NE ^{tableTrue.^{key}}"
      break
    endif
    calc L:entry entry 1 +
  endfor
  assert/text="^reg.main.name: ^myMsg" allPass


  ! Alter the record in the file with the set syntax
  set FILE(testfile).setData(0,ZTYP)  ^note_z1
  set FILE(testfile).setData(1,ZTYP) ^{note_z7}90 ! string too long will trim off "90"

  ! Read the new record from the file
  result table0 FILE(testfile).getDataTable(0)
  result table1 FILE(testfile).getDataTable(1)
  assert/text="^reg.main.name: T3000 update to 'Z' 256 ASCII field (short)" table0.ZTYP eqs ^note_z1
  assert/text="^reg.main.name: T3000 update to 'Z' 256 ASCII field (long)"  table1.ZTYP eqs ^note_z7

  keyword testfile get name=VER value=blueVer
  assert/text="^reg.main.name: T3000 with 'Z' 256 ASCII type is VER 1.2" blueVer EQS "1.2"
return

!******************************************************************************!
procedure test_addRecord_3000 fn:testfile
  !
  !  Test altering a type-3000 record with a table
  !
  if table REXISTS rem table
  result t:tableTrue {BYTE=21,INT=22,LONG=23,DBLE=24,ZTYP=^{note_z7}}
  
  status ^testfile size=size
  ! Add the record to the end of the file
  file open/d/w tag testfile
    result tag.setData(size) tableTrue
  file close tag
  
  ! Read the new record from the file
  file open/d tag testfile
    result table tag.getDataTable(size)
  file close tag
  
  result allPass "TRUE"
  result s:myMsg "T3000 add record w/ table with long String for 7Z field"
  result L:entry 1
  foreach key INTABLE tableTrue
    result tempStatus "PASS"
    if entry NEQ truth.numSubRecs
      if table.^{key} NEQ tableTrue.^{key} then
        result tempStatus "FAIL"
      endif
    else
      if "^{table.^{key}}" NEQS "^{tableTrue.^{key}}" then
        result tempStatus "FAIL"
      endif
    endif
    if tempStatus isFalse then
      result S:allPass "FALSE"
      result S:myMsg "type-3000 add record, &
                      ^key; ^{table.^{key}} NE ^{tableTrue.^{key}}"
      break
    endif
    calc L:entry entry 1 +
  endfor
  
  assert/text="^reg.main.name: ^myMsg" allPass

return

!******************************************************************************!
procedure test_time_from_Z

  res Z:boolTrue TRUE
  new nxm.sys.lib.Data("2020:09:29::15:34:01.1234567890123456789",boolTrue) zDataTime
  invoke timeFromZ nxm.sys.lib.Time.toTime(zDataTime)
  invoke timeFromS nxm.sys.lib.Time.toTime("2020:09:29::15:34:01.1234567890123456789")
  assert/text="^reg.main.name: Time for 'Z' Data Type" timeFromS EQ timeFromZ

return

!******************************************************************************!
procedure test_create_A_notes
  res base_note MyANote_
  res mystring base_note.toString()
  RESULT L:index 1
  WHILE L:index LE num_A_notes
    res note_a^index mystring
    res L:mult 2
    while L:mult LE index
      invoke note_a^index mystring.concat(^{note_a^index})
      calc L:mult mult 1 +
    endwhile
    calc L:index index 1 +
  ENDWHILE


return

!******************************************************************************!
procedure test_create_Z_notes
  res S:ones 1111111_
  res S:twos 2222222_
  res S:threes 3333333_
  res S:fours  4444444_
  res S:fives  5555555_
  res S:sixes  6666666_
  res S:sevens 7777777_
  res S:eights 8888888_
  res S:all8   ^{ones}^{twos}^{threes}^{fours}^{fives}^{sixes}^{sevens}^{eights}
  res S:last7  ^{twos}^{threes}^{fours}^{fives}^{sixes}^{sevens}^{eights}
  res base_note MyZNote_^{last7}^{all8}^{all8}^{all8}
  res mystring base_note.toString()
  RESULT L:index 1
  WHILE L:index LE num_A_notes
    res note_z^index mystring
    res L:mult 2
    while L:mult LE index
      invoke note_z^index mystring.concat(^{note_z^index})
      calc L:mult mult 1 +
    endwhile
    calc L:index index 1 +
  ENDWHILE


return
