## -*-SM-*- Set SM-mode in emacs
##
## This file provides regression tests for SM
##
## Regrettably, it was only started very late in SM's history, so it's very
## incomplete
##
## Basically, say
##      regress
## and decide which tests are passed. Then you can repeat them with
##      do_failed
## You can list the failed tests with "print { failed }"
##
## You can save all currently failed tests with
##      save_state filename
## and then, if you restart SM with
##      sm load regress restore_state filename
## you can use do_failed to see if you fixed the bug.
##
save_state 01	# save the state of the regression tests to $1
		macro all {}
		if(!$?1) {
		   define 1 regress.sav
		}
		SAVE $1 1 1 1
restore_state 01 # restore the state of the regression tests from $1
		if(!$?1) {
		   define 1 regress.sav
		}
		RESTORE $1
regress	01	# Run regression tests. With an argument, just run that 
		# test; if the argument is "help" describe the regression package
		set i local 
		foreach i {_ntest doit passed playback suite} {
		   define $i local
		}
		set suites local
		set suites = { \
		       arithmetic \
		       axis box ctype define grid histogram image label \
		       macro print ptype random read set sort table \
		       while window \
		    }
		if($?1) {
		   if('$1' == 'help' || '$1' == 'HELP') {
  echo This set of macros provides regression tests for SM. Regrettably, it
  echo was only started very late in SM's history, so it's very incomplete.
  echo
  echo Basically, say
  echo      regress
  echo and decide which tests are passed. Then you can repeat them with
  echo      do_failed
  echo If you only want to run one set of test, say something like
  echo      regress read
  echo
  echo You can save all currently failed tests with
  echo      save_state filename
  echo and then, if you restart SM with
  echo      sm load regress restore_state filename
  echo you can use do_failed to see if you fixed the bug.
  echo
  echo If you define passall, all tests that you'd normally be asked
  echo about are silently assumed to have passed
  echo
  echo Available test suites are:
		      define 2 \"\"
		      do 1=0,dimen(suites)-1 {
		         define 2 <$!2  $(suites[$1])>
		         if(modulo($1,8) == 7) {
		            echo $2
		            define 2 \"\"
		         }
		      }
		      if('$2' != '') {
		         echo $2
		      }
		      return
		   }
		}
		define doit 1           # run this test?
		define passed 1         # did this test pass?
		define playback 0       # we aren't playing back events
		set dimen(failed)=0.s
		#
		# Here are the list of suites to run, e.g. tst_axis
		#
		if($?1) {
		   if(!is_macro(tst_$1)) {
		      echo "I'm sorry, but no tests are available for \"$!1\""
		      return
		   }
		   run_suite $1
		} else {
		   do 1=0,dimen(suites)-1 {
		      define suite ( suites[$1] )
		      define doit ? <Run $suite tests? (-1 or q to quit)>
		      if('$doit' == '-1' || '$doit' == 'q') {
		         if(dimen(failed) < 1) {
		            delete failed
		         }
		         return
		      }
		      if('$doit' == '1' || '$doit' == 'y') {
		         run_suite $suite
		      }
		   }
		}
		if(dimen(failed) < 1) {
		   delete failed
		   return
		}
		define 1 0
		define 1 ? {print failed tests?}
		if('$1' == '1' || '$1' == 'y') {
		   print { failed }
		}
		#
run_suite 1	# run a suite of tests for a given command $1
		define suite {$!!1}
		define _ntest -1        # sequence for long test macros
		if(is_macro(setup_$1)) {
		   setup_$1
		}
		tst_$1
		if(is_macro(unsetup_$1)) {
		   unsetup_$1
		}
		#
do_failed       # Repeat all failed regression tests
		# you can list the failed tests with print { failed }
		define passed 0         # did this test pass?
		define playback 1       # we are playing back events
		if(!is_vector(failed)) {
		   echo I don't know of any failed tests
		} else {
		   if(dimen(failed) == 0) {
		      delete failed
		      echo There are no failed tests
		      return
		   }
		   set _failed=failed
		   do 1 = 0,dimen(_failed) - 1 {
		      define 2 (_failed[$1])
		      #
		      # look for the basename to run a setup_cmd macro
		      # This may involve stripping digits, or looking for
		      # a space. Note that all do_tst commands must start
		      # with the command for this to work
		      #
		      define basename $2
		      if(index('$basename',' ') >= 0) {
		         define basename ( \
		          substr('$basename',0,index('$basename',' ')) )
		      }

		      do 3 = 0,9 {
		         if(index('$basename','$3') >= 0) {
		            define basename \
		             ( substr('$basename',0,index('$basename','$3')) )
		         }
		      }
		      if(is_macro(setup_$basename)) {
		         setup_$basename
		      }
		      do_tst $2
		      if(is_macro(unsetup_$basename)) {
		         unsetup_$basename
		      }
		      define basename DELETE
		   }
		   delete _failed
		}
do_tst	111	# run a test
		ERASE
		define passed 1
		if($verbose) { echo Run \"$1\" }
		$1
		if($passed == 2) {      # we know that it passed
		   #
		} else {                # query user
		   if($?passall) {      # force a pass
		      define passed 10
		   } else {
		      define passed ? {Did it pass?}
		   }
		   if($playback) {
		      if('$passed' == '1' || '$passed' == 'y') {
		         set failed=failed if(failed != '$1')
		      }
		   } else {
		      if(!$passed) {
		         set failed=failed concat '$1'
		      }
		   }
		}
long_tst	# start the definition of a long test; these have the format
		# long_tst { .... } do_long_tst
		define _ntest ($_ntest + 1)
		macro $suite""$_ntest
do_long_tst     # end a long test definition, and carry it out
		define passed 1 do_tst $suite""$_ntest
##
###############################################################################
##
## Here are the real tests. Add their names to the vector suites in regress as
## you add more macros. Note that if you define $passed as 2, the test will
## be taken to have passed, and the user won't be queried
##
setup_arithmetic ##
		define pi {3.14159265358979}
tst_arithmetic
		long_tst {
		   local define pi1  (($pi/10)*10)
		   local define pi2  (($pi*10)/10)
		   local define pi3  ((pi*10)/10)
		   if(abs($pi-pi) > 1.25e-6 || \
		      abs($pi1-pi) > 1.25e-6 || \
		      abs($pi2-pi) > 1.25e-6 || \
		      abs($pi3-pi) > 1.25e-6) {
		      echo Can't do arithmetic on pi == $(pi):
		      echo    $pi ($(sprintf('%.2g',$pi-pi))) $pi1 ($(sprintf('%.2g',$pi1-pi))) $pi2 ($(sprintf('%.2g',$pi2-pi))) $pi3 ($(sprintf('%.2g',$pi3-pi)))
		      define passed 0
		   } else {
		      define passed 2
		   }
		} do_long_tst
unsetup_arithmetic ##
		define pi DELETE
	
tst_axis	# test AXIS
		set s LOCAL  set b LOCAL  set labs LOCAL
		long_tst {
		   angle 90
		   AXIS 0 1 0.05 0.2 3500 3500 27500 2 1
		   angle 0
		} do_long_tst
		
		long_tst {
		   angle 45
		   AXIS 0 1 0.05 0.2 3500 3500 27500 2 1
		   angle 0
		} do_long_tst
		
		long_tst {
		   SET b={1 2 3 5 7 11 13 17 19} SET s=0,20
		   axis 0 20 s b 3500 3500 27500 1 0
		} do_long_tst
		
		long_tst {
		   set s=1,7,.5 set b=1,7 set labs={ O B A F G K M }
		   limits 1 7 1 7
		   box 1 4 4 4
		   axis 1 7 s b labs 3500 2000 27500 1 0
		   limits 0 1 0 1
		} do_long_tst
		
		long_tst {
		   angle 90
		   limits 1 7 1 7
		   box 4 2 4 4
		   axis 1 7 s b labs 2000 3500 27500 2 1
		   limits 0 1 0 1
		   angle 0
		} do_long_tst

		long_tst {
		   limits -0.1 8.1 -0.1 8.1
		   ti -1 0 0 0
		   notation 100 100 0 0
		   box 1 2 4 4
		   limits 0 1 0 1
		   ti 0 0 0 0
		   notation 0 0 0 0
		} do_long_tst

		long_tst {
		   limits 1.7 2.1 0 0
		   ti -0.1 -1.0 0 0
		   box 1 4 4 4
		   limits 0 1 0 1
		   ti 0 0 0 0
		} do_long_tst
tst_box		# test BOX
		do_tst box
		do_tst box 1 2 3 3
		do_tst box 1 4 4 4
		do_tst box 4 2 4 4
		do_tst box 4 4 1 4
		do_tst box 4 4 4 2

		long_tst {
		   echo (note that 1 is written as 10^0)
		   notation 1000 1000 0 0
		   lim 0 6 0 1
		   ti -1 0 0 0
		   box
		   notation 0 0 0 0
		   ti 0 0 0 0
		} do_long_tst
tst_ctype	# test CTYPE
		macro _test_crings {
		   LIMITS -1 1 -1 1
		   local DEFINE _r .2
		   define cc local
		   FOREACH cc (black white red green blue cyan magenta yellow){
		      CTYPE $cc circle 0 0 $_r
		      DEFINE _r ($_r+0.07)
		   }
		}
		do_tst _test_crings

		long_tst {
		   local set colours = CTYPE()
		   local set cnames = CTYPE(STRING)
		   LIMITS -1 1 -1 1
		   local set i=0,255 CTYPE = i + 256*i
		   define i local
		   do i=0,255 {
		      ctype $i  circle 0 0 $($i/256)
		   }
		   define i y
		   define i ? {Restore colourmap and repeat crings?}
		   if('$i' != 'n') {
		      ctype = colours  ctype = cnames
		      ERASE 
		      _test_crings
		   }
		   
		   ctype 0
		   macro _test_crings DELETE
		} do_long_tst
		#
unsetup_ctype	#cleanup after ctype tests
		CTYPE default
setup_define	# setup for tst_define
tst_define	# test DEFINE
		long_tst {
		   echo Should count from 0 to 5 and back down to 0
		   macro bar 1 {#
		      echo $goo
		      define goo local 
		      define goo $1
		      if($goo < 5) {
		         bar $($goo+1)
		      }
		      echo $goo
		   }
		   define goo 0 bar 1 
		   echo $goo
		} do_long_tst
unsetup_define	# cleanup after tst_define
		macro bar delete  define goo delete
		#
tst_grid        # test GRID
		do_tst box grid
		do_tst box grid 0 ltype 1 grid 1 ltype 0
		do_tst box grid 0 1
		do_tst box grid 0 2
		long_tst {
		   define aspect |
		   aspect 1.3
		   box grid
		   aspect $aspect
		} do_long_tst
		long_tst {
		   limits 0 0 -1 3
		   ticksize 0 0 -1 0 ltype 1 grid 2 ltype 0
		   box grid 
		   ti 0 0 0 0 lim 0 1 0 1
		} do_long_tst
setup_histogram # define a macro for histogram
		set x=0,10  set y=sin(x/3)
		macro do_hist {
		   lim -1 11 y box
		   histogram x y if(l)
		   poi x y if(l)
		   ctype cyan poi x y if(!l) ctype default
		}
unsetup_histogram # define a macro for image
		DELETE x DELETE y DELETE l
		macro do_hist delete
tst_histogram	# test HISTOGRAM command
		long_tst {
		   lim -1 11 y box hi x y
		} do_long_tst

		long_tst {
		   set l={0 1 1 0 1 1 0 0 0 1 1}
		   do_hist
		} do_long_tst

		long_tst {
		   set l={1 1 1 0 1 1 0 1 0 1 0}
		   do_hist
		} do_long_tst

		long_tst {
		   set l={1 1 1 0 1 1 0 1 0 1 1}
		   set x=x + sin(x/10)/10
		   echo x is non-uniform; isolated point shouldn't appear
		   do_hist
		} do_long_tst
setup_image     # define a macro for image
		macro makeimage 4 {
		   image ( 30 , 20 ) $1 $2 $3 $4 
		   set image[2,2] = 100 set image[2,17] = 50 
		   set image[0,0]=10 set image[19,19]=10 
		   set image[0,19]=10 set image[19,0]=10
		   levels { 5 90 }
		   limits $1 $2 $3 $4
		}
		macro markcorner {
		   define 1 $expand define 2 $angle define 3 <$ptype>
		   expand 3 angle 0 ptype 4 3
		   relocate 0.05 0.05
		   dot
		   expand $1 angle $2 ptype $3
		}
unsetup_image     # define a macro for image
		image DELETE
		macro makeimage DELETE
		macro markcorner DELETE
tst_image	# test IMAGE command
		long_tst {
		   makeimage 0 1 0 1
		   define NX IMAGE define NY IMAGE
		   if($NX == 30 && $NY == 20) {
		      define passed 2
		      if($verbose) {
		         echo succesfully got image size from \$NX, \$NY
		      }
		   } else {
		      define passed 0
		      echo failed to define NX, NY from IMAGE
		   }
		} do_long_tst
		
		long_tst {
		   makeimage 0 1 0 1
		   set val local
		   set val=image[{2 2},{2 17}]
		   if(val[0] == 100 && val[1] == 50) {
		      define passed 2
		      if($verbose) {
		         echo succesfully extracted image value from index vector
		      }
		   } else {
		      define passed 0
		      echo failed to extract image values from index vector
		   }
		} do_long_tst
		
		long_tst {
		   makeimage 0 1 0 1
		   if(image[2,2] == 100 && image[2,17] == 50) {
		      define passed 2
		      if($verbose) {
		         echo succesfully extracted single image value from index
		      }
		   } else {
		      define passed 0
		      echo failed to extract single image values from index
		   }
		} do_long_tst
		
		long_tst {
		   makeimage 0 1 0 1
		   set rr local
		   set rr=image[2,*]
		   if(rr[2] == 100 && rr[17] == 50) {
		      define passed 2
		      if($verbose) {
		         echo succesfully extracted image row
		      }
		   } else {
		      define passed 0
		      echo failed to extract image row
		   }
		} do_long_tst
		
		long_tst {
		   makeimage 0 1 0 1
		   set col local
		   set col=image[*,19]
		   if(col[0] == 10 && col[19] == 10) {
		      define passed 2
		      if($verbose) {
		         echo succesfully extracted image column
		      }
		   } else {
		      define passed 0
		      echo failed to extract image column
		   }
		} do_long_tst
		
		long_tst {
		   makeimage 0 1 0 1
		   set image[*,*] = 2*image[*,*]
		   if(image[2,2] == 200 && image[2,17] == 100) {
		      define passed 2
		      if($verbose) {
		         echo succesfully extracted and set entire image
		      }
		   } else {
		      define passed 0
		      echo failed to extract and set entire image
		   }
		} do_long_tst
		
		long_tst {
		   makeimage 0 1 0 1
		   define NX IMAGE define NY IMAGE
		   if(image(2/($NX-1),2/($NY-1)) == 100) {
		      define passed 2
		      if($verbose) {
		         echo succesfully extracted single image value from coords
		      }
		   } else {
		      define passed 0
		      echo failed to extract single image values from coords
		   }
		} do_long_tst
		
		long_tst {
		   makeimage 0 1 0 1
		   define NX IMAGE define NY IMAGE
		   set val local
		   set val=image({2 2}/($NX - 1),{2 17}/($NY - 1))
		   if(abs(val[0] - 100) < 1e-4 && \
		       abs(val[1] - 50) < 1e-4) {
		      define passed 2
		      if($verbose) {
		         echo succesfully extracted value from coord vector
		      }
		   } else {
		      define passed 0
		      echo failed to extract image values from coord vector
		   }
		} do_long_tst
		
		long_tst {
		   makeimage 0 1 0 1
		   define NX IMAGE
		   set val local
		   echo Expect two out-of-range x-indices (-1 and $NX)
		   set val=image[do(-1,$NX),0]
		   if(val[0] > 1e25 && val[$NX+1] > 1e25) {
		      define passed 2
		      if($verbose) {
		         echo succesfully detected out-of-range x indices
		      }
		   } else {
		      define passed 0
		      echo failed to detect out-of-range x indices
		   }
		} do_long_tst
		
		long_tst {
		   makeimage 0 1 0 1
		   define NY IMAGE
		   set val local
		   echo Expect two out-of-range y-indices (-1 and $NY)
		   set val=image[1,do(-1,$NY)]
		   if(val[0] > 1e25 && val[$NY+1] > 1e25) {
		      define passed 2
		      if($verbose) {
		         echo succesfully detected out-of-range y indices
		      }
		   } else {
		      define passed 0
		      echo failed to detect out-of-range y indices
		   }
		} do_long_tst
		
		long_tst {
		   makeimage 0 1 0 1
		   define NY IMAGE
		   set val local
		   echo Expect warning of wrong dimensions for index and value vectors
		   set val=0,$NY
		   set image[do(1,2),do(1,3)] = val
		} do_long_tst

		long_tst {
		   echo All maps should be the same
		   window 2 2 1 1 makeimage 0 1 0 1 box contour
		   window 2 2 1 2 makeimage 1 0 0 1 box contour
		   window 2 2 2 1 makeimage 0 1 1 0 box contour
		   window 2 2 2 2 makeimage 1 0 1 0 box contour
		   window 1 1 1 1
		} do_long_tst
		
		long_tst {
		   echo mark is at (0.05, 0.05)
		   window 2 2 1 1 makeimage 0 1 0 1 box contour markcorner
		   window 2 2 1 2 lim 1 0 0 1 box contour markcorner
		   window 2 2 2 1 lim 0 1 1 0 box contour markcorner
		   window 2 2 2 2 lim 1 0 1 0 box contour markcorner
		   window 1 1 1 1
		} do_long_tst
setup_label     expand 4
		lim 0 1 0 1
unsetup_label     expand 1
tst_label	# test labels
		long_tst {
		   rel .5 .5 dot
		   do i=0,9 { rel .5 .5 putl $i $i}
		} do_long_tst

		long_tst {
		   rel .5 .5 dot
		   do i=0,9 { rel .5 .5 putl $i "\border{1000}{$!i}"}
		} do_long_tst

		long_tst {
		   rel .5 .5
		   putl 5 "\over{ABCD}{\over{\alpha}{\gamma\delta}}"
		} do_long_tst

		long_tst {
		   rel .1 .5
		label \colour{blue} {\color{red}\point 4 3 {\ctype{white}\apoint 45 4 1}} \line 1 4000
		} do_long_tst

		long_tst {
		   echo Expect 3 Japanese characters KA, middle one a little different
		   rel .5 .5
		   putl 5 \katakana \KA {\hiragana \KA}\KA
		} do_long_tst
setup_macro	# Make sure that we are ready to run macro tests
		macro macro_tst DELETE
unsetup_macro	# Cleanup
		macro macro_tst DELETE
		macro tst_a_macro DELETE
		macro old_mongo DELETE
		!/bin/rm -f old_mongo.mac macro_tst.sm
tst_macro	# test MACRO commands
		long_tst {
		   macro macro_tst {echo Hello World}
		   echo Expect a macro with no arguments
		   HELP macro_tst
		} do_long_tst
		
		long_tst {
		   macro macro_tst 123 {echo Hello World}
		   echo Expect a macro with 2-3 args, last to end of line
		   HELP macro_tst
		} do_long_tst
		
		long_tst {
		   macro macro_tst DELETE
		   echo Please create a macro to test MACRO EDIT
		   MACRO EDIT macro_tst
		   HELP macro_tst
		} do_long_tst
		   
		long_tst {
		   macro macro_tst {}
		   macro macro_tst DELETE
		   if(is_macro(macro_tst)) {
		      echo Failed to delete macro_tst
		   } else {
		      define passed 2
		      if($verbose) {
		         echo succesfully deleted macro_tst
		      }
		   }
		} do_long_tst
		
		long_tst {
		   macro macro_tst -1 -1
		   HELP macro_tst
		   echo Body of macro should be previous command entered
		} do_long_tst
		
		long_tst {
		   macro read "$!macro"stats
		   if(!is_macro(KS)) {
		      echo Failed to macro read $macro""stats
		   } else {
		      macro delete "$!macro/stats"
		      if(is_macro(KS)) {
		         echo Failed to delete $macro""stats
		      } else {
		         define passed 2
		         if($verbose) {
		            echo Read and deleted macro file succesfully
		         }
		      }
		   }
		} do_long_tst
		
		long_tst {
		   !/bin/rm -f old_mongo.mac
		   macro macro_tst DELETE
		   write old_mongo.mac echo I am an Old Mongo script
		   write old_mongo.mac def macro_tst
		   write old_mongo.mac echo I am &1
		   write old_mongo.mac end
		   read old old_mongo old_mongo.mac
		   if(!is_macro(old_mongo)) {
		      echo Failed to define macro with READ OLD
		   } else {
		      macro old_mongo DELETE
		      if(!is_macro(macro_tst)) {
		         echo Failed to define an embedded macro with READ OLD
		      } else {
		         define passed 2
		         if($verbose) {
		            echo READ OLD handles macros OK
		         }
		      }
		   }
		} do_long_tst
		
		long_tst {
		   macro macro_tst 123 {echo I am macro_tst}
		   !/bin/rm -f macro_tst.sm
		   macro write macro_tst macro_tst.sm
		   echo file should be: \"macro_tst  123  echo I am macro_tst\"
		   !cat macro_tst.sm; rm -f macro_tst.sm
		} do_long_tst

		if(1) {long_tst {
		   macro tst_a_macro 123 {echo RHL I am macro_tst}
		   !/bin/rm -f macro_tst.sm
		   macro write macro_tst.sm
		   # we mustn't change the current macro while it's running!
		   !perl -pi -e 's/^(\S+)\s/tst_a_macro /' macro_tst.sm
		   macro tst_a_macro DELETE
		   #USER ABORT
		   macro read macro_tst.sm
		   if(!is_macro(tst_a_macro)) {
		      echo Failed to read macro back from a macro dump file
		   } else {
		      define passed 2
		      if($verbose) {
		         echo succesfully wrote all macros to a file and read them back
		      }
		   }
		} do_long_tst}
		#
setup_print	# create vectors for tst_print
		set i = 0,9 set x=float(i) set y=x**2
unsetup_print	# create vectors for tst_print
		delete x delete y
tst_print       # test PRINT
		long_tst {
		   echo
		   echo Format: \"\"
		   print { i x y }
		} do_long_tst

		long_tst {
		   echo
		   echo Format: \"'0x%04x %-10.5g %20g\\n'\"
		   print '0x%04x %-10.5g %20g\\n' { i x y }
		} do_long_tst
		
		long_tst {
		   echo
		   echo Format: \"'%2d %-10.5g %20gHello World\\n'\"
		   print '%-4d %-10.5g %20gHello World\\n' { i x y }
		} do_long_tst

		long_tst {
		   echo
		   echo Format: \"'%s %g\\n' \"
		   print '%s %g\\n'  { x y }
		} do_long_tst

		long_tst {
		   !touch print.tst
		   echo Creating print.tst to test \$noclobber
		   define 2 $?noclobber
		   define noclobber 1
		   print print.tst { x }
		   if($2) { define noclobber 1 }
		   !/bin/rm -f print.tst
		} do_long_tst
setup_ptype     # create vectors for tst_ptype
		set x={1 2 3 4 5} 
		set e={2 4 8 10 12}
		limits x x
unsetup_ptype	# create vectors for tst_ptype
		ptype 4 1
		delete x delete e
tst_ptype	# test PTYPE
		define i local  foreach i {p} { set $i local }
		long_tst {
		   echo "Draw square boxes of various sizes"
		   set p={40 40 40 40 40}
		   box  ptype p  expand e  points x x
		   expand 1
		} do_long_tst
		long_tst {
		   define 2 "40 41 42 43 30"
		   echo "Draw ptypes $!2"
		   set p=<$2>
		   box  ptype p  expand e  points x x
		   expand 1
		} do_long_tst
		long_tst {
		   define 2 "{r 200 0 0 400 -200 0 0 -200 200 0}"
		   echo "Draw ptypes $!2"
		   box
		   ptype $2 expand 3
		   points x x
		   expand 1
		} do_long_tst
		#
tst_random	# test RANDOM
		set r local
		long_tst {
		   define mean local  define var local
		   set random 1000
		   set r=random(200000)
		   define mean ( sum(r)/dimen(r) )
		   define var ( sum((r-$mean)**2)/dimen(r) )

		   if(abs($mean - 0.000856) > 1e-6 || \
		       abs(1/$var - 1/11.9708) > 1e-6) {
		      define passed 2
		      if($verbose) {
		         echo Mean - 1/2 = $(sprintf('%.5f',$mean-0.5)),\
		          1/variance = $(sprintf('%.2f',1/$var))

		         echo succesfully generated uniform random numbers
		      }
		   }
		   
		} do_long_tst
		#
setup_read	# create files for tst_read
		unsetup_read
		set y local
		set x=0,9 set y=x**2
		print read.tst { x y }
		write read2.tst 1 2 3
		write read2.tst 1 two 3
		write read2.tst 1 2
		write read2.tst 1
		write read2.tst 10 20 30
		write read3.tst~ 1 2 3 BSLASH
		write read3.tst~ 10 20 30 BSLASH
		write read3.tst~ 100 200 300
		!sed -e 's/BSLASH.*/\\/' read3.tst~ > read3.tst; rm read3.tst~
unsetup_read	# cleanup files for tst_read
		delete x
		!/bin/rm -f read.tst read2.tst read3.tst
tst_read	# test READ
		define i local
		foreach i {y n0 s n1 n2} { set $i local }
		long_tst {
		   data read2.tst
		   define 1 read 1
		   if('$1' == '1 2 3') {
		      define passed 2
		      if($verbose) {
		         echo succesfully defined variable as line of file
		      }
		   } else {
		      define passed 0
		      echo failed to define variable as line of file
		   }
		} do_long_tst
		
		long_tst {
		   data read2.tst
		   define 1 read 1 2
		   if('$1' == '2') {
		      define passed 2
		      if($verbose) {
		         echo succesfully defined variable from line of file
		      }
		   } else {
		      define passed 0
		      echo failed to define variable from line of file
		   }
		} do_long_tst
		
		long_tst {
		   set x=0 delete x
		   data read.tst
		   read x 1
		   if(is_vector(x)) {
		      define passed 2
		      if($verbose) {
		         echo succesfully read x
		      }
		   } else {
		      define passed 0
		      echo failed to read x
		   }
		} do_long_tst
		
		long_tst {
		   set x=0 delete x
		   data read.tst
		   read { x 1 y 2 }
		   if(is_vector(y)) {
		      define passed 2
		      if($verbose) {
		         echo succesfully read y
		      }
		   } else {
		      define passed 0
		      echo failed to read y
		   }
		} do_long_tst		   

		long_tst {
		   set x=0 delete x
		   data read.tst
		   read { x 1-2 }
		   if(is_vector(x) && dimen(x) == 20) {
		      define passed 2
		      if($verbose) {
		         echo succesfully read x as two columns
		      }
		   } else {
		      define passed 0
		      echo failed to read x as two columns
		   }
		} do_long_tst		

		long_tst {
		   da read2.tst
		   read ! '%d %d %s\n' { x y s }
		   if(y[1] == 0 && s[1] == 'two') {
		      define passed 0
		      echo Error: read \"1 two 3\" as \"1 0 two\"
		   } else {
		      define passed 2
		      if($verbose) {
		         echo Read \"1 two 3\" correctly
		      }
		   }
		} do_long_tst

		long_tst {
		   da read2.tst
		   read ! '%d %s %n %s%n%n\n' { x y n0 s n1 n2}
		   if(n0 != {2 2 2 1 2} || n2 != {3 3 2 1 3}) {
		      echo Error: %n format set incorrectly
		      define passed 0
		   }
		   if(sum(n1 == n2) != dimen(n2)) {
		      echo Error: two %n formats disagree
		      define passed 0
		   } else {
		      define passed 2
		      if($verbose) {
		         echo Set number of vectors read correctly
		      }
		   }
		} do_long_tst

		long_tst {
		   da read3.tst
		   read { x 1 }
		   if(dimen(x) == 1) {
		      define passed 2
		      if($verbose) {
		         echo succesfully read x from a continued line
		      }
		   } else {
		      define passed 0
		      echo failed to read x from a continued line
		   }
		} do_long_tst

		long_tst {
		   da read3.tst
		   read row x 1
		   if(dimen(x) == 9) {
		      define passed 2
		      if($verbose) {
		         echo succesfully read row x from a continued line
		      }
		   } else {
		      define passed 0
		      echo failed to read row x from a continued line
		   }
		} do_long_tst
setup_set	# setup for tst_set
tst_set		# test SET
		long_tst {
		   echo Should count from 0 to 5 and back down to 0
		   macro bar 1 {#
		      echo $(goo)
		      set goo local 
		      set goo=$1
		      if(goo < 5) {
		         bar $(goo+1)
		      }
		      echo $(goo)
		   }
		   set goo=0 bar 1 
		   echo $(goo)
		} do_long_tst

		long_tst {
		   delete goo
		   macro bar {#
		      set goo local 
		      set goo=1234
		   }
		   bar
		   if(is_vector(goo)) {
		      define passed 0
		      echo Local vector goo is visible at outer scope
		   } else {
		      define passed 2
		   }
		} do_long_tst

		long_tst {
		   delete goo
		   macro foo {
		      set goo local
		      bar
		   }
		   macro bar {#
		      set goo=1234
		   }
		   if(is_vector(goo)) {
		      define passed 0
		      echo Local vector goo is visible at outer scope
		   } else {
		      define passed 2
		   }
		} do_long_tst

		long_tst {
		   delete goo
		   echo Expect complaint about deleting a local vector
		   macro bar {#
		      set goo local 
		      set goo=1234
		      define 1 $verbose 
		      VERBOSE 2
		      delete goo
		      VERBOSE $1		      
		   }
		   bar
		} do_long_tst

		long_tst {
		   define 1 $expand
		   EXPAND 1 define expand DELETE
		   macro bar {#
		      define expand local  
		      define expand |   # would fix $expand at 1 if not local
		      EXPAND 10
		   }
		   bar
		   if($expand != 10) {
		      echo LOCAL failed to implicitly delete a | variable
		      define passed 0
		   } else {
		      define passed 2
		   }
		   EXPAND $1
		} do_long_tst
unsetup_set	# cleanup after tst_set
		macro bar delete  delete goo
		#
tst_sort	# test SORT commands
		long_tst {
		   local set r=random(100)
		   local set i=1,dimen(r)
		   lim i r box
		   ctype red con i r
		   sort { r }
		   ctype magenta
		   con i r
		   ctype 0
		} do_long_tst

		long_tst {
		   local set r=random(100)
		   local set s=1 - r
		   local set t = 1 - r**2
		   local set i=1,dimen(r)
		   sort { r s t }
		   lim i ({0 1}) box
		   ctype magenta con i r
		   ctype cyan con i s con i t
		   ctype 0
		} do_long_tst

		long_tst {
		   set l = < 8 1 0 6 9 4 7 3 5 2 >
		   sort { l }
		   if(sum(l - do(0,9)) == 0) {
		      define passed 2
		   } else {
		      define passwd 0
		   }
		} do_long_tst

		long_tst {
		   set l = < 8 1 0 6 9 4 7 3 5 2 >
		   set s = l
		   sort { l s }
		   if(sum(s - do(0,9)) == 0) {
		      define passed 2
		   } else {
		      define passwd 0
		   }
		} do_long_tst

		long_tst {
		   set s = < G B A C H F E D >
		   sort { s }
		   print '%s ' { s }
		} do_long_tst

		long_tst {
		   set s = < G B A C H F E D >
		   set t = { 7 2 1 3 8 6 5 4 }
		   sort { s t }
		   print '%s:%d ' { s t }
		} do_long_tst
		#
setup_table     # define a macro for table
		define tab "tst.fits"
		macro maketable {
		   local set x = 1,10  local set y=sin(x)
		   table delete
		   define RHL local
		   image define RHL "Me"
		   !rm -f $tab
		   write table $tab {}
		   table delete
		   
		   write table + $tab { x y }
		   table delete

		   set x = x concat 15 + x  set y = y concat -y
		   local set z = 10*x
		   define PAM local
		   image define PAM "You"
		   write table + $tab { x y z }
		}
unsetup_table	# define a macro for table
		!rm -f $tab
		define tab DELETE
		table DELETE
		macro maketable DELETE
tst_table	# test TABLE command
		long_tst {
		   maketable		   

		   set x local  set y local
		   table 1 $tab  read table { x y }

		   if(dimen(x) == 10 && y == sin(x)) {
		      define passed 2
		      if($verbose) {
		         echo succesfully read HDU 1
		      }
		   } else {
		      define passed 0
		      echo failed to read HDU 1
		   }
		} do_long_tst

		long_tst {
		   maketable		   

		   set x local  set y local  set z local
		   table 2 $tab  read table { x y z }

		   if(dimen(x) == 20 && z == 10*x) {
		      define passed 2
		      if($verbose) {
		         echo succesfully read HDU 2
		      }
		   } else {
		      define passed 0
		      echo failed to read HDU 2
		   }
		} do_long_tst

		long_tst {
		   maketable		   

		   table 0 $tab
		   if($?RHL) { define RHL DELETE }
		   local define RHL image

		   if($?RHL) {
		      if('$RHL' == 'Me') {
		         define passed 2
		         if($verbose) {
		            echo "Succesfully read RHL from table's PDU"
		         }
		         return
		      }
		   }
		   define passed 0
		   echo "Failed to read RHL from table's PDU"
		} do_long_tst

		long_tst {
		   maketable		   

		   table 1 $tab
		   table 2
		   set x local  read table { x }
		   if($?PAM) { define PAM DELETE }
		   if($?RHL) { define RHL DELETE }

		   local define PAM image
		   local define RHL image
		   
		   define passed 0
		   if($?PAM) { if('$PAM' == 'You') {
		      if($verbose) {
		         echo "Succesfully read PAM from table's 2nd HDU"
		      }
		      if(!$?RHL) {
		         define passed 2
		         if($verbose) {
		            echo \
		             "Correctly failed to read RHL from table's 2nd HDU"
		         }
		      } else {
		         echo "Incorrectly read RHL from table's 2nd HDU"
		      }
		      return
		   }}
		   echo "Failed to read PAM from table's 2nd HDU"
		} do_long_tst
tst_while	# test WHILE loops
		long_tst {
		   local set n = 10
		   local set s = 0
		   local set i = 0
		   while {i < n} {
		      set s = s + i
		      
		      set i = i + 1
		   }
		   if(s == n*(n-1)/2) {
		      define passed 2
		   } else {
		      define passed 0
		      echo sum_i=0^$(n) (i) = $(s) -- should be $(n*(n-1)/2)
		   }
		} do_long_tst
		#
		long_tst {
		   local set n = 10
		   local set s = 0
		   local set i = 0
		   while {i < 2*n} {
		      set s = s + i

		      set i = i + 1
		      if(i == n) { break }
		   }
		   if(s == n*(n-1)/2) {
		      define passed 2
		   } else {
		      define passed 0
		      echo Failed to break out of WHILE loop
		   }
		} do_long_tst
		#
tst_window	# test WINDOW
		long_tst {
		   window 1 2 1 1 box
		   window 1 2 1 2 box
		   WINDOW 1 1 1 1
		} do_long_tst
		
		long_tst {
		   define verbose |
		   VERBOSE 1
		   echo Expect out-of-range warning
		   window 1 2 1 3 box
		   VERBOSE $verbose define verbose delete
		   WINDOW 1 1 1 1
		} do_long_tst

		long_tst {
		   do 1=1,6 {
		      WINDOW 1 -6 1 $1 BOX
		   }
		   WINDOW 1 1 1 1
		} do_long_tst

		long_tst {
		   WINDOW 2 2 2 2
		   box
		   xla X
		   yla Y
		   WINDOW 1 1 1 1
		} do_long_tst

		long_tst {
		   echo Default window should cover central 2x2 windows
		   ctype cyan
		   do x=1,4 { do y=1,6 {
		      WINDOW 4 -6 $x $y BOX 3 3 3 3
		   }}
		   ctype default
		   WINDOW 4 -6 2:3 3:4 BOX
		} do_long_tst

		long_tst {
		   define i local
		   WINDOW 1 1 1 1
		   foreach i (gx1 gx2 gy1 gy2) {
		      define $i local define $i |
		   }
		   echo Default windows should be within the cyan one
		   location 3500 15000 3500 10000
		   ctype cyan box 0 0 0 0 ctype 0
		   WINDOW -2 -2 1 1 box 0 0 0 0 
		   WINDOW -2 -2 2 2 box 0 0 0 0
		   WINDOW 1 1 1 1
		   location $gx1 $gx2 $gy1 $gy2
		} do_long_tst

		long_tst {
		   define i local
		   WINDOW 1 1 1 1
		   foreach i (gx1 gx2 gy1 gy2) {
		      define $i local define $i |
		   }
		   define verbose local define verbose |  VERBOSE 1
		   echo Expect warning about mixing WINDOW and LOCATION
		   WINDOW 2 2 1 1
		   location 3500 15000 3500 10000
		   WINDOW 1 1 1 1
		   location $gx1 $gx2 $gy1 $gy2
		   VERBOSE $verbose
		} do_long_tst
unsetup_window	# cleanup after window tests
		window 1 1 1 1
		limits 0 1 0 1
		#
		
