test-install : wip to add other information

This commit is contained in:
alalazo 2016-04-26 16:41:33 +02:00
parent ed16bd133a
commit 99b52e6e71

View file

@ -23,36 +23,39 @@
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
############################################################################## ##############################################################################
import argparse import argparse
import xml.etree.ElementTree as ET
import itertools
import re
import os
import codecs import codecs
import itertools
import os
import re
import time
import xml.etree.ElementTree as ET
import llnl.util.tty as tty import llnl.util.tty as tty
from llnl.util.filesystem import *
import spack import spack
import spack.cmd
from llnl.util.filesystem import *
from spack.build_environment import InstallError from spack.build_environment import InstallError
from spack.fetch_strategy import FetchError from spack.fetch_strategy import FetchError
import spack.cmd
description = "Run package installation as a unit test, output formatted results." description = "Run package installation as a unit test, output formatted results."
def setup_parser(subparser): def setup_parser(subparser):
subparser.add_argument( subparser.add_argument('-j',
'-j', '--jobs', action='store', type=int, '--jobs',
help="Explicitly set number of make jobs. Default is #cpus.") action='store',
type=int,
help="Explicitly set number of make jobs. Default is #cpus.")
subparser.add_argument( subparser.add_argument('-n',
'-n', '--no-checksum', action='store_true', dest='no_checksum', '--no-checksum',
help="Do not check packages against checksum") action='store_true',
dest='no_checksum',
help="Do not check packages against checksum")
subparser.add_argument( subparser.add_argument('-o', '--output', action='store', help="test output goes in this file")
'-o', '--output', action='store', help="test output goes in this file")
subparser.add_argument( subparser.add_argument('package', nargs=argparse.REMAINDER, help="spec of package to install")
'package', nargs=argparse.REMAINDER, help="spec of package to install")
class JunitResultFormat(object): class JunitResultFormat(object):
@ -102,8 +105,7 @@ def __eq__(self, other):
if not isinstance(other, BuildId): if not isinstance(other, BuildId):
return False return False
return ((self.name, self.version, self.hashId) == return ((self.name, self.version, self.hashId) == (other.name, other.version, other.hashId))
(other.name, other.version, other.hashId))
def fetch_log(path): def fetch_log(path):
@ -114,14 +116,13 @@ def fetch_log(path):
def failed_dependencies(spec): def failed_dependencies(spec):
return set(childSpec for childSpec in spec.dependencies.itervalues() if not return set(childSpec for childSpec in spec.dependencies.itervalues() if not spack.repo.get(childSpec).installed)
spack.repo.get(childSpec).installed)
def create_test_output(topSpec, newInstalls, output, getLogFunc=fetch_log): def create_test_output(top_spec, newInstalls, output, getLogFunc=fetch_log):
# Post-order traversal is not strictly required but it makes sense to output # Post-order traversal is not strictly required but it makes sense to output
# tests for dependencies first. # tests for dependencies first.
for spec in topSpec.traverse(order='post'): for spec in top_spec.traverse(order='post'):
if spec not in newInstalls: if spec not in newInstalls:
continue continue
@ -131,20 +132,17 @@ def create_test_output(topSpec, newInstalls, output, getLogFunc=fetch_log):
result = TestResult.SKIPPED result = TestResult.SKIPPED
dep = iter(failedDeps).next() dep = iter(failedDeps).next()
depBID = BuildId(dep) depBID = BuildId(dep)
errOutput = "Skipped due to failed dependency: {0}".format( errOutput = "Skipped due to failed dependency: {0}".format(depBID.stringId())
depBID.stringId())
elif (not package.installed) and (not package.stage.source_path): elif (not package.installed) and (not package.stage.source_path):
result = TestResult.FAILED result = TestResult.FAILED
errOutput = "Failure to fetch package resources." errOutput = "Failure to fetch package resources."
elif not package.installed: elif not package.installed:
result = TestResult.FAILED result = TestResult.FAILED
lines = getLogFunc(package.build_log_path) lines = getLogFunc(package.build_log_path)
errMessages = list(line for line in lines if errMessages = list(line for line in lines if re.search('error:', line, re.IGNORECASE))
re.search('error:', line, re.IGNORECASE))
errOutput = errMessages if errMessages else lines[-10:] errOutput = errMessages if errMessages else lines[-10:]
errOutput = '\n'.join(itertools.chain( errOutput = '\n'.join(itertools.chain([spec.to_yaml(), "Errors:"], errOutput, ["Build Log:",
[spec.to_yaml(), "Errors:"], errOutput, package.build_log_path]))
["Build Log:", package.build_log_path]))
else: else:
result = TestResult.PASSED result = TestResult.PASSED
errOutput = None errOutput = None
@ -153,7 +151,16 @@ def create_test_output(topSpec, newInstalls, output, getLogFunc=fetch_log):
output.add_test(bId, result, errOutput) output.add_test(bId, result, errOutput)
def get_top_spec_or_die(args):
specs = spack.cmd.parse_specs(args.package, concretize=True)
if len(specs) > 1:
tty.die("Only 1 top-level package can be specified")
top_spec = iter(specs).next()
return top_spec
def test_install(parser, args): def test_install(parser, args):
# Check the input
if not args.package: if not args.package:
tty.die("install requires a package argument") tty.die("install requires a package argument")
@ -162,21 +169,13 @@ def test_install(parser, args):
tty.die("The -j option must be a positive integer!") tty.die("The -j option must be a positive integer!")
if args.no_checksum: if args.no_checksum:
spack.do_checksum = False # TODO: remove this global. spack.do_checksum = False # TODO: remove this global.
specs = spack.cmd.parse_specs(args.package, concretize=True) # Get the one and only top spec
if len(specs) > 1: top_spec = get_top_spec_or_die(args)
tty.die("Only 1 top-level package can be specified")
topSpec = iter(specs).next()
newInstalls = set()
for spec in topSpec.traverse():
package = spack.repo.get(spec)
if not package.installed:
newInstalls.add(spec)
if not args.output: if not args.output:
bId = BuildId(topSpec) bId = BuildId(top_spec)
outputDir = join_path(os.getcwd(), "test-output") outputDir = join_path(os.getcwd(), "test-output")
if not os.path.exists(outputDir): if not os.path.exists(outputDir):
os.mkdir(outputDir) os.mkdir(outputDir)
@ -184,20 +183,27 @@ def test_install(parser, args):
else: else:
outputFpath = args.output outputFpath = args.output
for spec in topSpec.traverse(order='post'): new_installs = set()
for spec in top_spec.traverse(order='post'):
# Calling do_install for the top-level package would be sufficient but # Calling do_install for the top-level package would be sufficient but
# this attempts to keep going if any package fails (other packages which # this attempts to keep going if any package fails (other packages which
# are not dependents may succeed) # are not dependents may succeed)
package = spack.repo.get(spec) package = spack.repo.get(spec)
if not package.installed:
new_installs.add(spec)
duration = 0.0
if (not failed_dependencies(spec)) and (not package.installed): if (not failed_dependencies(spec)) and (not package.installed):
try: try:
package.do_install( start_time = time.time()
keep_prefix=False, package.do_install(keep_prefix=False,
keep_stage=True, keep_stage=True,
ignore_deps=False, ignore_deps=False,
make_jobs=args.jobs, make_jobs=args.jobs,
verbose=True, verbose=True,
fake=False) fake=False)
duration = time.time() - start_time
except InstallError: except InstallError:
pass pass
except FetchError: except FetchError:
@ -205,7 +211,13 @@ def test_install(parser, args):
jrf = JunitResultFormat() jrf = JunitResultFormat()
handled = {} handled = {}
create_test_output(topSpec, newInstalls, jrf) create_test_output(top_spec, new_installs, jrf)
with open(outputFpath, 'wb') as F: with open(outputFpath, 'wb') as F:
jrf.write_to(F) jrf.write_to(F)
# with JunitTestSuite(filename) as test_suite:
# for spec in top_spec.traverse(order='post'):
# test_case = install_test(spec)
# test_suite.append( test_case )
#