! Tests the PATH command.
!
! Author:  Jay Hallam / Neon Ngo
!
startmacro s:func[""]
  switch INTERACTIVE interAct GET DEF=TRUE  SDEF=TRUE
  switch BASELINE    baseline GET DEF=FALSE SDEF=TRUE

  ! Skip some tests when run in a thinned NeXtMidas - 4.0.0
  invoke optionExists reg.shell.M.dictionary.isDictionaryEntry(OPTION)
  invoke panelExists reg.shell.M.dictionary.isDictionaryEntry(PANEL)

  invoke isGradleBuild nxm.sys.lib.Shell.isGradleBuild()
  if isGradleBuild then
    info "Warning: Skipping test because this jar was built by gradle"
  else
  
    if func NEQS "" then
      call test_^{func}
      stop
    endif

    call test_get
    if optionExists then call test_set
    call test_add
    call test_add_plus
    call test_put
    call test_rem
    call test_add_matching_substr
    call test_rem_matching_substr
    if optionExists then
      call test_optstart
      %test_path_dict
    endif

    ! TODO: how to test "path redo" (maybe part of interactive test?)
    ! call test_redo

    ! Start Interactive test section
    if interAct AND panelExists then
      pipe on
        panel/msgid=MAIN/setup/controls=gc
        gcontrol label macro "MACRO"
        gcontrol menu main "Exit with Status = " "PASS,FAIL" /tleft
        set gc.main.itemColors {PASS=GREEN,FAIL=RED}

        set instructions "Should see current path displayed."
        gcontrol text idtext  "Instructions" "^instructions" 24 3 /title

        shellgui/id=idshellgui/attach
        say ""
        say "nM> PATH"
        ! test path without any args
        path

        ! test case for BUG 2206
        say ""
        info "Should see only ONE path (one line) displayed below the command:"
        say "nM> PATH,SHOW,"
        path,show,

      pipe off
    endif

  endmacro
endif

!****************************************************************************!
! process messages for interactive tests
!****************************************************************************!
procedure processMessage m:msg
  !say "msg.name ^msg.name, data ^msg.data"

  if msg.name eqs "MAIN" then
    assert/text="^reg.main.name: Tests" msg.data eqss "PASS"
    pipe stop
  else
    say "^reg.main.name: Unhandled message name: ^msg.name from fid: ^msg.fid data: ^msg.data"
  endif
return


!****************************************************************************!
! process expected exceptions for testing Bug 1436, see test_bug1436
!****************************************************************************!
procedure processException m:emsg
  !say "emsg.name ^emsg.name, data ^emsg.data"

  calc L:errCount errCount 1 +

  invoke errMsg emsg.data.getMessage()

  if errMsgs.^{errCount} rexists then
    assert/text="^reg.main.name: Caught expected exception '^{errMsg}'" errMsg eqs errMsgs.^{errCount}
  else
    assert/text="^reg.main.name: Caught unexpected exception ^{emsg.data}" "FALSE" isTrue
  endif
return

! *****************************************************
! Setup necessary directories, files, and option trees.
! *****************************************************
procedure initial_config
  FILE NAME rootOptDir (^{env.nmroot},nxm,sys,test,nmopts) "" ""

  ! Add new option trees
  option mytestopt1  ^rootOptDir
  option mytestopt2  ^rootOptDir

  ! Verify that the MYTESTOPT1 & MYTESTOPT2 option trees exist.
  call testOptExist "MYTESTOPT1 option tree exists." mytestopt1
  call testOptExist "MYTESTOPT2 option tree exists." mytestopt2

  if baseline then
    ! These tests need an additional option tree being built and added to the path, as such they
    ! only run with /BASELINE. Note that some of the commands in the test option tree are
    ! "non-functional" in order to test Bug 1436.
    ! Build the testpathprim primitive in each of the respective option trees.
    bld name=* area=prim opt=mytestopt1
  endif

  global global_mytestopt1_optstart
  global global_mytestopt2_optstart
return

! *****************************************************
! Check to see that commands.cnf exists for a given option.
! *****************************************************
procedure testOptExist s:text s:option
  invoke temp nxm.sys.lib.OptionTree.getOptPath(^option,cfg)
  ! Testing this change for 3.8.0 .... TODO investigate further
  assert/text="^text" "^{temp}commands.cnf" FEXISTS
return

! *****************************************************
! Cleanup directories, files and option trees.
! *****************************************************
procedure final_cleanup

  ! Remove test option trees from PATH.
  path rem mytestopt1 mytestopt2

  ! Remove option tree references from results table.
  OPTION/DELETE MYTESTOPT1
  OPTION/DELETE MYTESTOPT2

  remove/global global_mytestopt1_optstart
  remove/global global_mytestopt2_optstart
return

!****************************************************************************!
! test path set <opt1> <opt2> ... <optN>
!****************************************************************************!
procedure test_set
  ! save previous path
  res savepath opt.path
  !set hwfile to null for testing NXM-2834 hwc/cfg/optstart.mm
  env set HWFILE ""
  path set DSP
  assert/text="^reg.main.name: PATH SET DSP" opt.path EQS "DSP,SYS"
  env get "HWFILE" hwf
  !  info "BEFORE hwf = ^hwf"
  assert/text="^reg.main.name: PATH SET HWFILE to null" hwf EQS ""
  path set HWC HWC HWC UCL UCL DSP SYS
  assert/text="^reg.main.name: PATH SET <opt1> <opt2>..." opt.path EQS "HWC,UCL,DSP,SYS"
  env get "HWFILE" hwf
  !  info "AFTER hwf = ^hwf"
  assert/text="^reg.main.name: PATH SET HWFILE to hwconfig.prm" hwf EQS "nxm.sys.dat.hwconfig.prm"
  ! restore previous path
  path set ^savepath
return

!****************************************************************************!
! Test path add <opt>
! Depends on 'path set' working
!****************************************************************************!
procedure test_add
  ! save previous path
  res savepath opt.path

  path set SYS
  path add DSP
  assert/text="^reg.main.name: PATH ADD" opt.path EQS "DSP,SYS"

  path add DSP
  assert/text="^reg.main.name: PATH ADD (2nd time with same OPTION)" opt.path EQS "DSP,SYS"

  ! test case for "+" (since 3.3.0 Bug 2672)
  path + HWC UCL
  assert/text="^reg.main.name: PATH + " opt.path EQS "UCL,HWC,DSP,SYS"

  ! restore previous path
  path set ^savepath
return

!****************************************************************************!
! Test path put <opt>
! Depends on 'path add' working
!****************************************************************************!
procedure test_put
  ! save previous path
  res savepath opt.path

  path/warn=no add third
  path/warn=no add second

  info "Should see an INFO that 'Option Tree THIRD is already in path. Doing nothing.'
  path put third  ! should do nothing

  info "This will print out several 'No commands.cnf found...' warnings
  path put first ! should add to front

  assert/text="^reg.main.name: PATH PUT" opt.path EQS "FIRST,SECOND,THIRD,^savepath"

  ! restore previous path
  path set ^savepath
return

!****************************************************************************!
! test putting <option> on the end of the existing path but before SYS
! Depends on 'path set' working
!****************************************************************************!
procedure test_add_plus
  ! save previous path
  res savepath opt.path

  path set HWC
  path add+ DSP
  assert/text="^reg.main.name: PATH ADD+" opt.path EQS "HWC,DSP,SYS"

  ! test BUG 2365 ADD+ can corrupt path
  path/warn=no add+ JOEY,SP,MYTESTOPT,TESTOPT
  assert/text="^reg.main.name: PATH ADD+ <options that are substrings of path>" &
    opt.path EQS "HWC,DSP,JOEY,SP,MYTESTOPT,TESTOPT,SYS"

  ! run add+ again to make sure it is fine for BUG 2365
  path/warn=no add+ JOEY,SP,MYTESTOPT,TESTOPT
  assert/text="^reg.main.name: PATH ADD+ <options that are substrings of path> 2nd time" &
    opt.path EQS "HWC,DSP,JOEY,SP,MYTESTOPT,TESTOPT,SYS"

  ! restore previous path
  path set ^savepath
return

!****************************************************************************!
! test path get <option> <resname>
!****************************************************************************!
procedure test_get
  fname path1 AREA="" NAME="" EXT="" OPT=SYS
  path get SYS path2
  assert/text="^reg.main.name: PATH GET SYS <resname>" "^path1" eqs "^path2"
return

!****************************************************************************!
! test path rem <option>
! Depends on 'path set' working
!****************************************************************************!
procedure test_rem
  ! save previous path
  res savepath opt.path

  path set HWC UCL DSP
  path rem UCL DSP
  assert/text="^reg.main.name: PATH REMove" opt.path EQS "HWC,SYS"

  ! test case for "-" (since 3.3.0 Bug 2672)
  path - HWC
  assert/text="^reg.main.name: PATH - " opt.path EQS "SYS"

  ! restore previous path
  path set ^savepath
return

!****************************************************************************!
! Test path rem <opt> where <opt> is a substring of existing entry in path
! Test for BUG 1806 PATH REMOVE can corrupt path
! Depends on 'path set' working
!****************************************************************************!
procedure test_rem_matching_substr
  ! save previous path
  res savepath opt.path

  path/warn=no set TESTDSP DSP HWC SYS
  path/warn=no rem DSP
  assert/text="^reg.main.name: PATH REM <option that is substring of another option>" opt.path EQS "TESTDSP,HWC,SYS"

  ! restore previous path
  path set ^savepath
return

!****************************************************************************!
! Test path add <opt> where <opt> is a substring of existing entry in path
! Depends on 'path set' working
! Test for BUG 1160 PATH fails when one option tree is a substring of another
!****************************************************************************!
procedure test_add_matching_substr
  ! save previous path
  res savepath opt.path

  path set SYS
  path/warn=no add "MYTESTOPT"
  path/warn=no add "TESTOPT"
  assert/text="^reg.main.name: PATH ADD <option that is substring of another option>" &
    opt.path EQS "TESTOPT,MYTESTOPT,SYS"

  ! restore previous path
  path set ^savepath
return

!****************************************************************************!
! Test path ADD, ADD+, PUT, and SET functions should run option tree's
! optstart.mm macro (if exists) under cfg area.
! also run a few other tests with /baseline switch
!****************************************************************************!
procedure test_optstart
  ! save previous path
  res savepath opt.path
  call initial_config ! Setup test files and option trees.

  ! Add option tree to initial PATH
  set global_mytestopt1_optstart ""
  set global_mytestopt2_optstart ""
  path add mytestopt1

  assert/text="^reg.main.name: optstart.mm was run for MYTESTOPT1 (ADDed to path)" global_mytestopt1_optstart eqs "^{opt.path}"
  assert/text="^reg.main.name: optstart.mm not run for MYTESTOPT2 (not in path)"   global_mytestopt2_optstart eqs ""

  ! SET the path again (optstart should not be executed a second time)
  set global_mytestopt1_optstart ""
  set global_mytestopt2_optstart ""
  run path set mytestopt2 mytestopt1 sys
  assert/text="^reg.main.name: optstart.mm not run for MYTESTOPT1 (SET already in path)" global_mytestopt1_optstart eqs ""
  assert/text="^reg.main.name: optstart.mm was run for MYTESTOPT2 (SET in path)"         global_mytestopt2_optstart eqs "^{opt.path}"

  ! test ADD+ (calls optstart)
  path rem mytestopt1
  set global_mytestopt1_optstart ""
  set global_mytestopt2_optstart ""
  path add+ mytestopt1 mytestopt2
  assert/text="^reg.main.name: optstart.mm was run for MYTESTOPT1 (ADD+ to path)"             global_mytestopt1_optstart eqs "^{opt.path}"
  assert/text="^reg.main.name: optstart.mm not run for MYTESTOPT2 (ADD+ already in path)" global_mytestopt2_optstart eqs ""

  ! test for Bug 2283  (PATH/RERUN)
  set global_mytestopt1_optstart ""   ! reset
  set global_mytestopt2_optstart ""   ! reset
  path/rerun
  assert/text="^reg.main.name: /RERUN optstart.mm was run for MYTESTOPT1" global_mytestopt1_optstart eqs "^{opt.path}"
  assert/text="^reg.main.name: /RERUN optstart.mm was run for MYTESTOPT2" global_mytestopt2_optstart eqs "^{opt.path}"

  ! test for BUG 2359 (to skip running option tree's optstart)
  path set SYS
  set global_mytestopt1_optstart ""   ! reset
  set global_mytestopt2_optstart ""   ! reset
  path/skiprun set mytestopt2 mytestopt1 sys
  assert/text="^reg.main.name: /SKIPRUN optstart.mm not run for MYTESTOPT1" global_mytestopt1_optstart eqs ""
  assert/text="^reg.main.name: /SKIPRUN optstart.mm not run for MYTESTOPT2" global_mytestopt2_optstart eqs ""

  if baseline then
    ! These tests need an additional option tree being built and added to the path, as such they
    ! only run with /BASELINE. Note that some of the commands in the test option tree are
    ! "non-functional" in order to test Bug 1436.
    warn "^reg.main.name: Skipping tests for Bug 1285 -- known DR."
    !call test_bug1285
    if ^{env.NMROOT} EQS "classpath:" then
      INFO "^reg.main.name: Skipping test_bug1436 due to running from a jar (testoption trees do not work from jar)"
    else
      call test_bug1436
    endif
  else
    INFO "^reg.main.name: Skipping additional tests for DRs, specify /BASELINE to run them."
  endif

  call final_cleanup ! Clean up/ remove test files and option trees.
  ! restore previous path
  path set ^savepath
return

!****************************************************************************!
! Test for Bug 1285 (PATH: seems to not reset commands when path is changed inside a macro)
!****************************************************************************!
procedure test_bug1285
  ! Start test macro with MYTESTOPT1 on path, other option tree will be added to the path
  ! inside of the macro.
  %test_path_prim_scenarios/quiet ! Tests for Bug 1285 must run in a child macro
return

!****************************************************************************!
! Test for Bug 1436 (Shell: Unfriendly error message when primitive class is declared wrong.)
!****************************************************************************!
procedure test_bug1436
  ! These tests use RUN since otherwise Macro.java will error out when trying to load the class.
  ! All of the RUN lines throw exceptions that are caught in processException.
  set L:errCount 0
  set T:errMsgs  {1="Could not find a public no-argument constructor for nxm.mytestopt1.prim.testbadconstructor1.",&
                  2="Could not find a public no-argument constructor for nxm.mytestopt1.prim.testbadconstructor2.",&
                  3="The class nxm.mytestopt1.prim.testpackageprivate is not public."}

  run testbadconstructor1;MYTESTOPT1  ! <-- Error condition, will not load, used to test Bug 1436
  run testbadconstructor2;MYTESTOPT1  ! <-- Error condition, will not load, used to test Bug 1436
  run testpackageprivate;MYTESTOPT1   ! <-- Error condition, will not load, used to test Bug 1436

  assert/text="^reg.main.name: Correct number of exceptions caught" errCount eq 3
return
