Skip to content

Commit

Permalink
Bug 1257516 - Add a unit test for check_prog(). r=ted
Browse files Browse the repository at this point in the history
At the same time, shell quote the result it prints if it needs to be.
  • Loading branch information
glandium committed Mar 29, 2016
1 parent e8721f0 commit a2c9191
Show file tree
Hide file tree
Showing 4 changed files with 166 additions and 4 deletions.
7 changes: 4 additions & 3 deletions build/moz.configure/checks.configure
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,18 @@ def checking(what, callback=None):
# it can find. If PROG is already set from the environment or command line,
# use that value instead.
@template
@advanced
def check_prog(var, progs, allow_missing=False):
from mozbuild.shellutil import quote

option(env=var, nargs=1, help='Path to the %s program' % var.lower())

if not (isinstance(progs, tuple) or isinstance(progs, list)):
configure_error('progs should be a list or tuple!')
progs = list(progs)

@depends(var)
@checking('for %s' % var.lower(), lambda x: x or 'not found')
@checking('for %s' % var.lower(), lambda x: quote(x) if x else 'not found')
def check(value):
if value:
progs[:] = value
Expand All @@ -66,10 +69,8 @@ def check_prog(var, progs, allow_missing=False):
return result

@depends(check, var)
@advanced
def postcheck(value, raw_value):
if value is None and (not allow_missing or raw_value):
from mozbuild.shellutil import quote
die('Cannot find %s (tried: %s)', var.lower(),
', '.join(quote(p) for p in progs))

Expand Down
1 change: 1 addition & 0 deletions python/moz.build
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ PYTHON_UNIT_TESTS += [
'mozbuild/mozbuild/test/backend/test_recursivemake.py',
'mozbuild/mozbuild/test/backend/test_visualstudio.py',
'mozbuild/mozbuild/test/compilation/test_warnings.py',
'mozbuild/mozbuild/test/configure/test_checks_configure.py',
'mozbuild/mozbuild/test/configure/test_configure.py',
'mozbuild/mozbuild/test/configure/test_options.py',
'mozbuild/mozbuild/test/configure/test_util.py',
Expand Down
2 changes: 1 addition & 1 deletion python/mozbuild/mozbuild/configure/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -528,7 +528,7 @@ def _prepare_function(self, func):
glob = SandboxedGlobal(func.func_globals)
glob.update(
__builtins__=self.BUILTINS,
__file__=self._paths[-1],
__file__=self._paths[-1] if self._paths else '',
os=self.OS,
log=self.log_impl,
)
Expand Down
160 changes: 160 additions & 0 deletions python/mozbuild/mozbuild/test/configure/test_checks_configure.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

from __future__ import absolute_import, print_function, unicode_literals

from StringIO import StringIO
import os
import unittest

from mozunit import main

from mozbuild.configure import (
ConfigureError,
ConfigureSandbox,
)

from buildconfig import topsrcdir


class FindProgramSandbox(ConfigureSandbox):
def __init__(self, *args, **kwargs):
super(FindProgramSandbox, self).__init__(*args, **kwargs)

# We could define self.find_program_impl and have it automatically
# declared, but then it wouldn't be available in the tested templates.
# We also need to use super().__setitem__ because ours would do
# nothing.
super(FindProgramSandbox, self).__setitem__(
'find_program', self.template_impl(self.find_program))

PROGRAMS = {
'known-a': '/usr/bin/known-a',
'known-b': '/usr/local/bin/known-b',
'known c': '/home/user/bin/known c',
}

for p in PROGRAMS.values():
PROGRAMS[p] = p

@staticmethod
def find_program(prog):
return FindProgramSandbox.PROGRAMS.get(prog)

def __setitem__(self, key, value):
# Avoid util.configure overwriting our mock find_program
if key == 'find_program':
return

super(FindProgramSandbox, self).__setitem__(key, value)


class TestChecksConfigure(unittest.TestCase):
def get_result(self, command='', args=[], environ={},
prog='/bin/configure'):
config = {}
out = StringIO()
sandbox = FindProgramSandbox(config, environ, [prog] + args, out, out)
base_dir = os.path.join(topsrcdir, 'build', 'moz.configure')
sandbox.exec_file(os.path.join(base_dir, 'util.configure'))
sandbox.exec_file(os.path.join(base_dir, 'checks.configure'))

status = 0
try:
exec(command, sandbox)
except SystemExit as e:
status = e.code

return config, out.getvalue(), status

def test_check_prog(self):
config, out, status = self.get_result(
'check_prog("FOO", ("known-a",))')
self.assertEqual(status, 0)
self.assertEqual(config, {'FOO': '/usr/bin/known-a'})
self.assertEqual(out, 'checking for foo... /usr/bin/known-a\n')

config, out, status = self.get_result(
'check_prog("FOO", ("unknown", "known-b", "known c"))')
self.assertEqual(status, 0)
self.assertEqual(config, {'FOO': '/usr/local/bin/known-b'})
self.assertEqual(out, 'checking for foo... /usr/local/bin/known-b\n')

config, out, status = self.get_result(
'check_prog("FOO", ("unknown", "unknown-2", "known c"))')
self.assertEqual(status, 0)
self.assertEqual(config, {'FOO': '/home/user/bin/known c'})
self.assertEqual(out, "checking for foo... '/home/user/bin/known c'\n")

config, out, status = self.get_result(
'check_prog("FOO", ("unknown",))')
self.assertEqual(status, 1)
self.assertEqual(config, {})
self.assertEqual(out, 'checking for foo... not found\n'
'ERROR: Cannot find foo (tried: unknown)\n')

config, out, status = self.get_result(
'check_prog("FOO", ("unknown", "unknown-2", "unknown 3"))')
self.assertEqual(status, 1)
self.assertEqual(config, {})
self.assertEqual(out, 'checking for foo... not found\n'
'ERROR: Cannot find foo '
"(tried: unknown, unknown-2, 'unknown 3')\n")

config, out, status = self.get_result(
'check_prog("FOO", ("unknown", "unknown-2", "unknown 3"), '
'allow_missing=True)')
self.assertEqual(status, 0)
self.assertEqual(config, {'FOO': ':'})
self.assertEqual(out, 'checking for foo... not found\n')

def test_check_prog_with_args(self):
config, out, status = self.get_result(
'check_prog("FOO", ("unknown", "known-b", "known c"))',
['FOO=known-a'])
self.assertEqual(status, 0)
self.assertEqual(config, {'FOO': '/usr/bin/known-a'})
self.assertEqual(out, 'checking for foo... /usr/bin/known-a\n')

config, out, status = self.get_result(
'check_prog("FOO", ("unknown", "known-b", "known c"))',
['FOO=/usr/bin/known-a'])
self.assertEqual(status, 0)
self.assertEqual(config, {'FOO': '/usr/bin/known-a'})
self.assertEqual(out, 'checking for foo... /usr/bin/known-a\n')

config, out, status = self.get_result(
'check_prog("FOO", ("unknown", "known-b", "known c"))',
['FOO=/usr/local/bin/known-a'])
self.assertEqual(status, 1)
self.assertEqual(config, {})
self.assertEqual(out, 'checking for foo... not found\n'
'ERROR: Cannot find foo '
'(tried: /usr/local/bin/known-a)\n')

config, out, status = self.get_result(
'check_prog("FOO", ("unknown",))',
['FOO=known c'])
self.assertEqual(status, 0)
self.assertEqual(config, {'FOO': '/home/user/bin/known c'})
self.assertEqual(out, "checking for foo... '/home/user/bin/known c'\n")

config, out, status = self.get_result(
'check_prog("FOO", ("unknown", "unknown-2", "unknown 3"), '
'allow_missing=True)', ['FOO=unknown'])
self.assertEqual(status, 1)
self.assertEqual(config, {})
self.assertEqual(out, 'checking for foo... not found\n'
'ERROR: Cannot find foo (tried: unknown)\n')

def test_check_prog_configure_error(self):
with self.assertRaises(ConfigureError) as e:
self.get_result('check_prog("FOO", "foo")')

self.assertEqual(e.exception.message,
'progs should be a list or tuple!')


if __name__ == '__main__':
main()

0 comments on commit a2c9191

Please sign in to comment.