module : added unit tests

This commit is contained in:
alalazo 2016-07-02 12:14:30 +02:00
parent d10fceaacc
commit 3100c5948a
3 changed files with 101 additions and 11 deletions

View File

@ -32,12 +32,16 @@
import llnl.util.tty as tty import llnl.util.tty as tty
import spack.cmd import spack.cmd
import spack.cmd.common.arguments as arguments import spack.cmd.common.arguments as arguments
from llnl.util.filesystem import mkdirp import llnl.util.filesystem as filesystem
from spack.modules import module_types from spack.modules import module_types
#from spack.util.string import *
description = "Manipulate module files" description = "Manipulate module files"
# Dictionary that will be populated with the list of sub-commands
# Each sub-command must be callable and accept 3 arguments :
# - mtype : the type of the module file
# - specs : the list of specs to be processed
# - args : namespace containing the parsed command line arguments
callbacks = {} callbacks = {}
@ -51,6 +55,7 @@ def decorator(callback):
def setup_parser(subparser): def setup_parser(subparser):
sp = subparser.add_subparsers(metavar='SUBCOMMAND', dest='subparser_name') sp = subparser.add_subparsers(metavar='SUBCOMMAND', dest='subparser_name')
# spack module refresh # spack module refresh
refresh_parser = sp.add_parser('refresh', help='Regenerate module files') refresh_parser = sp.add_parser('refresh', help='Regenerate module files')
refresh_parser.add_argument('--delete-tree', help='Delete the module file tree before refresh', action='store_true') refresh_parser.add_argument('--delete-tree', help='Delete the module file tree before refresh', action='store_true')
@ -71,11 +76,12 @@ def setup_parser(subparser):
) )
loads_parser.add_argument( loads_parser.add_argument(
'--input-only', action='store_false', dest='shell', '--input-only', action='store_false', dest='shell',
help='Generate input for module command (instead of a shell script)') help='Generate input for module command (instead of a shell script)'
)
loads_parser.add_argument( loads_parser.add_argument(
'-p', '--prefix', dest='prefix', default='', '-p', '--prefix', dest='prefix', default='',
help='Prepend to module names when issuing module load commands') help='Prepend to module names when issuing module load commands'
)
arguments.add_common_arguments(loads_parser, ['constraint', 'module_type', 'recurse_dependencies']) arguments.add_common_arguments(loads_parser, ['constraint', 'module_type', 'recurse_dependencies'])
@ -86,8 +92,10 @@ class MultipleMatches(Exception):
class NoMatch(Exception): class NoMatch(Exception):
pass pass
@subcommand('loads') @subcommand('loads')
def loads(mtype, specs, args): def loads(mtype, specs, args):
"""Prompt the list of modules associated with a list of specs"""
# Get a comprehensive list of specs # Get a comprehensive list of specs
if args.recurse_dependencies: if args.recurse_dependencies:
specs_from_user_constraint = specs[:] specs_from_user_constraint = specs[:]
@ -123,6 +131,7 @@ def loads(mtype, specs, args):
d['name'] = mod d['name'] = mod
print(prompt_template.format(**d)) print(prompt_template.format(**d))
@subcommand('find') @subcommand('find')
def find(mtype, specs, args): def find(mtype, specs, args):
""" """
@ -146,13 +155,14 @@ def find(mtype, specs, args):
@subcommand('rm') @subcommand('rm')
def rm(mtype, specs, args): def rm(mtype, specs, args):
"""Deletes module files associated with items in specs"""
module_cls = module_types[mtype] module_cls = module_types[mtype]
specs_with_modules = [spec for spec in specs if os.path.exists(module_cls(spec).file_name)] specs_with_modules = [spec for spec in specs if os.path.exists(module_cls(spec).file_name)]
modules = [module_cls(spec) for spec in specs_with_modules] modules = [module_cls(spec) for spec in specs_with_modules]
if not modules: if not modules:
tty.msg('No module file matches your query') tty.msg('No module file matches your query')
return raise SystemExit(1)
# Ask for confirmation # Ask for confirmation
if not args.yes_to_all: if not args.yes_to_all:
@ -168,9 +178,7 @@ def rm(mtype, specs, args):
@subcommand('refresh') @subcommand('refresh')
def refresh(mtype, specs, args): def refresh(mtype, specs, args):
"""Regenerate module files for installed packages """Regenerate module files for item in specs"""
"""
# Prompt a message to the user about what is going to change # Prompt a message to the user about what is going to change
if not specs: if not specs:
tty.msg('No package matches your query') tty.msg('No package matches your query')
@ -205,7 +213,7 @@ def refresh(mtype, specs, args):
tty.msg('Regenerating {name} module files'.format(name=mtype)) tty.msg('Regenerating {name} module files'.format(name=mtype))
if os.path.isdir(cls.path) and args.delete_tree: if os.path.isdir(cls.path) and args.delete_tree:
shutil.rmtree(cls.path, ignore_errors=False) shutil.rmtree(cls.path, ignore_errors=False)
mkdirp(cls.path) filesystem.mkdirp(cls.path)
for x in writers: for x in writers:
x.write(overwrite=True) x.write(overwrite=True)

View File

@ -40,7 +40,7 @@
'cc', 'link_tree', 'spec_yaml', 'optional_deps', 'cc', 'link_tree', 'spec_yaml', 'optional_deps',
'make_executable', 'configure_guess', 'lock', 'database', 'make_executable', 'configure_guess', 'lock', 'database',
'namespace_trie', 'yaml', 'sbang', 'environment', 'cmd.find', 'namespace_trie', 'yaml', 'sbang', 'environment', 'cmd.find',
'cmd.uninstall', 'cmd.test_install', 'cmd.test_compiler_cmd'] 'cmd.uninstall', 'cmd.test_install', 'cmd.test_compiler_cmd', 'cmd.module']
def list_tests(): def list_tests():

View File

@ -0,0 +1,82 @@
##############################################################################
# Copyright (c) 2013-2016, Lawrence Livermore National Security, LLC.
# Produced at the Lawrence Livermore National Laboratory.
#
# This file is part of Spack.
# Created by Todd Gamblin, tgamblin@llnl.gov, All rights reserved.
# LLNL-CODE-647188
#
# For details, see https://github.com/llnl/spack
# Please also see the LICENSE file for our notice and the LGPL.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License (as
# published by the Free Software Foundation) version 2.1, February 1999.
#
# This program 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 terms and
# conditions of the GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
##############################################################################
import argparse
import os.path
import spack.cmd.module as module
import spack.modules as modules
import spack.test.mock_database
class TestModule(spack.test.mock_database.MockDatabase):
def _get_module_files(self, args):
return [
modules.module_types[args.module_type](spec).file_name for spec in args.specs
]
def test_module_common_operations(self):
parser = argparse.ArgumentParser()
module.setup_parser(parser)
# Try to remove a non existing module [tcl]
args = parser.parse_args(['rm', 'doesnotexist'])
self.assertRaises(SystemExit, module.module, parser, args)
# Remove existing modules [tcl]
args = parser.parse_args(['rm', '-y', 'mpileaks'])
module_files = self._get_module_files(args)
for item in module_files:
self.assertTrue(os.path.exists(item))
module.module(parser, args)
for item in module_files:
self.assertFalse(os.path.exists(item))
# Add them back [tcl]
args = parser.parse_args(['refresh', '-y', 'mpileaks'])
module.module(parser, args)
for item in module_files:
self.assertTrue(os.path.exists(item))
# TODO : test the --delete-tree option
# TODO : this requires having a separate directory for test modules
# Try to find a module with multiple matches
args = parser.parse_args(['find', 'mpileaks'])
self.assertRaises(SystemExit, module.module, parser, args)
# Try to find a module with no matches
args = parser.parse_args(['find', 'doesnotexist'])
self.assertRaises(SystemExit, module.module, parser, args)
# Try to find a module
args = parser.parse_args(['find', 'libelf'])
module.module(parser, args)
# Remove existing modules [dotkit]
args = parser.parse_args(['rm', '-y', '-m', 'dotkit', 'mpileaks'])
module_files = self._get_module_files(args)
for item in module_files:
self.assertTrue(os.path.exists(item))
module.module(parser, args)
for item in module_files:
self.assertFalse(os.path.exists(item))
# Add them back [dotkit]
args = parser.parse_args(['refresh', '-y', '-m', 'dotkit', 'mpileaks'])
module.module(parser, args)
for item in module_files:
self.assertTrue(os.path.exists(item))
# TODO : add tests for loads and find to check the prompt format