--- a/build/moz.configure/checks.configure
+++ b/build/moz.configure/checks.configure
@@ -43,38 +43,39 @@ def checking(what, callback=None):
# Template to check for programs in $PATH.
# check('PROG', ('a', 'b'))
# will look for 'a' or 'b' in $PATH, and set_config PROG to the one
# 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
for prog in progs:
result = find_program(prog)
if result:
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))
@depends(check)
def normalized_for_config(value):
return ':' if value is None else value
set_config(var, normalized_for_config)
--- a/python/moz.build
+++ b/python/moz.build
@@ -29,16 +29,17 @@ PYTHON_UNIT_TESTS += [
'mozbuild/mozbuild/test/action/test_buildlist.py',
'mozbuild/mozbuild/test/action/test_generate_browsersearch.py',
'mozbuild/mozbuild/test/backend/test_android_eclipse.py',
'mozbuild/mozbuild/test/backend/test_build.py',
'mozbuild/mozbuild/test/backend/test_configenvironment.py',
'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',
'mozbuild/mozbuild/test/controller/test_ccachestats.py',
'mozbuild/mozbuild/test/controller/test_clobber.py',
'mozbuild/mozbuild/test/frontend/test_context.py',
'mozbuild/mozbuild/test/frontend/test_emitter.py',
'mozbuild/mozbuild/test/frontend/test_namespaces.py',
new file mode 100644
--- /dev/null
+++ b/python/mozbuild/mozbuild/test/configure/test_checks_configure.py
@@ -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()