!******************************************************************************!
! Internally IF and ASSERT use the same code (Args.logicalTest()) to evaluate
! the test case. As such most of these tests
!
! Test macros for intrinsic IF
!
!  INPUTS:
!    /DEBUG -- To turn on output
!
!  DEPENDENCIES:
!    global, call, procedure, say, info, warn
!
! Author : Jay Hallam
!******************************************************************************!
startmacro s:func[""]
  set trueStates  "Y,YES,T,TRUE,ON,1,PASS,SUCCESS,ABSC,AB"
  set falseStates "N,NO,F,FALSE,OFF,0,FAIL,INDEX,IN"

  call setDatDir
  ! Allow some of the tests to run in a thinned NeXtMidas by skipping only ones needing missing dependencies - 4.0.0
  invoke convertExists reg.shell.M.dictionary.isDictionaryEntry(CONVERT)

  if func NEQS "" then
    call test^{func}
  else
    call TestInLine               ! Tests bad structure of ELSEIF (Bug 2540)   KEEP THIS FIRST FOR INFO STATEMENT PURPOSES
    call TestStructure            ! Tests: the structure of an IF statement
    call TestStrings              ! Tests: EQS, EQSS, SUBS
    call TestEquality             ! Tests: EQ, NEQ, NE, EQT, NEQT, EQ/?, NE/?, NEQ/?
    call TestInequality           ! Tests: NEQ,LT,NGE,GT,NLE,LE,NGT,GE,LT,NLT
    call TestTolerance            ! Tests: EQ/T with /TOL= vs /DELTA=
    call TestFEQ                  ! Tests: FEQ/? (excluding FEQ/H)
    call TestFEQH                 ! Tests: FEQ/H
    call TestMisc                 ! Tests: <true>, <false>, isTrue, isFalse, isNull
    call TestFEXISTS              ! Tests: FEXISTS
    call TestDEXISTS              ! Tests: DEXISTS
    call TestAEXISTS              ! Tests: AEXISTS
    call TestREXISTS              ! Tests: REXISTS
    call TestContains             ! Tests: CONTAINS
    call TestConjunctions         ! Tests: AND, OR
    call TestBITS                 ! Tests: ANYBITS, ALLBITS
    call TestCLogicalOperators    ! Tests: ==, !=, <, >, <=, >=
    call TestTYPEOF               ! Tests: TYPEOF
    call TestINSTANCEOF           ! Tests: INSTANCEOF
    call TestParenthesis          ! Tests: (..), ((..) AND (..)), ((..) OR (..))
    call TestRamFile              ! Tests: (ram:apenny FEXISTS) & if ram:apenny FEXISTS

  endif
endmacro

!******************************************************************************!
! 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 the structure of an IF statement
procedure TestStructure
  !==== ONE-LINE IF ====
  res x 1
  res y 2
  res q 3
  res r 4
  if 1 EQ 1 res x 100           ! <pass> and no THEN
  if 1 NE 1 res q 300           ! <fail> and no THEN
  if 1 EQ 1 THEN res y 200      ! <pass> with a THEN
  if 1 NE 1 THEN res r 400      ! <fail> with a THEN

  assert/text="^reg.main.name: One-line IF <pass> <expr>"      x EQ 100
  assert/text="^reg.main.name: One-line IF <fail> <expr>"      q EQ 3
  assert/text="^reg.main.name: One-line IF <pass> THEN <expr>" y EQ 200
  assert/text="^reg.main.name: One-line IF <fail> THEN <expr>" r EQ 4


  !==== IF...[THEN]...ENDIF ====
  res x 1
  res y 2
  res q 3
  res r 4
  if 1 EQ 1           ! <pass> and no THEN
    res x 100
  ENDIF
  if 1 NE 1           ! <fail> and no THEN
    res q 300
  ENDIF
  if 1 EQ 1 THEN      ! <pass> with a THEN
    res y 200
  ENDIF
  if 1 NE 1 THEN      ! <fail> with a THEN
    res r 400
  ENDIF

  assert/text="^reg.main.name: IF <pass> ... ENDIF"      x EQ 100
  assert/text="^reg.main.name: IF <fail> ... ENDIF"      q EQ 3
  assert/text="^reg.main.name: IF <pass> THEN ... ENDIF" y EQ 200
  assert/text="^reg.main.name: IF <fail> THEN ... ENDIF" r EQ 4


  !==== IF...[THEN]...ELSE...ENDIF ====
  res x 1
  res y 2
  res q 3
  res r 4
  if 1 EQ 1           ! <pass> and no THEN
    res x 100
  ELSE
    res x 111
  ENDIF
  if 1 NE 1           ! <fail> and no THEN
    res q 300
  ELSE
    res q 333
  ENDIF
  if 1 EQ 1 THEN      ! <pass> with a THEN
    res y 200
  ELSE
    res y 222
  ENDIF
  if 1 NE 1 THEN      ! <fail> with a THEN
    res r 400
  ELSE
    res r 444
  ENDIF

  assert/text="^reg.main.name: IF <pass> ... ELSE ... ENDIF"      x EQ 100
  assert/text="^reg.main.name: IF <fail> ... ELSE ... ENDIF"      q EQ 333
  assert/text="^reg.main.name: IF <pass> THEN ... ELSE ... ENDIF" y EQ 200
  assert/text="^reg.main.name: IF <fail> THEN ... ELSE ... ENDIF" r EQ 444


  !==== IF...THEN...ELSEIF...ELSE...ENDIF ====
  res a 0
  res b 0
  res c 0

  if 1 EQ 1 THEN
    res a 1
  elseif 1 EQ 1 THEN
    res a 2
  else
    res a 3
  endif

  if 1 EQ 2 THEN
    res b 1
  elseif 1 EQ 1 THEN
    res b 2
  else
    res b 3
  endif

  if 1 EQ 2 THEN
    res c 1
  elseif 1 EQ 2 THEN
    res c 2
  else
    res c 3
  endif

  assert/text="^reg.main.name: IF <pass> ... ELSEIF <n/a>  ... ELSE ... ENDIF" a EQ 1
  assert/text="^reg.main.name: IF <fail> ... ELSEIF <pass> ... ELSE ... ENDIF" b EQ 2
  assert/text="^reg.main.name: IF <fail> ... ELSEIF <fail> ... ELSE ... ENDIF" c EQ 3
return


!******************************************************************************!
procedure TestStrings
  result str1  UpperCase   ! A string entered without quotes is stored UPPERCASE
  result str2 "MixedCase"  ! A string entered with quotes is stored MixedCase

  assert/test=PASS    "aBc"  EQS "ABC"
  assert/test=PASS    "AA"   EQS "aa"
  assert/test=FAIL/CS "aBc"  EQS "ABC"
  assert/test=FAIL/CS "AA"   EQS "aa"
  assert/test=FAIL    "A"    EQS "A "
  assert/test=FAIL    " "    EQS ""
  assert/test=FAIL    ""     EQS "A"
  assert/test=FAIL    "A "   EQS "A"
  assert/test=PASS    "A "   EQS "A "
  assert/test=FAIL    " "    EQS ""
  assert/test=PASS    " "    EQS " "
  assert/test=FAIL    " "    EQS "A"
  assert/test=FAIL    "one"  EQS "two"       ! IF <string> EQS <string> (full identical comparison)
  assert/test=FAIL    "one"  EQS "onee"      ! IF <string> EQS <string> (one letter difference)
  assert/test=PASS    "one" NEQS "two"
  assert/test=PASS    str1   EQS "UPPERCASE" ! Mixed case string entered w/o quotes
  assert/test=PASS    str2   EQS "MixedCase" ! Mixed case string entered with quotes
  assert/test=PASS/CS=false "String With /CS=false" EQS "STRING WITH /CS=FALSE" ! since 3.5.4 test for BUG 2937
  assert/test=FAIL/CS=true  "String With /CS=true"  EQS "STRING WITH /CS=TRUE"  ! since 3.5.4 test for BUG 2937

  !==== EQSS ====
  assert/test=PASS "A"    EQSS "A "
  assert/test=PASS "A "   EQSS "A"
  assert/test=PASS "A "   EQSS "A  "
  assert/test=PASS " "    EQSS ""
  assert/test=PASS "ABC"  EQSS ""
  assert/test=FAIL " "    EQSS "ABC"
  assert/test=FAIL "A "   EQSS " "
  assert/test=FAIL "A "   EQSS " A"
  assert/test=FAIL "A"    EQSS " A"
  assert/test=FAIL "AB"   EQSS "BAB"
  assert/test=FAIL "A "   EQSS "AB "
  assert/test=PASS "A"    EQSS "AB"
  assert/test=FAIL "two"  EQSS "joy"
  assert/test=PASS "two"  EQSS "two longer"
  assert/test=PASS "                 Long string" EQSS " "
  assert/test=PASS "one" NEQSS "zero"
  assert/test=FAIL "one" NEQSS "one"

  !==== SUBS ====
  assert/test=PASS "A"     SUBS "A "
  assert/test=PASS "A"     SUBS "BCDA"
  assert/test=FAIL "A "    SUBS "A"
  assert/test=PASS "A "    SUBS "CA B"
  assert/test=FAIL " "     SUBS ""
  assert/test=FAIL "A "    SUBS " "
  assert/test=PASS " "     SUBS "A "
  assert/test=PASS "two"   SUBS "two longer"
  assert/test=PASS "Long"  SUBS "                    Long string"
  assert/test=PASS "one"  NSUBS "zero"
  assert/test=FAIL "two"  NSUBS "two longer"
  assert/test=PASS "two longer" NSUBS "two"
  assert/test=FAIL "END"  NSUBS "This is a great big long string you can hardly believe it END"


  !==== ENDS (ends with) ====
  assert/test=PASS    "ABCDEF"          ENDS "EF"
  assert/test=PASS    "NO /CS SWITCH"   ENDS "Switch"
  assert/test=FAIL/CS "With /CS SWITCH" ENDS "Switch"
  assert/test=FAIL    "ABCDEF"          ENDS "AB"

  !==== STARTS (starts with) ====
  assert/test=PASS    "ABCDEF"          STARTS "AB"
  assert/test=PASS    "NO /CS SWITCH"   STARTS "NO "
  assert/test=FAIL/CS "With /CS SWITCH" STARTS "WITH"
  assert/test=FAIL    "ABCDEF"          STARTS "EF"

  !==== BUG 2811 on-the-fly invocation of startswith() and endswith() ====
  result lowerword "prefixwordsuffix"
  result upperword "PREFIXWORDSUFFIX"
  assert/test=PASS lowerword.startswith("prefix")
  assert/test=FAIL upperword.startswith("prefix")
  assert/test=FAIL lowerword.startswith("PREFIX")
  assert/test=PASS upperword.startswith("PREFIX")
  assert/test=PASS lowerword.endswith("suffix")
  assert/test=FAIL upperword.endswith("suffix")
  assert/test=FAIL lowerword.endswith("SUFFIX")
  assert/test=PASS upperword.endswith("SUFFIX")
return

!******************************************************************************!
procedure TestEquality
  res d:one 1
  res d:uno 1
  res d:two 2
  res l:dos 2 ! <-- LONG not DOUBLE

  !=== BASIC EQUALITY TESTS ====
  assert/test=PASS 1   EQ 1
  assert/test=FAIL 1   EQ 2
  assert/test=PASS one EQ uno
  assert/test=PASS two EQ dos
  assert/test=FAIL one EQ two

  assert/test=PASS 1 EQ/T 1.0000001
  assert/test=FAIL 1 EQ/T 1.000002

  assert/test=PASS one EQ/B uno
  assert/test=FAIL two EQ/B dos

  assert/test=PASS (1,2) EQ/V   (1,2)

  assert/test=PASS (1,2) EQ/V   (1,2)
  assert/test=FAIL (1,2) EQ/V   (2,1)
  assert/test=FAIL (1,2) EQ/V   (1,2,0)
  assert/test=PASS (1,1) EQ/V/T (1,1.0000001)
  assert/test=FAIL (1,1) EQ/V/T (1,1.000002)

  assert/test=PASS (1,2) EQ/M   (1,2)
  assert/test=PASS (1,2) EQ/M   (2,1)
  assert/test=FAIL (1,2) EQ/M   (2,2)
  assert/test=PASS (1,2) EQ/M   (1,2,0)
  assert/test=PASS (1,1) EQ/M/T (1,1.0000001)
  assert/test=FAIL (1,1) EQ/M/T (1,1.2)

  !=== BASIC INEQUALITY TESTS (same as above but swap NE with EQ and PASS with FAIL) ====
  assert/test=FAIL 1   NE 1
  assert/test=PASS 1   NE 2
  assert/test=FAIL one NE uno
  assert/test=FAIL two NE dos
  assert/test=PASS one NE two

  assert/test=FAIL 1 NE/T 1.0000001
  assert/test=PASS 1 NE/T 1.000002

  assert/test=FAIL one NE/B uno
  assert/test=PASS two NE/B dos

  assert/test=FAIL (1,2) NE/V   (1,2)

  assert/test=FAIL (1,2) NE/V   (1,2)
  assert/test=PASS (1,2) NE/V   (2,1)
  assert/test=PASS (1,2) NE/V   (1,2,0)
  assert/test=FAIL (1,1) NE/V/T (1,1.0000001)
  assert/test=PASS (1,1) NE/V/T (1,1.000002)

  assert/test=FAIL (1,2) NE/M   (1,2)
  assert/test=FAIL (1,2) NE/M   (2,1)
  assert/test=PASS (1,2) NE/M   (2,2)
  assert/test=FAIL (1,2) NE/M   (1,2,0)
  assert/test=FAIL (1,1) NE/M/T (1,1.0000001)
  assert/test=PASS (1,1) NE/M/T (1,1.2)

  !=== BASIC INEQUALITY TESTS (same as above but NEQ rather than NE) ====
  assert/test=FAIL 1   NEQ 1
  assert/test=PASS 1   NEQ 2
  assert/test=FAIL one NEQ uno
  assert/test=FAIL two NEQ dos
  assert/test=PASS one NEQ two

  assert/test=FAIL 1 NEQ/T 1.0000001
  assert/test=PASS 1 NEQ/T 1.000002

  assert/test=FAIL one NEQ/B uno
  assert/test=PASS two NEQ/B dos

  assert/test=FAIL (1,2) NEQ/V   (1,2)

  assert/test=FAIL (1,2) NEQ/V   (1,2)
  assert/test=PASS (1,2) NEQ/V   (2,1)
  assert/test=PASS (1,2) NEQ/V   (1,2,0)
  assert/test=FAIL (1,1) NEQ/V/T (1,1.0000001)
  assert/test=PASS (1,1) NEQ/V/T (1,1.000002)

  assert/test=FAIL (1,2) NEQ/M   (1,2)
  assert/test=FAIL (1,2) NEQ/M   (2,1)
  assert/test=PASS (1,2) NEQ/M   (2,2)
  assert/test=FAIL (1,2) NEQ/M   (1,2,0)
  assert/test=FAIL (1,1) NEQ/M/T (1,1.0000001)
  assert/test=PASS (1,1) NEQ/M/T (1,1.2)

  !=== TOLERANCE ====
  ! The tolerance defaults to 1e-6. A method exists to set it, but no
  ! intrinsic currently calls the method.
  assert/test=PASS 1           EQT   1.0000001
  assert/test=FAIL 1           EQT   1.000002
  assert/test=PASS 0           EQT   0                 ! Make sure we don't have a divide by zero problem
  assert/test=PASS 1e-6       NEQT   1e-7
  assert/test=PASS/TOL=1e-5 1.00001e-8  EQT   1e-8
  assert/test=PASS/TOL=1e-5 1.0001e-8  NEQT   1e-8
  assert/test=PASS 1           EQTOL 1.0000001         ! Check EQTOL as alias for EQT
  assert/test=FAIL 1           EQTOL 1.000002         ! Check EQTOL as alias for EQT
  info "This should print a deprecation warning..."
  assert/test=PASS 1           EQTxx 1.0000001         ! Check for any alias starting with EQT -- DEPRECATED

  !=== OTHER ====
  ! These should through exceptions since you can not compare 2 strings with EQ
  remove n
  remove Y
  assert/except/test  n  EQ  Y
  assert/except/test "n" EQ "Y"
return

!******************************************************************************!
procedure TestFEQ
  result 0k "temp_test_if_0k"
  result sin4k  "temp_test_if_sin4k"
  result sin4k2 "temp_test_if_sin4k2"
  result sin8k  "temp_test_if_sin8k"
  result ramp4k "temp_test_if_ramp4k"
  waveform OUT=0k  ELEM=0k
  waveform OUT=sin4k  ELEM=4k
  waveform OUT=sin4k2 ELEM=4k
  waveform OUT=sin8k  ELEM=8k
  waveform OUT=ramp4k ELEM=4k shape=ramp

  result sameKeys1 "^sin4k"
  result sameKeys2 "^ramp4k"
  result diffKeys1 "^sin4k2"
  key sameKeys1 "SET" dummy "dummy string 1"
  key sameKeys1 "SET" dummy "dummy string 2"
  key sameKeys2 "SET" dummy "dummy string 1"
  key sameKeys2 "SET" dummy "dummy string 2"
  key diffkeys1 "SET" dummy "a different dummy string"

  ! A file should equal itself
  assert/text="FEQ: file equals itself" sin4k FEQ sin4k

  ! A non-zero-length file should not equal a zero-length file (since 3.7.0 for BUG 2861)
  assert/test=FAIL sin4k FEQ 0k

  ! A zero-length file should not equal a non-zero-length file (since 3.7.0 for BUG 2861)
  assert/test=FAIL 0k FEQ sin4k

  ! A non-zero-length file should not equal a zero-length file (/L) (since 3.7.0 for BUG 2861)
  assert/test=FAIL sin4k FEQ/L 0k

  ! A zero-length file should not equal a non-zero-length file (/L) (since 3.7.0 for BUG 2861)
  assert/test=FAIL 0k FEQ/L sin4k

  ! A zero-length file should equal a zero-length file (/L) (since 3.7.0 for BUG 2861)
  assert/text="FEQ: zero file equals zero file" 0k FEQ 0k

  ! A zero-length file should equal a zero-length file (/B/L) (since 3.7.0 for BUG 2861)
  assert/text="FEQ/B/L: zero file equals zero file (BINARY, LENGTH LIMIT)" 0k FEQ/B/L 0k

  ! A file should equal another file that is identical except in name
  assert/text="FEQ: file equals identical file; different name" sin4k FEQ sin4k2

  ! Binary test on identical files of different names
  assert/text="FEQ/B: file equals identical file; different name (BINARY)" sin4k FEQ/B sin4k2

  ! Binary test on identical files of different names (/L) (since 3.7.0 for BUG 2861)
  assert/text="FEQ/L: file equals identical file; different name (LENGTH LIMIT)" sin4k FEQ/L sin4k2

  ! Binary test on identical files of different names
  assert/text="FEQ/B: file equals file w/ same header/data, diff size (BINARY)" sin4k FEQ/B sin8k

  ! Binary test on identical files of different names (/L) (since 3.7.0 for BUG 2861)
  assert/text="FEQ/L: file equals identical file; but different size (/L LENGTH LIMIT)" sin4k FEQ/L sin8k

  ! Binary test on identical files of different names (/H/D/L) (since 3.7.0 for BUG 2861)
  assert/text="FEQ/H/D/L: file equals identical file; but different size (/H/D/L LENGTH LIMIT)" sin4k FEQ/H/D/L sin8k

  ! Two identical files, EXCEPT IN SIZE (size is NO LONGER ignored by default). This was Legacy behavior. - this should fail now! (since 3.7.0 for BUG 2861)
  assert/test=FAIL sin4k FEQ sin8k

  ! Two identical files, EXCEPT IN SIZE (use /H/D and explicitly ignore size) - this should fail now! (since 3.7.0 for BUG 2861)
  assert/test=FAIL sin4k FEQ/H/D sin8k

  ! Do size test of two different files
  assert/text="FEQ/S: different files, same size" sin4k FEQ/S ramp4k

  ! Two files with identical keywords
  assert/text="FEQ/K: same keywords" sameKeys1 FEQ/K sameKeys2

  ! Two files with different keywords
  assert/text="NFEQ/K: different keywords" sameKeys1 NFEQ/K diffKeys1

  ! Two ASCII midas type 1000 files
  assert/text="FEQ: type100_file_format_XA" ^{datDir}.test1000.prm feq ^{datDir}.test1000.prm

  ! Two Different Jnlp Files
  assert/text="FEQ: Different Jnlp files" nxm.sys.test.jnlp_master.jnlp NFEQ nxm.sys.test.test_webstart_autotest.jnlp

  ! Two Same Jnlp Files
  assert/text="FEQ: Same Jnlp file" nxm.sys.test.jnlp_master.jnlp FEQ nxm.sys.test.jnlp_master.jnlp

  ! Two Same Jnlp Files with extra whitespace and newlines
  assert/text="FEQ: Same Jnlp file with variations" nxm.sys.test.jnlp_master.jnlp FEQ nxm.sys.test.jnlp_master_var.jnlp

  ! Two Same Jnlp Files with extra whitespace and newlines. Size comparison
  assert/text="FEQ: Same Jnlp file with variations. Size" nxm.sys.test.jnlp_master.jnlp FEQ/S nxm.sys.test.jnlp_master_var.jnlp

  ! Two Same Jnlp Files with extra whitespace and newlines. Binary comparison
  assert/text="FEQ: Same Jnlp file with variations. Binary" nxm.sys.test.jnlp_master.jnlp NFEQ/B nxm.sys.test.jnlp_master_var.jnlp

  erase sin4k
  erase sin4k2
  erase sin8k
  erase ramp4k
return

!******************************************************************************!
! Tests FEQ/H
procedure TestFEQH
  res temp1 "temp_test_feqh1"
  res temp2 "temp_test_feqh2"
  res temp3 "temp_test_feqh3"
  res temp4 "temp_test_feqh4"
  res temp5 "temp_test_feqh5"

  HEADERMOD/CREATE temp1 SR=(LABL/2A,ABSC/SD,ORD/SD)

  noop ^temp1 ^temp2     ! nothing differs
  noop ^temp1 ^temp3     ! name differs    (ABSC->ABS)
  noop ^temp1 ^temp4     ! type differs    (SD->SF)
  noop ^temp1 ^temp5     ! offset differs  (24->32)

  HEADERMOD ^temp3 TYPE=3000 FORM=NH NSR=3 RL=32 SR(1)=(LABL,2A,0) SR(2)=(ABS,SD,16)  SR(3)=(ORD,SD,24)
  HEADERMOD ^temp4 TYPE=3000 FORM=NH NSR=3 RL=32 SR(1)=(LABL,2A,0) SR(2)=(ABSC,SD,16) SR(3)=(ORD,SF,24)
  HEADERMOD ^temp5 TYPE=3000 FORM=NH NSR=3 RL=32 SR(1)=(LABL,2A,0) SR(2)=(ABSC,SD,16) SR(3)=(ORD,SD,32)

  assert/text="FEQ/H Type 3000: matches self"   ^temp1 FEQ/H ^temp1
  assert/text="FEQ/H Type 3000: matches a copy" ^temp1 FEQ/H ^temp2
  assert/text="FEQ/H Type 3000: names differ"   ^temp1 NFEQ/H ^temp3
  assert/text="FEQ/H Type 3000: types differ"   ^temp1 NFEQ/H ^temp4
  assert/text="FEQ/H Type 3000: offsets differ" ^temp1 NFEQ/H ^temp5

  erase ^temp1
  erase ^temp2
  erase ^temp3
  erase ^temp4
  erase ^temp5

  ! Test for Type 5001 file with quadwords (Bug 2678)
  if ("DisableQuadwordsEqualityChecks" SUBS ENV.IOOPTIONS) then
    warn "Use of DisableQuadwordsEqualityChecks in IOOPTIONS will cause some of the FEQ/H tests to fail"
  endif
  noop ^{datDir}.sv1.prm ram:sv_copy

  assert/text="FEQ/H Type 5001: matches self (ECR)" ^{datDir}.sv1.prm FEQ/H ^{datDir}.sv1.prm
  assert/text="FEQ/H Type 5001: matches copy (ECR)" ^{datDir}.sv1.prm FEQ/H ram:sv_copy

  if convertExists then
    ! We need to test with non-ECR files since ECR doesn't use the QW(1) through QW(11)
    convert ^{datDir}.sv1.prm ECI ram:sv_eci       EPOCH=2012:01:01::00:00:00
    convert ^{datDir}.sv1.prm ECI ram:sv_eci_same  EPOCH=2012:01:01::00:00:00
    convert ^{datDir}.sv1.prm ECI ram:sv_eci_diff1 EPOCH=2012:01:01::00:00:00
    convert ^{datDir}.sv1.prm ECI ram:sv_eci_diff2 EPOCH=2012:01:01::00:00:00
  
    headermod ram:sv_eci_diff1 QUADWORD(1)=10.0   ! <-- QW not applicable to ECI
    headermod ram:sv_eci_diff2 QUADWORD(9)=2010   ! <-- QW is  applicable to ECI
  
    assert/text="FEQ/H Type 5001: matches self (ECI)"   ram:sv_eci  FEQ/H ram:sv_eci
    assert/text="FEQ/H Type 5001: matches copy (ECI)"   ram:sv_eci  FEQ/H ram:sv_eci_same
    assert/text="FEQ/H Type 5001: matches diff1 (ECI)"  ram:sv_eci  FEQ/H ram:sv_eci_diff1
    assert/text="FEQ/H Type 5001: differs diff2 (ECI)"  ram:sv_eci NFEQ/H ram:sv_eci_diff2
  
    ! Same tests but with Type 5000 files (here ALL quadwords are checked)
    headermod ram:sv_eci       TYPE=5000
    headermod ram:sv_eci_same  TYPE=5000
    headermod ram:sv_eci_diff1 TYPE=5000
    headermod ram:sv_eci_diff2 TYPE=5000
  
    assert/text="FEQ/H Type 5000: matches self (ECI)"   ram:sv_eci  FEQ/H ram:sv_eci
    assert/text="FEQ/H Type 5000: matches copy (ECI)"   ram:sv_eci  FEQ/H ram:sv_eci_same
    assert/text="FEQ/H Type 5000: differs diff1 (ECI)"  ram:sv_eci NFEQ/H ram:sv_eci_diff1
    assert/text="FEQ/H Type 5000: differs diff2 (ECI)"  ram:sv_eci NFEQ/H ram:sv_eci_diff2
  endif

return

!******************************************************************************!
!  CHEAD Boolean Numerical tests
procedure TestMisc
  ! NOTE: IF (boolean) is equivalent to IF 0 NE 0
  assert/test=PASS 1     ! IF <boolean> (then activate)
  assert/test=FAIL 0     ! IF <boolean> (else activated)

  foreach state inList trueStates
    assert/test=PASS state
  endfor
  foreach state inList falseStates
    assert/test=FAIL state
  endfor

  !==== Test the "IS..." Unary operators====
  assert/test=PASS true       ISTRUE
  assert/test=FAIL false      ISTRUE
  assert/test=FAIL true       ISFALSE
  assert/test=PASS false      ISFALSE
  assert/test=PASS "NuLl"     isNull      ! IF null (mixed case) ISNULL
  assert/test=PASS "notnull" NisNull

  foreach state inList trueStates
    assert/test=PASS state ISTRUE
    assert/test=FAIL state ISFALSE
  endfor
  foreach state inList falseStates
    assert/test=FAIL state ISTRUE
    assert/test=PASS state ISFALSE
  endfor

  ! test for BUG 2737 (regression) to compare boolean with numerics
  set z:true_boolean true
  assert/text="boolean (true) == 1" true_boolean == 1
  assert/text="boolean (true) >  0" true_boolean >  0
  assert/test=FAIL                  true_boolean <  1
  set z:false_boolean false
  assert/text="boolean (false) == 0" false_boolean == 0
  assert/text="boolean (false) <  1" false_boolean <  1
  assert/test=FAIL                   false_boolean <  0
return

!******************************************************************************!
procedure TestInequality
  !==== CHEAD Numerical Equality tests ====
  assert/test=PASS 1 NEQ 2    ! IF <numeric> NEQ <numeric>
  assert/test=PASS 1 LT  2    ! IF <numeric> LT  <numeric>
  assert/test=PASS 1 NGE 2    ! IF <numeric> NGE <numeric> (activate else clause)
  assert/test=PASS 2 GT  1    ! IF <numeric> GT  <numeric> (activate then clause)
  assert/test=PASS 2 NLE 1    ! IF <numeric> NLE <numeric> (activate then clause)
  assert/test=PASS 1 LE  1    ! IF <numeric> LE  <numeric>
  assert/test=PASS 1 LE  2    ! IF <numeric> LE  <numeric>
  assert/test=PASS 1 NGT 2    ! IF <numeric> NGT <numeric>
  assert/test=PASS 2 GE  1    ! IF <numeric> GE  <numeric>
  assert/test=PASS 2 GE  2    ! IF <numeric> GE  <numeric>
  assert/test=PASS 2 NLT 1    ! IF <numeric> NLT <numeric>
  assert/test=PASS 2 NLT 2    ! IF <numeric> NLT <numeric>

  !==== ADDITIONAL SCALAR TESTS ====
  !== LT ==
  assert/test=PASS 1 LT 2
  assert/test=FAIL 2 LT 2
  assert/test=FAIL 3 LT 2

  assert/test=FAIL 1 NLT 2
  assert/test=PASS 2 NLT 2
  assert/test=PASS 3 NLT 2

  !== LE ==
  assert/test=PASS 1 LE 2
  assert/test=PASS 2 LE 2
  assert/test=FAIL 3 LE 2

  assert/test=FAIL 1 NLE 2
  assert/test=FAIL 2 NLE 2
  assert/test=PASS 3 NLE 2

  !== GT ==
  assert/test=FAIL 1 GT 2
  assert/test=FAIL 2 GT 2
  assert/test=PASS 3 GT 2

  assert/test=PASS 1 NGT 2
  assert/test=PASS 2 NGT 2
  assert/test=FAIL 3 NGT 2

  !== GE ==
  assert/test=FAIL 1 GE 2
  assert/test=PASS 2 GE 2
  assert/test=PASS 3 GE 2

  assert/test=PASS 1 NGE 2
  assert/test=FAIL 2 NGE 2
  assert/test=FAIL 3 NGE 2

  !==== MAGNITUDE TESTS ====
  do i -1 1
    do j -2 2
      do x -1 1
        do y -2 2
          calc mag1 i i * j j * + SQRT     ! magnitude of left-hand-side
          calc mag2 x x * y y * + SQRT     ! magnitude of right-hand-side

          ! Expected results based on manually-computed magnitude
          res passFailLT  TEST(^mag1,LT,^mag2)
          res passFailLE  TEST(^mag1,LE,^mag2)
          res passFailGT  TEST(^mag1,GT,^mag2)
          res passFailGE  TEST(^mag1,GE,^mag2)
          res passFailNLT TEST(^mag1,NLT,^mag2)
          res passFailNLE TEST(^mag1,NLE,^mag2)
          res passFailNGT TEST(^mag1,NGT,^mag2)
          res passFailNGE TEST(^mag1,NGE,^mag2)

          ! Actual results compute magnitude internally
          assert/test=^passFailLT  (^i,^j) LT/M (^x,^y)
          assert/test=^passFailLE  (^i,^j) LE/M (^x,^y)
          assert/test=^passFailGT  (^i,^j) GT/M (^x,^y)
          assert/test=^passFailGE  (^i,^j) GE/M (^x,^y)
          assert/test=^passFailNLT (^i,^j) NLT/M (^x,^y)
          assert/test=^passFailNLE (^i,^j) NLE/M (^x,^y)
          assert/test=^passFailNGT (^i,^j) NGT/M (^x,^y)
          assert/test=^passFailNGE (^i,^j) NGE/M (^x,^y)
        enddo
      enddo
    enddo
  enddo
return

!******************************************************************************!
! Tests for tolerance with /TOL= vs /DATA= added for Bug 2532.
! @since NeXtMidas 3.3.2
procedure TestTolerance
  ! These tests require the default tolerance to be 1e-6 which is the NXM default,
  ! but (in rare situations) may have been overridden by the user.
  invoke saveTol  nxm.sys.libm.Tolerance.getTolerance()
  invoke ,, nxm.sys.libm.Tolerance.setTolerance(1e-6)

  ! ==== VALUES THAT ARE EQUAL =================================================
  assert/test=PASS   100.00 EQ/T 100.00
  assert/test=PASS   100.00 EQ/T 100.00 /TOL=1e-6
  assert/test=PASS   100.00 EQ/T 100.00 /DELTA=0.2

  assert/test=PASS   (27,100.00,42) EQ/T/V (27,100.00,42)
  assert/test=PASS   (27,100.00,42) EQ/T/V (27,100.00,42) /TOL=1e-6
  assert/test=PASS   (27,100.00,42) EQ/T/V (27,100.00,42) /DELTA=0.2

  assert/test=PASS   (100.00,27,42) EQ/T/M (27,100.00,42)
  assert/test=PASS   (100.00,27,42) EQ/T/M (27,100.00,42) /TOL=1e-6
  assert/test=PASS   (100.00,27,42) EQ/T/M (27,100.00,42) /DELTA=0.2

  ! ==== VALUES THAT DIFFER RELATIVE ===========================================
  assert/test=FAIL   100.00 EQ/T  99.95
  assert/test=FAIL   100.00 EQ/T  99.95 /TOL=1e-6
  assert/test=PASS   100.00 EQ/T  99.95 /DELTA=0.2

  assert/test=FAIL   (27,100.00,42) EQ/T/V (27, 99.95,42)
  assert/test=FAIL   (27,100.00,42) EQ/T/V (27, 99.95,42) /TOL=1e-6
  assert/test=PASS   (27,100.00,42) EQ/T/V (27, 99.95,42) /DELTA=0.2

  assert/test=FAIL   (100.00,27,42) EQ/T/M (27, 99.95,42)
  assert/test=FAIL   (100.00,27,42) EQ/T/M (27, 99.95,42) /TOL=1e-6
  assert/test=PASS   (100.00,27,42) EQ/T/M (27, 99.95,42) /DELTA=0.2

  ! ==== VALUES THAT DIFFER ABSOLUTE ===========================================
  assert/test=PASS   100.00 EQ/T  99.999999
  assert/test=PASS   100.00 EQ/T  99.999999 /TOL=1e-6
  assert/test=FAIL   100.00 EQ/T  99.999999 /DELTA=0.0000002

  assert/test=PASS   (27,100.00,42) EQ/T/V (27, 99.999999,42)
  assert/test=PASS   (27,100.00,42) EQ/T/V (27, 99.999999,42) /TOL=1e-6
  assert/test=FAIL   (27,100.00,42) EQ/T/V (27, 99.999999,42) /DELTA=0.0000002

  assert/test=PASS   (100.00,27,42) EQ/T/M (27, 99.999999,42)
  assert/test=PASS   (100.00,27,42) EQ/T/M (27, 99.999999,42) /TOL=1e-6
  assert/test=FAIL   (100.00,27,42) EQ/T/M (27, 99.999999,42) /DELTA=0.0000002

  ! ==== VALUES THAT DIFFER ABSOLUTE & RELATIVE ================================
  assert/test=FAIL   100.00 EQ/T  99.95
  assert/test=FAIL   100.00 EQ/T  99.95 /TOL=1e-6
  assert/test=FAIL   100.00 EQ/T  99.95 /DELTA=0.02

  assert/test=FAIL   (27,100.00,42) EQ/T/V (27, 99.95,42)
  assert/test=FAIL   (27,100.00,42) EQ/T/V (27, 99.95,42) /TOL=1e-6
  assert/test=FAIL   (27,100.00,42) EQ/T/V (27, 99.95,42) /DELTA=0.02

  assert/test=FAIL   (100.00,27,42) EQ/T/M (27, 99.95,42)
  assert/test=FAIL   (100.00,27,42) EQ/T/M (27, 99.95,42) /TOL=1e-6
  assert/test=FAIL   (100.00,27,42) EQ/T/M (27, 99.95,42) /DELTA=0.02

  ! ==== DEFAULT TOL vs /TOL= ==================================================
  do i 1 12
    res S:tolerance "1e-^{i}"

    if (tolerance GT 1e-8) then
      assert/test=PASS   100.00 EQ/T 99.999999
      assert/test=PASS   100.00 EQ/T 99.999999 /TOL=^{tolerance}
    else
      assert/test=PASS   100.00 EQ/T 99.999999
      assert/test=FAIL   100.00 EQ/T 99.999999 /TOL=^{tolerance}
    endif
  enddo

  ! ==== DONE ==================================================================
  invoke ,, nxm.sys.libm.Tolerance.setTolerance(saveTol)
return

!******************************************************************************!
! HEAD File Existence tests
procedure TestFEXISTS
  assert/test=FAIL nonexistent  FEXISTS
  assert/test=PASS nonexistent NFEXISTS
  assert/test=PASS nxm.sys.cfg.commands.cnf  FEXISTS
  assert/test=FAIL nxm.sys.cfg.commands.cnf NFEXISTS
  ! test cases for Bug 1584 to check if file exists without extension
  fname noExtensionFN cfg keystore ,, sys
  assert/test=PASS noExtensionFN  FEXISTS
  assert/test=FAIL noExtensionFN NFEXISTS
  ! end test case for Bug 1584

  ! test cases for BUG 2569 check that "" and NULL return false for fexists
  aux/store
  aux ^{aux.write} ^{aux.write}
  assert/test=false ""   FEXISTS
  assert/test=false NULL FEXISTS
  aux/restore
  ! end test case for BUG 2569
return

!******************************************************************************!
procedure TestDEXISTS
  if ^{env.NMROOT} EQS "classpath:" then
    info "SKIPPING ^reg.main.name DEXISTS/NDEXISTS NMROOT. Running from jar file. NDEXISTS does not support the root directory of jar. TODO - is this useful? The nmroot has to exist in this case as it is the jar file"

  else
    assert/test=PASS "^{env.nmroot}"                DEXISTS  ! $NMROOT (should end with '/')
    assert/test=FAIL "^{env.nmroot}"               NDEXISTS  ! $NMROOT (should end with '/')
  endif

  invoke isGradleBuild nxm.sys.lib.Shell.isGradleBuild() ! Since NeXtMidas 4.0.1 NXM-3588
  if isGradleBuild isFalse then
    assert/test=PASS "^{env.nmroot}nxm"             DEXISTS  ! $NMROOT/nxm
    assert/test=FAIL "^{env.nmroot}nxm"            NDEXISTS  ! $NMROOT/nxm
  endif
  assert/test=FAIL "^{env.nmroot}shouldnotexist"  DEXISTS  ! $NMROOT/shouldnotexist
  assert/test=PASS "^{env.nmroot}shouldnotexist" NDEXISTS  ! $NMROOT/shouldnotexist
return

!******************************************************************************!
procedure TestAEXISTS
  ! Files all lowercase with dot syntax
  assert/test=PASS nxm.sys.cfg.commands.cnf   AEXISTS
  assert/test=FAIL nxm.sys.cfg.commands.cnf  NAEXISTS

  ! Files all lowercase with no dots - adjust aux.dat in case dat is in nxm/sys/test/dat - NXM-3671 since NeXtMidas 4.1.1
  set auxDatOrig aux.dat
  invoke auxDatNew auxDatOrig.replace("nxm/sys/dat","^{datDirSlash}")
  set aux.dat auxDatNew

  assert/test=PASS apenny                     AEXISTS ! No extension with apenny.prm file
  assert/test=FAIL apenny                    NAEXISTS

  set aux.dat auxDatOrig

  assert/test=PASS nxm.sys.test.bad_keywords  AEXISTS ! No extension with bad_keywords.tmp file
  assert/test=FAIL nxm.sys.test.bad_keywords NAEXISTS
  assert/test=FAIL nonexistent                AEXISTS
  assert/test=PASS nonexistent               NAEXISTS

  ! Files mixed case with dot syntax
  waveform Test_Waveform1.prm{AUX=WRITE}
  waveform Test_Waveform2.tmp{AUX=WRITE}

  assert/test=PASS nxm.sys.test.kmlTest.kml     AEXISTS
  assert/test=FAIL nxm.sys.test.kmlTest.kml    NAEXISTS
  assert/test=PASS Test_Waveform1               AEXISTS ! No extension with Test_Waveform1.prm file
  assert/test=FAIL Test_Waveform1              NAEXISTS
  assert/test=PASS Test_Waveform2               AEXISTS ! No extension with Test_Waveform2.tmp file
  assert/test=FAIL Test_Waveform2              NAEXISTS
  assert/test=FAIL nxm.sys.test.ShouldNotExist  AEXISTS
  assert/test=PASS nxm.sys.test.ShouldNotExist NAEXISTS

  erase Test_Waveform1.prm
  erase Test_Waveform2.tmp

  ! Directories all uppercase with full path syntax
  invoke homeUpper                env.home.toUpperCase()
  invoke homeLength               homeUpper.length()
  invoke homeUpperNoTrailingSlash homeUpper.substring(0,^homeLength-1)
  assert/test=PASS ^homeUpperNoTrailingSlash   AEXISTS  ! $HOME all uppercase with no trailing slash
  assert/test=FAIL ^homeUpperNoTrailingSlash  NAEXISTS  ! $HOME all uppercase with no trailing slash

  ! Directories all lowercase with full path syntax
  assert/test=FAIL ^{env.nmroot}shouldnotexist  AEXISTS  ! $NMROOT/shouldnotexist
  assert/test=PASS ^{env.nmroot}shouldnotexist NAEXISTS  ! $NMROOT/shouldnotexist

  ! Directories mixed case with full path syntax
  assert/test=FAIL "^{env.nmroot}ShouldNotExist"  AEXISTS  ! $NMROOT/ShouldNotExist
  assert/test=PASS "^{env.nmroot}ShouldNotExist" NAEXISTS  ! $NMROOT/ShouldNotExist

  if ^{env.NMROOT} NEQS "classpath:" then
    ! Files all lowercase with full path syntax
    assert/test=PASS "^{env.nmroot}nxm/sys/cfg/commands.cnf"  AEXISTS  ! $NMROOT/nxm/sys/cfg/commands.cnf
    assert/test=FAIL "^{env.nmroot}nxm/sys/cfg/commands.cnf" NAEXISTS  ! $NMROOT/nxm/sys/cfg/commands.cnf
    assert/test=FAIL "^{env.nmroot}shouldnotexist.tmp"        AEXISTS  ! $NMROOT/shouldnotexist.tmp
    assert/test=PASS "^{env.nmroot}shouldnotexist.tmp"       NAEXISTS  ! $NMROOT/shouldnotexist.tmp

    ! Files mixed case with full path syntax
    assert/test=PASS "^{env.nmroot}nxm/sys/test/kmlTest.kml"         AEXISTS
    assert/test=FAIL "^{env.nmroot}nxm/sys/test/kmlTest.kml"        NAEXISTS
    assert/test=FAIL "^{env.nmroot}nxm/sys/test/ShouldNotExist.tmp"  AEXISTS
    assert/test=PASS "^{env.nmroot}nxm/sys/test/ShouldNotExist.tmp" NAEXISTS

    ! Directories lowercase with full path syntax - no jar file
    assert/test=PASS ^{env.nmroot}                AEXISTS  ! $NMROOT (should end with '/')
    assert/test=FAIL ^{env.nmroot}               NAEXISTS  ! $NMROOT (should end with '/')

    assert/test=PASS ^{env.nmroot}nxm             AEXISTS  ! $NMROOT/nxm
    assert/test=FAIL ^{env.nmroot}nxm            NAEXISTS  ! $NMROOT/nxm

    ! Directories mixed case with full path syntax - no jar file
    assert/test=PASS "^{env.nmroot}META-INF"        AEXISTS  ! $NMROOT/META-INF
    assert/test=FAIL "^{env.nmroot}META-INF"       NAEXISTS  ! $NMROOT/META-INF
  endif

return

!******************************************************************************!
procedure TestContains
  res tab   {x=1,y=2}
  res mykey "X"
  res str   "xxx"
  assert/test=PASS tab contains mykey
  assert/test=PASS tab contains X
  assert/test=PASS tab contains Y
  assert/test=FAIL tab contains Z
  assert/test=FAIL str CONTAINS yyy  ! Make sure an object, returns for CONTAINS
  assert/test=PASS tab contains "x"  ! test added in 3.5.4 (to show upper-casing of key)
  ! since 3.5.4 (inject mixed-cased key) into table via "special trick"
  res "TAB.MixedCaseKey" "3"
  assert/test=PASS tab contains "MixedCaseKey" /cs  ! since 3.5.4 as part of BUG 2931
  assert/test=FAIL tab contains "MIXEDCASEKEY"

  ! since 3.5.4 test CONTAINS on java.util.Map (such as HashTable) for BUG 2931
  new java.util.Hashtable Hashtable
  res key "One"
  res value1 "Value1"
  invoke ,, Hashtable.put(key,value1)
  assert/test=PASS Hashtable contains key
  assert/test=PASS Hashtable contains "^key"
  assert/test=FAIL Hashtable contains ^key   ! <-- fails b/c caret resolves to One, but since it is NOT quoted, it becomes "ONE"
  assert/test=FAIL Hashtable contains "ONE"
  assert/test=FAIL Hashtable contains "TWO"

  ! since 3.5.4 test CONTAINS with HashMap and Objects for Keys (BUG 2931)
  res value2 "Value 2"
  invoke IntegerObject1=java.lang.Integer.valueOf("1") DoubleObject2=java.lang.Double.valueOf("2.0") &
         ByteObject1=java.lang.Byte.valueOf("1")
  new java.util.HashMap HashMap
  invoke ,, HashMap.put(IntegerObject1, value1)
  invoke ,, HashMap.put(DoubleObject2,  value2)
  assert/test=PASS HashMap contains IntegerObject1
  assert/test=PASS HashMap contains DoubleObject2
  assert/test=FAIL HashMap contains ByteObject1
  assert/test=FAIL HashMap contains 1
  assert/test=FAIL HashMap contains "1"
  assert/test=FAIL HashMap contains 2.0

  ! since 3.5.4, test CONTAINS/V (value)
  assert/test=PASS tab contains/v 1
  assert/test=PASS tab contains/v 2
  assert/test=PASS tab contains/v "3"
  assert/test=FAIL tab contains/v "value not in Table"
  assert/test=FAIL tab contains/v "2"

  assert/test=PASS Hashtable contains/v value1
  assert/test=FAIL Hashtable contains/v value2
  assert/test=FAIL Hashtable contains/v " value not in Hashtable"

  assert/test=PASS HashMap contains/v value1
  assert/test=PASS HashMap contains/v value2
  assert/test=FAIL HashMap contains/v "value not in HashMap"

return

!******************************************************************************!
!  CHEAD Logical conjuctions (and, or)
procedure TestConjunctions
  assert/test=FAIL 3 NE 0 AND "D" SUBS "ABC"  ! IF <numericCompare> AND <stringCompare>
  assert/test=PASS 5 LT 3 OR  "C" SUBS "ABC"  ! IF <numericCompare> OR  <stringCompare>
  assert/test=FAIL "D" SUBS "ABC" AND 3 NE 0  ! IF <stringCompare>  AND <numericCompare>
  assert/test=PASS "C" SUBS "ABC" OR  5 LT 3  ! IF <stringCompare>  OR  <numericCompare>
return

!******************************************************************************!
procedure TestREXISTS
  res existent "EXISTS"
  assert/test=FAIL nonexistent  REXISTS
  assert/test=PASS nonexistent NREXISTS
  assert/test=PASS existent     REXISTS
  assert/test=FAIL existent    NREXISTS
return

!*******************************************************************************
procedure testBITS
  res v1 1
  res v2 2
  res v3 3
  assert/test=FAIL v1 ANYBITS v2
  assert/test=PASS v1 ANYBITS v3
  assert/test=FAIL v1 ALLBITS v2
  assert/test=PASS v1 ALLBITS v1
return

!******************************************************************************!
! NEW: in NeXtMidas version 2.5 and above. C-style operators in logcials like
!      ==,!=,<,<=,>,>= operators and the use of ! to negate
procedure TestCLogicalOperators
  assert/test=PASS 1 ==  1
  assert/test=FAIL 1 ==  2
!  assert/test=PASS 1 !=  2
!  assert/test=FAIL 1 !=  1
!  assert/test=PASS 1 !=  2

  assert/test=PASS 1 <  2
  assert/test=FAIL 2 <  2
  assert/test=PASS 2 >  1
  assert/test=FAIL 1 >  1
  assert/test=PASS 1 <= 2
  assert/test=PASS 2 <= 2
  assert/test=FAIL 3 <= 2
  assert/test=PASS 2 >= 2
  assert/test=PASS 2 >= 2
  assert/test=FAIL 1 >= 2

!  assert/except/test 1 !== 2
!  assert/except/test 1 !!= 1
!  assert/except/test 2 !<  1
!  assert/except/test 1 !>  2
!  assert/except/test 2 !<= 1
!  assert/except/test 1 !>= 2

  assert/except/test 1 n== 2
  assert/except/test 1 n!= 1
  assert/except/test 2 n<  1
  assert/except/test 1 n>  2
  assert/except/test 2 n<= 1
  assert/except/test 1 n>= 2

  assert/except/test "1" ==  "1"
!  assert/except/test "1" !=  "2"
  assert/except/test "1" <   "2"
  assert/except/test "2" >   "1"
  assert/except/test "1" <=  "2"
  assert/except/test "2" <=  "2"
  assert/except/test "2" >=  "1"
  assert/except/test "2" >=  "1"
return

!******************************************************************************!
procedure TestTYPEOF
  res s:mystr "My String"
  res d:myval 3.14
  res t:mytbl {A=1,B=2}

  assert/text="^reg.main.name: mystr  TYPEOF java.lang.String (quoted)"    mystr  TYPEOF "java.lang.String"
  assert/text="^reg.main.name: mystr  TYPEOF java.lang.String (unquoted)"  mystr  TYPEOF  java.lang.String
  assert/text="^reg.main.name: mystr  TYPEOF JAVA.LANG.STRING (uppercase)" mystr  TYPEOF "JAVA.LANG.STRING"

  assert/text="^reg.main.name: mystr  TYPEOF java.lang.String" mystr  TYPEOF "java.lang.String"
  assert/text="^reg.main.name: mystr NTYPEOF nxm.sys.lib.Data" mystr NTYPEOF "nxm.sys.lib.Data"
  assert/text="^reg.main.name: mystr NTYPEOF java.lang.Object" mystr NTYPEOF "java.lang.Object"
  assert/text="^reg.main.name: mystr  TYPEOF S"                mystr  TYPEOF S
  assert/text="^reg.main.name: mystr NTYPEOF D"                mystr NTYPEOF D
  assert/text="^reg.main.name: mystr NTYPEOF F"                mystr NTYPEOF F

  assert/text="^reg.main.name: myval NTYPEOF java.lang.String" myval NTYPEOF "java.lang.String"
  assert/text="^reg.main.name: myval  TYPEOF nxm.sys.lib.Data" myval  TYPEOF "nxm.sys.lib.Data"
  assert/text="^reg.main.name: myval NTYPEOF java.lang.Object" myval NTYPEOF "java.lang.Object"
  assert/text="^reg.main.name: myval NTYPEOF S"                myval NTYPEOF S
  assert/text="^reg.main.name: myval  TYPEOF D"                myval  TYPEOF D
  assert/text="^reg.main.name: myval  TYPEOF SD"               myval  TYPEOF SD
  assert/text="^reg.main.name: myval NTYPEOF 1D"               myval NTYPEOF 1D
  assert/text="^reg.main.name: myval NTYPEOF VD"               myval NTYPEOF VD
  assert/text="^reg.main.name: myval NTYPEOF F"                myval NTYPEOF F
  assert/text="^reg.main.name: myval NTYPEOF SF"               myval NTYPEOF SF
  assert/text="^reg.main.name: myval NTYPEOF 1F"               myval NTYPEOF 1F
  assert/text="^reg.main.name: myval NTYPEOF VF"               myval NTYPEOF VF

  assert/text="^reg.main.name: mytbl NTYPEOF java.lang.String"    mytbl NTYPEOF "java.lang.String"
  assert/text="^reg.main.name: mytbl NTYPEOF nxm.sys.lib.Data"    mytbl NTYPEOF "nxm.sys.lib.Data"
  assert/text="^reg.main.name: mytbl NTYPEOF java.lang.Object"    mytbl NTYPEOF "java.lang.Object"
  assert/text="^reg.main.name: mytbl  TYPEOF nxm.sys.lib.Table"   mytbl  TYPEOF "nxm.sys.lib.Table"
  assert/text="^reg.main.name: mytbl NTYPEOF nxm.sys.lib.Keyable" mytbl NTYPEOF "nxm.sys.inc.Keyable"
  assert/text="^reg.main.name: mytbl NTYPEOF S"                   mytbl NTYPEOF S
  assert/text="^reg.main.name: mytbl NTYPEOF D"                   mytbl NTYPEOF D
  assert/text="^reg.main.name: mytbl NTYPEOF F"                   mytbl NTYPEOF F
return

!******************************************************************************!
procedure TestINSTANCEOF
  res s:mystr "My String"
  res d:myval 3.14
  res t:mytbl {A=1,B=2}

  assert/text="^reg.main.name: mystr  INSTANCEOF java.lang.String (quoted)"   mystr  INSTANCEOF "java.lang.String"
  assert/text="^reg.main.name: mystr  INSTANCEOF java.lang.String (unquoted)" mystr  INSTANCEOF  java.lang.String

  assert/text="^reg.main.name: mystr  INSTANCEOF java.lang.String" mystr  INSTANCEOF "java.lang.String"
  assert/text="^reg.main.name: mystr NINSTANCEOF nxm.sys.lib.Data" mystr NINSTANCEOF "nxm.sys.lib.Data"
  assert/text="^reg.main.name: mystr  INSTANCEOF java.lang.Object" mystr  INSTANCEOF "java.lang.Object"

  assert/text="^reg.main.name: myval NINSTANCEOF java.lang.String" myval NINSTANCEOF "java.lang.String"
  assert/text="^reg.main.name: myval  INSTANCEOF nxm.sys.lib.Data" myval  INSTANCEOF "nxm.sys.lib.Data"
  assert/text="^reg.main.name: myval  INSTANCEOF java.lang.Object" myval  INSTANCEOF "java.lang.Object"

  assert/text="^reg.main.name: mytbl NINSTANCEOF java.lang.String"    mytbl NINSTANCEOF "java.lang.String"
  assert/text="^reg.main.name: mytbl NINSTANCEOF nxm.sys.lib.Data"    mytbl NINSTANCEOF "nxm.sys.lib.Data"
  assert/text="^reg.main.name: mytbl  INSTANCEOF java.lang.Object"    mytbl  INSTANCEOF "java.lang.Object"
  assert/text="^reg.main.name: mytbl  INSTANCEOF nxm.sys.lib.Table"   mytbl  INSTANCEOF "nxm.sys.lib.Table"
  assert/text="^reg.main.name: mytbl  INSTANCEOF nxm.sys.lib.Keyable" mytbl  INSTANCEOF "nxm.sys.inc.Keyable"
return

!******************************************************************************!
procedure TestParenthesis
  res s:mystr "My String"
  res d:myval 3.14
  res t:mytbl {A=1,B=2}

  ! Single set of parenthesis
  assert/test=PASS (myval EQ 3.14)
  assert/test=FAIL (myval EQ 10)
  assert/test=PASS (myval == 3.14)
  assert/test=FAIL (myval == 10)
  assert/test=PASS (myval LT 4)
  assert/test=FAIL (myval LT 3)
  assert/test=PASS (myval <  4)
  assert/test=FAIL (myval <  3)
  assert/test=PASS (myval GT 3)
  assert/test=FAIL (myval GT 4)
  assert/test=PASS (myval >  3)
  assert/test=FAIL (myval >  4)

  ! Pair of parenthesis with AND (no outer parenthesis)
  assert/test=PASS  (1 eq 1) AND (2 eq 2)     ! (TRUE  AND TRUE ) -> TRUE
  assert/test=FAIL  (1 eq 1) AND (1 eq 2)     ! (TRUE  AND FALSE) -> FALSE
  assert/test=FAIL  (1 eq 2) AND (2 eq 2)     ! (FALSE AND TRUE ) -> FALSE
  assert/test=FAIL  (1 eq 2) AND (1 eq 2)     ! (FALSE AND FALSE) -> FALSE

  ! Pair of parenthesis with OR (no outer parenthesis)
  assert/test=PASS  (1 eq 1) OR (2 eq 2)      ! (TRUE  OR TRUE ) -> TRUE
  assert/test=PASS  (1 eq 1) OR (1 eq 2)      ! (TRUE  OR FALSE) -> TRUE
  assert/test=PASS  (1 eq 2) OR (2 eq 2)      ! (FALSE OR TRUE ) -> TRUE
  assert/test=FAIL  (1 eq 2) OR (1 eq 2)      ! (FALSE OR FALSE) -> FALSE

  ! Pair of parenthesis with AND (with outer parenthesis)
  assert/test=PASS ((1 eq 1) AND (2 eq 2))    ! (TRUE  AND TRUE ) -> TRUE
  assert/test=FAIL ((1 eq 1) AND (1 eq 2))    ! (TRUE  AND FALSE) -> FALSE
  assert/test=FAIL ((1 eq 2) AND (2 eq 2))    ! (FALSE AND TRUE ) -> FALSE
  assert/test=FAIL ((1 eq 2) AND (1 eq 2))    ! (FALSE AND FALSE) -> FALSE

  ! Pair of parenthesis with OR (with outer parenthesis)
  assert/test=PASS ((1 eq 1) OR (2 eq 2))     ! (TRUE  OR TRUE ) -> TRUE
  assert/test=PASS ((1 eq 1) OR (1 eq 2))     ! (TRUE  OR FALSE) -> TRUE
  assert/test=PASS ((1 eq 2) OR (2 eq 2))     ! (FALSE OR TRUE ) -> TRUE
  assert/test=FAIL ((1 eq 2) OR (1 eq 2))     ! (FALSE OR FALSE) -> FALSE

return

!******************************************************************************!
procedure TestInLine
  INFO "!!!!!!!! You should have seen a warning message that some text [SET VAL 2] following a THEN will be ignored.!!!!!!!!"

  set val 0

  if val eq 0 then set cond "TRUE"

  if cond eqs "FALSE" then
    set val 1
  elseif cond eqs "TRUE" then set val 2    ! This is TRUE but should not execute the 'set val 2'
    set val 3                              ! This should execute
  elseif cond isTrue then
    set val 4
  else
    set val 6
  endif

  assert/text="^reg.main.name: Proper handling of THEN in ELSEIF line" val eq 3
return

!******************************************************************************!
!   test finding files in RAM when IF test is nested and not nested
!   since NeXtMidas 3.3.1 (Bug 2695)
procedure TestRamFile

  noop ^{datDir}.apenny.prm ram:apenny2

  if (ram:apenny2 FEXISTS) then
    assert/text="^reg.main.name (nested IF) found file in RAM." true
  else
    assert/text="^reg.main.name (nested IF) found file in RAM." false
  endif

  if  ram:apenny2 FEXISTS  then
    assert/text="^reg.main.name  non-nested IF found file in RAM" true
    assert/text="^reg.main.name  non-nested IF using F/EQ for file in RAM" ram:apenny2 FEQ ^{datDir}.apenny.prm
  else
    assert/text="^reg.main.name  non-nested IF found file in RAM" false
  endif

return
