test-install : wip to add other information
This commit is contained in:
parent
ed16bd133a
commit
99b52e6e71
1 changed files with 64 additions and 52 deletions
|
@ -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 )
|
||||||
|
#
|
||||||
|
|
Loading…
Reference in a new issue