#!/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_dir/input"
set file_in2    "$test_dir/input2"
set file_in3    "$test_dir/input3"
set file_out    "$test_dir/output"
set file_out2   "$test_dir/output2"
set file_out3   "$test_dir/output3"
set file_out4   "$test_dir/output4"
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_name}-cluster-1"
set tc2         "${test_name}-cluster-2"
set tc3         "${test_name}-cluster-3"
set acc         Account
set nams        names
set ta1         "${test_name}-account.1"
set ta2         "${test_name}-account.2"
set ta3         "${test_name}-account.3"
set ta4         "${test_name}-account.4"
set dsc         Description
set org         Organization
set usr         User
set tu1         "${test_name}-user.1"
set tu2         "${test_name}-user.2"
set tu3         "${test_name}-user.3"
set tu4         "${test_name}-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 {[get_admin_level] ne "Administrator"} {
	skip "This test can't be run without being an Accounting administrator.\nUse: sacctmgr mod user \$USER set admin=admin"
}

proc cleanup {} {
	global qs2 ta2 ta3 ta4 tc1 tc2 tc3 tu1 tu2 tu3 tu4

	remove_user "" "" "$tu1,$tu2,$tu3,$tu4"
	remove_acct "" "$ta2,$ta3,$ta4"
	remove_qos "$qs2"
	remove_cluster "$tc1,$tc2,$tc3"
}

# Make sure we have a clean system and permission to do this work
cleanup
if {$access_err != 0} {
	skip "Not authorized to perform this test"
}

# Add qos
if [add_qos "$qs2" ""] {
	fail "Unable to add qos ($qs2)"
}

#
# Add cluster
if [add_cluster $tc3 [array get clus_req]] {
	fail "Unable to add cluster ($tc3)"
}

# Add accounts
if [add_acct $ta4 [array get acct_req]] {
	fail "Unable to add account ($ta4)"
}

if [add_acct $ta3 [array get acct_req2]] {
	fail "Unable to add account ($ta3)"
}

if [add_acct $ta2 [array get acct_req3]] {
	fail "Unable to add account ($ta2)"
}

# Add users
if [add_user $tu3 [array get user_req]] {
	fail "Unable to add user ($tu3)"
}

if [add_user $tu2 [array get user_req2]] {
	fail "Unable to add user ($tu2)"
}

if [add_user $tu1 [array get user_req3]] {
	fail "Unable to add user ($tu1)"
}

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

if {$matches != 1} {
	fail "File load 1 incorrect ($matches != 1)"
}

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

	if {$line eq "No such file or directory"} {
		fail "There was a problem with the sacctmgr command"
	} elseif {$line eq "$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 {$line eq "$par - '$roo'"} {
		log_debug "Match 2"
		incr matches
	} elseif {$line eq "$usr - '$roo':$dac='$roo':$al='$ala':$fs=1"} {
		log_debug "Match 3"
		incr matches
	} elseif {$line eq "$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 {$line eq "$par - '$ta4'"} {
		log_debug "Match 5"
		incr matches
	} elseif {$line eq "$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 {$line eq "$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 {$line eq "$par - '$ta3'"} {
		log_debug "Match 8"
		incr matches
	} elseif {$line eq "$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 {$line eq "$par - '$ta2'"} {
		log_debug "Match 10"
		incr matches
	} elseif {$line eq "$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 {$line eq "$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} {
	fail "Parse of file for 14 entries incorrect ($matches != 14)"
}
