##############################################################################
#   Modules Revision 3.0
#   Providing a flexible user environment
#
#   File:		modules.50-cmds/%M%
#   Revision:		%I%
#   First Edition:	2018/08/28
#   Last Mod.:		%U%, %G%
#
#   Authors:		Xavier Delaruelle, xavier.delaruelle@cea.fr
#
#   Description:	Testuite testsequence
#   Command:        load, unload, is-loaded, info-loaded
#   Modulefiles:
#   Sub-Command:    prereq, conflict
#
#   Comment:	%C{
#           Test resolution of modulefile alternative names
#		}C%
#
##############################################################################

set mp "$modpath.deps"

# setup specific environment
setenv_path_var MODULEPATH $mp

# tests with a top MODULERCFILE enabled
setenv_var MODULERCFILE "$env(TESTSUITEDIR)/etc/modulerc.altname"

# ensure auto symbolic versions are not set for these tests
setenv_var MODULES_ADVANCED_VERSION_SPEC 0


proc altname_test_case {mod args} {
    set defaltlist [concat [list $mod] $args]
    foreach name $defaltlist {
        if {[string range $name 0 2] eq {al|}} {
            set name [string range $name 3 end]
        }
        lappend defnamelist $name
    }
    # determine all names that can be tested
    set testnamelist [list]
    foreach name $defnamelist {
        set testname {}
        foreach nelt [split $name /] {
            if {$testname ne {}} {
                append testname /
            }
            append testname $nelt
            if {[lsearch -exact $testnamelist $testname] == -1} {
                lappend testnamelist $testname
            }
        }
    }

    set ans [list]
    lappend ans [list setpath LOADEDMODULES $mod]
    lappend ans [list setpath _LMFILES_ $::mp/$mod]
    lappend ans [list setpath MODULES_LMALTNAME [join $defaltlist &]]

    foreach name $defnamelist {
        testouterr_cmd "sh" "load $name" $ans ""
    }
    foreach name $testnamelist {
        testouterr_cmd "sh" "is-loaded $name" "ERR" ""
        testouterr_cmd "sh" "info-loaded $name" "" ""
    }

    # setup environment with targeted module loaded
    setenv_loaded_module [list $mod] [list $::mp/$mod]
    setenv_path_var MODULES_LMALTNAME [join $defaltlist &]

    set ans [list]
    lappend ans [list unsetpath LOADEDMODULES]
    lappend ans [list unsetpath _LMFILES_]
    lappend ans [list unsetpath MODULES_LMALTNAME]

    set ansinfo [list [list text $mod]]

    foreach name $testnamelist {
        testouterr_cmd "sh" "unload $name" $ans ""
        testouterr_cmd "sh" "is-loaded $name" "OK" ""
        testouterr_cmd "sh" "info-loaded $name" $ansinfo ""
    }

    # restore environment with no loaded module
    unsetenv_loaded_module
    unsetenv_path_var MODULES_LMALTNAME
}

altname_test_case alt/1 alt/sym al|foo
altname_test_case alt/dir/2 al|altfoo
altname_test_case alt/dir/3 al|alt/bar
altname_test_case alt/dir/4 al|altbar/4
altname_test_case alt/dir/5 alt/dir/sym2
altname_test_case alt/dir/6 alt/dir/default alt/dir al|alt/dir/al


# alias defined in a different module dir, alias will not be found thus registered
# if module is loaded with its regular name
set ans [list]
lappend ans [list setpath LOADEDMODULES alt2/1]
lappend ans [list setpath _LMFILES_ $mp/alt2/1]
lappend ans [list setpath MODULES_LMALTNAME alt2/1&al|alt/ext]
testouterr_cmd "sh" "load alt/ext" $ans ""
set ans [list]
lappend ans [list setpath LOADEDMODULES alt2/1]
lappend ans [list setpath _LMFILES_ $mp/alt2/1]
testouterr_cmd "sh" "load alt2/1" $ans ""

setenv_loaded_module [list alt2/1] [list $mp/alt2/1]
setenv_path_var MODULES_LMALTNAME alt2/1&al|alt/ext

set ans [list [list text alt2/1]]
foreach name [list alt2/1 alt/ext] {
    testouterr_cmd "sh" "is-loaded $name" "OK" ""
    testouterr_cmd "sh" "info-loaded $name" $ans ""
}

unsetenv_path_var MODULES_LMALTNAME
testouterr_cmd "sh" "is-loaded alt2/1" "OK" ""
testouterr_cmd "sh" "info-loaded alt2/1" $ans ""
testouterr_cmd "sh" "is-loaded alt/ext" "ERR" ""
testouterr_cmd "sh" "info-loaded alt/ext" "" ""

# restore environment with no loaded module
unsetenv_loaded_module


# alias and symbolic version defined within modulefile: will not be found
set ans [list]
lappend ans [list setpath LOADEDMODULES alt/7]
lappend ans [list setpath _LMFILES_ $mp/alt/7]
testouterr_cmd "sh" "load alt/7" $ans ""
testouterr_cmd "sh" "load alt/int" ERR "$err_path'alt/int'"
testouterr_cmd "sh" "load alt/int2" ERR "$err_path'alt/int2'"


# enable auto_handling with environment variable
setenv_var MODULES_AUTO_HANDLING 1


# load module whereas its alias-named prereq and its symbolic-version-named prereq are not loaded
set ans [list]
lappend ans [list setpath LOADEDMODULES alt/dir/2:alt/1:i1]
lappend ans [list setpath _LMFILES_ $mp/alt/dir/2:$mp/alt/1:$mp/i1]
lappend ans [list setpath MODULES_LMNOTUASKED alt/dir/2:alt/1]
lappend ans [list setpath MODULES_LMALTNAME alt/dir/2&al|altfoo:alt/1&alt/sym&al|foo]
lappend ans [list setpath MODULES_LMPREREQ i1&altfoo&alt/sym]
testouterr_cmd_re "sh" "load i1" $ans [msg_top_load i1 {} [list alt/dir/2 alt/1] {}]

# load module whereas its alias-named prereq and its symbolic-version-named prereq are loaded
setenv_loaded_module [list alt/dir/2 alt/1] [list $mp/alt/dir/2 $mp/alt/1]
setenv_path_var MODULES_LMALTNAME alt/dir/2&al|altfoo alt/1&alt/sym&al|foo
set ans [list]
lappend ans [list setpath LOADEDMODULES alt/dir/2:alt/1:i1]
lappend ans [list setpath _LMFILES_ $mp/alt/dir/2:$mp/alt/1:$mp/i1]
lappend ans [list setpath MODULES_LMPREREQ i1&altfoo&alt/sym]
testouterr_cmd_re "sh" "load i1" $ans ""

# load alternative-named prereq after its dependent module
setenv_loaded_module [list alt/dir/2 i1] [list $mp/alt/dir/2 $mp/i1]
setenv_path_var MODULES_LMALTNAME alt/dir/2&al|altfoo
setenv_path_var MODULES_LMPREREQ i1&altfoo&alt/sym
set ans [list]
lappend ans [list setpath LOADEDMODULES alt/dir/2:alt/1:i1]
lappend ans [list setpath _LMFILES_ $mp/alt/dir/2:$mp/alt/1:$mp/i1]
lappend ans [list setpath MODULES_LMALTNAME alt/dir/2&al|altfoo:alt/1&alt/sym&al|foo]
lappend ans [list setpath MODULES_LMPREREQ i1&altfoo&alt/sym]
testouterr_cmd_re "sh" "load alt/sym" $ans [msg_top_load alt/1 {} {} i1]
testouterr_cmd_re "sh" "load alt/1" $ans [msg_top_load alt/1 {} {} i1]

# unload module whereas its alias-named prereq and its symbolic-version-named prereq are not loaded
setenv_loaded_module [list i1] [list $mp/i1]
unsetenv_path_var MODULES_LMALTNAME
setenv_path_var MODULES_LMPREREQ i1&altfoo&alt/sym
set ans [list]
lappend ans [list unsetpath LOADEDMODULES]
lappend ans [list unsetpath _LMFILES_]
lappend ans [list unsetpath MODULES_LMPREREQ]
testouterr_cmd "sh" "unload i1" $ans ""

# unload module whereas its alias-named prereq and its symbolic-version-named prereq are loaded
setenv_loaded_module [list alt/dir/2 alt/1 i1] [list $mp/alt/dir/2 $mp/alt/1 $mp/i1] [list alt/dir/2 alt/1]
setenv_path_var MODULES_LMALTNAME alt/dir/2&al|altfoo alt/1&alt/sym&al|foo
setenv_path_var MODULES_LMPREREQ i1&altfoo&alt/sym

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]
lappend ans [list unsetpath MODULES_LMALTNAME]
testouterr_cmd "sh" "unload i1" $ans [msg_top_unload i1 {} [list alt/1 alt/dir/2] {}]

# unload alias-named prereq
testouterr_cmd "sh" "unload altfoo" $ans [msg_top_unload alt/dir/2 i1 alt/1 {}]

# unload symbolic-version-named prereq
testouterr_cmd "sh" "unload alt/sym" $ans [msg_top_unload alt/1 i1 alt/dir/2 {}]


# load module whereas its alias-named conflict and its symbolic-version-named conflict are not loaded
unsetenv_loaded_module
unsetenv_path_var MODULES_LMALTNAME
unsetenv_path_var MODULES_LMPREREQ
set ans [list]
lappend ans [list setpath LOADEDMODULES i2]
lappend ans [list setpath _LMFILES_ $mp/i2]
lappend ans [list setpath MODULES_LMCONFLICT i2&altfoo&alt/sym]
testouterr_cmd_re "sh" "load i2" $ans ""

# load module whereas its alias-named conflict and its symbolic-version-named conflict are loaded
setenv_loaded_module [list alt/dir/2 alt/1] [list $mp/alt/dir/2 $mp/alt/1]
setenv_path_var MODULES_LMALTNAME alt/dir/2&al|altfoo alt/1&alt/sym&al|foo
testouterr_cmd_re "sh" "load i2" ERR [msg_load i2 [err_conflict altfoo]]

# load module whose alterative name conflicts with an already loaded module
setenv_loaded_module [list i2] [list $mp/i2]
unsetenv_path_var MODULES_LMALTNAME
setenv_path_var MODULES_LMCONFLICT i2&altfoo&alt/sym
testouterr_cmd_re "sh" "load altfoo" ERR [msg_load alt/dir/2 [err_conflict i2]]
testouterr_cmd_re "sh" "load alt/dir/2" ERR [msg_load alt/dir/2 [err_conflict i2]]

# unload module whereas its alias-named conflict and its symbolic-version-named conflict are not loaded
set ans [list]
lappend ans [list unsetpath LOADEDMODULES]
lappend ans [list unsetpath _LMFILES_]
lappend ans [list unsetpath MODULES_LMCONFLICT]
testouterr_cmd "sh" "unload i2" $ans ""

# unload module whereas its alias-named conflict and its symbolic-version-named conflict are loaded
setenv_loaded_module [list alt/dir/2 alt/1 i2] [list $mp/alt/dir/2 $mp/alt/1 $mp/i2]
setenv_path_var MODULES_LMALTNAME alt/dir/2&al|altfoo alt/1&alt/sym&al|foo
setenv_path_var MODULES_LMCONFLICT i2&altfoo&alt/sym
set ans [list]
lappend ans [list setpath LOADEDMODULES alt/dir/2:alt/1]
lappend ans [list setpath _LMFILES_ $mp/alt/dir/2:$mp/alt/1]
lappend ans [list setpath MODULES_LMALTNAME alt/dir/2&al|altfoo:alt/1&alt/sym&al|foo]
lappend ans [list unsetpath MODULES_LMCONFLICT]
testouterr_cmd_re "sh" "unload i2" $ans [msg_top_unload i2 {} {} [list alt/dir/2 alt/1]]

# unload alias-named conflict
set ans [list]
lappend ans [list setpath LOADEDMODULES alt/1:i2]
lappend ans [list setpath _LMFILES_ $mp/alt/1:$mp/i2]
lappend ans [list setpath MODULES_LMALTNAME alt/1&alt/sym&al|foo]
testouterr_cmd_re "sh" "unload altfoo" $ans ""

# unload symbolic-version-named conflict
set ans [list]
lappend ans [list setpath LOADEDMODULES alt/dir/2:i2]
lappend ans [list setpath _LMFILES_ $mp/alt/dir/2:$mp/i2]
lappend ans [list setpath MODULES_LMALTNAME alt/dir/2&al|altfoo]
testouterr_cmd_re "sh" "unload alt/sym" $ans ""

# unload both conflicts
set ans [list]
lappend ans [list setpath LOADEDMODULES i2]
lappend ans [list setpath _LMFILES_ $mp/i2]
lappend ans [list unsetpath MODULES_LMALTNAME]
lappend ans [list setpath MODULES_LMCONFLICT i2&altfoo&alt/sym]
testouterr_cmd_re "sh" "unload alt/sym altfoo" $ans [msg_top_unload alt/dir/2 {} {} i2]

# load module who conflicts with an alternatively named module currently loading
unsetenv_loaded_module
unsetenv_path_var MODULES_LMALTNAME
unsetenv_path_var MODULES_LMCONFLICT
testouterr_cmd_re "sh" "load i3" ERR [msg_load alt/8 [err_conloi i3]]\n\n[msg_load i3 [err_reqlo alt/8]]

# load module whose prereq conflicts with an alternatively named module currently loading
testouterr_cmd_re "sh" "load i4" ERR [msg_load alt/8 [err_conloi alt/i4]]\n\n[msg_load i4 [err_reqlo alt/8]]

# use alternate name of alt/8 on prereq command
testouterr_cmd_re "sh" "load i3b" ERR [msg_load alt/8 [err_conloi i3b]]\n\n[msg_load i3b [err_reqlo alt/v8]]
testouterr_cmd_re "sh" "load i4b" ERR [msg_load alt/8 [err_conloi alt/i4b]]\n\n[msg_load i4b [err_reqlo alt/v8]]

# reflexive conflict set on an alternative name
set ans [list]
lappend ans [list setpath LOADEDMODULES i5/1]
lappend ans [list setpath _LMFILES_ $mp/i5/1]
lappend ans [list setpath MODULES_LMCONFLICT i5/1&irefcon]
lappend ans [list setpath MODULES_LMALTNAME i5/1&al|irefcon]
testouterr_cmd_re "sh" "load i5/1" $ans ""
set ans [list]
lappend ans [list setpath _LMFILES_ $mp/i5/1]
lappend ans [list setpath LOADEDMODULES i5/1]
lappend ans [list setpath MODULES_LMALTNAME i5/1&al|irefcon]
lappend ans [list setpath MODULES_LMCONFLICT i5/1&irefcon]
lappend ans [list ERR]
testouterr_cmd_re "sh" "load i5/1 i5/2" $ans [msg_load i5/2 [err_conlo irefcon]]


# 'module load' set on an alternative name
set ans [list]
lappend ans [list setpath LOADEDMODULES alt/dir/2:i6]
lappend ans [list setpath _LMFILES_ $mp/alt/dir/2:$mp/i6]
lappend ans [list setpath MODULES_LMPREREQ i6&altfoo]
lappend ans [list setpath MODULES_LMNOTUASKED alt/dir/2]
lappend ans [list setpath MODULES_LMALTNAME alt/dir/2&al|altfoo]
testouterr_cmd_re sh {load i6} $ans [msg_top_load i6 {} alt/dir/2 {}]

setenv_loaded_module [list alt/dir/2 i6] [list $mp/alt/dir/2 $mp/i6] [list alt/dir/2]
setenv_path_var MODULES_LMALTNAME alt/dir/2&al|altfoo
setenv_path_var MODULES_LMPREREQ i6&altfoo
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]
lappend ans [list unsetpath MODULES_LMALTNAME]
testouterr_cmd_re sh {unload alt/dir/2} $ans [msg_top_unload alt/dir/2 i6 {} {}]

# 'module unload' set on an alternative name
setenv_loaded_module [list alt/dir/2] [list $mp/alt/dir/2]
setenv_path_var MODULES_LMALTNAME alt/dir/2&al|altfoo
unsetenv_path_var MODULES_LMPREREQ
set ans [list]
lappend ans [list setpath LOADEDMODULES i7]
lappend ans [list setpath _LMFILES_ $mp/i7]
lappend ans [list unsetpath MODULES_LMALTNAME]
lappend ans [list setpath MODULES_LMCONFLICT i7&altfoo]
testouterr_cmd_re sh {load i7} $ans [msg_top_load i7 alt/dir/2 {} {}]

setenv_loaded_module [list i7] [list $mp/i7]
unsetenv_path_var MODULES_LMALTNAME
setenv_path_var MODULES_LMCONFLICT i7&altfoo
testouterr_cmd_re sh {load alt/dir/2} ERR [msg_load alt/dir/2 [err_conflict i7]]


# test empty or bad element found in MODULES_LMALTNAME control variable
foreach badelt [list {} alt/dir/2] {
setenv_path_var MODULES_LMALTNAME $badelt
unsetenv_path_var MODULES_LMCONFLICT
unsetenv_loaded_module
set ans [list]
lappend ans [list setpath LOADEDMODULES alt/dir/2]
lappend ans [list setpath _LMFILES_ $mp/alt/dir/2]
lappend ans [list setpath MODULES_LMALTNAME $badelt:alt/dir/2&al|altfoo]
testouterr_cmd_re sh {load alt/dir/2} $ans {}
testouterr_cmd_re sh {load altfoo} $ans {}

setenv_loaded_module [list alt/dir/2] [list $mp/alt/dir/2]
setenv_path_var MODULES_LMALTNAME $badelt:alt/dir/2&al|altfoo
set ans [list]
lappend ans [list unsetpath LOADEDMODULES]
lappend ans [list unsetpath _LMFILES_]
lappend ans [list setpath MODULES_LMALTNAME $badelt]
testouterr_cmd_re sh {unload alt/dir/2} $ans {}
testouterr_cmd_re sh {unload altfoo} $ans {}
}


# test use of is-loaded command on alternative name in modulerc
# here to spawn a module alias when a given modulefile is seen loaded
testouterr_cmd sh {load extloaded} ERR "$err_path'extloaded'"

setenv_loaded_module [list alt2/1] [list $mp/alt2/1]
setenv_path_var MODULES_LMALTNAME alt2/1&al|alt/ext
set ans [list]
lappend ans [list setpath LOADEDMODULES alt2/1:alt/9]
lappend ans [list setpath _LMFILES_ $mp/alt2/1:$mp/alt/9]
lappend ans [list setpath MODULES_LMALTNAME alt2/1&al|alt/ext:alt/9&al|extloaded]
testouterr_cmd_re sh {load extloaded} $ans {}


#
#  Cleanup
#

reset_test_env

# remove procs
rename altname_test_case {}
