#!/usr/bin/env expect
############################################################################
# Purpose: Test of Slurm functionality
#          sacctmgr dump test
############################################################################
# Copyright (C) 2008-2010 Lawrence Livermore National Security.
# Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
# Written by Joseph Donaghy <donaghy1@llnl.gov>
# CODE-OCEC-09-009. All rights reserved.
#
# 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_accounting

set file_in     "test$test_id.input"
set file_in2    "test$test_id.input2"
set file_in3    "test$test_id.input3"
set file_out    "test$test_id.output"
set file_out2   "test$test_id.output2"
set file_out3   "test$test_id.output3"
set file_out4   "test$test_id.output4"
set exit_code   0
set lis		list
set as		assoc
set fmt		format
set cln		clean
set tre		tree
set was		withassoc
set wco		withcoordinator
set par		Parent
set roo		root
set clu		Cluster
set tc1		"test$test_id-cluster-1"
set tc2		"test$test_id-cluster-2"
set tc3		"test$test_id-cluster-3"
set acc		Account
set nams	names
set ta1		"test$test_id-account.1"
set ta2		"test$test_id-account.2"
set ta3		"test$test_id-account.3"
set ta4		"test$test_id-account.4"
set dsc		Description
set org		Organization
set usr		User
set tu1         "test$test_id-user.1"
set tu2         "test$test_id-user.2"
set tu3         "test$test_id-user.3"
set tu4         "test$test_id-user.4"
set qs          QOS
set qs2         runfirst
set al		AdminLevel
set aln		None
set ala		Administrator
set alo		Operator
set coo         Coordinator
set col         CoordinatorList
set dac		DefaultAccount
set pts		Partitions
set pde		pdebug
set pba		pbatch
set dw		DefaultWCKey
set wk		WCKeys
set fs		Fairshare
set gm		GrpTRESMins
set gc		GrpTRES
set gj		GrpJobs
set gs		GrpSubmitJobs
set gw		GrpWall
set mm		MaxTRESMins
set mp		MaxTRESMinsPerJob
set mc		MaxTRES
set mu		MaxTRESPerJob
set mj		MaxJobs
set ms		MaxSubmitJobs
set mw		MaxWall
set md		MaxWallDurationPerJob

set wckey_check hole,latch,stone,turn

# Accounts
array set acct_req {
	parent         root
	description    appliedacct
	organization   organization
	fairshare      5678
	grptresmins    cpu=5500
	grptres        cpu=50,node=530
	grpjobs        510
	grpsubmitjobs  520
	grpwall        300
	maxtres        cpu=540,node=570
	maxtresmins    cpu=550000
	maxjobs        550
	maxsubmitjobs  560
	maxnodes       570
	maxwall        350
}
set acct_req(qos) $qs2
set acct_req(cluster) $tc3

array set acct_req2 {
	description    theoryacct
	organization   theoryorg
	fairshare      4321
	grptresmins    cpu=4000
	grptres        cpu=40,node=430
	grpjobs        410
	grpsubmitjobs  420
	grpwall        240
	maxtresmins    cpu=420000
	maxtres        cpu=440,node=470
	maxjobs        450
	maxsubmitjobs  460
	maxwall        280
}
set acct_req2(qos) $qs2
set acct_req2(cluster) $tc3
set acct_req2(parent) $ta4

array set acct_req3 {
	description    physicsacct
	organization   physicsorg
	fairshare      3240
	grptresmins    cpu=3300
	grptres        cpu=30,node=330
	grpjobs        310
	grpsubmitjobs  320
	grpwall        180
	maxtresmins    cpu=330000
	maxtres        cpu=340,node=370
	maxjobs        350
	maxsubmitjobs  360
	maxwall        210
}
set acct_req3(qos) $qs2
set acct_req3(cluster) $tc3
set acct_req3(parent) $ta3

# Users
array set user_req {
	adminlevel     Administrator
	defaultwckey   hole
	wckey          latch,stone,turn
	fairshare      3240
	grptresmins    cpu=3300
	grptres        cpu=30,node=330
	grpjobs        310
	grpsubmitjobs  320
	grpwall        180
	maxtresmins    cpu=330000
	maxtres        cpu=340,node=370
	maxjobs        350
	maxsubmitjobs  360
	maxwall        210
}
set user_req(qos) $qs2
set user_req(cluster) $tc3
set user_req(account) $ta4
set user_req(defaultaccount) $ta3

array set user_req2 {
	adminlevel     Operator
	defaultwckey   stone
	wckey          latch,hole,turn
	fairshare      2375
	grptresmins    cpu=2000
	grptres        cpu=20,node=230
	grpjobs        210
	grpsubmitjobs  220
	grpwall        120
	maxtresmins    cpu=220000
	maxtres        cpu=240,node=270
	maxjobs        250
	maxsubmitjobs  260
	maxwall        140

}
set user_req2(qos) $qs2
set user_req2(cluster) $tc3
set user_req2(account) $ta3
set user_req2(defaultaccount) $ta2

array set user_req3 {
	adminlevel     None
	defaultwckey   latch
	wckey          stone,hole,turn
	fairshare      1000
	grptresmins    cpu=1100
	grptres        cpu=10,node=140
	grpjobs        120
	grpsubmitjobs  130
	grpwall        60
	maxtresmins    cpu=110000
	maxtres        cpu=150,node=180
	maxjobs        160
	maxsubmitjobs  170
	maxwall        70

}
set user_req3(qos) $qs2
set user_req3(cluster) $tc3
set user_req3(account) $ta2
set user_req3(defaultaccount) $ta2

# Clusters
array set clus_req {
	fairshare 6789
	grptres	  cpu=60,node=630
	grpjob	  610
	grpsubmit 620
	maxtres   cpu=640,node=670
	maxtresmin cpu=660000
	maxjobs   650
	maxsubmit 660
	maxwall   2880
}
# I couldn't figure out how to make a variable in an array to = the value of
# another variable.  If you figure this out just move this into the above
# array definition.
set clus_req(qos) $qs2

set timeout     60
set access_err  0

set timeout 60

#
# Check accounting config and bail if not found.
#
if {[get_config_param "AccountingStorageType"] ne "accounting_storage/slurmdbd"} {
	skip "This test can't be run without a usable AccountStorageType"
}
if {[string compare [get_admin_level] "Administrator"]} {
	skip "This test can't be run without being an Accounting administrator.\nUse: sacctmgr mod user \$USER set admin=admin"
}

#make sure we have a clean system and permission to do this work
remove_user "" "" "$tu1,$tu2,$tu3,$tu4"
remove_acct "" "$ta2,$ta3,$ta4"
remove_qos "$qs2"
remove_cluster "$tc1,$tc2,$tc3"
if {$access_err != 0} {
	skip "Not authorized to perform this test"
}

#add qos
incr exit_code [add_qos "$qs2" ""]
if { $exit_code } {
	remove_user "" "" "$tu1,$tu2,$tu3,$tu4"
	remove_acct "" "$ta2,$ta3,$ta4"
	remove_qos "$qs2"
	remove_cluster "$tc1,$tc2,$tc3"
	fail "Unable to add qos ($qs2)"
}

#
#add cluster
incr exit_code [add_cluster $tc3 [array get clus_req]]
if { $exit_code } {
	remove_user "" "" "$tu1,$tu2,$tu3,$tu4"
	remove_acct "" "$ta2,$ta3,$ta4"
	remove_qos "$qs2"
	remove_cluster "$tc1,$tc2,$tc3"
	fail "Unable to add cluster ($tc3)"
}

#add accounts
incr exit_code [add_acct $ta4 [array get acct_req]]
if { $exit_code } {
	remove_user "" "" "$tu1,$tu2,$tu3,$tu4"
	remove_acct "" "$ta2,$ta3,$ta4"
	remove_qos "$qs2"
	remove_cluster "$tc1,$tc2,$tc3"
	fail "Unable to add account ($ta4)"
}

incr exit_code [add_acct $ta3 [array get acct_req2]]
if { $exit_code } {
	remove_user "" "" "$tu1,$tu2,$tu3,$tu4"
	remove_acct "" "$ta2,$ta3,$ta4"
	remove_qos "$qs2"
	remove_cluster "$tc1,$tc2,$tc3"
	fail "Unable to add account ($ta3)"
}

incr exit_code [add_acct $ta2 [array get acct_req3]]
if { $exit_code } {
	remove_user "" "" "$tu1,$tu2,$tu3,$tu4"
	remove_acct "" "$ta2,$ta3,$ta4"
	remove_qos "$qs2"
	remove_cluster "$tc1,$tc2,$tc3"
	fail "Unable to add account ($ta2)"
}

#add users
incr exit_code [add_user $tu3 [array get user_req]]
if { $exit_code } {
	remove_user "" "" "$tu1,$tu2,$tu3,$tu4"
	remove_acct "" "$ta2,$ta3,$ta4"
	remove_qos "$qs2"
	remove_cluster "$tc1,$tc2,$tc3"
	fail "Unable to add user ($tu3)"
}

incr exit_code [add_user $tu2 [array get user_req2]]
if { $exit_code } {
	remove_user "" "" "$tu1,$tu2,$tu3,$tu4"
	remove_acct "" "$ta2,$ta3,$ta4"
	remove_qos "$qs2"
	remove_cluster "$tc1,$tc2,$tc3"
	fail "Unable to add user ($tu2)"
}

incr exit_code [add_user $tu1 [array get user_req3]]
if { $exit_code } {
	remove_user "" "" "$tu1,$tu2,$tu3,$tu4"
	remove_acct "" "$ta1,$ta2,$ta3,$ta4"
	remove_qos "$qs2"
	remove_cluster "$tc1,$tc2,$tc3"
	fail "Unable to add user ($tu1)"
}

exec $bin_rm -f $file_out4

set matches 0
set my_pid [spawn $sacctmgr -i dump $clu=$tc3 file=$file_out4]
expect {
	-re "(Cluster .* returned nothing)" {
		log_error "There was a problem with the dump"
	    incr exit_code 1
	}
	-re "(No filename given)" {
		log_error "There was a problem with the file name"
	    incr exit_code 1
	}
	-re "(Can only do one cluster at a time)" {
		log_error "There was a problem with the dump"
	    incr exit_code 1
	}
	-re "too few arguments for keyword" {
		log_error "There was a problem with the dump request"
	    incr exit_code 1
	}
	-re "Unknown option" {
		log_error "There was a problem with the request"
	    incr exit_code 1
	}
	-re "(sacctmgr: Cluster)" {
		incr matches
		exp_continue
	}
	timeout {
		log_error "sacctmgr list associations not responding"
		slow_kill $my_pid
		incr exit_code 1
	}
	eof {
		wait
	}
}

if {$matches != 1} {
	log_error "File load 1 incorrect with only $matches"
	incr exit_code 1
}

set matches 0
set tfile [open "$file_out4" r]
while {[gets $tfile line] != -1} {

	if {![string compare $line "No such file or directory"]} {
		log_error "There was a problem with the sacctmgr command"
		incr exit_code 1
	} elseif {![string compare $line "$clu - '$tc3':$fs=$clus_req(fairshare):$gc=$clus_req(grptres):$gj=$clus_req(grpjob):$gs=$clus_req(grpsubmit):$mp=$clus_req(maxtresmin):$mu=$clus_req(maxtres):$mj=$clus_req(maxjobs):$ms=$clus_req(maxsubmit):$md=$clus_req(maxwall):$qs='$clus_req(qos)'"]} {
		log_debug "Match 1"
		incr matches
	} elseif {![string compare $line "$par - '$roo'"]} {
		log_debug "Match 2"
		incr matches
	} elseif {![string compare $line "$usr - '$roo':$dac='$roo':$al='$ala':$fs=1"]} {
		log_debug "Match 3"
		incr matches
	} elseif {![string compare $line "$acc - '$ta4':$dsc='$acct_req(description)':$org='$acct_req(organization)':$fs=$acct_req(fairshare):$gm=$acct_req(grptresmins):$gc=$acct_req(grptres):$gj=$acct_req(grpjobs):$gs=$acct_req(grpsubmitjobs):$gw=$acct_req(grpwall):$mp=$acct_req(maxtresmins):$mu=$acct_req(maxtres):$mj=$acct_req(maxjobs):$ms=$acct_req(maxsubmitjobs):$md=$acct_req(maxwall):$qs='$acct_req(qos)'"]} {
		log_debug "Match 4"
		incr matches
	} elseif {![string compare $line "$par - '$ta4'"]} {
		log_debug "Match 5"
		incr matches
	} elseif {![string compare $line "$usr - '$tu3':$dac='$user_req(defaultaccount)':$dw='$user_req(defaultwckey)':$al='$user_req(adminlevel)':$wk='$wckey_check':$fs=$user_req(fairshare):$gm=$user_req(grptresmins):$gc=$user_req(grptres):$gj=$user_req(grpjobs):$gs=$user_req(grpsubmitjobs):$gw=$user_req(grpwall):$mp=$user_req(maxtresmins):$mu=$user_req(maxtres):$mj=$user_req(maxjobs):$ms=$user_req(maxsubmitjobs):$md=$user_req(maxwall):$qs='$user_req(qos)'"]} {
		# should come through 2 times
		log_debug "Match 6"
		incr matches
	} elseif {![string compare $line "$acc - '$ta3':$dsc='$acct_req2(description)':$org='$acct_req2(organization)':$fs=$acct_req2(fairshare):$gm=$acct_req2(grptresmins):$gc=$acct_req2(grptres):$gj=$acct_req2(grpjobs):$gs=$acct_req2(grpsubmitjobs):$gw=$acct_req2(grpwall):$mp=$acct_req2(maxtresmins):$mu=$acct_req2(maxtres):$mj=$acct_req2(maxjobs):$ms=$acct_req2(maxsubmitjobs):$md=$acct_req2(maxwall):$qs='$acct_req2(qos)'"]} {
		log_debug "Match 7"
		incr matches
	} elseif {![string compare $line "$par - '$ta3'"]} {
		log_debug "Match 8"
		incr matches
	} elseif {![string compare $line "$acc - '$ta2':$dsc='$acct_req3(description)':$org='$acct_req3(organization)':$fs=$acct_req3(fairshare):$gm=$acct_req3(grptresmins):$gc=$acct_req3(grptres):$gj=$acct_req3(grpjobs):$gs=$acct_req3(grpsubmitjobs):$gw=$acct_req3(grpwall):$mp=$acct_req3(maxtresmins):$mu=$acct_req3(maxtres):$mj=$acct_req3(maxjobs):$ms=$acct_req3(maxsubmitjobs):$md=$acct_req3(maxwall):$qs='$acct_req3(qos)'"]} {
		log_debug "Match 9"
		incr matches
	} elseif {![string compare $line "$par - '$ta2'"]} {
		log_debug "Match 10"
		incr matches
	} elseif {![string compare $line "$usr - '$tu1':$dac='$user_req3(defaultaccount)':$dw='$user_req3(defaultwckey)':$wk='$wckey_check':$fs=$user_req3(fairshare):$gm=$user_req3(grptresmins):$gc=$user_req3(grptres):$gj=$user_req3(grpjobs):$gs=$user_req3(grpsubmitjobs):$gw=$user_req3(grpwall):$mp=$user_req3(maxtresmins):$mu=$user_req3(maxtres):$mj=$user_req3(maxjobs):$ms=$user_req3(maxsubmitjobs):$md=$user_req3(maxwall):$qs='$user_req3(qos)'"]} {
		log_debug "Match 11"
		incr matches
	} elseif {![string compare $line "$usr - '$tu2':$dac='$user_req2(defaultaccount)':$dw='$user_req2(defaultwckey)':$al='$user_req2(adminlevel)':$wk='$wckey_check':$fs=$user_req2(fairshare):$gm=$user_req2(grptresmins):$gc=$user_req2(grptres):$gj=$user_req2(grpjobs):$gs=$user_req2(grpsubmitjobs):$gw=$user_req2(grpwall):$mp=$user_req2(maxtresmins):$mu=$user_req2(maxtres):$mj=$user_req2(maxjobs):$ms=$user_req2(maxsubmitjobs):$md=$user_req2(maxwall):$qs='$user_req2(qos)'"]} {
		# should come through 2 times
		log_debug "Match 12"
		incr matches
	}
}


if {$matches != 14} {
	log_error "Parse of file for 14 entries incorrect with only $matches"
	incr exit_code 1
}

#
# This is the end below here

incr exit_code [remove_user "" "" "$tu1,$tu2,$tu3,$tu4"]
incr exit_code [remove_acct "" "$ta2,$ta3,$ta4"]
incr exit_code [remove_qos "$qs2"]
incr exit_code [remove_cluster "$tc1,$tc2,$tc3"]

if {$exit_code == 0} {
   	exec $bin_rm -f $file_out4
} else {
	fail "Test failed due to previous errors"
}
