!******************************************************************************!
! Tests the MENU command.
!
! Author:  Neon Ngo
!******************************************************************************!
startmacro
  switch BASELINE    baseline GET DEF=FALSE SDEF=TRUE

  invoke isGradleBuild        nxm.sys.lib.Shell.isGradleBuild()
  invoke isGradleBuildCommand nxm.sys.lib.Shell.isGradleBuildCommand()

  ! Allow most of the tests to run in a thinned NeXtMidas by skipping only ones needing missing dependencies - 4.0.0
  invoke sourcedgExists reg.shell.M.dictionary.isDictionaryEntry(SOURCEDG)
  invoke panelExists reg.shell.M.dictionary.isDictionaryEntry(PANEL)

  ! test BUG 2804 (to reproduce set path to DSP,HWC,SYS then to SYS, then exit/reenter NeXtMidas shell)
  call test_list_no_dups SYS
  ! end test for BUG 2804 (this must come before adjusting the PATH again (i.e. in the below test cases)

  if sourcedgExists then call test_name_and_opt
  call test_percent_sup
  if panelExists then call test_f_and_opt_switch ! skip this test if running in LIBNXM NeXtMidas
  if sourcedgExists then call test_advanced

endmacro

!******************************************************************************!
! If an unexpected exception is caught, mark test as failed, unless it is expected
!******************************************************************************!
procedure processException m:emsg
  if expectedException REXISTS then
    assert/text="^reg.main.name: Expected ERROR starts with: ^{expectedException}" expectedException EQSS emsg.data.message
    remove expectedException
  else
    assert/text="^reg.main.name: Caught unexpected exception ^{emsg.data}" "FALSE" isTrue
    if "Trace" SUBS ENV.DEBUG then invoke ,, emsg.data.printStackTrace()
  endif
return

!******************************************************************************!
! Automatic test helper routine that passes specified name=, opt=, sup= to MENU
! and verifies that it at least contains items in expectedSet (since 3.1.1)
! This also tests /F to output results to file.
!******************************************************************************!
procedure common_helper S:testName["unknown"] S:nameArg["*"] S:optArg["*"] S:supArg["IPMHDOU"] S:format[""] O:expectedSet[]
  set outfile "test_menu.tmp"
  if format neqs "" then
    ! test /f, /opt, and /format for BUG 2567
    MENU/F=outfile/opt/format=^format NAME="^nameArg" OPT="^optArg" sup="^supArg"
  else
    MENU/F=outfile NAME="^nameArg" OPT="^optArg" sup="^supArg"
  endif

  ! Skip this test when dealing with an option tree other than SYS
  ! during a Gradle build command - NXM-3755 since NeXtMidas 4.0.1
  invoke optArg optArg.toUpperCase()
  if isGradleBuildCommand isFalse or optArg eqs "SYS" then
    foreach name inFile outfile
      invoke removed expectedSet.remove("^name")
      assert/text="^reg.main.name: ^{testName}: found expected command listing: ^name (^removed)" TRUE
    endfor
    assert/text="^reg.main.name: ^{testName}: found ALL expected command listing, remaining=^expectedSet is empty" expectedSet.isEmpty() isTrue
  else
    info "SKIPPING ^reg.main.name: ^{testName} for command listing because fails in Gradle build command"
  endif

  if format neqs "" then
    ! test /f, /opt, and /format for BUG 2567
    status outfile form=form
    assert/text="^reg.main.name: ^{testName}: FORMAT expected=^format actual=^form" format eqs form
  endif

  erase outfile
return

!******************************************************************************!
procedure test_name_and_opt
  new java.util.HashSet() expSet
  invoke ,, expSet.add("SOURCEDG")
  invoke ,, expSet.add("SOURCEFILE")
  invoke ,, expSet.add("SOURCESDDS")

  call common_helper "NAME= and OPT=" SOURCE* SYS ,,, expSet
return

!******************************************************************************!
procedure test_percent_sup
  if isGradleBuild isFalse then
    new java.util.HashSet() expSet
    invoke ,, expSet.add("%TEST_MENU")
    call common_helper "SUP=%" "%TEST_MEN*" ,, "%" ,, expSet
  endif
return

!******************************************************************************!
! Since 3.1.1: test /F with /OPT and /FORMAT switches for BUG 2567
procedure test_f_and_opt_switch
  new java.util.HashSet() expSet
  invoke ,, expSet.add("HW;HWC")
  invoke ,, expSet.add("HWDRIVER;HWC")

  ! save previous path
  res savepath opt.path
  ! add HWC into path needed for this test case
  path add HWC

  call common_helper "/F, /OPT and /FORMAT" * "HWC" "MP" "8A" expSet

  ! restore previous path
  path set ^savepath
return

!******************************************************************************!
! since 3.1.1: automatic test for /F, NAME= and OPT=
procedure test_advanced
  new java.util.HashSet() expSet
  invoke ,, expSet.add("SOURCEDG")
  invoke ,, expSet.add("SOURCEFILE")
  invoke ,, expSet.add("SOURCESDDS")

  set outfile "ram:test_menu.tmp"
  MENU/F=outfile NAME=SOURCE* OPT=SYS

  foreach name inFile outfile
    invoke removed expSet.remove("^name")
    assert/text="^reg.main.name: Found expected command listing: ^name (^removed)" TRUE
  endfor

  assert/text="^reg.main.name: Found ALL expected command listing, remaining=^expSet is empty" expSet.isEmpty() isTrue
  erase outfile

  ! since 3.1.3 test using /f state switch to save to menu.tmp
  if menu.tmp fexists then
    info "^reg.main.name: Skipping /F test b/c of existing menu.tmp in the way."
  else
    menu/f "SOURCE*" opt="SYS"
    assert/text="^reg.main.name: /F writes to menu.tmp" menu.tmp fexists
    erase/quiet/warn=no menu.tmp
  endif
  ! end since 3.1.3 test case
return

!******************************************************************************!
! test for BUG 2804. to reproduce:
! 1. path set DSP,HWC,SYS
! 2. path set SYS
! 3. then exit/reenter NeXtMidas shell)
! 4. then run this test macro
procedure test_list_no_dups S:optionTree["SYS"]
  set fn_opt_cmds_list ram:temp_menu_list_opt_commands
  MENU/F=fn_opt_cmds_list opt=^optionTree

  new java.util.HashSet() hashSet
  new java.util.ArrayList() dupList
  foreach cmdName inDF fn_opt_cmds_list
    invoke addResult hashSet.add(^cmdName)
    if addResult isFalse then
      invoke ,, dupList.add(^cmdName)
      assert/text="^reg.main.name: ^optionTree: found duplicate command entry for ^cmdName" FAIL
    endif
  endfor

  set numDuplicates dupList.size()
  if numDuplicates gt 0 then
    assert/text="^reg.main.name: found ^numDuplicates duplicate command listing for ^optionTree. dupList: ^dupList" FAIL
  endif

  erase/all fn_opt_cmds_list
return