#!/bin/sh  
# \
exec oagwish "$0" "$@"
set auto_path [linsert $auto_path 0  /usr/local/oag/apps/lib/$env(HOST_ARCH)]
set auto_path [linsert $auto_path 0 /usr/local/oag/lib_patch/$env(HOST_ARCH)]
# $Log: not supported by cvs2svn $
# Revision 1.11  2006/03/24 23:37:07  shang
# moved the tests files from Bob Soliday's directory to /home/oxygen/OAG/sddsEpicsTests;
# and added tests of ActuatorLowerLimit, ActuatorUpperLimit, runControlPV to sddsfeedforward
# test.
#
# Revision 1.10  2006/01/10 19:23:16  soliday
# Updated test for sddsglitchlogger.
#
# Revision 1.9  2004/10/05 19:30:53  shang
# added test of cavget and cavput
#
# Revision 1.8  2004/03/25 15:21:43  shang
# added waiting time after set the casave pv to 1 in test_sddscasr proc
#
# Revision 1.7  2004/03/16 21:00:32  shang
# added inputFilePV option test of sddscasr and set the setpoints to zero before using
# sddscasr restore
#
# Revision 1.6  2004/03/02 19:57:16  shang
# added test of sddscasr
#
# Revision 1.5  2002/04/18 15:52:51  soliday
# Added sddsfeedforward
#
# Revision 1.4  2002/04/05 22:13:08  shang
# added sddswget test
#
# Revision 1.3  2001/09/14 18:39:27  soliday
# Added sddsoptimize and sddsglitchlogger
#
# Revision 1.2  2001/07/31 20:09:25  soliday
# Added more testing for sddscontrollaw.
#
# Revision 1.1  2000/02/02 18:56:12  soliday
# First version.
#
# 
#
wm geometry . +50+10
set CVSRevisionAuthor "\$Revision: 1.12 $ \$Author: soliday $"
APSApplication . \
    -name "Test SDDS Epics Procedures" \
    -version $CVSRevisionAuthor \
    -overview "This program uses a simulated linac running on the IOC in Soliday's office to test SDDS epics software."
set status "Ready"
APSScrolledStatus .status \
    -parent .userFrame \
    -textVariable status \
    -packOption "-expand true -fill both" \
    -width 92
update

frame .frame1
frame .frame3
frame .frame4 -borderwidth 3 -relief raised
frame .frame5 
pack .frame1 -in .userFrame -side left
pack .frame3 -in .userFrame -side left -fill both -expand true
pack .frame4 -side top -fill both -expand true 
pack .frame5 -in .frame4 -side top -fill x -expand true
set env(EPICS_CA_ADDR_LIST) "164.54.50.58 127.0.0.1 "

APSButton .cawait -parent .frame1 -text cawait -packOption "-side top -fill x"\
    -command {setCheckButtons -program cawait -options "interval timeLimit totalTimeLimit waitFor and or not repeat emit preEvent onEvent postEvent onEnd subprocess pendIOTime"}
APSButton .cavget -parent .frame1 -text cavget -packOption "-side top -fill x"\
    -command {setCheckButtons -program cavget -options "list range floatFormat delimiter labeled noQuotes embrace cavputForm pendIOTime dryRun errorValue excludeErrors numerical repeat statistics"}
APSButton .cavput -parent .frame1 -text cavput -packOption "-side top -fill x"\
    -command {setCheckButtons -program cavput -options "list range pendIOTime dryRun deltaMode numerical ramp blunderAhead"}
APSButton .sddssynchlog -parent .frame1 -text sddssynchlog -packOption "-side top -fill x"\
    -command {setCheckButtons -program sddssynchlog -options "slowData samples timeLimit eraseFile pendEventTime connectTimeout verbose comment synchinterval precision"}
#APSButton .mV20image2sdds -parent .frame1 -text MV20image2sdds -packOption "-side top -fill x" -command {setCheckButtons -program MV20image2sdds -options "definition verbose"}
APSButton .sddsexperiment -parent .frame1 -text sddsexperiment -packOption "-side top -fill x"\
    -command {setCheckButtons -program sddsexperiment -options "echoinput dryrun summarize verbose ezcaTiming describeInput"}
APSButton .sddsvexperiment -parent .frame1 -text sddsvexperiment -packOption "-side top -fill x"\
    -command {setCheckButtons -program sddsvexperiment -options "suffixFile rootnameFile echoinput dryrun summarize verbose ezcaTiming describeInput"}
APSButton .sddsmonitor -parent .frame1 -text sddsmonitor -packOption "-side top -fill x"\
    -command {setCheckButtons -program sddsmonitor -options "erase append generations dailyFiles steps time interval enforceTimeLimit offsetTimeOfDay updateinterval verbose singleshot precision oncaerror pendIOtime ezcaTiming glitch trigger alarmTrigger circularBuffer holdoffTime autoHoldoff conditions noezca comment getUnits inhibitPV"}
APSButton .sddsstatmon -parent .frame1 -text sddsstatmon -packOption "-side top -fill x"\
    -command {setCheckButtons -program sddsstatmon -options "erase generations steps time interval singleShot enforceTimeLimit offsetTimeOfDay includeStatistics samplesPerStatistic verbose precision updateInterval ezcaTiming oncaerror comment conditions getUnits inhibitPV"}
APSButton .sddsvmonitor -parent .frame1 -text sddsvmonitor -packOption "-side top -fill x"\
    -command {setCheckButtons -program sddsvmonitor -options "rootnames suffixes erase append generations steps time interval enforceTimeLimit offsetTimeOfDay verbose singleShot precision onCAerror PVlist ezcatiming scalars conditions logDuplicates comment"}
APSButton .sddswmonitor -parent .frame1 -text sddswmonitor -packOption "-side top -fill x"\
    -command {setCheckButtons -program sddswmonitor -options "PVnames erase generations steps time interval enforceTimeLimit offsetTimeOfDay verbose singleShot precision dataType onCAerror ezcaTiming scalars conditions accumulate logOnChange comment"}
#APSButton .bPS16monitor -parent .frame1 -text BPS16monitor -packOption "-side top -fill x" -command {setCheckButtons -program BPS16monitor -options "assignments scalars interval steps time singleShot onCAerror sparse baselineFraction headFraction tailFraction slopesStartFraction expIntervalFraction meanRegion ezcaTiming logWaveforms listAnalyses waveformLength sampleInterval"}
APSButton .squishPVs -parent .frame1 -text squishPVs -packOption "-side top -fill x"\
    -command {setCheckButtons -program squishPVs -options "count averages stepSize subdivisions upstep repeat ezcaTiming settlingTime verbose criterion threshold actionLevel maximize runControlPV runControlDescription"}
APSButton .sddssnapshot -parent .frame1 -text sddssnapshot -packOption "-side top -fill x"\
    -command {setCheckButtons -program sddssnapshot -options "pipe ezcaTiming unitsOfData nameOfData serverMode average"}
APSButton .sddscontrollaw -parent .frame1 -text sddscontrollaw -packOption "-side top -fill x"\
    -command {setCheckButtons -program sddscontrollaw -options "actuatorColumn generations dailyFiles controlQuantityDefinition gain interval steps updateInterval integration proportional holdPresentValues offsets verbose dryRun warning average testValues statistics deltaLimit readbackLimit actionLimit ezcaTiming groupEzca runControlPV runControlDescription despike servermode controlLogFile glitchLogFile CASecurityTest"}
#APSButton .sddsalarmlog -parent .frame1 -text sddsalarmlog -packOption "-side top -fill x" -command {setCheckButtons -program sddsalarmlog -options "timeDuration offsetTimeOfDay append eraseFile generations pendEventTime durations connectTimeout explicit verbose comment requireChange inhibitPV"}
#APSButton .toggle -parent .frame1 -text toggle -packOption "-side top -fill x" -command {setCheckButtons -program toggle -options "controlName interval cycles finalSet ezcaTiming prompt verbose warning"}
APSButton .sddslogger -parent .frame1 -text sddslogger -packOption "-side top -fill x"\
    -command {setCheckButtons -program sddslogger -options "generations dailyFiles sampleInterval logInterval steps time enforceTimeLimit offsetTimeOfDay verbose singleshot precision onerror pendIOtime conditions inhibitPV"}
#APSButton .sddsfeedforward -parent .frame1 -text sddsfeedforward -packOption "-side top -fill x" -command {setCheckButtons -program sddsfeedforward -options "interval steps verbose dryRun offsetOnly averageOf advance testValues ezcaTiming runControlPV runControlDescription CASecurityTest"}
APSButton .sddsoptimize -parent .frame1 -text sddsoptimize -packOption "-side top -fill x"\
    -command {setCheckButtons -program sddsoptimize -options "measFile measScript varFile knobFiles simplex logFile verbose tolerance maximize 1dscan target testValues runControlPV runControlDescription"}
APSButton .sddsglitchlogger -parent .frame1 -text sddsglitchlogger -packOption "-side top -fill x"\
    -command {setCheckButtons -program sddsglitchlogger -options "triggerFile lockFile sampleInterval time circularBuffer holdoffTime autoHoldoff inhibitPV conditions verbose watchInput"}
APSButton .sddswget -parent .frame1 -text sddswget -packOption "-side top -fill x"\
    -command {setCheckButtons -program sddswget -options "PVnames ezcaTiming"}
APSButton .sddsfeedforward \
    -parent .frame1 \
    -text sddsfeedforward \
    -packOption "-side top -fill x"\
    -command {
	setCheckButtons \
	    -program sddsfeedforward \
	    -options "interval steps verbose dryRun offsetOnly averageOf advance testValues ezcaTiming runControlPV runControlDescription CASecurityTest"
    }
APSButton .sddscasr \
    -parent .frame1 \
    -text sddscasr \
    -packOption "-side top -fill x"\
    -command {
	setCheckButtons \
	    -program sddscasr \
	    -options "dailyFiles semaphore daemon save restore logFile pendIOTime pidFile\
            interval casavePV outputFilePV unique pipe description runControlPV \
            runControlDescription numerical waveform inputFilePV"
    }




set testProgramName ""

APSLabeledEntry .testProgram -parent .frame5 -label "Program location:" \
    -textVariable testProgramName -width 73 -packOption "-side left"
APSButton .getTestProgram -parent .frame5 -text F -packOption "-side right" \
    -command {set testProgramNameTemp [APSFileSelectDialog [APSUniqueName .]]; if {[string compare "" $testProgramNameTemp]!=0} {set testProgramName $testProgramNameTemp}}

APSButton .startTest -parent .frame4 -text "Test selected program" -command {testProgram -program [.frame3.checkButtonFrame.label cget -text]}

APSButton .startTestAll -parent .frame4 -text "Test all programs" -command {testAllPrograms}

APSButton .showLinac -parent .frame4 -text "Display Simulated Linac" -command {exec medm -x -macro "user=oag" /home/oxygen/SOLIDAY/epics/iocapps/medm/linac.adl &}

APSButton .showPrivateLinac -parent .frame4 -text "Display Private Linac" -command {exec medm -x -macro "user=$env(USER)" /home/oxygen/SOLIDAY/epics/iocapps/medm/linac.adl &}

proc setCheckButtons {args} {
    set options none
    set program none
    APSStrictParseArguments {program options}
    global buttonList buttonVar testProgramName
    set buttonList $options
    set buttonVar ""
    set testProgramName [exec which $program]
    foreach button $buttonList {
	append buttonVar "${button}_$program "
    }
    destroy .frame3.checkButtonFrame
    foreach button $buttonVar {
	global $button
	if {![info exists $button]} {
	    set $button 1
	}
    }
    APSCheckButtonFrame .checkButtonFrame -parent .frame3 -buttonList $buttonList \
	-variableList $buttonVar -allNone 1 -label $program -limitPerRow 12 -packOption "-side left"
    update
}

proc testProgram {args} {
    set program none
    APSStrictParseArguments {program}
    global testProgramName status finalResults
    set finalResults "" 
    if {![file exists $testProgramName]} {
	APSSetVarAndUpdate status "$testProgramName Program does not exist"
	return
    }
    APSSetVarAndUpdate status "Testing $program using $testProgramName"
    if [string match "*sddscasr*" $testProgramName] {
        APSSetVarAndUpdate status "The first step may take several seconds, because it has to compare six output files and five waveform files with the results of sddswget"
    }
    set outFile /tmp/[APSTmpString]
    APSAddToTempFileList $outFile
    set passedValue [test_$program \
			 -testProgramName $testProgramName \
			 -inDir /home/oxygen/OAG/sddsEpicsTests/ \
			 -outFile $outFile]
    set frameName .frame1
    if {$passedValue} {
	if {[string compare $status "Testing for this program is not available yet."]==0} {
	    ${frameName}.${program}.button configure -background yellow
	} else {
	    APSSetVarAndUpdate status "$program Passed"
	    ${frameName}.${program}.button configure -background green
	}
    } else {
	APSSetVarAndUpdate status "$program Failed"
	${frameName}.${program}.button configure -background red
	destroy .${program}Results
	toplevel .${program}Results
	APSScrolledText .text \
	    -parent .${program}Results \
	    -width 80 \
	    -name $program
	.${program}Results.text.text insert end $finalResults
	pack [frame .${program}Results.frame] \
	    -fill x
	pack [button .${program}Results.frame.ok \
		  -text "         OK          " \
		  -command "destroy .${program}Results"] \
	    -side left \
	    -fill x \
	    -expand true
	global replacement
	if [info exists replacement(old)] {
	    pack [button .${program}Results.frame.update \
		      -text "Replace Standard File" \
		      -command "ReplaceFile -old $replacement(old) -new $replacement(new)"] \
		-side right \
		-fill x \
		-expand true
	}
    }
}

proc ReplaceFile {args} {
    APSStrictParseArguments {old new}
    global env
    if {$env(USER) != "oag"} {
	APSSetVarAndUpdate status "You must be logged in as oag to replace standard files"
	return
    }
    if [catch {file copy -force -- $new $old} results] {
	APSSetVarAndUpdate status $results
	return
    }
    APSSetVarAndUpdate status "File copied"
}

proc testAllPrograms {} {
    set names "sddssynchlog sddsexperiment sddsvexperiment sddsmonitor sddsstatmon sddsvmonitor sddswmonitor squishPVs sddssnapshot sddscontrollaw sddslogger sddsoptimize sddsglitchlogger sddswget sddsfeedforward"
    foreach name $names {
	eval [.frame1.${name}.button cget -command]
	testProgram -program [.frame3.checkButtonFrame.label cget -text]
    }
}
 
proc compareOutput1 {args} {
    APSStrictParseArguments {testProgramName execute standardFile testFile}
    global finalResults replacement
    APSAddToTempFileList ${testFile}2 ${testFile}3
   
    foreach file {standard test} {
        set Parameters [lsort [exec sddsquery [set ${file}File] -parameterlist]]
        set Arrays [lsort [exec sddsquery [set ${file}File] -arraylist]]
        set Columns [lsort [exec sddsquery [set ${file}File] -columnlist]]
        set ${file}Parameters [join $Parameters ","]
        set ${file}Arrays [join $Arrays ","]
            set ${file}Columns [join $Columns ","]
    }
    if [catch "eval exec sddsprintout $standardFile ${testFile}2 \
		   {-parameters=($standardParameters)} {-arrays=($standardArrays)} \
		   {-columns=($standardColumns)} -noTitle -nowarn;exec sddsprintout $testFile \
		   ${testFile}3 {-parameters=($testParameters)} {-arrays=($testArrays)} \
		   {-columns=($testColumns)} -noTitle -nowarn;exec tcomp ${testFile}2 ${testFile}3" results] {
        append finalResults "$testProgramName\n\n$execute\n\n$standardFile differs from $testFile\n\n$results\n"
        set replacement(old) $standardFile
        set replacement(new) $testFile
    } else {
        upvar valid x
        set x 1
    }
}

proc compareOutput {args} {
    APSStrictParseArguments {testProgramName execute standardFile testFile}
    global finalResults

    if [catch {sdds load $testFile testfile} results] {
	append finalResults "$testProgramName\n$execute\nsdds load $testFile testfile\n$results\n"
	return
    }
    if [catch {sdds load $standardFile standardfile} results] {
	append finalResults "$testProgramName\n$execute\nsdds load $standardFile standardfile\n$results\n"
	return
    }
    if {[string compare $testfile(ParameterNames) $standardfile(ParameterNames)]!=0} {
	append finalResults "$testProgramName\nParameter names doesn't match\ntestfile: $testfile(ParameterNames)\nstandardfile: $standardfile(ParameterNames)"
	return
    }
    if {[string compare $testfile(ColumnNames) $standardfile(ColumnNames)]!=0} {
	append finalResults "$testProgramName\nColumn names doesn't match\ntestfile: $testfile(ColumnNames)\nstandardfile: $standardfile(ColumnNames)"
	return
    }
    foreach column $testfile(ColumnNames) {
	if {($column == "Sample") || ($column == "Step") || ($column == "Index")} {
	    if {[string compare $testfile(Column.$column) $standardfile(Column.$column)]} {
		append finalResults "$testProgramName\n$column column doesn't match"
		return
	    }
	} elseif {$column == "Time"} {
	    foreach testData $testfile(Column.$column) standardData $standardfile(Column.$column) {
		set testTimeInterval [expr [lindex $testData end] - [lindex $testData 0]]
		set standardTimeInterval [expr [lindex $standardData end] - [lindex $standardData 0]]
		if {[expr abs($standardTimeInterval - $testTimeInterval)] > 5} {
		    append finalResults "$testProgramName\nTime column has a time interval difference of greater then 5 seconds"
		    return
		}  
	    }
	} elseif {($column == "TimeOfDay") || ($column == "DayOfMonth") || ($column == "ElapsedTime")} {
	    continue
	} else {
	    array set info $testfile(ColumnInfo.$column)
	    if {($info(type) == "SDDS_STRING") || ($info(type) == "SDDS_CHARACTER")} {
		if {[string compare $testfile(Column.$column) $standardfile(Column.$column)]} {
		    append finalResults "$testProgramName\n$column column doesn't match"
		    return
		}
	    } else {
		foreach testData $testfile(Column.$column) standardData $standardfile(Column.$column) {
		    set tmp1 0
		    set tmp2 0
		    foreach data $testData {
			set tmp1 [expr {$tmp1 + $data}]
		    }
		    foreach data $standardData {
			set tmp2 [expr {$tmp2 + $data}]
		    }
		    set num1 [llength $testData]
		    set num2 [llength $standardData]
		    if {$num1 != $num2} {
			append finalResults "$testProgramName\n$column column has a different number of rows then the standard file"
			return
		    }
		    set tmp1 [expr {$tmp1 / $num1}]
		    set tmp2 [expr {$tmp2 / $num2}]
		    set columnSuffix [string range $column [expr [string length $column] - 5] end]
		    if {($columnSuffix == "StDev") || ($columnSuffix == "Sigma")} {
			set maxDiff [expr abs($tmp2 * 0.5)]
			set percentAllowed "50%"
		    } elseif {($column == ":intensityM")} {
			set maxDiff [expr abs($tmp2 * 0.1)]
			set percentAllowed "10%"			
		    } elseif {$tmp2 < 1} {
			set maxDiff [expr abs($tmp2 * 0.25)]
			set percentAllowed "25%"
		    } else {
			set maxDiff [expr abs($tmp2 * 0.05)]
			set percentAllowed "5%"
		    }
		    set diff [expr abs($tmp1 - $tmp2)]
		    global status
		    if {$maxDiff < $diff} {
			append finalResults "$testProgramName\n$column column has a difference of greater then $percentAllowed of the standard file."
			return
		    }
		}
	    }
	}
    }
    upvar valid x
    set x 1
}

proc optionsPassed {args} {
    APSStrictParseArguments {pass}
    upvar 2 program name
    foreach option $pass {
	global ${option}_$name
	set ${option}_$name 0
    }
    update
}

proc test_cawait {args} {
    APSStrictParseArguments {testProgramName inDir outFile}
    global finalResults
    
    APSSetVarAndUpdate status "Please bring up the linac simulator for testing of cawait"
    #set the corrector off so that the value of position becomes out of range
    set execute "cavput -list=oag:H1:setCurrentC=5.0 -pend=10"
    if [catch {eval exec $execute} results] {
        append finalResults "cavput failure:\n$execute\n$results"
        return 0
    }
    set tolerance 1.0
    set execute "$testProgramName -waitFor=oag:PM1:X:positionM,lowerLimit=-$tolerance,upperLimit=$tolerance -waitFor=oag:PM1:Y:positionM,lowerLimit=-$tolerance,upperLimit=$tolerance -and -waitFor=oag:PM2:X:positionM,lowerLimit=-$tolerance,upperLimit=$tolerance -and -waitFor=oag:PM1:intensityM,below=0.5 -or -interval=1 -timelimit=30 -emit=event=0,timeout=1"
    global waitdone
    set waitdone 0
    APSExecLog .cawait -name "Waiting for cawait" -width 80 \
      -unixCommand "$execute" -callback "set waitdone 1"
    if !$waitdone {
        tkwait variable waitdone
    }
    #if [catch {eval exec $execute} results] {
     #   append finalResults "$testProgramName\n$execute\n$results"
      #  return 0
    #}

    
    #program will wait for here until the value of oag:H1:setCurrentC is restored by chosing a file from Quick BURT list or after 30 seconds"
    
    return 1
}

proc test_cavput {args} {
    APSStrictParseArguments {testProgramName inDir outFile}
    global finalResults
    
    set result [cavput_list_test -testProgramName $testProgramName]
    
    if !$result {
        return 0
    }
    optionsPassed -pass {list pendIOTime}
    set execute "$testProgramName -list=shang -list=:H,:V -range=begin=1,end=5,interval=1 -pend=10 -list=:setCurrentC=1"
    if [catch {eval exec $execute} results] {
        append finalResults "$testProgramName\n$execute\n$results\n"
        return 0
    }
    set execute1 "cavget -list=shang -list=:H,:V -range=begin=1,end=5 -pend=10 -list=:setCurrentC"
    if [catch {eval exec $execute1} results] {
        append finalResults "$testProgramName\n$execute1\n$results\n"
        return 0
    }
    foreach val $results {
        if {$val!=1} {
            append finalResults "$val != 1 (cavput value), cavput failed.\n$execute"
            return 0
        }
    }
    optionsPassed -pass {range}
    set execute "$testProgramName -list=shang -list=:H,:V -range=begin=1,end=5 -dryRun -pend=10 -list=:setCurrentC=0"
    if [catch {eval exec $execute} results] {
        append finalResults "$testProgramName\n$execute\n$results\n"
        return 0
    }
    array set dryPut $results
    foreach name [array name dryPut] {
        if {[set dryPut($name) ]!= 0} {
            append finalResults "$testProgramName\n$execute\n$name!=0 (dryRun value)\n"
            return 0
        }
    }
    if [catch {eval exec $execute1} results] {
        append finalResults "$testProgramName\n$execute1\n$results\n"
        return 0
    }
    foreach val $results {
        if {$val!=1} {
            append finalResults "$val != 1, cavput dryRun option failed.\n$execute"
            return 0
        }
    }
    optionsPassed -pass {dryRun}
    set execute "$testProgramName -list=shang:H1:setCurrentC=0.1,shang:H2:setCurrentC=0.2,shang:H3:setCurrentC=0.3 -deltaMode"
    if [catch {eval exec $execute} results] {
        append finalResults "$testProgramName\n$execute\n$results\n"
        return 0
    }
    set execute1 "cavget -list=shang:H1:setCurrentC,shang:H2:setCurrentC,shang:H3:setCurrentC"
    if [catch {eval exec $execute1} results] {
        append finalResults "$testProgramName\n$execute1\n$results\n"
        return 0
    }
    set val1 [lindex $results 0]
    set val2 [lindex $results 1]
    set val3 [lindex $results 2]
    if {$val1!=1.1 || $val2!=1.2 || $val3!=1.3} {
        append finalResults "$testProgramName\n$execute1\ncavput -deltaMode test failed\n"
        return 0 
    }
    optionsPassed -pass {deltaMode}
    set execute "$testProgramName -list=shang:casave=1 -pend=10"
    if [catch {eval exec $execute} results] {
        append finalResults "$testProgramName\n$execute1\n$results"
        return 0  
    }
    set execute "$testProgramName -list=shang:casave=-1 -deltaMode -numerical -pend=10"
    if [catch {eval exec $execute} results] {
        append finalResults "$testProgramName\n$execute\n$results"
        return 0  
    }
    set execute1 "cavget -list=shang:casave -pend=10 -numerical"
    if [catch {eval exec $execute1} results] {
        append finalResults "$testProgramName\n$execute1\n$results"
        return 0  
    }
    if {$results !=0} {
        append finalResults "$testProgramName\n$execute\ncavput -numerical option failed"
        return 0  
    }
    optionsPassed -pass {numerical}
    
    #shang:h2:setCurrentC does not exist
    set execute "$testProgramName -list=shang:H1:setCurrentC=1,shang:h2:setCurrentC=0 -blunderAhead=silently"
    if [catch {eval exec $execute} results] {
        append finalResults "$testProgramName\n$execute\n$results"
        return 0  
    }
    if [catch {exec cavget -list=shang:H1:setCurrentC -pend=10} result] {
        append finalResults "$testProgramName\n$execute\n$result"
        return 0  
    }
    if {$result!=1} {
        append finalResults "$testProgramName\n$execute\ncavput with -blunderAhead option failed"
        return 0  
    }
    optionsPassed -pass {blunderAhead}
    
    #ramp option test
    
    return 1
}

proc cavput_list_test {args} {
    APSStrictParseArguments {testProgramName inDir outFile}
    global finalResults

    set list "-list=shang -list=:V1:setCurrentC=-1.0,:H2:setCurrentC=2,:V2:setCurrentC=2"
    set execute "$testProgramName $list -pend=10"
    if [catch {eval exec $execute} results] {
        append finalResults "$testProgramName\n$execute\n$results\n"
        return 0
    }
    set list "-list=shang -list=:V1:setCurrentC,:H2:setCurrentC,:V2:setCurrentC"
    set execute1 "cavget $list -pend=10"
    if [catch {eval exec $execute1} results] {
        append finalResults "$testProgramName\n$execute1\n$results\n"
        return 0
    }
    set values {-1.0 2.0 2.0}
    foreach val1 $values val2 $results {
        if {$val1 != $val2} {
            append finalResults "cavput value $val1 != cavget value $val2: cavput failed.\n$execute"
            return 0
        }
    }
    set list "-list=shang=0 -list=:V1:setCurrentC,:H2:setCurrentC=2,:V2:setCurrentC=2"
    set execute "$testProgramName $list -pend=10"
    if [catch {eval exec $execute} results] {
        append finalResults "$testProgramName\n$execute\n$results\n"
        return 0
    }
    set list "-list=shang -list=:V1:setCurrentC,:H2:setCurrentC,:V2:setCurrentC"
    set execute1 "cavget $list -pend=10"
    if [catch {eval exec $execute1} results] {
        append finalResults "$testProgramName\n$execute1\n$results\n"
        return 0
    }
    set values {0 2.0 2.0}
    foreach val1 $values val2 $results {
        if {$val1 != $val2} {
            append finalResults "cavput value $val1 != cavget value $val2: cavput failed.\n$execute"
            return 0
        }
    }
    set list "-list=shang=0 -list=:V1,:H1,:H2 -list=:setCurrentC"
    set execute "$testProgramName $list -pend=10"
    if [catch {eval exec $execute} results] {
        append finalResults "$testProgramName\n$execute\n$results\n"
        return 0
    }
    set list "-list=shang -list=:V1,:H1,:H2 -list=:setCurrentC"
    set execute1 "cavget $list -pend=10"
    if [catch {eval exec $execute} results] {
        append finalResults "$testProgramName\n$execute1\n$results\n"
        return 0
    }
    foreach val $results {
        if {$val !=0} {
            append finalResults "$val (should be 0), cavput failed"
            return 0
        }
    }
    
    set list "-list=shang -list=:V1,:H1,:H2 -list=:setCurrentC=1"
    set execute "$testProgramName $list -pend=10"
    if [catch {eval exec $execute} results] {
        append finalResults "$testProgramName\n$execute\n$results\n"
        return 0
    }
    set list "-list=shang -list=:V1,:H1,:H2 -list=:setCurrentC"
    set execute1 "cavget $list -pend=10"
    if [catch {eval exec $execute} results] {
        append finalResults "$testProgramName\n$execute1\n$results\n"
        return 0
    }
    foreach val $results {
        if {$val !=1.0} {
            append finalResults "$val (should be 1.0), cavput failed.\n\$execute"
            return 0
        }
    }

    set list "-list=shang -list=:V1=-0.5,:H1=0.5,:H2=1.0 -list=:setCurrentC"
    set execute "$testProgramName $list -pend=10"
    if [catch {eval exec $execute} results] {
        append finalResults "$testProgramName\n$execute\n$results\n"
        return 0
    }
    
    set list "-list=shang -list=:V1,:H1,:H2 -list=:setCurrentC"
    set execute1 "cavget $list -pend=10"
    if [catch {eval exec $execute1} results] {
        append finalResults "$testProgramName\n$execute1\n$results\n"
        return 0
    }
    
    set values {-0.5 0.5 1.0}
    foreach val1 $values val2 $results {
        if {$val2 !=$val1} {
            append finalResults "$val2 (should be $val1), cavput failed.\n$execute"
            return 0
        }
    }
    return 1
}

proc cavget_list_test {args} {
    APSStrictParseArguments {testProgramName}
    global finalResults

    set execute "caput shang:V1:setCurrentC,shang:H2:setCurrentC,shang:V2:setCurrentC -1.0,2.0,2.0"
    if [catch {eval exec $execute} results] {
        append finalResults "caput\n$execute\n$results\n"
        return 0
    }
    set execute1 "$testProgramName -list=shang: -list=V1,H2,V2 -list=:setCurrentC -pend=10"
    set execute2 "$testProgramName -list=shang:V1:setCurrentC,shang:H2:setCurrentC,shang:V2:setCurrentC -pend=10"
    set execute3 "$testProgramName -list=shang -list=:V1:setCurrentC,:H2:setCurrentC,:V2:setCurrentC -pend=10"
    set values {-1.0 2.0 2.0}
    for {set index 1} {$index<4} {incr index} {
        set execute [set execute$index]
        if [catch {eval exec $execute} results] {
            append finalResults "$testProgramName\n$execute\n$results\n"
            return 0
        }
        foreach val1 $values val2 $results {
            if {$val1 != $val2} {
                append finalResults "cavget value $val2 != caput value $val1: $testProgramName failed.\n$execute"
                return 0
            }
        }
    }
    
    return 1
}

proc test_cavget {args} {
    APSStrictParseArguments {testProgramName inDir outFile}
    global finalResults env

    set env(EPICS_CA_ADDR_LIST) "164.54.188.65 164.54.50.58"
    set results [cavget_list_test -testProgramName $testProgramName]
    if !$results {
        set env(EPICS_CA_ADDR_LIST) "164.54.50.58 127.0.0.1 "
        return 0
    }
    optionsPassed -pass {list}
    set list "-list=S -range=beg=2,end=5 -list=A:H1,A:H2 -list=:InUseMBBO"
    set execute "$testProgramName -pend=30 $list"
    if [catch {eval exec $execute} results] {
        append finalResults "$testProgramName\n$execute\n$results\n"
        set env(EPICS_CA_ADDR_LIST) "164.54.50.58 127.0.0.1 "
        return 0
    }
    set execute1 "$testProgramName -pend=10 $list -dryRun"
    if [catch {eval exec $execute1} pvList] {
        append finalResults "$testProgramName\n$execute1\n$pvList\n"
        set env(EPICS_CA_ADDR_LIST) "164.54.50.58 127.0.0.1 "
        return 0
    }
    set execute2 "caget [join $pvList ] -t"
    if [catch {eval exec $execute2} values] {
        append finalResults "$testProgramName\n$execute2\n$values\n"
        set env(EPICS_CA_ADDR_LIST) "164.54.50.58 127.0.0.1 "
        return 0
    }
    set values [split $values "\n"]
    foreach val1 $results val2 $values pv $pvList {
        #remove the empty space after the last character of caget value
        set len [string length $val2]
        set val2 [string range $val2 0 [expr $len -2]]
        if [string compare $val1 $val2]!=0 {
            append finalResults "$testProgramName: cavget value ($val1) !=caget value ($val2) (pv: $pv)"
            set env(EPICS_CA_ADDR_LIST) "164.54.50.58 127.0.0.1 "
            return 0
        }
    }
    optionsPassed -pass {range dryRun}
    
    set execute "$testProgramName -pend=30 $list -numerical"
    if [catch {eval exec $execute} results] {
        append finalResults "$testProgramName\n$execute\n$results\n"
        set env(EPICS_CA_ADDR_LIST) "164.54.50.58 127.0.0.1 "
        return 0
    }
    set execute2 "caget [join $pvList ] -t -n"
    if [catch {eval exec $execute2} values] {
        append finalResults "$testProgramName\n$execute2\n$values\n"
        set env(EPICS_CA_ADDR_LIST) "164.54.50.58 127.0.0.1 "
        return 0
    }
    foreach val1 $results val2 $values pv $pvList {
        if {$val1!=$val2} {
            append finalResults "$testProgramName: cavget value ($val1) !=caget value ($val2) (pv: $pv)"
            set env(EPICS_CA_ADDR_LIST) "164.54.50.58 127.0.0.1 "
            return 0
        }
    }
    optionsPassed -pass {numerical}
    set test [cavget_statistics_test -testProgramName $testProgramName]
    if !$test {
        return 0
    }
    optionsPassed -pass {statistics repeat}

    set list1 "-numerical -list=SRFB:S -range=beg=5,end=10 -list=B:P1:y:IncludeInRmsC -labeled -embrace"
    set list2 "-list=SRFB:S -range=beg=5,end=10 -list=B:P1:y:IncludeInRmsC -labeled -embrace"
    
    foreach comm {list1 list2} {
        set com1 "cavget [set $comm] -pend=30"
        set com2 "$testProgramName [set $comm] -pend=10"
        if [catch {eval exec $com1} result1] {
            append finalResults "$testProgramName\n$com1\$result1"
            return 0
        }
        if [catch {eval exec $com2} result2] {
            append finalResults "$testProgramName\n$com2\n$result2"
            return 0
        }
        if [string compare $result1 $result2] {
            append finalResults "$testProgramName\n$com2\n(from official version:)$result1\n(from current version:)$result2"
            return 0
        } 
    }
    optionsPassed -pass {labeled embrace pendIOTime}
    
    set execute "cavget -list=A014-IETS:BTC:SRSetFreqM -floatFormat=%21.15e"
    if [catch {eval exec $execute} refFreq] {
        append finalResults "cavget\n$execute\n$refFreq"
        return 0
    }
    set execute "$testProgramName -list=A014-IETS:BTC:SRSetFreqM -floatFormat=%21.15e"
    if [catch {eval exec $execute} results] {
        append finalResults "$testProgramName\n$execute\n$results"
        return 0
    }
    if {$results!=$refFreq} {
        append finalResults "$testProgramName\n$execute\n(official value)$refFreq != (current value)$results"
        return 0
    }
    optionsPassed -pass {floatFormat}
    
    set execute "$testProgramName -list=S10A:H1:InUseMBBO -noQuotes -pend=30"
    if [catch {eval exec $execute} results] {
        append finalResults "$testProgramName\n$execute\n$results"
        return 0
    }
    if {[string compare [string range $results 0 0] "\""]==0 || \
          [string compare [string range $results end end] "\""]==0 } {
        append finalResults "$testProgramName\n$execute\n$results"
        return 0
    }
    optionsPassed -pass {noQuotes}
    set execute "$testProgramName -list=S -range=begin=1,end=3 -list=A:H1:InUseMBBO \"-delimiter=;\" -pend=10"
    if [catch {eval exec $execute} results] {
        append finalResults "$testProgramName\n$execute\n$results"
        return 0
    }
    set execute1 "$testProgramName -list=S -range=begin=1,end=3 -list=A:H1:InUseMBBO -pend=30"
    if [catch {eval exec $execute1} results1] {
        append finalResults "$testProgramName\n$execute1\n$results1"
        return 0
    }
    regsub -all "\"" $results "" removed
    set results1 [join $results1 ";"]
    if [string compare $removed $results1]!=0 {
        append finalResults "$testProgramName\n$execute\n$results"
        return 0
    }
    optionsPassed -pass {delimiter}
    set test [cavget_putForm_test  -testProgramName $testProgramName]
    if !$test {
        return 0
    }
    optionsPassed -pass {cavputForm}

    #SA:H1:SetCurrentAO pv does not exist"
    set execute "$testProgramName -list=SA:H1:SetCurrentAO -errorValue=-999"
    if [catch {eval exec $execute} results] {
        append finalResults "$testProgramName\n$execute\n$results"
        return 0
    }
    if {$results !=-999} {
        append finalResults "$testProgramName\n$execute\nThe value should be -999."
        return 0
    }

    #SQ:H pv does not exist
    #return value should be: 
    #SQ:H -999
    #S1A:H1:CurrentAO -0.0297551    
    set execute "$testProgramName -list=SQ:H,S1A:H1:CurrentAO -label -errorValue=-999"
    if [catch {eval exec $execute} results] {
        append finalResults "$testProgramName\n$execute\n$results"
        return 0
    }
    array set pvValue $results
    if {$pvValue(SQ:H)!=-999} {
        append finalResults "$testProgramName\n$execute\nThe value should be -999."
        return 0
    }
    set execute "$testProgramName -list=SQ:H,S1A:H1:CurrentAO -label -errorValue=-999 -excludeErrors"
    if [catch {eval exec $execute} results] {
        append finalResults "$testProgramName\n$execute\n$results"
        return 0
    }
    array set pvValue1 $results
    if [info exist pvValue1(SQ:H)] {
        append finalResults "$testProgramName\n$execute\nThe value of SQ:H should been removed with -excludeErrors option"
        return 0
    }
    optionsPassed -pass {errorValue excludeErrors}
    return 1
}

proc cavget_statistics_test {args} {
    APSStrictParseArguments {testProgramName inDir outFile}
    global finalResults
    
    APSSetVarAndUpdate status "$testProgramName statistics test ..."
    set exec1 "-list=shang:PM1:X:positionM,shang:PM1:Y:positionM \
       -statis=n=3,pause=0.1,format=pretty -label -pend=30"
    set exec2 "-list=shang:PM -range=begin=1,end=5 -list=:X,:Y -list=:positionM \
         -statis=n=3,pause=0.1,format=SDDS,file=tmp1 -label -pend=30"
    set exec3 "-list=shang:PM -range=begin=1,end=5 -list=:X,:Y -list=:positionM \
         -statis=n=3,pause=0.1,format=SDDS,file=tmp1 -label -pend=30"
    set exec3 "-list=shang:PM -range=begin=1,end=5 -list=:X,:Y -list=:positionM \
         -statis=n=3,pause=0.1,format=pretty -label -pend=30"
    set exec4 "-list=shang:PM -range=begin=1,end=5 -list=:X,:Y -list=:positionM \
         -statis=n=3,pause=0.1,format=tag -pend=30"
    set exec5 "-list=shang:PM -range=begin=1,end=5 -list=:intensityM \
            -statis=n=10,pause=0.1,format=pretty -pend=30"
    set exec6 "-list=shang: -list=V,H -range=begin=1,end=5 -list=:setCurrentC \
        -repeat=n=10,pause=0.1,ave -pend=30 -label"
    set exec7 "-list=shang: -list=V,H -range=begin=1,end=5 -list=:setCurrentC \
        -repeat=n=10,pause=0.1,ave,sig -pend=30 -label"
    for {set index 1} {$index < 8} {incr index} {
        set com [set exec$index]
        set com1 "cavget $com"
        set com2 "$testProgramName $com"
        if [catch {eval exec $com1} result1] {
            append finalResults "$testProgramName\n$com1\n$result1"
            return 0
        } 
        if [catch {eval exec $com2} result2] {
            append finalResults "$testProgramName\n$com2\n$result2"
            return 0
        }
        if {$index>5} {
            if [string compare $result1 $result2] {
                append finalResults "$testProgramName\n$com2\n(from official version:)$result1\n(from current version:)$result2"
                return 0
            } 
        }
    }
    APSSetVarAndUpdate status "$testProgramName statistics test done."
    return 1
}

proc cavget_putForm_test {args} {
    APSStrictParseArguments {testProgramName inDir outFile}
    global finalResults

    set list1 "-list=shang:H1:setCurrentC -pend=10 -repeat=number=3,pause=0.1,average -cavputForm"
    set list2 "-list=shang: -list=H1,H2,V1,V2 -list=:setCurrentC -pend=10 -repeat=number=3,pause=0.1,average -cavputForm"
    set list3 "-list=shang: -list=H1,H2,V1,V2 -list=:setCurrentC -pend=10 -cavputForm"
    
    foreach comm {list1 list2 list3} {
        set execute "cavget [set $comm]"
        set execute1 "$testProgramName [set $comm]"
        if [catch {eval exec $execute} results] {
            append finalResults "cavget\n$execute\n$results"
            return 0
        }
        if [catch {eval exec $execute1} results1] {
            append finalResults "$testProgramName\n$execute1\n$results1"
            return 0
        }
        if [string compare $results $results1] {
            append finalResults "$testProgramName\n$execute1\n$results1"
            return 0
        }
    }
    return 1
}

proc test_sddssynchlog {args} {
    APSStrictParseArguments {testProgramName inDir outFile}
    global finalResults
    set standardFile ${inDir}sddssynchlog.output
    set execute "$testProgramName ${inDir}sddssynchlog.input $outFile -samples=60 -timeLimit=100 -verbose -synchinterval=.02 -eraseFile -comment=Test,test"
    if [catch {eval exec $execute} results] {
	if {[string compare [lindex [split $results \n] end] "60 aligned samples found"]!=0} {
	    append finalResults "$testProgramName\n$execute\n$results\n"
	    return 0
	}
    }
    set valid 0
    compareOutput -testProgramName $testProgramName -execute $execute \
	-standardFile $standardFile -testFile $outFile
    if {$valid} {
	optionsPassed -pass {samples timeLimit verbose synchinterval comment}
	set standardFile ${inDir}sddssynchlog.output2
	set execute "$testProgramName ${inDir}sddssynchlog.input $outFile -samples=60 -timeLimit=100 -verbose -synchinterval=.02 -eraseFile -comment=Test,test -precision=single -slowData=${inDir}sddssynchlog.input2 -pendEventTime=1 -connectTimeout=10"
	if [catch {eval exec $execute} results] {
	    if {[string compare [lindex [split $results \n] end] "60 aligned samples found"]!=0} {
		append finalResults "$testProgramName\n$execute\n$results\n"
		return 0
	    }
	}
	set valid 0
	compareOutput -testProgramName $testProgramName -execute $execute \
	    -standardFile $standardFile -testFile $outFile
	if {$valid} {
	    optionsPassed -pass {eraseFile precision slowData pendEventTime connectTimeout}
	    return 1
	}
    }
    return 0
}

proc test_sddssnapshot {args} {
    APSStrictParseArguments {testProgramName inDir outFile}
    global finalResults
    set standardFile ${inDir}sddssnapshot.output
    set execute "sddsconvert ${inDir}sddssnapshot.input -pipe=out | $testProgramName -pipe=in $outFile -ezcaTiming=.5,2 -unitsOfData=mA -nameOfData=TestData -average=5,.2"
    if [catch {eval exec $execute} results] {
	append finalResults "$testProgramName\n$execute\n$results\n"
	return 0
    }
    set valid 0
    compareOutput -testProgramName $testProgramName -execute $execute \
	-standardFile $standardFile -testFile $outFile
    if {$valid} {
	optionsPassed -pass {pipe ezcaTiming unitsOfData nameOfData average}
	return 1
    }
    return 0
}

proc test_sddslogger {args} {
    APSStrictParseArguments {testProgramName inDir outFile}
    global finalResults
    set standardFile ${inDir}sddslogger.output
    set execute "$testProgramName ${inDir}sddslogger.input $outFile -sampleInterval=.3,seconds -logInterval=2 -steps=30 -pendIOtime=2 -verbose"
    if [catch {eval exec $execute} results] {
	append finalResults "$testProgramName\n$execute\n$results\n"
	return 0
    }
    set valid 0
    compareOutput -testProgramName $testProgramName -execute $execute \
	-standardFile $standardFile -testFile $outFile
    if {$valid} {
	optionsPassed -pass {sampleInterval logInterval steps pendIOtime verbose}
	file delete $outFile
	set standardFile ${inDir}sddslogger.output2
	set execute "$testProgramName ${inDir}sddslogger.input $outFile -time=10 -enforceTimeLimit -offsetTimeOfDay -precision=single -onerror=usezero"
	if [catch {eval exec $execute} results] {
	    append finalResults "$testProgramName\n$execute\n$results\n"
	    return 0
	}
	set valid 0
	compareOutput -testProgramName $testProgramName -execute $execute -standardFile $standardFile -testFile $outFile
	if {$valid} {
	    optionsPassed -pass {time enforceTimeLimit offsetTimeOfDay precision onerror}
	    return 1
	}
    }
    return 0
}

proc test_sddsmonitor {args} {
    APSStrictParseArguments {testProgramName inDir outFile}
    global finalResults
    set standardFile ${inDir}sddsmonitor.output
    set execute "$testProgramName ${inDir}sddsmonitor.input $outFile -interval=.3,seconds -updateinterval=2 -steps=30 -pendIOtime=2 -verbose -comment=Test,test"
    if [catch {eval exec $execute} results] {
	append finalResults "$testProgramName\n$execute\n$results\n"
	return 0
    }
    set valid 0
    compareOutput -testProgramName $testProgramName -execute $execute \
	-standardFile $standardFile -testFile $outFile
    if {$valid} {
	optionsPassed -pass {interval updateinterval steps pendIOtime verbose comment}
	set standardFile ${inDir}sddsmonitor.output2
	set execute "$testProgramName ${inDir}sddsmonitor.input $outFile -time=10 -enforceTimeLimit -offsetTimeOfDay -precision=single -erase -oncaerror=usezero"
	if [catch {eval exec $execute} results] {
	    append finalResults "$testProgramName\n$execute\n$results\n"
	    return 0
	}
	set valid 0
	compareOutput -testProgramName $testProgramName -execute $execute -standardFile $standardFile -testFile $outFile
	if {$valid} {
	    optionsPassed -pass {time enforceTimeLimit offsetTimeOfDay precision erase oncaerror}
	    return 1
	}
    }
    return 0
}

proc test_sddsexperiment {args} {
    APSStrictParseArguments {testProgramName inDir outFile}
    global finalResults
    set standardFile ${inDir}sddsexperiment.output
    set execute "sddsexperiment ${inDir}sddsexperiment.input $outFile"
    if [catch {eval exec $execute} results] {
	set temp [split $results \n]
	if {([lindex [lindex $temp 0] 0] != "Ramping") || 
	    ([lindex [lindex $temp 1] 0] != "Done") || 
	    ([lindex [lindex $temp 2] 0] != "Storing") || 
	    ([llength $temp] != 3)} {
	    append finalResults "$testProgramName\n$execute\n$results\n"
	    return 0
	}
    }
    if [catch {sdds load ${inDir}sddsexperiment.output standardFile} results] {
	append finalResults "$testProgramName\nunable to open ${inDir}sddsexperiment.output\n$results\n"
	return 0
    }
    if [catch {sdds load $outFile testFile} results] {
	append finalResults "$testProgramName\nunable to open $outFile\n$results\n"
	return 0
    }
    foreach value1 [lindex $standardFile(Column.oag:PM1:X:positionM) 0] \
	value2 [lindex $testFile(Column.oag:PM1:X:positionM) 0] {
	if {[expr abs($value1 - $value2)] > 5} {
	    append finalResults "$testProgramName\ncolumn oag:PM1:X:positionM is different from standard file\n"
	    return 0
	}
    }
    return 1
}

proc test_sddsvexperiment {args} {
    APSStrictParseArguments {testProgramName inDir outFile}
    global finalResults
    set standardFile ${inDir}sddsvexperiment.output
    set execute "sddsvexperiment ${inDir}sddsvexperiment.input $outFile"
    if [catch {eval exec $execute} results] {
	set temp [split $results \n]
	if {([lindex [lindex $temp 0] 0] != "Storing") || ([lindex [lindex $temp 1] 0] != "Ramping") || ([lindex [lindex $temp 2] 0] != "Done") || ([llength $temp] != 3)} {
	    append finalResults "$testProgramName\n$execute\n$results\n"
	    return 0
	}
    }
    set valid 0
    compareOutput -testProgramName $testProgramName -execute $execute \
	-standardFile $standardFile -testFile $outFile
    if {$valid} {
	file delete $outFile
	set execute "sddsvexperiment ${inDir}sddsvexperiment.input2 $outFile -suffixFile=${inDir}sddsvexperiment.suffix -rootnameFile=${inDir}sddsvexperiment.root"
	if [catch {eval exec $execute} results] {
	    set temp [split $results \n]
	    if {([lindex [lindex $temp 0] 0] != "Storing") || ([lindex [lindex $temp 1] 0] != "Ramping") || ([lindex [lindex $temp 2] 0] != "Done") || ([llength $temp] != 3)} {
		append finalResults "$testProgramName\n$execute\n$results\n"
		return 0
	    }
	}
	set valid 0
	compareOutput -testProgramName $testProgramName -execute $execute \
	    -standardFile $standardFile -testFile $outFile
	if {$valid} {
	    optionsPassed -pass {suffixFile rootnameFile}
	    return 1
	}
    }
    return 0
}

proc test_sddsstatmon {args} {
    APSStrictParseArguments {testProgramName inDir outFile}
    global finalResults
    set standardFile ${inDir}sddsstatmon.output
    set execute "$testProgramName ${inDir}sddsstatmon.input $outFile -interval=.3,seconds -includeStatistics=mean -samplesPerStatistic=2 -steps=30 -verbose"
    if [catch {eval exec $execute} results] {
	append finalResults "$testProgramName\n$execute\n$results\n"
	return 0
    }
    set valid 0
    compareOutput -testProgramName $testProgramName -execute $execute \
	-standardFile $standardFile -testFile $outFile
    if {$valid} {
	optionsPassed -pass {interval includeStatistics samplePerStatistic steps verbose}
	set standardFile ${inDir}sddsstatmon.output2
	set execute "$testProgramName ${inDir}sddsstatmon.input $outFile -time=10 -enforceTimeLimit -offsetTimeOfDay -precision=single -oncaerror=repeat -comment=Test,test -getUnits=force -updateInterval=2 -erase"
	if [catch {eval exec $execute} results] {
	    append finalResults "$testProgramName\n$execute\n$results\n"
	    return 0
	}
	set valid 0
	compareOutput -testProgramName $testProgramName -execute $execute \
	    -standardFile $standardFile -testFile $outFile
	if {$valid} {
	    optionsPassed -pass {time enforceTimeLimit offsetTimeOfDay precision oncaerror comment getUnits updateInterval erase}
	    return 1
	}
    }
    return 0
}

proc test_sddsvmonitor {args} {
    APSStrictParseArguments {testProgramName inDir outFile}
    global finalResults
    set standardFile ${inDir}sddsvmonitor.output
    set execute "$testProgramName ${inDir}sddsvmonitor.input $outFile -interval=.3,seconds -steps=30 -verbose -comment=Test,test -logDuplicates=countThreshold=0"
    if [catch {eval exec $execute} results] {
	append finalResults "$testProgramName\n$execute\n$results\n"
	return 0
    }
    set valid 0
    compareOutput -testProgramName $testProgramName -execute $execute \
	-standardFile $standardFile -testFile $outFile
    if {$valid} {
	optionsPassed -pass {interval steps verbose comment logDuplicates}
	set standardFile ${inDir}sddsvmonitor.output2
	set execute "$testProgramName -rootnames=${inDir}sddsvmonitor.root -suffixes=${inDir}sddsvmonitor.suffix $outFile -time=10 -enforceTimeLimit -offsetTimeOfDay -precision=single -erase -onCAerror=useZero -logDuplicates=countThreshold=0"
	if [catch {eval exec $execute} results] {
	    append finalResults "$testProgramName\n$execute\n$results\n"
	    return 0
	}
	set valid 0
	compareOutput -testProgramName $testProgramName -execute $execute \
	    -standardFile $standardFile -testFile $outFile
	if {$valid} {
	    optionsPassed -pass {rootnames suffixes time enforceTimeLimit offsetTimeOfDay precision erase onCAerror}
	    return 1
	}
    }
    return 0
}

proc test_sddswmonitor {args} {
    set returnValue 1
    global finalResults
    APSSetVarAndUpdate status "Testing for this program is not available yet."
    return $returnValue
}

proc test_squishPVs {args} {
    APSStrictParseArguments {testProgramName inDir outFile}
    global finalResults
    if [catch {exec sddscasr -restore ${inDir}squishPVs.snap} results] {
	append finalResults "$testProgramName\nunable to run burtwb\n$results\n"
	return 0
    }
    APSWaitWithUpdate -waitSeconds 3
    set execute "$testProgramName ${inDir}squishPVs.input -stepSize=.5 -settlingTime=.2 -subdivisions=6,2 -averages=2,.1"
    if [catch {eval exec $execute} results] {
	append finalResults "$testProgramName\n$execute\n$results\n"
	return 0
    }
    if [catch {exec cavget -list=oag:H1:setCurrentC} current] {
	append finalResults "$testProgramName\nunable to run cavget\n$current\n"
	return 0
    }
    if {($current < -1.2) && ($current > -1.4)} {
	optionsPassed -pass {stepSize settlingTime subdivisions averages}
	return 1
    }
    append finalResults "$testProgramName\noag:H1:setCurrentC is not close to -1.3 where it should be"
    return 0
}

proc test_sddscontrollaw {args} {
    APSStrictParseArguments {testProgramName inDir outFile}
    global finalResults
    if [catch {exec sddscasr -restore ${inDir}sddscontrollaw.snap} results] {
	append finalResults "$testProgramName\nunable to run burtwb\n$results\n"
	return 0
    }
    APSWaitWithUpdate -waitSeconds 3
    set execute "$testProgramName ${inDir}sddscontrollaw.inv -interval=1 -steps=10 -gain=.75"
    if [catch {eval exec $execute} results] {
	append finalResults "$testProgramName\n$execute\n$results\n"
	return 0
    }
    if [catch {exec cavget -list=oag:H1:setCurrentC,oag:H2:setCurrentC,oag:H4:setCurrentC,oag:H5:setCurrentC} currents] {
	append finalResults "$testProgramName\nunable to run cavget\n$currents\n"
	return 0
    }
    if {!(([lindex $currents 0] < -1.15) && 
	  ([lindex $currents 0] > -1.45) && 
	  ([lindex $currents 1] < 2.75) && 
	  ([lindex $currents 1] > 2.3) && 
	  ([lindex $currents 2] < 1.8) && 
	  ([lindex $currents 2] > 1.50) && 
	  ([lindex $currents 3] < -1.65) && 
	  ([lindex $currents 3] > -1.95))} {
	append finalResults "$testProgramName\nCurrent setpoints are not where they are suppose to be"
	return 0
    }
    optionsPassed -pass {interval steps gain}
    if [catch {exec sddscasr -restore ${inDir}sddscontrollaw.snap} results] {
	append finalResults "$testProgramName\nunable to run burtwb\n$results\n"
	return 0
    }
    APSWaitWithUpdate -waitSeconds 3
    set execute "$testProgramName ${inDir}sddscontrollaw.inv2 -interval=1 -steps=10 -gain=.75 -controlQuantityDefinition=${inDir}sddscontrollaw.cqdf -testValues=${inDir}sddscontrollaw.test -despike -average=3,interval=.1"
    if [catch {eval exec $execute} results] {
	append finalResults "$testProgramName\n$execute\n$results\n"
	return 0
    }
    if [catch {exec cavget -list=oag:H1:setCurrentC,oag:H2:setCurrentC,oag:H4:setCurrentC,oag:H5:setCurrentC} currents] {
	append finalResults "$testProgramName\nunable to run cavget\n$currents\n"
	return 0
    }
    if {!(([lindex $currents 0] < -1.15) && 
	  ([lindex $currents 0] > -1.45) && 
	  ([lindex $currents 1] < 2.75) && 
	  ([lindex $currents 1] > 2.3) && 
	  ([lindex $currents 2] < 1.8) && 
	  ([lindex $currents 2] > 1.50) && 
	  ([lindex $currents 3] < -1.65) && 
	  ([lindex $currents 3] > -1.95))} {
	append finalResults "$testProgramName\nCurrent setpoints are not where they are suppose to be"
	return 0
    }
    optionsPassed -pass {controlQuantityDefinition despike average}
    if [catch {exec sddscasr -restore ${inDir}sddscontrollaw.snap} results] {
	append finalResults "$testProgramName\nunable to run burtwb\n$results\n"
	return 0
    }
    APSWaitWithUpdate -waitSeconds 1
    set execute "$testProgramName ${inDir}sddscontrollaw.inv -interval=1 -steps=5 -testValues=${inDir}sddscontrollaw.test2"
    if [catch {eval exec $execute} results] {
	append finalResults "$testProgramName\n$execute\n$results\n"
	return 0
    }
    if [catch {exec cavget -list=oag:H1:setCurrentC} currents] {
	append finalResults "$testProgramName\nunable to run cavget\n$currents\n"
	return 0
    }
    if {($currents < -2.01) || ($currents > -1.99)} {
	append finalResults "$testProgramName\nCurrent setpoints are not where they are suppose to be"
	return 0
    }
    optionsPassed -pass {testValues}
    if [catch {exec sddscasr -restore /home/oxygen/SOLIDAY/epics/iocapps/burt/linac_1_oag.snap} results] {
	append finalResults "$testProgramName\nunable to run burtwb\n$results\n"
	return 0
    }
    APSWaitWithUpdate -waitSeconds 1
    set execute "$testProgramName ${inDir}sddscontrollaw.inv -interval=1 -steps=15 -gain=1.2 -holdPresentValues &"
    if [catch {eval exec $execute} results] {
	append finalResults "$testProgramName\n$execute\n$results\n"
	return 0
    }
    APSWaitWithUpdate -waitSeconds 2
    if [catch {exec sddscasr -restore ${inDir}sddscontrollaw.snap} results] {
	append finalResults "$testProgramName\nunable to run burtwb\n$results\n"
	return 0
    }
    APSWaitWithUpdate -waitSeconds 15
    if [catch {exec cavget -list=oag:H1:setCurrentC,oag:H2:setCurrentC,oag:H4:setCurrentC,oag:H5:setCurrentC} currents] {
	append finalResults "$testProgramName\nunable to run cavget\n$currents\n"
	return 0
    }
    if {!(([lindex $currents 0] < -1.15) && 
	  ([lindex $currents 0] > -1.45) && 
	  ([lindex $currents 1] < 2.75) && 
	  ([lindex $currents 1] > 2.3) && 
	  ([lindex $currents 2] < 1.8) && 
	  ([lindex $currents 2] > 1.50) && 
	  ([lindex $currents 3] < -1.65) && 
	  ([lindex $currents 3] > -1.95))} {
	append finalResults "$testProgramName\nCurrent setpoints are not where they are suppose to be"
	return 0
    }
    optionsPassed -pass {holdPresentValues}
    if [catch {exec sddscasr -restore ${inDir}sddscontrollaw.snap} results] {
	append finalResults "$testProgramName\nunable to run burtwb\n$results\n"
	return 0
    }
    APSWaitWithUpdate -waitSeconds 3
    set execute "$testProgramName ${inDir}sddscontrollaw.inv -interval=1 -steps=15 -gain=1.1 -deltaLimit=value=.8 -readbackLimit=minValue=-.8,maxValue=.8 -actionLimit=value=.01"
    if [catch {eval exec $execute} results] {
	append finalResults "$testProgramName\n$execute\n$results\n"
	return 0
    }
    if [catch {exec cavget -list=oag:H1:setCurrentC,oag:H2:setCurrentC,oag:H4:setCurrentC,oag:H5:setCurrentC} currents] {
	append finalResults "$testProgramName\nunable to run cavget\n$currents\n"
	return 0
    }
    if {!(([lindex $currents 0] < -1.15) && 
	  ([lindex $currents 0] > -1.45) && 
	  ([lindex $currents 1] < 2.75) && 
	  ([lindex $currents 1] > 2.3) && 
	  ([lindex $currents 2] < 1.8) && 
	  ([lindex $currents 2] > 1.50) && 
	  ([lindex $currents 3] < -1.65) && 
	  ([lindex $currents 3] > -1.95))} {
	append finalResults "$testProgramName\nCurrent setpoints are not where they are suppose to be"
	return 0
    }
    optionsPassed -pass {deltaLimit readbackLimit actionLimit}
    if 0 {
    if [catch {exec sddscasr -restore ${inDir}sddscontrollaw.snap} results] {
	append finalResults "$testProgramName\nunable to run burtwb\n$results\n"
	return 0
    }
    APSWaitWithUpdate -waitSeconds 3
    set execute "$testProgramName ${inDir}sddscontrollaw.inv -interval=1 -steps=15 -gain=1.1 -offsets=${inDir}sddscontrollaw.offsets"
    if [catch {eval exec $execute} results] {
	append finalResults "$testProgramName\n$execute\n$results\n"
	return 0
    }
    if [catch {exec cavget -list=oag:H1:setCurrentC,oag:H2:setCurrentC,oag:H4:setCurrentC,oag:H5:setCurrentC} currents] {
	append finalResults "$testProgramName\nunable to run cavget\n$currents\n"
	return 0
    }
    if {!(([lindex $currents 0] < -1.15) && 
	  ([lindex $currents 0] > -1.45) && 
	  ([lindex $currents 1] < 2.75) && 
	  ([lindex $currents 1] > 2.3) && 
	  ([lindex $currents 2] < 1.8) && 
	  ([lindex $currents 2] > 1.50) && 
	  ([lindex $currents 3] < -1.65) && 
	  ([lindex $currents 3] > -1.95))} {
	append finalResults "$testProgramName\nCurrent setpoints are not where they are suppose to be"
	return 0
    }
    optionsPassed -pass {deltaLimit readbackLimit actionLimit}
    }
    
    
    
    
    if [catch {exec sddscasr -restore /home/oxygen/SOLIDAY/epics/iocapps/burt/linac_1_oag.snap} results] {
	append finalResults "$testProgramName\nunable to run burtwb\n$results\n"
	return 0
    }
    APSWaitWithUpdate -waitSeconds 3
    return 1
}

proc test_sddsoptimize {args} {
    APSStrictParseArguments {testProgramName inDir outFile}
    global finalResults
    set execute "$testProgramName -varFile=${inDir}sddsoptimize.var.input -measFile=${inDir}sddsoptimize.meas.input -testValues=file=${inDir}sddsoptimize.test.input,limit=4 -runControlPV=string=oag:ControlLawRC -runControlDescription=string=test -simplex=evaluations=100 -maximize"
    if [catch {eval exec $execute} results] {
	set r [split $results \n]
	set i [expr [llength $r] - 3]
	if {[string compare [lindex $r $i] "The best parameters obtained is:"]!=0} {
	    append finalResults "$testProgramName\n$execute\n$results\n"
	    return 0
	}
    }
    if [catch {exec cavget -list=oag:H1:setCurrentC,oag:V1:setCurrentC} current] {
	append finalResults "$testProgramName\nunable to run cavget\n$current\n"
	return 0
    }
    if {([lindex $current 0] > -1.2) || ([lindex $current 0] < -1.4)} {
	append finalResults "$testProgramName\noag:H1:setCurrentC is not close to -1.3 where it should be"
	return 0
    }
    if {([lindex $current 1] > 1.9) || ([lindex $current 1] < 1.7)} {
	append finalResults "$testProgramName\noag:V1:setCurrentC is not close to 1.8 where it should be"
	return 0
    }
    optionsPassed -pass {varFile measFile testValues runControlPV runControlDescription verbose simplex maximize}

    set logFile /tmp/[APSTmpString].log
    APSAddToTempFileList $logFile
    set execute "$testProgramName -varFile=${inDir}sddsoptimize.var.input -measScript=${inDir}sddsoptimize.meas.script -testValues=file=${inDir}sddsoptimize.test.input,limit=4 -simplex=evaluations=100 -maximize -logFile=$logFile -tolerance=.1"
    if [catch {eval exec $execute} results] {
	set r [split $results \n]
	set i [expr [llength $r] - 3]
	if {[string compare [lindex $r $i] "The best parameters obtained is:"]!=0} {
	    append finalResults "$testProgramName\n$execute\n$results\n"
	    return 0
	}
    }
    if [catch {exec cavget -list=oag:H1:setCurrentC,oag:V1:setCurrentC} current] {
	append finalResults "$testProgramName\nunable to run cavget\n$current\n"
	return 0
    }
    if {([lindex $current 0] > -1.2) || ([lindex $current 0] < -1.4)} {
	append finalResults "$testProgramName\noag:H1:setCurrentC is not close to -1.3 where it should be"
	return 0
    }
    if {([lindex $current 1] > 1.9) || ([lindex $current 1] < 1.7)} {
	append finalResults "$testProgramName\noag:V1:setCurrentC is not close to 1.8 where it should be"
	return 0
    }
    optionsPassed -pass {measScript logFile tolerance}
    return 1
}

proc test_sddsglitchlogger {args} {
    APSStrictParseArguments {testProgramName inDir outFile}
    global finalResults
    set files [glob -nocomplain /tmp/oagPM1X*]
    if {[llength $files]} {
	eval file delete $files
    }
    if [catch {exec sddscasr -restore /home/oxygen/SOLIDAY/epics/iocapps/burt/linac_1_oag.snap} results] {
	append finalResults "$testProgramName\nunable to run burtwb\n$results\n"
	return 0
    }
    APSWaitWithUpdate -waitSeconds 1

#test 1
    set execute "$testProgramName ${inDir}sddsglitchlogger.input /tmp -circularBuffer=before=3,after=3 -time=10"
    if [catch {eval exec $execute} results] {
	set r [split $results \n]
	set fileNoAlarm [lindex [lindex $r end] end]
	set i [expr [llength $r] - 2]
	set fileMinorAlarm [lindex [lindex $r $i] end]
	incr i -1
	set fileMajorAlarm [lindex [lindex $r $i] end]
	foreach file "$fileNoAlarm $fileMinorAlarm $fileMajorAlarm" {
	    if {![file exists $file]} {
		append finalResults "$testProgramName\n$execute\n$results\n"
		return 0
	    }
	}
    }
    if {[catch {exec sdds2stream $fileNoAlarm -rows=bare,total} rowsNoAlarm]} {
	append finalResults "$testProgramName\nunable to run sdds2stream\n$rowsNoAlarm\n"
	return 0
    }
    if {[catch {exec sdds2stream $fileMinorAlarm -rows=bare,total} rowsMinorAlarm]} {
	append finalResults "$testProgramName\nunable to run sdds2stream\n$rowsMinorAlarm\n"
	return 0
    }
    if {[catch {exec sdds2stream $fileMajorAlarm -rows=bare,total} rowsMajorAlarm]} {
	append finalResults "$testProgramName\nunable to run sdds2stream\n$rowsMajorAlarm\n"
	return 0
    }
    if {($rowsNoAlarm != 5) || 
	($rowsMinorAlarm != 0) || 
	($rowsMajorAlarm != 0)} {
	append finalResults "$testProgramName\n$execute\nInvalid number of output rows found\n$results\n"
	return 0
    }

#test 2
    set execute "$testProgramName ${inDir}sddsglitchlogger.input2 /tmp/oagPM1Xtrig -triggerFile=${inDir}sddsglitchlogger.trig -circularBuffer=before=3,after=3 -time=10"
    if [catch {eval exec $execute} results] {
	set file [glob -nocomplain /tmp/oagPM1Xtrig*]
	if {![file exists $file]} {
	    append finalResults "$testProgramName\n$execute\n$results\n"
	    return 0
	}
    }
    if {[catch {exec sdds2stream $file -rows=bare,total} rows]} {
	append finalResults "$testProgramName\nunable to run sdds2stream\n$rows\n"
	return 0
    }
    if {($rows != 4)} {
	append finalResults "$testProgramName\n$execute\nInvalid number of output rows found\n$results\n"
	return 0
    }

#test 3
    if [catch {exec cavput -list=oag:H1:setCurrentC=-1.8} current] {
	append finalResults "$testProgramName\nunable to run cavput\n$current\n"
	return 0
    }
    APSWaitWithUpdate -waitSeconds 1
    set execute "$testProgramName ${inDir}sddsglitchlogger.input /tmp -circularBuffer=before=3,after=3 -time=10"
    if [catch {eval exec $execute} results] {
	set r [split $results \n]
	set fileNoAlarm [lindex [lindex $r end] end]
	set i [expr [llength $r] - 2]
	set fileMinorAlarm [lindex [lindex $r $i] end]
	incr i -1
	set fileMajorAlarm [lindex [lindex $r $i] end]
	foreach file "$fileNoAlarm $fileMinorAlarm $fileMajorAlarm" {
	    if {![file exists $file]} {
		append finalResults "$testProgramName\n$execute\n$results\n"
		return 0
	    }
	}
    }
    if {[catch {exec sdds2stream $fileNoAlarm -rows=bare,total} rowsNoAlarm]} {
	append finalResults "$testProgramName\nunable to run sdds2stream\n$rowsNoAlarm\n"
	return 0
    }
    if {[catch {exec sdds2stream $fileMinorAlarm -rows=bare,total} rowsMinorAlarm]} {
	append finalResults "$testProgramName\nunable to run sdds2stream\n$rowsMinorAlarm\n"
	return 0
    }
    if {[catch {exec sdds2stream $fileMajorAlarm -rows=bare,total} rowsMajorAlarm]} {
	append finalResults "$testProgramName\nunable to run sdds2stream\n$rowsMajorAlarm\n"
	return 0
    }
    if {($rowsNoAlarm <= 4) || 
	($rowsMinorAlarm <= 4) || 
	($rowsMajorAlarm != 0)} {
	append finalResults "$testProgramName\n$execute\nInvalid number of output rows found\n$results\n"
	return 0
    }

#test 4
    set files [glob -nocomplain /tmp/oagPM1Xtrig*]
    if {[llength $files]} {
	eval file delete $files
    }
    set execute "$testProgramName ${inDir}sddsglitchlogger.input2 /tmp/oagPM1Xtrig -triggerFile=${inDir}sddsglitchlogger.trig -circularBuffer=before=3,after=3 -time=10 -verbose"
    if [catch {eval exec $execute} results] {
	set file [glob -nocomplain /tmp/oagPM1Xtrig*]
	if {![file exists $file]} {
	    append finalResults "$testProgramName\n$execute\n$results\n"
	    return 0
	}
    }
    if {[catch {exec sdds2stream $file -rows=bare,total} rows]} {
	append finalResults "$testProgramName\nunable to run sdds2stream\n$rows\n"
	return 0
    }
    if {($rows <= 4)} {
	append finalResults "$testProgramName\n$execute\nInvalid number of output rows found\n$results\n"
	return 0
    }

#test 5
    if [catch {exec cavput -list=oag:H1:setCurrentC=-2.89} current] {
	append finalResults "$testProgramName\nunable to run cavput\n$current\n"
	return 0
    }
    APSWaitWithUpdate -waitSeconds 1
    set execute "$testProgramName ${inDir}sddsglitchlogger.input /tmp -circularBuffer=before=3,after=3 -time=10 -watchInput"
    if [catch {eval exec $execute} results] {
	set r [split $results \n]
	set fileNoAlarm [lindex [lindex $r end] end]
	set i [expr [llength $r] - 2]
	set fileMinorAlarm [lindex [lindex $r $i] end]
	incr i -1
	set fileMajorAlarm [lindex [lindex $r $i] end]
	foreach file "$fileNoAlarm $fileMinorAlarm $fileMajorAlarm" {
	    if {![file exists $file]} {
		append finalResults "$testProgramName\n$execute\n$results\n"
		return 0
	    }
	}
    }
    if {[catch {exec sdds2stream $fileNoAlarm -rows=bare,total} rowsNoAlarm]} {
	append finalResults "$testProgramName\nunable to run sdds2stream\n$rowsNoAlarm\n"
	return 0
    }
    if {[catch {exec sdds2stream $fileMinorAlarm -rows=bare,total} rowsMinorAlarm]} {
	append finalResults "$testProgramName\nunable to run sdds2stream\n$rowsMinorAlarm\n"
	return 0
    }
    if {[catch {exec sdds2stream $fileMajorAlarm -rows=bare,total} rowsMajorAlarm]} {
	append finalResults "$testProgramName\nunable to run sdds2stream\n$rowsMajorAlarm\n"
	return 0
    }
    if {($rowsNoAlarm != 0) || 
	($rowsMinorAlarm <= 4) || 
	($rowsMajorAlarm <= 4)} {
	append finalResults "$testProgramName\n$execute\nInvalid number of output rows found\n$results\n"
	return 0
    }

#finished
    optionsPassed -pass {circularBuffer time watchInput triggerFile verbose}
    if [catch {exec sddscasr -restore /home/oxygen/SOLIDAY/epics/iocapps/burt/linac_1_oag.snap} results] {
	append finalResults "$testProgramName\nunable to run burtwb\n$results\n"
	return 0
    }
    set files [glob -nocomplain /tmp/oagPM1X*]
    if {[llength $files]} {
	eval file delete $files
    }

    return 1
}

proc test_sddswget {args} {
    APSStrictParseArguments {testProgramName inDir outFile}
    global finalResults
    
    set wfDir /home/oxygen/SHANG/test/sddsEpicsTest/wget_put
    set wfFile $wfDir/waveforms
    #note that, the order in waveforms is: short, long, float, double
    
    APSSetVarAndUpdate status "test sddswget, please run SR simulator first!"
    if ![APSYesNoPopUp "Ready to run sddswget?"] {
        return 1
    }
    set inputs [list $wfDir/short $wfDir/long $wfDir/float $wfDir/double]
    set output1 [list /tmp/short_1 /tmp/long_1 /tmp/float_1 /tmp/double_1]
    set output2 [list /tmp/short_2 /tmp/long_2 /tmp/float_2 /tmp/double_2]
    set types [list short long float double]
    set pvNames [list Tmp:Waveform:Short Tmp:Waveform:Long Tmp:Waveform:Float Tmp:Waveform:Double]
    foreach input $inputs out1 $output1 type $types {
        if [catch {exec sddsprocess $input $out1 \
                     "-redefine=col,Waveform,rnd 100 *,type=$type"} result] {
            append finalResults "sddsprocess: $result "
            return 0
        }
    }
    APSAddToTmpFileList -ID 1 -fileList "$output1 $output2"
    
    #use sddswput to set Tmp:Waveform:Short
    foreach out $output1 {
        if [catch {exec sddswput $out} result] {
            append finalResults "sddswput $out: $result"
            return 0
        }
    }
    #use sddswget to get value of Tmp:Waveform:Short
    foreach out $output2 pv $pvNames {
        if [catch {exec sddswget -PVname=$pv $out} result] {
            append finalResults "sddswget -PVname=$pv $out: $result"
            return 0
        }
    }
    foreach out1 $output1 out2 $output2 pv $pvNames {
        APSSetVarAndUpdate status "testing $pv..."
        if [catch {set putdata [APSGetSDDSColumn -fileName $out1 -column Waveform -page 1]} result] {
            append finalResults "Error: $result"
            return 0
        }
        if [catch {set getdata [APSGetSDDSColumn -fileName $out2 -column Waveform -page 1]} result] {
            append finalResults "Error: $result"
            return 0
        }
        if [string compare $putdata $getdata]!=0 {
            append finalResults "Test failed for $pv."
            return 0
        } else {
            APSSetVarAndUpdate status "$pv test passed."
        }
    }
    optionsPassed -pass PVnames
    #test multiple waveforms, which are given in file waveforms
    APSSetVarAndUpdate status "test multiple waveforms..."
    foreach input $inputs out1 $output1 type $types {
        if [catch {exec sddsprocess $input $out1 \
                     "-redefine=col,Waveform,rnd 100 *,type=$type"} result] {
            append finalResults "sddsprocess: $result "
            return 0
        }
    }
    if [catch {eval exec sddscombine $output1 /tmp/waveformData -overwrite} result] {
        append finalResults "$result"
        return 0
    }
    if [catch {exec sddscast /tmp/waveformData -pipe=out -cast=col,Waveform,*,double -nowarning \
             | sddsconvert -pipe=in /tmp/waveformData -ascii -retain=par,WaveformPV  \
                 -retain=col,* -nowarning } result] {
        append finalResults "$result"
        return 0
    }
    if [catch {exec sddswput /tmp/waveformData} result] {
        append finalResults "Can not run sddswput /tmp/waveformData: $result"
        return 0
    }
    if [catch {exec sddswget $wfFile /tmp/waveformData1} result] {
        append finalResults "Can not run sddswget $wfFile /tmp/waveformData1: $result"
        return 0
    }
    if [catch {exec sddsconvert -ascii -nowarning /tmp/waveformData1  \
                 -retain=col,* -retain=par,WaveformPV} result] {
        append finalResults "$result"
        return 0
    }
    set execute "sddswget $wfFile /tmp/waveformData1"
    set valid 0
    compareOutput -testProgramName sddswget  -standardFile /tmp/waveformData \
      -testFile /tmp/waveformData1 -execute $execute
    if  !$valid {
        append finalResults $finalResults
        return 0
    }
    APSSetVarAndUpdate status "multiple waveforms test passed."
    APSAddToTmpFileList -ID 1 -fileList "/tmp/waveformData /tmp/waveformData1"
    return 1
}

proc test_sddsfeedforward {args} {
    APSStrictParseArguments {testProgramName inDir outFile}
    global finalResults
    if [catch {exec sddscasr -restore /home/oxygen/SOLIDAY/epics/iocapps/burt/linac_1_oag.snap} results] {
        append finalResults "$testProgramName\nunable to run burtwb\n$results\n"
        return 0
    }
    APSWaitWithUpdate -waitSeconds 1

    set execute "$testProgramName ${inDir}sddsfeedforward.input -interval=.2 -steps=6"
    if [catch {eval exec $execute} results] {
        append finalResults "$testProgramName\n$execute\n$results\n"
        return 0
    }
    optionsPassed -pass {interval steps}
    if [catch {exec sddscasr -restore /home/oxygen/SOLIDAY/epics/iocapps/burt/linac_1_oag.snap} results] {
        append finalResults "$testProgramName\nunable to run burtwb\n$results\n"
        return 0
    }

    set execute "$testProgramName ${inDir}sddsfeedforward.input -interval=.2 -steps=6 -advance=2 -testValues=${inDir}sddsfeedforward.test"
    if [catch {eval exec $execute} results] {
        append finalResults "$testProgramName\n$execute\n$results\n"
        return 0
    }
    optionsPassed -pass {advance testValues}
    if [catch {exec sddscasr -restore /home/oxygen/SOLIDAY/epics/iocapps/burt/linac_1_oag.snap} results] {
        append finalResults "$testProgramName\nunable to run burtwb\n$results\n"
        return 0
    }
    
    set execute "$testProgramName ${inDir}sddsfeedforward.input -interval=.2 -steps=6 -offsetOnly -ezcaTiming=.5,1 -CASecurityTest"
    if [catch {eval exec $execute} results] {
        append finalResults "$testProgramName\n$execute\n$results\n"
        return 0
    }
    optionsPassed -pass {offsetOnly ezcaTiming CASecurityTest}
    if [catch {exec sddscasr -restore /home/oxygen/SOLIDAY/epics/iocapps/burt/linac_1_oag.snap} results] {
        append finalResults "$testProgramName\nunable to run burtwb\n$results\n"
        return 0
    }
    
    set execute "$testProgramName ${inDir}sddsfeedforward.input -steps=6 -ave=2,int=.2"
    if [catch {eval exec $execute} results] {
        append finalResults "$testProgramName\n$execute\n$results\n"
        return 0
    }
    optionsPassed -pass {averageOf}
    if [catch {exec sddscasr -restore /home/oxygen/SOLIDAY/epics/iocapps/burt/linac_1_oag.snap} results] {
        append finalResults "$testProgramName\nunable to run burtwb\n$results\n"
        return 0
    }
    
    set execute "$testProgramName ${inDir}sddsfeedforward.input -interval=.2 -steps=6 -dry -verbose"
    if [catch {eval exec $execute} results] {
        #	append finalResults "$testProgramName\n$execute\n$results\n"
        #	return 0
    }
    optionsPassed -pass {dryRun verbose}
    if [catch {exec sddscasr -restore /home/oxygen/SOLIDAY/epics/iocapps/burt/linac_1_oag.snap} results] {
        append finalResults "$testProgramName\nunable to run burtwb\n$results\n"
        return 0
    }
    exec medm -x -attach -macro RCPV=oag:ControlLawRC  /usr/local/iocapps/adlsys/sr/psApp/APSRunControlSingle.adl  &
    set execute "$testProgramName ${inDir}sddsfeedforward.input1 -steps=5 -runControlPV=string=oag:ControlLawRC,pingTimeout=12 -runControlDescription=GapFeedforward -testValues=${inDir}sddsfeedforward.tests"
    if [catch {eval exec $execute} results] {
        append finalResults "$testProgramName\n$execute\n$results\n"
        return 0
    }
    optionsPassed -pass {runControlPV runControlDescription testValues}
    if [catch {exec sddscasr -restore /home/oxygen/SOLIDAY/epics/iocapps/burt/linac_1_oag.snap} results] {
        append finalResults "$testProgramName\nunable to run burtwb\n$results\n"
        return 0
    }
    
    
    return 1
}

proc test_sddscasr {args} {
    APSStrictParseArguments {testProgramName inDir outFile}
    global finalResults status
  #  set inDir /home/oxygen/OAG/sddsTests/
    #remove this test because, it is in real LPL system, the values can be changed by operatores
    #during tests
    
    ##testing save and restore option with both scalar and waveform PVs
    #take a snapshot first
    set execute "{$testProgramName} ${inDir}sddscasr.input2 -save \
            -waveform=rootname=[file tail ${outFile}.snapshot],directory=[file dirname ${outFile}.snapshot] \
            -pipe=out | sddsconvert -pipe=in  -delete=par,* ${outFile}.snapshot"
    if [catch {eval exec $execute} results] {
        append finalResults "$testProgramName\n$execute\n$results\n"
        return 0
    }
    #set correctors to zero before restoring it
    if [catch {exec cavput -list=oag: -list=H1,V1,H2,V2,H2,V3,H3,V4,H5,V5 -list=:setCurrentC=0 -pend=10} result] {
        return -code error $result
    }
    after 500
    set execute "{$testProgramName} ${outFile}.snapshot -restore -waveform=rootname=${outFile}.snapshot"
    #restore the PVs value and then read, compare the output of save with the input of the restore
    
    if [catch {eval exec $execute} results] {
        append finalResults "$testProgramName\n$execute\n$results\n"
        return 0
    }
    after 2000
    if [catch {exec $testProgramName ${inDir}sddscasr.input2 $outFile -save} result] {
        append finalResults "sddscasr: $result "
        return 0
    }
    #compare the input of restore with the output of save
    if [catch {exec sddsconvert ${outFile}.snapshot  \
                 -delete=par,* ${outFile}.1} result] {
        append finalResults "sddscasr: $result "
        return 0
    }
    if [catch {exec sddsconvert $outFile  \
                 -delete=par,* ${outFile}.2} result] {
        append finalResults "sddscasr: $result "
        return 0
    }
    set valid 0
    compareOutput1 -testProgramName $testProgramName  -standardFile ${outFile}.1 \
      -testFile ${outFile}.2 -execute $execute
    if !$valid {
        append finalResults $finalResults
        return 0
    }
    #test waveform file
    foreach wave {oag:W:Char oag:W:String oag:W:Double oag:W:Long oag:W:Short} {
        if [catch {exec sddsconvert ${outFile}.snapshot.$wave \
                     -retain=par,WaveformPV  ${outFile}1.$wave} result] {
            append finalResults "sddsconvert: $result"
            return 0
        }
        if [catch {exec sddsconvert ${outFile}.$wave \
                     -retain=par,WaveformPV  ${outFile}2.$wave} result] {
            append finalResults "sddsconvert: $result"
            return 0
        }
        set valid 0
        compareOutput1 -testProgramName $testProgramName  -standardFile ${outFile}1.$wave \
          -testFile ${outFile}2.$wave -execute $execute
        if !$valid {
            return 0
        }
    }
    #test the waveform using sddswget
    foreach wave {oag:W:Char oag:W:String oag:W:Double oag:W:Long oag:W:Short} {
        if [catch {exec sddswget -pvname=$wave ${outFile}3.$wave } result] {
            append finalResults "sddswget: $result"
            return 0
        }
        if [catch {exec sddsconvert ${outFile}3.$wave -retain=par,WaveformPV \
                     -nowarning } result] {
            append finalResults "sddsconvert: $result"
            return 0
        }
        #compare two files
        set valid 0
        compareOutput1 -testProgramName $testProgramName  -standardFile ${outFile}1.$wave \
          -testFile ${outFile}3.$wave -execute $execute
        if !$valid {
            return 0
        }
    }
    optionsPassed -pass {restore save pipe waveform}
    
    #testing waveform numerical description 
    set root [file tail $outFile].snapshot1
    set dir [file dirname $outFile]
    set execute "{$testProgramName} ${inDir}sddscasr.input2 -save \
                  -waveform=rootname=$root,directory=$dir -pipe=out \
                 \"-description=desc_par_test\" -numerical \
                 | sddsconvert -pipe=in  \
                 -retain=par,SnapshotDescription ${outFile}.snapshot1"
  
    if [catch {eval exec $execute} results] {
        append finalResults "$testProgramName\n$execute\n$results\n"
        return 0
    }
    set description [exec sdds2stream ${outFile}.snapshot1 -par=SnapshotDescription]
    if [string compare "desc_par_test" $description]!=0 {
        append finalResults "$testProgramName\n$execute\nError: description option failed!\n"
        return 0
    }
    set num [exec sddsprocess ${outFile}.snapshot1 -pipe=out \
               -match=col,ControlName=oag:gunOnC \
               | sdds2stream -pipe -col=ValueString]
    if [catch {expr $num * 2} result] {
        append finalResults "$testProgramName\n$execute\nError: -numerical option failed!\n"
        return 0
    }
    optionsPassed -pass {numerical}
  
    #test  logFile  semaphore dailyFiles outputFilePV
    set execute "{$testProgramName} ${inDir}sddscasr.input3 $outFile -save \
             -dailyFiles -outputFilePV=oag:W:Char \
             -semaphore=${outFile}.semaphore -logFile=${outFile}.log"
    #  puts $execute
    if [catch {eval exec $execute} results] {
        append finalResults "$testProgramName\n$execute\n$results\n"
        return 0
    }
    if ![file exist ${outFile}.log] {
        append finalResults "$testProgramName\n$execute\n-logFile option failed!\n"
        return 0
    }
    if ![file exist ${outFile}.semaphore] {
        append finalResults "$testProgramName\n$execute\n-semaphore option failed!\n"
        return 0
    }
    set fd [open ${outFile}.semaphore "r"]
    set out1 [gets $fd]
    close $fd
    if [catch {APScagetTextFromWaveform -pvName oag:W:Char} out2] {
        append finalResults "$testProgramName\n$execute\n$out2\n"
        return 0
    }
    if [string compare $out1 $out2]!=0 {
        append finalResults "$testProgramName\n$execute\neither -semaphoreFile or -outputFilePV option failed\n"
        return 0
    }
    optionsPassed -pass {semaphore dailyFiles logFile outputFilePV}
    
    #test unique: sddscasr.input3 has two identical rows, only
    #one of them will be read and set values to avoid CA errors
    #oag:V5:setCurrentC appears twice in sddscasr.input3 with two
    #different values: 2.23692 and 0, test the value of oag:V5:setCurrentC after restore
    set execute1 "{$testProgramName} ${inDir}sddscasr.input3 -restore -unique"
    set execute2 "{$testProgramName} ${inDir}sddscasr.input3 -save -pipe=out \
                 | sddsconvert -pipe=in -del=par,* $outFile "
                 
    #set correctors to zero before restoring it
    if [catch {exec cavput -list=oag: -list=H1,V1,H2,V2,H2,V3,H3,V4,H5,V5 -list=:setCurrentC=0 -pend=10} result] {
        return -code error $result
    }
    after 500
    if [catch {eval exec $execute1} results] {
        append finalResults "$testProgramName\n$execute1\n$results\n"
        return 0
    }
    if [catch {eval exec $execute2} results] {
        append finalResults "$testProgramName\n$execute2\n$results\n"
        return 0
    }
    after 2000
    if [catch {exec cavget -list=oag:V5:setCurrentC -pend=10} result] {
        append finalResults "cavget: $result"
    }
    if $result!=2.23692 {
        append finalResults "$testProgramName\n$execute1\n-unique option failed\n"
        return 0
    }
    optionsPassed -pass {unique}
    
    
    #test daemon with save, outputFilePV, runControlPV, runControlDescription, casavePV
    exec medm -x -attach -macro RCPV=oag:ControlLawRC  /usr/local/iocapps/adlsys/sr/psApp/APSRunControlSingle.adl & 
    #abort controllaw
    if [catch {exec cavput -list=oag:ControlLawRC.ABRT=1 -pend=10} result] {
        append finalResult $result
        return 0
    }
    set execute "{$testProgramName} ${inDir}sddscasr.input2 -save -daemon out -daily \
               -semaphore=${outFile}.semaphore \
               -pidFile=${outFile}.pid -casavePV=oag:casave \
               -logFile=${outFile}.log -pendIOTime=10 \
               -runControlPV=string=oag:ControlLawRC,pingTimeout=10 \
               -runControlDesc=string=save"
    #puts $execute
    if [catch {eval exec $execute & } pid] {
        append finalResults "$testProgramName\n$execute\n$pid\n"
        return 0
    }
    after 2000
    if ![file exist ${outFile}.pid] {
        append finalResults "$testProgramName\n$execute\n-pidFile option failed (1)!\n"
        return 0
    }
    set fd [open ${outFile}.pid "r"]
    set pid1 [gets $fd]
    close $fd
    if {$pid1 !=$pid} {
        append finalResults "$testProgramName\n$execute\n-pidFile option failed (2)!\n"
        return 0
    }
    if [catch {exec cavget -list=oag:ControlLawRC.RUN -pend=10} running] {
        append finalResults "cavget:$running"
        return 0
    }
    if !$running {
        append finalResults "$testProgramName\n$execute\noag:ControlLaw is not running, error in daemon mode!\n"
        return 0
    }
    if [catch {exec cavget -list=oag:ControlLawRC.DESC -pend=10} desc] {
        append finalResults "cavget: $desc"
        return 0
    }
    if {$desc!="save"} {
        append finalResults "$testProgramName\n$execute\n-runControlDescription option failed.!\n"
        return 0
    }
    
    if [catch {APScagetTextFromWaveform -pvName oag:W:Char} out1] {
        append finalResults "$testProgramName\n$execute\n$out1\n"
        return 0
    }
    #now test casavePV feature, when its value is changed to 1, a new save should
    #occur, a different output file name will be stored in the outputFilePV 
    #set oag:casave to 1
    if [catch {exec cavput -list=oag:casave=1 -pend=10} result] {
        append finalResults "cavget: $result"
        return 0
    }
    while {1} {
        if [catch {exec cavget -list=oag:casave -pend=10 -num } val] {
            return -code error $val
        }
        if !$val {
            break
        }
        after 500
    }
    
    if ![file exist ${outFile}.semaphore] {
        #the existence of semaphore indicates CA connection completes
        append finalResults "$testProgramName\n$execute\n-daemon mode in save failed!\n"
        return 0
    }
    if [catch {APScagetTextFromWaveform -pvName oag:W:Char} out2] {
        append finalResults "$testProgramName\n$execute\n$out2\n"
        return 0
    }
    if [catch {exec sddsconvert $out1  -delete=par,* ${outFile}.tmp1} result] {
        append finalResults "$testProgramName\n$execute\n$result\n"
        return 0
    }
    if [catch {exec sddsconvert $out2  -delete=par,* ${outFile}.tmp2} result] {
        append finalResults "$testProgramName\n$execute\n$result\n"
        return 0
    }
    set valid 0
    compareOutput1 -testProgramName $testProgramName -execute $execute \
      -standardFile ${outFile}.tmp1 -testFile ${outFile}.tmp2
    if !$valid {
        return 0
    }
    #abort controllaw
    if [catch {exec cavput -list=oag:ControlLawRC.ABRT=1 -pend=10} result] {
        append finalResult $result
        return 0
    }

    #test daemon with restore
    file copy -force ${outFile}.snapshot ${outFile}.input
    set execute "{$testProgramName} ${outFile}.input -restore -daemon \
                 -waveform=rootname=${outFile}.snapshot \
                 -interval=1 -pendIOTime=10 \
                 -runControlPV=string=oag:ControlLawRC,pingTimeout=10 \
                 -runControlDesc=string=restore -casavePV=oag:casave -unique "
   # puts $execute
    #set correctors to zero before restoring it
    if [catch {exec cavput -list=oag: -list=H1,V1,H2,V2,H2,V3,H3,V4,H5,V5 -list=:setCurrentC=0 -pend=10} result] {
        return -code error $result
    }
    after 1000
    if [catch {eval exec $execute &} results] {
	append finalResults "$testProgramName\n$execute\n$results\n"
        return 0
    }
    
    after 2000
    set dir [file dirname $outFile]
    set root [file tail $outFile]
    if [catch {exec $testProgramName ${outFile}.snapshot -save -pipe=out \
                 -waveform=rootname=$root,directory=$dir \
                 | sddsconvert -pipe=in  -delete=par,* $outFile } result] {
        append finalResults "$testProgramName\n$execute\n$result\n"
        return 0
    }
    set valid 0
    compareOutput1 -testProgramName $testProgramName  -standardFile ${outFile}.snapshot \
      -testFile $outFile -execute $execute
    if !$valid {
        return 0
    }
    #compare waveforms 
    foreach wave {oag:W:Char oag:W:String oag:W:Double oag:W:Long oag:W:Short} {
        if [catch {exec sddsconvert ${outFile}.snapshot.$wave \
                     -retain=par,WaveformPV  ${outFile}1.$wave} result] {
            append finalResults "sddsconvert: $result"
            return 0
        }
        if [catch {exec sddsconvert $dir/${root}.$wave \
                     -retain=par,WaveformPV  ${outFile}2.$wave} result] {
            append finalResults "sddsconvert: $result"
            return 0
        }
        set valid 0
        compareOutput1 -testProgramName $testProgramName  -standardFile ${outFile}1.$wave \
          -testFile ${outFile}2.$wave -execute $execute
        if !$valid {
            return 0
        }
    }

    file copy -force ${inDir}sddscasr.input3 ${outFile}.input
    #this file does not contain waveform pvs
   
    #do another restore
    #set correctors to zero before restoring it
    if [catch {exec cavput -list=oag: -list=H1,V1,H2,V2,H2,V3,H3,V4,H5,V5 -list=:setCurrentC=0 -pend=10} result] {
        return -code error $result
    }
    after 2000
    if [catch {exec cavput -list=oag:casave=1 -pend=10} result] {
        append finalResults "$result"
        return 0
    }
    while {1} {
        if [catch {exec cavget -list=oag:casave -pend=10 -num } val] {
            return -code error $val
        }
        if !$val {
            break
        }
        after 500
    }
    after 1000
    if [catch {exec $testProgramName ${outFile}.input -save -pipe=out \
                 | sddsconvert -pipe=in  -delete=par,* ${outFile}.out3} result] {
        append finalResults "$result"
        return 0
    }
    set valid 0
    compareOutput1 -testProgramName $testProgramName  -standardFile ${inDir}sddscasr.output3 \
      -testFile ${outFile}.out3 -execute $execute
    if !$valid {
        return 0
    }
    optionsPassed -pass {daemon interval pendIOTime runControlPV runControlDescription pidFile casavePV}
    if [catch {exec cavput -list=oag:ControlLawRC.ABRT=1 -pend=10} result] {
        return -code error $result
    }

    #following tests are for new added options -inputFilePV and -description=pv
    #test -description=<string> or -description=pv=<pvname> option
    set text "test description pv"
    if [catch {APScaputTextToWaveform -pvName oag:W:Char -text $text} result] {
        return -code error $result
    }
    if [catch {exec $testProgramName ${inDir}sddscasr.input3 -save ${outFile}.test1 \
                 -description=pv=oag:W:Char} result] {
        append finalResults "$testProgramName\nError: -description=pv=<pvname> option failed!\n"
        return 0
    }
    set desp [exec sdds2stream ${outFile}.test1 -par=SnapshotDescription -noquotes]
    if [string compare $text $desp]!=0 {
        append finalResults "$testProgramName\nError: -description=pv=<pvname> option failed!\n"
        return 0
    }
    set text "new description test"
  
    if [catch {exec $testProgramName ${inDir}sddscasr.input3 -save \
                 ${outFile}.test2 "-description=$text"} result] {
        append finalResults "$testProgramName\nError: -description=<string> option failed!\n"
        return 0
    }
    set desp [exec sdds2stream ${outFile}.test2 -par=SnapshotDescription -noquotes]
    if [string compare $text $desp]!=0 {
        append finalResults "$testProgramName\nError: -description=<string> option failed!\n"
        return 0
    }
    optionsPassed -pass {description}

    #test -inputFilePV option with daemon mode
    
    set execute "$testProgramName -save ${inDir}sddscasr.input2 -pipe=out \
                 -waveform=rootname=[file tail $outFile],directory=[file dirname $outFile] \
                 | sddsconvert -pipe=in  -delete=par,* ${outFile}.test1"
    #puts $execute
    if [catch {eval exec $execute} results] {
        append finalResults "$testProgramName\n$execute\n$results\n"
        return 0
    }
    if [catch {APScaputTextToWaveform -pvName oag:W:Char -text ${inDir}sddscasr.input2} result] {
        return -code error $result
    }
    set execute "$testProgramName -save ${outFile}.test -dailyFiles \
                 -semaphoreFile=${outFile}.semaphore   \
                 -runControlPV=string=oag:ControlLawRC,pingTimeOut=10 \
                 -runControlDesc=string=save1 \
                 -inputFilePV=oag:W:Char -casavePV=oag:casave \
                 -daemon"
    #puts $execute
    if [catch {eval exec $execute &} results] {
        append finalResults "$testProgramName\n$execute\n$results\n"
        return 0
    }
    after 1000
    set fd [open ${outFile}.semaphore "r"]
    set file1 [gets $fd]
    close $fd
    if [catch {exec sddsconvert  -delete=par,* $file1 ${outFile}.test2} result] {
        return -code error $result
    }
    set valid 0
    compareOutput1 -testProgramName $testProgramName -execute $execute \
      -standardFile ${outFile}.test1 -testFile ${outFile}.test2
    if {!$valid} {
        return 0
    }
    #now set the inputFilePV to different input file, which is sddscasr.input4
    #we should get different output also, but it is the same as test1 created in following command
    if [catch {exec sddscasr -save ${inDir}sddscasr.input4 -pipe=out \
                 | sddsconvert -pipe=in  -delete=par,* ${outFile}.test3 } result] {
        return -code error $result
    }
    set text ${inDir}sddscasr.input4
    #reset the inputfile pv
    if [catch {APScaputTextToWaveform -pvName oag:W:Char -text $text} result] {
        return -code error $result
    }
    #trigger another save
    if [catch {exec cavput -list=oag:casave=1 -pend=5} result] {
        return -code error $result
    }
    while {1} {
        if [catch {exec cavget -list=oag:casave -pend=10 -num } val] {
            return -code error $val
        }
        if !$val {
            break
        }
        after 500
    }
    set fd1 [open ${outFile}.semaphore "r"]
    set file2 [gets $fd1]
    close $fd1
    if [catch {exec sddsconvert  -delete=par,* $file2 ${outFile}.test4} result] {
        return -code error $result
    }
    set valid 0
    compareOutput1 -testProgramName $testProgramName -execute $execute \
      -standardFile ${outFile}.test3 -testFile ${outFile}.test4
    if !$valid {
        return 0
    }
    #abort controllaw
    if [catch {exec cavput -list=oag:ControlLawRC.ABRT=1 -pend=10} result] {
        append finalResult $result
        return 0
    }
    
    #testing inputFilePV with restore in daemon mode
    set text ${outFile}.test4
    if [catch {APScaputTextToWaveform -pvName oag:W:Char -text $text} result] {
        return -code error $result
    }
    #this input file does not have waveform pvs. the waveform option is prepared for next restoring
    #which input has waveform pvs
    set execute "$testProgramName -restore -inputFilePV=oag:W:Char -daemon \
                 -waveform=rootname=${outFile}.snapshot \
                 -casavePV=oag:casave \
                 -runControlPV=string=oag:ControlLawRC,pingTimeOut=10 \
                 -runControlDesc=string=restore1 "
    #set correctors to zero before restoring it
    if [catch {exec cavput -list=oag: -list=H1,V1,H2,V2,H2,V3,H3,V4,H5,V5 -list=:setCurrentC=0 -pend=10} result] {
        return -code error $result
    }
    after 500
    if [catch {eval exec $execute &} results] {
        append finalResults "$testProgramName\n$execute\n$resutls\n"
        return 0
    }
    after 2000
    if [catch {exec sddscasr -save  $text -pipe=out \
                 | sddsconvert -pipe=in  -delete=par,* ${outFile}.test5 } result] {
        return -code error $result
    }
    
    set valid 0
    compareOutput1 -testProgramName $testProgramName -execute $execute \
      -standardFile ${outFile}.test4 -testFile ${outFile}.test5
    if {!$valid} {
        return 0
    }
    set text ${outFile}.snapshot
    #reset the input file pv
    if [catch {APScaputTextToWaveform -pvName oag:W:Char -text $text} result] {
        return -code error $result
    }
    after 1000
    #trigger another restore
    #set correctors to zero before restoring it
    if [catch {exec cavput -list=oag: -list=H1,V1,H2,V2,H2,V3,H3,V4,H5,V5 -list=:setCurrentC=0 -pend=10} result] {
        return -code error $result
    }
    after 500
    if [catch {exec cavput -list=oag:casave=1 -pend=5} result] {
        return -code error $result
    }
    while {1} {
        if [catch {exec cavget -list=oag:casave -pend=10 -num } val] {
            return -code error $val
        }
        if !$val {
            break
        }
        after 500
    }
    if [catch {exec sddscasr -save $text -pipe=out -numeric \
                 -waveform=rootname=[file tail $outFile],directory=[file dirname $outFile] \
                 | sddsconvert -pipe=in  -delete=par,* ${outFile}.test6} result] {
        return -code error $result
    }
    if [catch {exec sddsconvert ${outFile}.snapshot1 -delete=par,* ${outFile}.test7} result] {
        return -code error $result
    }
    set valid 0
    compareOutput1 -testProgramName $testProgramName -execute $execute \
      -standardFile ${outFile}.test7 -testFile ${outFile}.test6
    if {!$valid} {
        return 0
    }
    optionsPassed -pass {inputFilePV}
    #abort controllaw
    if [catch {exec cavput -list=oag:ControlLawRC.ABRT=1 -pend=10} result] {
        append finalResult $result
        return 0
    }
    
    set fileList [glob -nocomplain ${outFile}*]
    APSAddToTmpFileList -ID sddscasrTest -fileList $fileList
    return 1
}
