##############################################################################
#   Modules Revision 3.0
#   Providing a flexible user environment
#
#   File:		modules.50-cmds/%M%
#   Revision:		%I%
#   First Edition:	2018/06/06
#   Last Mod.:		%U%, %G%
#
#   Authors:		Xavier Delaruelle, xavier.delaruelle@cea.fr
#
#   Description:	Testuite testsequence
#   Command:        load, unload
#   Modulefiles:
#   Sub-Command:    prereq, conflict
#
#   Comment:	%C{
#           Test automatic resolution of modulefile dependencies when the
#           auto-handling mode is enabled (dependent modules handling)
#		}C%
#
##############################################################################

# enable auto_handling with environment variable
setenv_var MODULES_AUTO_HANDLING 1

set mp "$modpath.deps"

# setup specific environment
setenv_path_var MODULEPATH $mp

# test correct dependency resolution
set ans [list]
lappend ans [list setpath LOADEDMODULES "ca:cc:cd:ce:cf:cg"]
lappend ans [list setpath _LMFILES_ "$mp/ca:$mp/cc:$mp/cd:$mp/ce:$mp/cf:$mp/cg"]
lappend ans [list setpath MODULES_LMPREREQ "cc&ca|cb:cd&cc:ce&cd:cf&cc:cg&cf"]
lappend ans [list setpath MODULES_LMNOTUASKED "ca:cc:cd:cf"]
set tserr [list "load ca" "load cc" "load cd" "load ce" \n[msg_top_load ce {} [list ca cc cd] {}] "\nload cf" "load cg" \n[msg_top_load cg {} cf {}]]
testouterr_cmd_re "sh" "load ce cg" $ans [join $tserr "\n"]

# set environment with above result
setenv_loaded_module [list ca cc cd ce cf cg] [list "$mp/ca" "$mp/cc" "$mp/cd" "$mp/ce" "$mp/cf" "$mp/cg"] [list ca cc cd cf]
setenv_path_var MODULES_LMPREREQ "cc&ca|cb" "cd&cc" "ce&cd" "cf&cc" "cg&cf"

# load optional prereq module (alternative module was loaded automatically)
set ans [list]
lappend ans [list setpath LOADEDMODULES "ca:cb:cc:cd:ce:cf:cg"]
lappend ans [list setpath _LMFILES_ "$mp/ca:$mp/cb:$mp/cc:$mp/cd:$mp/ce:$mp/cf:$mp/cg"]
# LMPREREQ and LMNOTUASKED are updated as dependencies are reloaded
lappend ans [list setpath MODULES_LMPREREQ "cc&ca|cb:cd&cc:ce&cd:cf&cc:cg&cf"]
lappend ans [list setpath MODULES_LMNOTUASKED "ca:cc:cd:cf"]
set tserr [list "unload cg" "unload cf" "unload ce" "unload cd" "unload cc" "load cb" "load cc" "load cd" "load ce" "load cf" "load cg" \n[msg_top_load cb {} {} [list cc cd ce cf cg]]]
testouterr_cmd_re "sh" "load cb" $ans [join $tserr "\n"]

# set environment where every module has been asked by user
setenv_loaded_module [list ca cc cd ce cf cg] [list "$mp/ca" "$mp/cc" "$mp/cd" "$mp/ce" "$mp/cf" "$mp/cg"]
setenv_path_var MODULES_LMPREREQ "cc&ca|cb" "cd&cc" "ce&cd" "cf&cc" "cg&cf"

# load optional prereq module (every module loaded by user)
set ans [list]
lappend ans [list setpath LOADEDMODULES "ca:cb:cc:cd:ce:cf:cg"]
lappend ans [list setpath _LMFILES_ "$mp/ca:$mp/cb:$mp/cc:$mp/cd:$mp/ce:$mp/cf:$mp/cg"]
# LMPREREQ is updated as dependencies are reloaded
lappend ans [list setpath MODULES_LMPREREQ "cc&ca|cb:cd&cc:ce&cd:cf&cc:cg&cf"]
set tserr [list "unload cg" "unload cf" "unload ce" "unload cd" "unload cc" "load cb" "load cc" "load cd" "load ce" "load cf" "load cg" \n[msg_top_load cb {} {} [list cc cd ce cf cg]]]
testouterr_cmd_re "sh" "load cb" $ans [join $tserr "\n"]


# test with alternative prereq already loaded (asked by user)
setenv_loaded_module [list cb] [list "$mp/cb"]
unsetenv_path_var MODULES_LMPREREQ

set ans [list]
lappend ans [list setpath LOADEDMODULES "cb:cc:cd:ce:cf:cg"]
lappend ans [list setpath _LMFILES_ "$mp/cb:$mp/cc:$mp/cd:$mp/ce:$mp/cf:$mp/cg"]
lappend ans [list setpath MODULES_LMPREREQ "cc&ca|cb:cd&cc:ce&cd:cf&cc:cg&cf"]
lappend ans [list setpath MODULES_LMNOTUASKED "cc:cd:cf"]
set tserr [list "load cc" "load cd" "load ce" \n[msg_top_load ce {} [list cc cd] {}] "\nload cf" "load cg" \n[msg_top_load cg {} cf {}]]
testouterr_cmd_re "sh" "load ce cg" $ans [join $tserr "\n"]

# set environment with above result
setenv_loaded_module [list cb cc cd ce cf cg] [list "$mp/cb" "$mp/cc" "$mp/cd" "$mp/ce" "$mp/cf" "$mp/cg"] [list cc cd cf]
setenv_path_var MODULES_LMPREREQ "cc&ca|cb" "cd&cc" "ce&cd" "cf&cc" "cg&cf"

# load optional first-in-list prereq module
set ans [list]
lappend ans [list setpath LOADEDMODULES "cb:ca:cc:cd:ce:cf:cg"]
lappend ans [list setpath _LMFILES_ "$mp/cb:$mp/ca:$mp/cc:$mp/cd:$mp/ce:$mp/cf:$mp/cg"]
# LMPREREQ and LMNOTUASKED are updated as dependencies are reloaded
lappend ans [list setpath MODULES_LMPREREQ "cc&ca|cb:cd&cc:ce&cd:cf&cc:cg&cf"]
lappend ans [list setpath MODULES_LMNOTUASKED "cc:cd:cf"]
set tserr [list "unload cg" "unload cf" "unload ce" "unload cd" "unload cc" "load ca" "load cc" "load cd" "load ce" "load cf" "load cg" \n[msg_top_load ca {} {} [list cc cd ce cf cg]]]
testouterr_cmd_re "sh" "load ca" $ans [join $tserr "\n"]

# set environment where every module has been asked by user
setenv_loaded_module [list cb cc cd ce cf cg] [list "$mp/cb" "$mp/cc" "$mp/cd" "$mp/ce" "$mp/cf" "$mp/cg"]
setenv_path_var MODULES_LMPREREQ "cc&ca|cb" "cd&cc" "ce&cd" "cf&cc" "cg&cf"

# load optional first-in-list prereq module (every module loaded by user)
set ans [list]
lappend ans [list setpath LOADEDMODULES "cb:ca:cc:cd:ce:cf:cg"]
lappend ans [list setpath _LMFILES_ "$mp/cb:$mp/ca:$mp/cc:$mp/cd:$mp/ce:$mp/cf:$mp/cg"]
# LMPREREQ is updated as dependencies are reloaded
lappend ans [list setpath MODULES_LMPREREQ "cc&ca|cb:cd&cc:ce&cd:cf&cc:cg&cf"]
set tserr [list "unload cg" "unload cf" "unload ce" "unload cd" "unload cc" "load ca" "load cc" "load cd" "load ce" "load cf" "load cg" \n[msg_top_load ca {} {} [list cc cd ce cf cg]]]
testouterr_cmd_re "sh" "load ca" $ans [join $tserr "\n"]


# set environment with both optional prereq loaded
setenv_loaded_module [list ca cb cc cd ce cf cg] [list "$mp/ca" "$mp/cb" "$mp/cc" "$mp/cd" "$mp/ce" "$mp/cf" "$mp/cg"] [list ca cc cd cf]
setenv_path_var MODULES_LMPREREQ "cc&ca|cb" "cd&cc" "ce&cd" "cf&cc" "cg&cf"

# unload optional first-in-list prereq module
set ans [list]
lappend ans [list setpath LOADEDMODULES "cb:cc:cd:ce:cf:cg"]
lappend ans [list setpath _LMFILES_ "$mp/cb:$mp/cc:$mp/cd:$mp/ce:$mp/cf:$mp/cg"]
# LMPREREQ and LMNOTUASKED are updated as dependencies are reloaded
lappend ans [list setpath MODULES_LMPREREQ "cc&ca|cb:cd&cc:ce&cd:cf&cc:cg&cf"]
lappend ans [list setpath MODULES_LMNOTUASKED "cc:cd:cf"]
set tserr [list "unload cg" "unload cf" "unload ce" "unload cd" "unload cc" "unload ca" "load cc" "load cd" "load ce" "load cf" "load cg" \n[msg_top_unload ca {} {} [list cc cd ce cf cg]]]
testouterr_cmd_re "sh" "unload ca" $ans [join $tserr "\n"]

# unload optional second-in-list prereq module
set ans [list]
lappend ans [list setpath LOADEDMODULES "ca:cc:cd:ce:cf:cg"]
lappend ans [list setpath _LMFILES_ "$mp/ca:$mp/cc:$mp/cd:$mp/ce:$mp/cf:$mp/cg"]
# LMPREREQ and LMNOTUASKED are updated as dependencies are reloaded
lappend ans [list setpath MODULES_LMPREREQ "cc&ca|cb:cd&cc:ce&cd:cf&cc:cg&cf"]
lappend ans [list setpath MODULES_LMNOTUASKED "ca:cc:cd:cf"]
set tserr [list "unload cg" "unload cf" "unload ce" "unload cd" "unload cc" "unload cb" "load cc" "load cd" "load ce" "load cf" "load cg" \n[msg_top_unload cb {} {} [list cc cd ce cf cg]]]
testouterr_cmd_re "sh" "unload cb" $ans [join $tserr "\n"]


# restore environment
unsetenv_path_var MODULES_LMPREREQ
unsetenv_loaded_module

# test load of first-operational-in-list prereq module
set ans [list]
lappend ans [list setpath LOADEDMODULES "dd:df:dg"]
lappend ans [list setpath _LMFILES_ "$mp/dd:$mp/df:$mp/dg"]
lappend ans [list setpath MODULES_LMNOTUASKED "dd:df"]
lappend ans [list setpath MODULES_LMCONFLICT "dg&db"]
lappend ans [list setpath MODULES_LMPREREQ "df&da|db|dc|dd|de:dg&df"]
lappend ans [list ERR]
# as da, db and dc are not valid requirement, their load attempt output is dropped
set tserr [list "load dd" "load df" "load dg" \n[msg_top_load dg {} [list dd df] {}]]
testouterr_cmd_re "sh" "load dg" $ans [join $tserr "\n"]

# test with alternative prereq already loaded (asked by user)
setenv_loaded_module [list de] [list "$mp/de"]

# test load of first-operational-in-list prereq module with alternative prereq already loaded
set ans [list]
lappend ans [list setpath LOADEDMODULES "de:df:dg"]
lappend ans [list setpath _LMFILES_ "$mp/de:$mp/df:$mp/dg"]
lappend ans [list setpath MODULES_LMNOTUASKED "df"]
lappend ans [list setpath MODULES_LMCONFLICT "dg&db"]
lappend ans [list setpath MODULES_LMPREREQ "df&da|db|dc|dd|de:dg&df"]
set tserr [list "load df" "load dg" \n[msg_top_load dg {} df {}]]
testouterr_cmd_re "sh" "load dg" $ans [join $tserr "\n"]

# set environment where every module has been asked by user
setenv_loaded_module [list de df dg] [list "$mp/de" "$mp/df" "$mp/dg"]
setenv_path_var MODULES_LMPREREQ "df&da|db|dc|dd|de" "dg&df"
setenv_path_var MODULES_LMCONFLICT "dg&db"

# attempt to unload first-operational-in-list prereq module
set ans [list]
lappend ans [list unsetpath LOADEDMODULES]
lappend ans [list unsetpath _LMFILES_]
lappend ans [list unsetpath MODULES_LMCONFLICT]
lappend ans [list unsetpath MODULES_LMPREREQ]
set tserr [list "unload dg" "unload df" "unload de" \n[msg_top_unload de [list dg df] {} {}]]
testouterr_cmd_re "sh" "unload de" $ans [join $tserr "\n"]


# tests with prereq suite fully loaded
setenv_loaded_module [list dd df dg] [list "$mp/dd" "$mp/df" "$mp/dg"] [list dd df]
setenv_path_var MODULES_LMPREREQ "df&da|db|dc|dd|de" "dg&df"
setenv_path_var MODULES_LMCONFLICT "dg&db"

# attempt to load broken/conflicting prereq alternative
# dependent modules are unloaded prior "da" load but cannot be reloaded as "da" declares a conflict on them
set tserr [list "unload dg" "unload df" "load da" "load df" \n[msg_load df [err_conlo da]] \n[msg_load da [err_depre df]]]
testouterr_cmd_re "sh" "load da" ERR [join $tserr "\n"]
set tserr [list "load db" \n[msg_load db [err_conflict dg]]]
testouterr_cmd_re "sh" "load db" "ERR" [join $tserr "\n"]
# dependent modules are unloaded prior "dc" load but as dc breaks everything is restored
set tserr [list "unload dg" "unload df" "load dc" \n[msg_load dc $err_evalabort]]
testouterr_cmd_re "sh" "load dc" "ERR" [join $tserr "\n"]


# tests with one module missing from prereq suite
setenv_loaded_module [list df dg] [list "$mp/df" "$mp/dg"]
setenv_path_var MODULES_LMPREREQ "df&da|db|dc|dd|de" "dg&df"
setenv_path_var MODULES_LMCONFLICT "dg&db"

# attempt to load broken/conflicting module solving missing prereq requirement
set ans [list]
lappend ans [list setpath LOADEDMODULES "da"]
lappend ans [list setpath _LMFILES_ "$mp/da"]
lappend ans [list unsetpath MODULES_LMPREREQ]
lappend ans [list setpath MODULES_LMCONFLICT "da&df"]
lappend ans [list ERR]
# dependent modules are unloaded prior "da" load but cannot be reloaded as "da" declares a conflict on them
set tserr [list "unload dg" "unload df" "load da" "load df" \n[msg_load df [err_conlo da]] \n[msg_load da [err_depre df]]]
testouterr_cmd_re "sh" "load da" ERR [join $tserr "\n"]
set tserr [list "load db" \n[msg_load db [err_conflict dg]]]
testouterr_cmd_re "sh" "load db" "ERR" [join $tserr "\n"]
# dependent modules are unloaded prior "dc" load but as dc breaks everything is restored
set tserr [list "unload dg" "unload df" "load dc" \n[msg_load dc $err_evalabort]]
testouterr_cmd_re "sh" "load dc" "ERR" [join $tserr "\n"]
set ans [list]
lappend ans [list setpath LOADEDMODULES "dd:df:dg"]
lappend ans [list setpath _LMFILES_ "$mp/dd:$mp/df:$mp/dg"]
lappend ans [list setpath MODULES_LMCONFLICT "dg&db"]
lappend ans [list setpath MODULES_LMPREREQ "df&da|db|dc|dd|de:dg&df"]
set tserr [list "unload dg" "unload df" "load dd" "load df" "load dg" \n[msg_top_load dd  {} {} [list df dg]]]
testouterr_cmd_re "sh" "load dd" $ans [join $tserr "\n"]


# test reload dependent mechanism order with modulefiles looking at currently loaded prereqs to define variable
setenv_loaded_module [list g1 g4] [list "$mp/g1" "$mp/g4"]
setenv_path_var MODULES_LMPREREQ "g4&g1|g2|g3"
unsetenv_path_var MODULES_LMCONFLICT
setenv_path_var FOO "/path/to/g4-g1"

set ans [list]
lappend ans [list setpath FOO "/path/to/g4-g1-g2"]
lappend ans [list setpath LOADEDMODULES "g1:g2:g4"]
lappend ans [list setpath _LMFILES_ "$mp/g1:$mp/g2:$mp/g4"]
lappend ans [list setpath MODULES_LMPREREQ "g4&g1|g2|g3"]
testouterr_cmd_re "sh" "load g2" $ans [msg_top_load g2 {} {} g4]

set ans [list]
lappend ans [list setpath FOO "/path/to/g4-g2"]
lappend ans [list setpath LOADEDMODULES "g2:g4"]
lappend ans [list setpath _LMFILES_ "$mp/g2:$mp/g4"]
lappend ans [list setpath MODULES_LMPREREQ "g4&g1|g2|g3"]
testouterr_cmd_re "sh" "switch g1 g2" $ans [msg_top_switch g1 g2 {} {} {} {} g4]

# unload test that creates a prereq violation
set ans [list]
lappend ans [list setpath LOADEDMODULES "g4"]
lappend ans [list setpath _LMFILES_ "$mp/g4"]
testouterr_cmd_re "sh" "unload --force --no-auto g1" $ans [msg_unload g1 [err_deplof g4]]

# set loaded situation where a prereq violation exists
setenv_loaded_module [list g4] [list "$mp/g4"]

# load test that solves a prereq violation
set ans [list]
lappend ans [list set FOO "/path/to/g4-g1"]
lappend ans [list set FOO_modshare "/path/to/g4-g1:2"]
lappend ans [list setpath LOADEDMODULES "g1:g4"]
lappend ans [list setpath _LMFILES_ "$mp/g1:$mp/g4"]
lappend ans [list setpath MODULES_LMPREREQ "g4&g1|g2|g3"]
# g4 unload phase did not correctly unset path in FOO (double reference to g1 path)
testouterr_cmd_re "sh" "load g1" $ans [msg_top_load g1 {} {} g4]

set ans [list]
lappend ans [list setpath FOO "/path/to/g4-g2:/path/to/g4-g1"]
lappend ans [list setpath LOADEDMODULES "g2:g4"]
lappend ans [list setpath _LMFILES_ "$mp/g2:$mp/g4"]
lappend ans [list setpath MODULES_LMPREREQ "g4&g1|g2|g3"]
# g4 unload phase did not correctly unset path in FOO (still reference to g1 path)
testouterr_cmd_re "sh" "load g2" $ans [msg_top_load g2 {} {} g4]

# set loaded situation with multiple optional prereqs loaded
setenv_loaded_module [list g1 g2 g4] [list "$mp/g1" "$mp/g2" "$mp/g4"]
setenv_path_var FOO "/path/to/g4-g1-g2"

set ans [list]
lappend ans [list setpath FOO "/path/to/g4-g2"]
lappend ans [list setpath LOADEDMODULES "g2:g4"]
lappend ans [list setpath _LMFILES_ "$mp/g2:$mp/g4"]
lappend ans [list setpath MODULES_LMPREREQ "g4&g1|g2|g3"]
testouterr_cmd_re "sh" "unload g1" $ans [msg_top_unload g1 {} {} g4]

# load test that creates a conflict violation
set ans [list]
lappend ans [list setpath FOO "/path/to/g4-g1-g2-g3"]
lappend ans [list setpath LOADEDMODULES "g1:g2:g3:g4"]
lappend ans [list setpath _LMFILES_ "$mp/g1:$mp/g2:$mp/g3:$mp/g4"]
lappend ans [list setpath MODULES_LMPREREQ "g4&g1|g2|g3"]
lappend ans [list setpath MODULES_LMCONFLICT "g3&g2"]
testouterr_cmd_re "sh" "load --force g3" $ans [msg_top_load g3 {} {} g4 [err_conlof g2]]

# set loaded situation where a conflict violation exists
setenv_loaded_module [list g1 g2 g3 g4] [list "$mp/g1" "$mp/g2" "$mp/g3" "$mp/g4"]
setenv_path_var MODULES_LMCONFLICT "g3&g2"
setenv_path_var FOO "/path/to/g4-g1-g2-g3"

# unload test that solves a conflict violation
set ans [list]
lappend ans [list setpath FOO "/path/to/g4-g1-g2"]
lappend ans [list setpath LOADEDMODULES "g1:g2:g4"]
lappend ans [list setpath _LMFILES_ "$mp/g1:$mp/g2:$mp/g4"]
lappend ans [list setpath MODULES_LMPREREQ "g4&g1|g2|g3"]
lappend ans [list unsetpath MODULES_LMCONFLICT]
testouterr_cmd_re "sh" "unload g3" $ans [msg_top_unload g3 {} {} [list g2 g4]]

# set loaded situation where a conflict violation exists on main module
setenv_loaded_module [list g1 g2 g4 g5] [list "$mp/g1" "$mp/g2" "$mp/g4" "$mp/g5"]
setenv_path_var MODULES_LMCONFLICT "g5&g4"
setenv_path_var FOO "/path/to/g4-g1-g2"

# as conflict exist, main module is not reloaded whereas one of its optional prereq has been unloaded
set ans [list]
lappend ans [list setpath LOADEDMODULES "g1:g4:g5"]
lappend ans [list setpath _LMFILES_ "$mp/g1:$mp/g4:$mp/g5"]
testouterr_cmd_re "sh" "unload g2" $ans ""

# set previous result as loaded situation
setenv_loaded_module [list g1 g4 g5] [list "$mp/g1" "$mp/g4" "$mp/g5"]

# although conflict is solved g4 is not able to correctly unset previous FOO value as it was not
# updated when conflict violation was there
set ans [list]
lappend ans [list setpath FOO "/path/to/g4-g1:/path/to/g4-g1-g2"]
lappend ans [list setpath LOADEDMODULES "g1:g4"]
lappend ans [list setpath _LMFILES_ "$mp/g1:$mp/g4"]
lappend ans [list setpath MODULES_LMPREREQ "g4&g1|g2|g3"]
lappend ans [list unsetpath MODULES_LMCONFLICT]
testouterr_cmd_re "sh" "unload g5" $ans [msg_top_unload g5 {} {} g4]


# test situation where an automatically loaded prereq (h1) of a module currently being unloaded (h2)
# is also a prereq of a module (h4) optionally dependent of the module being unloaded, this prereq
# (h1) should not be considered unloadable as it is still needed by the dependent module (h4)
setenv_loaded_module [list h1 h2 h3 h4] [list "$mp/h1" "$mp/h2" "$mp/h3" "$mp/h4"] [list h1]
setenv_path_var MODULES_LMPREREQ "h2&h1" "h4&h1&h2|h3"
unsetenv_path_var MODULES_LMCONFLICT

set ans [list]
lappend ans [list setpath LOADEDMODULES "h1:h3:h4"]
lappend ans [list setpath _LMFILES_ "$mp/h1:$mp/h3:$mp/h4"]
lappend ans [list setpath MODULES_LMPREREQ "h4&h1&h2|h3"]
set tserr [list "unload h4" "unload h2" "load h4" \n[msg_top_unload h2 {} {} h4]]
testouterr_cmd_re "sh" "unload h2" $ans [join $tserr "\n"]


# test situation where a useless requirement module is also a requirement of another useless requirement module
setenv_loaded_module [list h10 h11 h12] [list "$mp/h10" "$mp/h11" "$mp/h12"] [list h10 h11]
setenv_path_var MODULES_LMPREREQ "h11&h10" "h12&h11&h10"

set ans [list]
lappend ans [list unsetpath LOADEDMODULES]
lappend ans [list unsetpath _LMFILES_]
lappend ans [list unsetpath MODULES_LMPREREQ]
lappend ans [list unsetpath MODULES_LMNOTUASKED]
set tserr [list "unload h12" "unload h11" "unload h10" \n[msg_top_unload h12 {} [list h11 h10] {}]]
testouterr_cmd_re "sh" "unload h12" $ans [join $tserr "\n"]


# test situation where useless requirement modules are interconnected but everything should be unloaded when top module is unloaded
setenv_loaded_module [list h20 h21 h22 h23 h24 h25] [list "$mp/h20" "$mp/h21" "$mp/h22" "$mp/h23" "$mp/h24" "$mp/h25"] [list h20 h21 h22 h23 h24]
setenv_path_var MODULES_LMPREREQ "h21&h20" "h22&h21" "h23&h21" "h24&h23" "h25&h21&h22&h24"

set ans [list]
lappend ans [list unsetpath LOADEDMODULES]
lappend ans [list unsetpath _LMFILES_]
lappend ans [list unsetpath MODULES_LMPREREQ]
lappend ans [list unsetpath MODULES_LMNOTUASKED]
set tserr [list "unload h25" "unload h24" "unload h23" "unload h22" "unload h21" "unload h20" \n[msg_top_unload h25 {} [list h24 h23 h22 h21 h20] {}]]
testouterr_cmd_re "sh" "unload h25" $ans [join $tserr "\n"]


# test situations where candidate useless requirement modules still hold an optional dependency link
# useless requirement module candidate is still optional requirement of another module, no unload
setenv_loaded_module [list h30 h31 h32 h34 h35] [list "$mp/h30" "$mp/h31" "$mp/h32" "$mp/h34" "$mp/h35"] [list h30 h31]
setenv_path_var MODULES_LMPREREQ "h31&h30" "h32&h31" "h35&h34|h31"
set ans [list]
lappend ans [list setpath LOADEDMODULES "h30:h31:h34:h35"]
lappend ans [list setpath _LMFILES_ "$mp/h30:$mp/h31:$mp/h34:$mp/h35"]
lappend ans [list setpath MODULES_LMPREREQ "h31&h30:h35&h34|h31"]
set tserr [list "unload h32"]
testouterr_cmd_re "sh" "unload h32" $ans [join $tserr "\n"]

# useless requirement module candidate is still optional requirement of another module, no unload
# but main module was also optional requirement, so dependent is reloaded
setenv_loaded_module [list h30 h31 h32 h34 h36] [list "$mp/h30" "$mp/h31" "$mp/h32" "$mp/h34" "$mp/h36"] [list h30 h31]
setenv_path_var MODULES_LMPREREQ "h31&h30" "h32&h31" "h36&h34|h30|h32"
set ans [list]
lappend ans [list setpath LOADEDMODULES "h30:h34:h36"]
lappend ans [list setpath _LMFILES_ "$mp/h30:$mp/h34:$mp/h36"]
lappend ans [list setpath MODULES_LMPREREQ "h36&h34|h30|h32"]
lappend ans [list setpath MODULES_LMNOTUASKED "h30"]
set tserr [list "unload h36" "unload h32" "unload h31" "load h36" \n[msg_top_unload h32 {} h31 h36]]
testouterr_cmd_re "sh" "unload h32" $ans [join $tserr "\n"]

# useless requirement module candidates are both still optional requirement of another module, no unload
setenv_loaded_module [list h30 h31 h32 h34 h37] [list "$mp/h30" "$mp/h31" "$mp/h32" "$mp/h34" "$mp/h37"] [list h30 h31]
setenv_path_var MODULES_LMPREREQ "h31&h30" "h32&h31" "h37&h34|h30|h31"
set ans [list]
lappend ans [list setpath LOADEDMODULES "h30:h31:h34:h37"]
lappend ans [list setpath _LMFILES_ "$mp/h30:$mp/h31:$mp/h34:$mp/h37"]
lappend ans [list setpath MODULES_LMPREREQ "h31&h30:h37&h34|h30|h31"]
set tserr [list "unload h32"]
testouterr_cmd_re "sh" "unload h32" $ans [join $tserr "\n"]


# test situations where unload of useless requirement modules triggers reload of conflicting module
# unload of a useless requirement module solves a conflict violation
setenv_loaded_module [list h30 h31 h32 h33] [list "$mp/h30" "$mp/h31" "$mp/h32" "$mp/h33"] [list h30 h31]
setenv_path_var MODULES_LMPREREQ "h31&h30" "h32&h31"
setenv_path_var MODULES_LMCONFLICT "h33&h31"
set ans [list]
lappend ans [list setpath LOADEDMODULES "h33"]
lappend ans [list setpath _LMFILES_ "$mp/h33"]
lappend ans [list setpath MODULES_LMCONFLICT "h33&h31"]
lappend ans [list unsetpath MODULES_LMPREREQ]
lappend ans [list unsetpath MODULES_LMNOTUASKED]
set tserr [list "unload h33" "unload h32" "unload h31" "unload h30" "load h33" \n[msg_top_unload h32 {} [list h31 h30] h33]]
testouterr_cmd_re "sh" "unload h32" $ans [join $tserr "\n"]

# unload of two useless requirement modules solves a conflict violation
setenv_loaded_module [list h30 h31 h32 h38] [list "$mp/h30" "$mp/h31" "$mp/h32" "$mp/h38"] [list h30 h31]
setenv_path_var MODULES_LMCONFLICT "h38&h30&h31"
set ans [list]
lappend ans [list setpath LOADEDMODULES "h38"]
lappend ans [list setpath _LMFILES_ "$mp/h38"]
lappend ans [list setpath MODULES_LMCONFLICT "h38&h30&h31"]
lappend ans [list unsetpath MODULES_LMPREREQ]
lappend ans [list unsetpath MODULES_LMNOTUASKED]
set tserr [list "unload h38" "unload h32" "unload h31" "unload h30" "load h38" \n[msg_top_unload h32 {} [list h31 h30] h38]]
testouterr_cmd_re "sh" "unload h32" $ans [join $tserr "\n"]

# unload of a useless requirement module and main module solves a conflict violation (just one reload)
setenv_loaded_module [list h30 h31 h32 h39] [list "$mp/h30" "$mp/h31" "$mp/h32" "$mp/h39"] [list h30 h31]
setenv_path_var MODULES_LMCONFLICT "h39&h31&h32"
set ans [list]
lappend ans [list setpath LOADEDMODULES "h39"]
lappend ans [list setpath _LMFILES_ "$mp/h39"]
lappend ans [list setpath MODULES_LMCONFLICT "h39&h31&h32"]
lappend ans [list unsetpath MODULES_LMPREREQ]
lappend ans [list unsetpath MODULES_LMNOTUASKED]
set tserr [list "unload h39" "unload h32" "unload h31" "unload h30" "load h39" \n[msg_top_unload h32 {} [list h31 h30] h39]]
testouterr_cmd_re "sh" "unload h32" $ans [join $tserr "\n"]

# unload of a useless requirement module and main module reduce a conflict violation but one conflicting module is still loaded (no reload)
setenv_loaded_module [list h30 h31 h32 h40 h34] [list "$mp/h30" "$mp/h31" "$mp/h32" "$mp/h40" "$mp/h34"] [list h30 h31]
setenv_path_var MODULES_LMCONFLICT "h40&h31&h32&h34"
set ans [list]
lappend ans [list setpath LOADEDMODULES "h40:h34"]
lappend ans [list setpath _LMFILES_ "$mp/h40:$mp/h34"]
lappend ans [list unsetpath MODULES_LMPREREQ]
lappend ans [list unsetpath MODULES_LMNOTUASKED]
set tserr [list "unload h32" "unload h31" "unload h30" \n[msg_top_unload h32 {} [list h31 h30] {}]]
testouterr_cmd_re "sh" "unload h32" $ans [join $tserr "\n"]


# Dependent Unload (DU) mechanism
setenv_loaded_module [list h50 h51] [list "$mp/h50" "$mp/h51"] [list h50]
setenv_path_var MODULES_LMPREREQ "h51&h50"
unsetenv_path_var MODULES_LMCONFLICT
set ans [list]
lappend ans [list unsetpath LOADEDMODULES]
lappend ans [list unsetpath _LMFILES_]
lappend ans [list unsetpath MODULES_LMPREREQ]
lappend ans [list unsetpath MODULES_LMNOTUASKED]
set tserr [list "unload h51" "unload h50" \n[msg_top_unload h50 h51 {} {}]]
testouterr_cmd_re "sh" "unload h50" $ans [join $tserr "\n"]

setenv_loaded_module [list h50 h51 h53 h54] [list "$mp/h50" "$mp/h51" "$mp/h53" "$mp/h54"] [list h50]
setenv_path_var MODULES_LMPREREQ "h51&h50" "h53&h51" "h54&h51|h57"
set ans [list]
lappend ans [list unsetpath LOADEDMODULES]
lappend ans [list unsetpath _LMFILES_]
lappend ans [list unsetpath MODULES_LMPREREQ]
lappend ans [list unsetpath MODULES_LMNOTUASKED]
set tserr [list "unload h54" "unload h53" "unload h51" "unload h50" \n[msg_top_unload h50 [list h54 h53 h51] {} {}]]
testouterr_cmd_re "sh" "unload h50" $ans [join $tserr "\n"]

setenv_loaded_module [list h50 h51 h52] [list "$mp/h50" "$mp/h51"  "$mp/h52"]
setenv_path_var MODULES_LMPREREQ "h51&h50" "h52&h50"
set ans [list]
lappend ans [list unsetpath LOADEDMODULES]
lappend ans [list unsetpath _LMFILES_]
lappend ans [list unsetpath MODULES_LMPREREQ]
set tserr [list "unload h52" "unload h51" "unload h50" \n[msg_top_unload h50 [list h52 h51] {} {}]]
testouterr_cmd_re "sh" "unload h50" $ans [join $tserr "\n"]

setenv_loaded_module [list h50 h51 h52 h53 h54 h55 h58 h56] [list "$mp/h50" "$mp/h51"  "$mp/h52" "$mp/h53" "$mp/h54" "$mp/h55" "$mp/h58" "$mp/h56"] [list h58]
setenv_path_var MODULES_LMPREREQ "h51&h50" "h52&h50" "h53&h51" "h54&h51|h57" "h55&h51&h52" "h56&h52&h58"
set ans [list]
lappend ans [list unsetpath LOADEDMODULES]
lappend ans [list unsetpath _LMFILES_]
lappend ans [list unsetpath MODULES_LMPREREQ]
lappend ans [list unsetpath MODULES_LMNOTUASKED]
set tserr [list "unload h56" "unload h55" "unload h54" "unload h53" "unload h52" "unload h51" "unload h50" "unload h58" \n[msg_top_unload h50 [list h56 h55 h54 h53 h52 h51] h58 {}]]
testouterr_cmd_re "sh" "unload h50" $ans [join $tserr "\n"]

# uncommon case where a requirement is loaded after a module requiring it and has been automatically loaded by some module not loaded anymore
# (loaded from a 'module load' command in a modulefile which has been loaded in a --no-auto mode)
# this required module (h58) will not take part of the unload process as it is loaded after its dependent
setenv_loaded_module [list h50 h51 h52 h53 h54 h55 h56 h58] [list "$mp/h50" "$mp/h51"  "$mp/h52" "$mp/h53" "$mp/h54" "$mp/h55" "$mp/h56" "$mp/h58"] [list h58]
setenv_path_var MODULES_LMPREREQ "h51&h50" "h52&h50" "h53&h51" "h54&h51|h57" "h55&h51&h52" "h56&h52&h58"
set ans [list]
lappend ans [list setpath LOADEDMODULES h58]
lappend ans [list setpath _LMFILES_ $mp/h58]
lappend ans [list unsetpath MODULES_LMPREREQ]
set tserr [list "unload h56" "unload h55" "unload h54" "unload h53" "unload h52" "unload h51" "unload h50" \n[msg_top_unload h50 [list h56 h55 h54 h53 h52 h51] {} {}]]
testouterr_cmd_re "sh" "unload h50" $ans [join $tserr "\n"]

# h58 has been loaded in no-auto mode, thus h56 has not been reloaded when h58 has been loaded,
# so h58 has been asked by user and it is not part of the unloading batch (UreqUn)
setenv_loaded_module [list h50 h51 h52 h53 h54 h55 h56 h58] [list "$mp/h50" "$mp/h51"  "$mp/h52" "$mp/h53" "$mp/h54" "$mp/h55" "$mp/h56" "$mp/h58"]
setenv_path_var MODULES_LMPREREQ "h51&h50" "h52&h50" "h53&h51" "h54&h51|h57" "h55&h51&h52" "h56&h52&h58"
set ans [list]
lappend ans [list setpath LOADEDMODULES h58]
lappend ans [list setpath _LMFILES_ $mp/h58]
lappend ans [list unsetpath MODULES_LMPREREQ]
set tserr [list "unload h56" "unload h55" "unload h54" "unload h53" "unload h52" "unload h51" "unload h50" \n[msg_top_unload h50 [list h56 h55 h54 h53 h52 h51] {} {}]]
testouterr_cmd_re "sh" "unload h50" $ans [join $tserr "\n"]

setenv_loaded_module [list h50 h51 h52 h53 h57 h54 h55 h56 h58] [list "$mp/h50" "$mp/h51"  "$mp/h52" "$mp/h53" "$mp/h57" "$mp/h54" "$mp/h55" "$mp/h56" "$mp/h58"]
setenv_path_var MODULES_LMPREREQ "h51&h50" "h52&h50" "h53&h51" "h54&h51|h57" "h55&h51&h52" "h56&h52&h58"
set ans [list]
lappend ans [list setpath LOADEDMODULES "h57:h58:h54"]
lappend ans [list setpath _LMFILES_ "$mp/h57:$mp/h58:$mp/h54"]
lappend ans [list setpath MODULES_LMPREREQ "h54&h51|h57"]
set tserr [list "unload h54" "unload h56" "unload h55" "unload h53" "unload h52" "unload h51" "unload h50" "load h54" \n[msg_top_unload h50 [list h56 h55 h53 h52 h51] {} h54]]
testouterr_cmd_re "sh" "unload h50" $ans [join $tserr "\n"]


# DepUn mechanism impact on UReqUn mechanism
setenv_loaded_module [list h60 h61 h62] [list "$mp/h60" "$mp/h61" "$mp/h62"] [list h60 h61]
setenv_path_var MODULES_LMPREREQ "h62&h60&h61"
set ans [list]
lappend ans [list unsetpath LOADEDMODULES]
lappend ans [list unsetpath _LMFILES_]
lappend ans [list unsetpath MODULES_LMPREREQ]
lappend ans [list unsetpath MODULES_LMNOTUASKED]
set tserr [list "unload h62" "unload h60" "unload h61" \n[msg_top_unload h60 h62 h61 {}]]
testouterr_cmd_re "sh" "unload h60" $ans [join $tserr "\n"]

setenv_loaded_module [list h60 h61 h62] [list "$mp/h60" "$mp/h61" "$mp/h62"] [list h61]
setenv_path_var MODULES_LMPREREQ "h62&h60&h61"
testouterr_cmd_re "sh" "unload h60" $ans [join $tserr "\n"]

# try DepUn UReqUn impact with main module in prereq violation (h60)
setenv_loaded_module [list h61 h62 h63] [list "$mp/h61" "$mp/h62" "$mp/h63"] [list h61]
setenv_path_var MODULES_LMPREREQ "h62&h60&h61" "h63&h61&h62"
set tserr [list "unload h63" "unload h62" "unload h61" \n[msg_top_unload h62 h63 h61 {}]]
testouterr_cmd_re "sh" "unload h62" $ans [join $tserr "\n"]

setenv_loaded_module [list h60 h61 h62 h63] [list "$mp/h60" "$mp/h61" "$mp/h62" "$mp/h63"] [list h60 h61]
setenv_path_var MODULES_LMPREREQ "h62&h60&h61" "h63&h61&h62"
set tserr [list "unload h63" "unload h62" "unload h60" "unload h61" \n[msg_top_unload h60 [list h63 h62] h61 {}]]
testouterr_cmd_re "sh" "unload h60" $ans [join $tserr "\n"]

setenv_loaded_module [list h60 h61 h62 h63] [list "$mp/h60" "$mp/h61" "$mp/h62" "$mp/h63"] [list h60]
setenv_path_var MODULES_LMPREREQ "h62&h60&h61" "h63&h61&h62"
set ans [list]
lappend ans [list setpath LOADEDMODULES "h61"]
lappend ans [list setpath _LMFILES_ "$mp/h61"]
lappend ans [list unsetpath MODULES_LMPREREQ]
lappend ans [list unsetpath MODULES_LMNOTUASKED]
set tserr [list "unload h63" "unload h62" "unload h60" \n[msg_top_unload h60 [list h63 h62] {} {}]]
testouterr_cmd_re "sh" "unload h60" $ans [join $tserr "\n"]

setenv_loaded_module [list h60 h61 h62 h63 h64] [list "$mp/h60" "$mp/h61" "$mp/h62" "$mp/h63" "$mp/h64"] [list h60 h61]
setenv_path_var MODULES_LMPREREQ "h62&h60&h61" "h63&h61&h62" "h64&h61"
set ans [list]
lappend ans [list setpath LOADEDMODULES "h61:h64"]
lappend ans [list setpath _LMFILES_ "$mp/h61:$mp/h64"]
lappend ans [list setpath MODULES_LMPREREQ "h64&h61"]
lappend ans [list setpath MODULES_LMNOTUASKED "h61"]
set tserr [list "unload h63" "unload h62" "unload h60" \n[msg_top_unload h60 [list h63 h62] {} {}]]
testouterr_cmd_re "sh" "unload h60" $ans [join $tserr "\n"]


# DepUn mechanism impact on DepRe mechanism
setenv_loaded_module [list h60 h61 h62 h65] [list "$mp/h60" "$mp/h61" "$mp/h62" "$mp/h65"] [list h60 h61]
setenv_path_var MODULES_LMPREREQ "h62&h60&h61" "h65&h60"
setenv_path_var MODULES_LMCONFLICT "h65&h62"
set ans [list]
lappend ans [list setpath LOADEDMODULES "h60:h65"]
lappend ans [list setpath _LMFILES_ "$mp/h60:$mp/h65"]
lappend ans [list setpath MODULES_LMPREREQ "h65&h60"]
lappend ans [list setpath MODULES_LMCONFLICT "h65&h62"]
lappend ans [list setpath MODULES_LMNOTUASKED "h60"]
set tserr [list "unload h65" "unload h62" "unload h61" "load h65" \n[msg_top_unload h61 h62 {} h65]]
testouterr_cmd_re "sh" "unload h61" $ans [join $tserr "\n"]

# same test, but a prereq violation exists for both h62 and h65
setenv_loaded_module [list h61 h62 h65] [list "$mp/h61" "$mp/h62" "$mp/h65"] [list h61]
set ans [list]
lappend ans [list setpath LOADEDMODULES "h65"]
lappend ans [list setpath _LMFILES_ "$mp/h65"]
lappend ans [list setpath MODULES_LMPREREQ "h65&h60"]
lappend ans [list unsetpath MODULES_LMNOTUASKED]
set tserr [list "unload h62" "unload h61" \n[msg_top_unload h61 h62 {} {}]]
testouterr_cmd_re "sh" "unload h61" $ans [join $tserr "\n"]

setenv_loaded_module [list h60 h61 h62 h66] [list "$mp/h60" "$mp/h61" "$mp/h62" "$mp/h66"] [list h60 h61]
setenv_path_var MODULES_LMPREREQ "h62&h60&h61" "h66&h60|h61"
unsetenv_path_var MODULES_LMCONFLICT
set ans [list]
lappend ans [list setpath LOADEDMODULES "h60:h66"]
lappend ans [list setpath _LMFILES_ "$mp/h60:$mp/h66"]
lappend ans [list setpath MODULES_LMPREREQ "h66&h60|h61"]
lappend ans [list setpath MODULES_LMNOTUASKED "h60"]
set tserr [list "unload h66" "unload h62" "unload h61" "load h66" \n[msg_top_unload h61 h62 {} h66]]
testouterr_cmd_re "sh" "unload h61" $ans [join $tserr "\n"]

setenv_loaded_module [list h60 h61 h62 h65 h66] [list "$mp/h60" "$mp/h61" "$mp/h62" "$mp/h65" "$mp/h66"] [list h60 h61]
setenv_path_var MODULES_LMPREREQ "h62&h60&h61" "h65&h60" "h66&h60|h61"
setenv_path_var MODULES_LMCONFLICT "h65&h62"
set ans [list]
lappend ans [list setpath LOADEDMODULES "h60:h65:h66"]
lappend ans [list setpath _LMFILES_ "$mp/h60:$mp/h65:$mp/h66"]
lappend ans [list setpath MODULES_LMPREREQ "h65&h60:h66&h60|h61"]
lappend ans [list setpath MODULES_LMCONFLICT "h65&h62"]
lappend ans [list setpath MODULES_LMNOTUASKED "h60"]
set tserr [list "unload h66" "unload h65" "unload h62" "unload h61" "load h65" "load h66" \n[msg_top_unload h61 h62 {} [list h65 h66]]]
testouterr_cmd_re "sh" "unload h61" $ans [join $tserr "\n"]

setenv_loaded_module [list h60 h61 h62 h65 h68 h67] [list "$mp/h60" "$mp/h61" "$mp/h62" "$mp/h65" "$mp/h68" "$mp/h67"] [list h60 h61 h68]
setenv_path_var MODULES_LMPREREQ "h62&h60&h61" "h65&h60" "h67&h68|h61"
set ans [list]
lappend ans [list setpath LOADEDMODULES "h60:h68:h65:h67"]
lappend ans [list setpath _LMFILES_ "$mp/h60:$mp/h68:$mp/h65:$mp/h67"]
lappend ans [list setpath MODULES_LMPREREQ "h65&h60:h67&h68|h61"]
lappend ans [list setpath MODULES_LMCONFLICT "h65&h62"]
lappend ans [list setpath MODULES_LMNOTUASKED "h60:h68"]
set tserr [list "unload h67" "unload h65" "unload h62" "unload h61" "load h65" "load h67" \n[msg_top_unload h61 h62 {} [list h65 h67]]]
testouterr_cmd_re "sh" "unload h61" $ans [join $tserr "\n"]

setenv_loaded_module [list h60 h61 h62 h65 h68 h67 h70 h69] [list "$mp/h60" "$mp/h61" "$mp/h62" "$mp/h65" "$mp/h68" "$mp/h67" "$mp/h70" "$mp/h69"] [list h60 h61 h68 h70]
setenv_path_var MODULES_LMPREREQ "h62&h60&h61" "h65&h60" "h67&h68|h61" "h69&h70&h61"
set ans [list]
lappend ans [list setpath LOADEDMODULES "h60:h68:h65:h67"]
lappend ans [list setpath _LMFILES_ "$mp/h60:$mp/h68:$mp/h65:$mp/h67"]
lappend ans [list setpath MODULES_LMPREREQ "h65&h60:h67&h68|h61"]
lappend ans [list setpath MODULES_LMCONFLICT "h65&h62"]
lappend ans [list setpath MODULES_LMNOTUASKED "h60:h68"]
set tserr [list "unload h67" "unload h65" "unload h69" "unload h62" "unload h61" "unload h70" "load h65" "load h67" \n[msg_top_unload h61 [list h69 h62] h70 [list h65 h67]]]
testouterr_cmd_re "sh" "unload h61" $ans [join $tserr "\n"]


# multiple DepUn modules freeing conflict violation
setenv_loaded_module [list h60 h61 h62 h71 h72] [list "$mp/h60" "$mp/h61" "$mp/h62" "$mp/h71" "$mp/h72"] [list h60 h61]
setenv_path_var MODULES_LMPREREQ "h62&h60&h61" "h71&h62"
setenv_path_var MODULES_LMCONFLICT "h72&h62&h63&h71"
set ans [list]
lappend ans [list setpath LOADEDMODULES "h72"]
lappend ans [list setpath _LMFILES_ "$mp/h72"]
lappend ans [list unsetpath MODULES_LMPREREQ]
lappend ans [list setpath MODULES_LMCONFLICT "h72&h62&h63&h71"]
lappend ans [list unsetpath MODULES_LMNOTUASKED]
set tserr [list "unload h72" "unload h71" "unload h62" "unload h61" "unload h60" "load h72" \n[msg_top_unload h61 [list h71 h62] h60 h72]]
testouterr_cmd_re "sh" "unload h61" $ans [join $tserr "\n"]

setenv_loaded_module [list h60 h61 h62 h63 h72] [list "$mp/h60" "$mp/h61" "$mp/h62" "$mp/h63" "$mp/h72"] [list h60 h61]
setenv_path_var MODULES_LMPREREQ "h62&h60&h61" "h63&h61&h62"
setenv_path_var MODULES_LMCONFLICT "h72&h62&h63&h71"
set ans [list]
lappend ans [list setpath LOADEDMODULES "h72"]
lappend ans [list setpath _LMFILES_ "$mp/h72"]
lappend ans [list unsetpath MODULES_LMPREREQ]
lappend ans [list setpath MODULES_LMCONFLICT "h72&h62&h63&h71"]
lappend ans [list unsetpath MODULES_LMNOTUASKED]
set tserr [list "unload h72" "unload h63" "unload h62" "unload h61" "unload h60" "load h72" \n[msg_top_unload h61 [list h63 h62] h60 h72]]
testouterr_cmd_re "sh" "unload h61" $ans [join $tserr "\n"]

# multiple DepUn modules triggering DepRe
setenv_loaded_module [list h60 h61 h62 h71 h73 h74] [list "$mp/h60" "$mp/h61" "$mp/h62" "$mp/h71" "$mp/h73" "$mp/h74"] [list h60 h61]
setenv_path_var MODULES_LMPREREQ "h62&h60&h61" "h71&h62" "h74&h73|h62|h63|h71"
unsetenv_path_var MODULES_LMCONFLICT
set ans [list]
lappend ans [list setpath LOADEDMODULES "h73:h74"]
lappend ans [list setpath _LMFILES_ "$mp/h73:$mp/h74"]
lappend ans [list setpath MODULES_LMPREREQ "h74&h73|h62|h63|h71"]
lappend ans [list unsetpath MODULES_LMNOTUASKED]
set tserr [list "unload h74" "unload h71" "unload h62" "unload h61" "unload h60" "load h74" \n[msg_top_unload h61 [list h71 h62] h60 h74]]
testouterr_cmd_re "sh" "unload h61" $ans [join $tserr "\n"]

setenv_loaded_module [list h60 h61 h62 h63 h73 h74] [list "$mp/h60" "$mp/h61" "$mp/h62" "$mp/h63" "$mp/h73" "$mp/h74"] [list h60 h61]
setenv_path_var MODULES_LMPREREQ "h62&h60&h61" "h63&h61&h62" "h74&h73|h62|h63|h71"
unsetenv_path_var MODULES_LMCONFLICT
set ans [list]
lappend ans [list setpath LOADEDMODULES "h73:h74"]
lappend ans [list setpath _LMFILES_ "$mp/h73:$mp/h74"]
lappend ans [list setpath MODULES_LMPREREQ "h74&h73|h62|h63|h71"]
lappend ans [list unsetpath MODULES_LMNOTUASKED]
set tserr [list "unload h74" "unload h63" "unload h62" "unload h61" "unload h60" "load h74" \n[msg_top_unload h61 [list h63 h62] h60 h74]]
testouterr_cmd_re "sh" "unload h61" $ans [join $tserr "\n"]


# DepUn mechanism where all modules part of an optional prereq list are unloaded
# so dependent module should not be skipped as none of its optional requirements are there anymore
setenv_loaded_module [list ia ib ic id] [list $mp/ia $mp/ib $mp/ic $mp/id] [list ia ib]
setenv_path_var MODULES_LMPREREQ ib&ia ic&ia id&ib|ic
set ans [list]
lappend ans [list unsetpath LOADEDMODULES]
lappend ans [list unsetpath _LMFILES_]
lappend ans [list unsetpath MODULES_LMPREREQ]
lappend ans [list unsetpath MODULES_LMNOTUASKED]
set tserr [list {unload id} {unload ic} {unload ib} {unload ia} \n[msg_top_unload ia [list id ic ib] {} {}]]
testouterr_cmd_re sh {unload ia} $ans [join $tserr \n]


# test module evaluation detection when conflict is expressed against bare module name
testouterr_cmd sh {load con2/2.1} ERR [msg_load con1/1.1 [err_conloi con2/2.1]]\n\n[msg_load con2/2.1 [err_reqlo con1/1.1]]
testouterr_cmd sh {load con2/2.2} ERR [msg_load con2/2.2 [err_conlo con1]]
testouterr_cmd sh {load con2/2.3} ERR [msg_load con1/1.2 [err_conloi con2]]\n\n[msg_load con2/2.3 [err_reqlo con1/1.2]]


#
#  Cleanup
#

reset_test_env
