#!/usr/bin/env expect
############################################################################
# Purpose: Test scancel with --full and/or --batch.
#
# Note:    This script generates and then deletes files in the working directory
#          named test6.15.input, test6.15.output, and test6.15.error
############################################################################
# Copyright (C) SchedMD LLC.
#
# This file is part of Slurm, a resource management program.
# For details, see <https://slurm.schedmd.com/>.
# Please also read the included file: DISCLAIMER.
#
# Slurm is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation; either version 2 of the License, or (at your option)
# any later version.
#
# Slurm is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along
# with Slurm; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA.
############################################################################
source ./globals

set file_in     "$test_dir/input"
set file_out    "$test_dir/output"
set file_prog   "$test_name.prog"
set job_id      0

proc cleanup {} {
	global job_id file_prog

	cancel_job $job_id
	file delete $file_prog
}

# Build prog
run_command -fail "$bin_cc -o $file_prog $file_prog.c"

#
# Build input script files
#
make_bash_script $file_in "
catch()
{
	echo 'Signaled: script'
	exit 0
}

trap catch USR1

$bin_echo Job \$SLURM_JOB_ID is running
./test6.15.prog &
$srun ./test6.15.prog step
wait
exit 0
"

set proctracktype [get_config_param "ProctrackType"]
log_debug "Proctrack: $proctracktype"
if {$proctracktype ne "proctrack/cgroup" && $proctracktype ne "proctrack/linuxproc" && $proctracktype ne "proctrack/pgid"} {
	skip "This test only works for proctrack/cgroup, proctrack/linuxproc or proctrack/pgid"
}

#
# Main testproc function
#
# It submits a batch script that runs a background command and a step.
# Both command and step are the same app that creates parent and child process.
# All three, the script, the command and the step have a signal handler
# for SIGUSR1 to print that the signal is received.
#
# The function uses scancel to signal the job, and finally check the stdout
# to verify that the signals are received as expected.
# The scancel can be used with $params to check them.
#
proc test_signaling { batch full } {
	global max_job_delay proctracktype
	global bin_sleep bin_cat job_id
	global sbatch scancel file_out file_in
	global number re_word_str bin_grep

	# Cleanup result from previous call
	file delete $file_out

	#
	# Submit sbatch job
	#
	log_debug "Submit the job"
	set timeout $max_job_delay
	set job_id [submit_job -fail "--output=$file_out -e /dev/null -t2 $file_in"]

	#
	# Wait for job to start running
	#
	# If slurmd gets the job signal request before the tasks have actually been
	# started, the asynchronous call can fail to signal the job script. Wait
	# for evidence that the job has started and has written to its output file.
	wait_for_job -fail $job_id "RUNNING"
	wait_for_file -fail $file_out
	wait_for_command_match -fail -pollinterval .1 "$bin_grep -c Started $file_out" 4

	#
	# Signal the job
	#
	set params ""
	if { $batch } {
		set params [concat $params " --batch"]
	}
	if { $full } {
		set params [concat $params " --full"]
	}

	log_debug "Signal the job"
	run_command -fail "$scancel -s SIGUSR1 $params $job_id"

	#
	# Wait for job completion
	#
	wait_for_job -fail $job_id DONE

	set expected_script_signaled 0
	set expected_parent_step_signaled 0
	set expected_parent_command_signaled 0
	set expected_child_step_signaled 0
	set expected_child_command_signaled 0

	if {$batch && !$full} {
		set expected_script_signaled 1
	} elseif {!$batch && !$full} {
		set expected_parent_step_signaled 1
		if {$proctracktype == "proctrack/linuxproc" || $proctracktype == "proctrack/pgid"} {
			set expected_child_step_signaled 1
		}
	} else {
		set expected_script_signaled 1
		set expected_parent_step_signaled 1
		set expected_parent_command_signaled 1
		set expected_child_command_signaled 1
		if {$proctracktype == "proctrack/linuxproc" || $proctracktype == "proctrack/pgid"} {
			set expected_child_step_signaled 1
		}
	}

	#
	# Grep the output file for the signaled process
	#
	set script_signaled          0
	set parent_step_signaled     0
	set parent_command_signaled  0
	set child_step_signaled      0
	set child_command_signaled   0

	spawn $bin_cat $file_out
	expect {
		-re "Signaled: ($re_word_str)" {
			set signaled $expect_out(1,string)
			if {$signaled == "script"} {
				incr script_signaled
			} elseif {$signaled == "parent_step"} {
				incr parent_step_signaled
			} elseif {$signaled == "parent_command"} {
				incr parent_command_signaled
			} elseif {$signaled == "child_step"} {
				incr child_step_signaled
			} elseif {$signaled == "child_command"} {
				incr child_command_signaled
			}
			exp_continue
		}
		eof {
			wait
		}
	}
	subtest {$script_signaled == $expected_script_signaled} "Script should [expr ($expected_script_signaled==1)?{be}:{NOT be}] signaled"
	subtest {$parent_step_signaled == $expected_parent_step_signaled} "Parent step should [expr ($expected_parent_step_signaled==1)?{be}:{NOT be}] signaled"
	subtest {$parent_command_signaled == $expected_parent_command_signaled} "Parent command should [expr ($expected_parent_command_signaled==1)?{be}:{NOT be}] signaled"
	subtest {$child_step_signaled == $expected_child_step_signaled} "Child step should [expr ($expected_child_step_signaled==1)?{be}:{NOT be}] signaled"
	subtest {$child_command_signaled == $expected_child_command_signaled} "Child command should [expr ($expected_child_command_signaled==1)?{be}:{NOT be}] signaled"
}

#
# Run the tests
#
testproc test_signaling 0 0
testproc test_signaling 1 0
testproc test_signaling 0 1
testproc test_signaling 1 1
