Bug 1269513 - Add a helper for check_output in Python configure. r=glandium

MozReview-Commit-ID: H3IX5HLyJeu
This commit is contained in:
Chris Manchester 2016-05-17 14:40:03 -07:00
Родитель 0a11236205
Коммит 2a763b7273
4 изменённых файлов: 126 добавлений и 29 удалений

Просмотреть файл

@ -10,15 +10,12 @@ yasm = check_prog('YASM', ['yasm'], allow_missing=True)
@depends_if(yasm)
@checking('yasm version')
@imports('subprocess')
def yasm_version(yasm):
try:
version = Version(subprocess.check_output(
[yasm, '--version']
).splitlines()[0].split()[1])
return version
except subprocess.CalledProcessError as e:
die('Failed to get yasm version: %s', e.message)
version = check_cmd_output(
yasm, '--version',
onerror=lambda: die('Failed to get yasm version.')
).splitlines()[0].split()[1]
return version
# Until we move all the yasm consumers out of old-configure.
# bug 1257904
@ -174,7 +171,6 @@ add_old_configure_assignment('TOOLCHAIN_PREFIX', toolchain_prefix)
@imports('os')
@imports('subprocess')
@imports(_from='mozbuild.configure.util', _import='LineIO')
@imports(_from='mozbuild.shellutil', _import='quote')
@imports(_from='tempfile', _import='mkstemp')
def try_preprocess(compiler, language, source):
suffix = {
@ -192,22 +188,8 @@ def try_preprocess(compiler, language, source):
os.write(fd, source)
os.close(fd)
cmd = compiler + ['-E', path]
log.debug('Executing: `%s`', quote(*cmd))
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
stdout, stderr = proc.communicate()
retcode = proc.wait()
if retcode == 0:
return stdout
log.debug('The command returned non-zero exit status %d.', retcode)
for out, desc in ((stdout, 'output'), (stderr, 'error output')):
if out:
log.debug('Its %s was:', desc)
with LineIO(lambda l: log.debug('| %s', l)) as o:
o.write(out)
return check_cmd_output(*cmd)
finally:
os.remove(path)

Просмотреть файл

@ -18,6 +18,37 @@ def configure_error(message):
their inputs from moz.configure usage.'''
raise ConfigureError(message)
# A wrapper to obtain a process' output that returns the output generated
# by running the given command if it exits normally, and streams that
# output to log.debug and calls die or the given error callback if it
# does not.
@imports('subprocess')
@imports('sys')
@imports(_from='mozbuild.configure.util', _import='LineIO')
@imports(_from='mozbuild.shellutil', _import='quote')
def check_cmd_output(*args, **kwargs):
onerror = kwargs.pop('onerror', None)
with log.queue_debug():
log.debug('Executing: `%s`', quote(*args))
proc = subprocess.Popen(args, stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
stdout, stderr = proc.communicate()
retcode = proc.wait()
if retcode == 0:
return stdout
log.debug('The command returned non-zero exit status %d.',
retcode)
for out, desc in ((stdout, 'output'), (stderr, 'error output')):
if out:
log.debug('Its %s was:', desc)
with LineIO(lambda l: log.debug('| %s', l)) as o:
o.write(out)
if onerror:
return onerror()
die('Command `%s` failed with exit status %d.' %
(quote(*args), retcode))
@imports('os')
def is_absolute_or_relative(path):

Просмотреть файл

@ -116,12 +116,11 @@ add_old_configure_assignment('PERL', perl_for_old_configure)
def perl_version_check(min_version):
@depends(perl)
@checking('for minimum required perl version >= %s' % min_version)
@imports('subprocess')
def get_perl_version(perl):
try:
return Version(subprocess.check_output([perl, '-e', 'print $]']))
except subprocess.CalledProcessError as e:
die('Failed to get perl version: %s', e.message)
return Version(check_cmd_output(
perl, '-e', 'print $]',
onerror=lambda: die('Failed to get perl version.')
))
@depends(get_perl_version)
def check_perl_version(version):

Просмотреть файл

@ -7,18 +7,24 @@ from __future__ import absolute_import, print_function, unicode_literals
import logging
import os
import tempfile
import textwrap
import unittest
import sys
from StringIO import StringIO
from mozunit import main
from mozpack import path as mozpath
from mozbuild.configure.util import (
ConfigureOutputHandler,
LineIO,
Version,
)
from mozbuild.util import exec_
from buildconfig import topsrcdir
from common import ConfigureTestSandbox
class TestConfigureOutputHandler(unittest.TestCase):
@ -438,6 +444,85 @@ class TestVersion(unittest.TestCase):
self.assertEqual(v.minor, 0)
self.assertEqual(v.patch, 0)
class TestCheckCmdOutput(unittest.TestCase):
def get_result(self, command='', paths=None):
paths = paths or {}
config = {}
out = StringIO()
sandbox = ConfigureTestSandbox(paths, config, {}, ['/bin/configure'],
out, out)
sandbox.include_file(mozpath.join(topsrcdir, 'build',
'moz.configure', 'util.configure'))
status = 0
try:
exec_(command, sandbox)
sandbox.run()
except SystemExit as e:
status = e.code
return config, out.getvalue(), status
def test_simple_program(self):
def mock_simple_prog(_, args):
if len(args) == 1 and args[0] == '--help':
return 0, 'simple program help...', ''
self.fail("Unexpected arguments to mock_simple_program: %s" %
args)
prog_path = mozpath.abspath('/simple/prog')
cmd = "log.info(check_cmd_output('%s', '--help'))" % prog_path
config, out, status = self.get_result(cmd,
paths={prog_path: mock_simple_prog})
self.assertEqual(config, {})
self.assertEqual(status, 0)
self.assertEqual(out, 'simple program help...\n')
def test_failing_program(self):
def mock_error_prog(_, args):
if len(args) == 1 and args[0] == '--error':
return (127, 'simple program output',
'simple program error output')
self.fail("Unexpected arguments to mock_error_program: %s" %
args)
prog_path = mozpath.abspath('/simple/prog')
cmd = "log.info(check_cmd_output('%s', '--error'))" % prog_path
config, out, status = self.get_result(cmd,
paths={prog_path: mock_error_prog})
self.assertEqual(config, {})
self.assertEqual(status, 1)
self.assertEqual(out, textwrap.dedent('''\
DEBUG: Executing: `%s --error`
DEBUG: The command returned non-zero exit status 127.
DEBUG: Its output was:
DEBUG: | simple program output
DEBUG: Its error output was:
DEBUG: | simple program error output
ERROR: Command `%s --error` failed with exit status 127.
''' % (prog_path, prog_path)))
def test_error_callback(self):
def mock_error_prog(_, args):
if len(args) == 1 and args[0] == '--error':
return 127, 'simple program error...', ''
self.fail("Unexpected arguments to mock_error_program: %s" %
args)
prog_path = mozpath.abspath('/simple/prog')
cmd = textwrap.dedent('''\
check_cmd_output('%s', '--error',
onerror=lambda: die('`prog` produced an error'))
''' % prog_path)
config, out, status = self.get_result(cmd,
paths={prog_path: mock_error_prog})
self.assertEqual(config, {})
self.assertEqual(status, 1)
self.assertEqual(out, textwrap.dedent('''\
DEBUG: Executing: `%s --error`
DEBUG: The command returned non-zero exit status 127.
DEBUG: Its output was:
DEBUG: | simple program error...
ERROR: `prog` produced an error
''' % prog_path))
if __name__ == '__main__':
main()