summaryrefslogtreecommitdiffstats
path: root/python/mozbuild/mozbuild/test/configure/test_checks_configure.py
diff options
context:
space:
mode:
Diffstat (limited to 'python/mozbuild/mozbuild/test/configure/test_checks_configure.py')
-rw-r--r--python/mozbuild/mozbuild/test/configure/test_checks_configure.py1169
1 files changed, 1169 insertions, 0 deletions
diff --git a/python/mozbuild/mozbuild/test/configure/test_checks_configure.py b/python/mozbuild/mozbuild/test/configure/test_checks_configure.py
new file mode 100644
index 0000000000..53361ff199
--- /dev/null
+++ b/python/mozbuild/mozbuild/test/configure/test_checks_configure.py
@@ -0,0 +1,1169 @@
+# 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/.
+
+import os
+import sys
+import textwrap
+import unittest
+
+from buildconfig import topsrcdir
+from mozpack import path as mozpath
+from mozunit import MockedOpen, main
+from six import StringIO
+
+from common import ConfigureTestSandbox, ensure_exe_extension, fake_short_path
+from mozbuild.configure import ConfigureError, ConfigureSandbox
+from mozbuild.shellutil import quote as shell_quote
+from mozbuild.util import exec_
+
+
+class TestChecksConfigure(unittest.TestCase):
+ def test_checking(self):
+ def make_test(to_exec):
+ def test(val, msg):
+ out = StringIO()
+ sandbox = ConfigureSandbox({}, stdout=out, stderr=out)
+ base_dir = os.path.join(topsrcdir, "build", "moz.configure")
+ sandbox.include_file(os.path.join(base_dir, "checks.configure"))
+ exec_(to_exec, sandbox)
+ sandbox["foo"](val)
+ self.assertEqual(out.getvalue(), msg)
+
+ return test
+
+ test = make_test(
+ textwrap.dedent(
+ """
+ @checking('for a thing')
+ def foo(value):
+ return value
+ """
+ )
+ )
+ test(True, "checking for a thing... yes\n")
+ test(False, "checking for a thing... no\n")
+ test(42, "checking for a thing... 42\n")
+ test("foo", "checking for a thing... foo\n")
+ data = ["foo", "bar"]
+ test(data, "checking for a thing... %r\n" % data)
+
+ # When the function given to checking does nothing interesting, the
+ # behavior is not altered
+ test = make_test(
+ textwrap.dedent(
+ """
+ @checking('for a thing', lambda x: x)
+ def foo(value):
+ return value
+ """
+ )
+ )
+ test(True, "checking for a thing... yes\n")
+ test(False, "checking for a thing... no\n")
+ test(42, "checking for a thing... 42\n")
+ test("foo", "checking for a thing... foo\n")
+ data = ["foo", "bar"]
+ test(data, "checking for a thing... %r\n" % data)
+
+ test = make_test(
+ textwrap.dedent(
+ """
+ def munge(x):
+ if not x:
+ return 'not found'
+ if isinstance(x, (str, bool, int)):
+ return x
+ return ' '.join(x)
+
+ @checking('for a thing', munge)
+ def foo(value):
+ return value
+ """
+ )
+ )
+ test(True, "checking for a thing... yes\n")
+ test(False, "checking for a thing... not found\n")
+ test(42, "checking for a thing... 42\n")
+ test("foo", "checking for a thing... foo\n")
+ data = ["foo", "bar"]
+ test(data, "checking for a thing... foo bar\n")
+
+ KNOWN_A = ensure_exe_extension(mozpath.abspath("/usr/bin/known-a"))
+ KNOWN_B = ensure_exe_extension(mozpath.abspath("/usr/local/bin/known-b"))
+ KNOWN_C = ensure_exe_extension(mozpath.abspath("/home/user/bin/known c"))
+ OTHER_A = ensure_exe_extension(mozpath.abspath("/lib/other/known-a"))
+
+ def get_result(
+ self,
+ command="",
+ args=[],
+ environ={},
+ prog="/bin/configure",
+ extra_paths=None,
+ includes=("util.configure", "checks.configure"),
+ ):
+ config = {}
+ out = StringIO()
+ paths = {self.KNOWN_A: None, self.KNOWN_B: None, self.KNOWN_C: None}
+ if extra_paths:
+ paths.update(extra_paths)
+ environ = dict(environ)
+ if "PATH" not in environ:
+ environ["PATH"] = os.pathsep.join(os.path.dirname(p) for p in paths)
+ paths[self.OTHER_A] = None
+ sandbox = ConfigureTestSandbox(paths, config, environ, [prog] + args, out, out)
+ base_dir = os.path.join(topsrcdir, "build", "moz.configure")
+ for f in includes:
+ sandbox.include_file(os.path.join(base_dir, f))
+
+ status = 0
+ try:
+ exec_(command, sandbox)
+ sandbox.run()
+ 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": self.KNOWN_A})
+ self.assertEqual(out, "checking for foo... %s\n" % self.KNOWN_A)
+
+ config, out, status = self.get_result(
+ 'check_prog("FOO", ("unknown", "known-b", "known c"))'
+ )
+ self.assertEqual(status, 0)
+ self.assertEqual(config, {"FOO": self.KNOWN_B})
+ self.assertEqual(out, "checking for foo... %s\n" % self.KNOWN_B)
+
+ config, out, status = self.get_result(
+ 'check_prog("FOO", ("unknown", "unknown-2", "known c"))'
+ )
+ self.assertEqual(status, 0)
+ self.assertEqual(config, {"FOO": fake_short_path(self.KNOWN_C)})
+ self.assertEqual(
+ out, "checking for foo... %s\n" % shell_quote(fake_short_path(self.KNOWN_C))
+ )
+
+ config, out, status = self.get_result('check_prog("FOO", ("unknown",))')
+ self.assertEqual(status, 1)
+ self.assertEqual(config, {})
+ self.assertEqual(
+ out,
+ textwrap.dedent(
+ """\
+ checking for foo... not found
+ DEBUG: foo: Looking for unknown
+ ERROR: Cannot find foo
+ """
+ ),
+ )
+
+ config, out, status = self.get_result(
+ 'check_prog("FOO", ("unknown", "unknown-2", "unknown 3"))'
+ )
+ self.assertEqual(status, 1)
+ self.assertEqual(config, {})
+ self.assertEqual(
+ out,
+ textwrap.dedent(
+ """\
+ checking for foo... not found
+ DEBUG: foo: Looking for unknown
+ DEBUG: foo: Looking for unknown-2
+ DEBUG: foo: Looking for 'unknown 3'
+ ERROR: Cannot find foo
+ """
+ ),
+ )
+
+ config, out, status = self.get_result(
+ 'check_prog("FOO", ("unknown", "unknown-2", "unknown 3"), '
+ "allow_missing=True)"
+ )
+ self.assertEqual(status, 0)
+ self.assertEqual(config, {})
+ self.assertEqual(out, "checking for foo... not found\n")
+
+ @unittest.skipIf(not sys.platform.startswith("win"), "Windows-only test")
+ def test_check_prog_exe(self):
+ config, out, status = self.get_result(
+ 'check_prog("FOO", ("unknown", "known-b", "known c"))', ["FOO=known-a.exe"]
+ )
+ self.assertEqual(status, 0)
+ self.assertEqual(config, {"FOO": self.KNOWN_A})
+ self.assertEqual(out, "checking for foo... %s\n" % self.KNOWN_A)
+
+ config, out, status = self.get_result(
+ 'check_prog("FOO", ("unknown", "known-b", "known c"))',
+ ["FOO=%s" % os.path.splitext(self.KNOWN_A)[0]],
+ )
+ self.assertEqual(status, 0)
+ self.assertEqual(config, {"FOO": self.KNOWN_A})
+ self.assertEqual(out, "checking for foo... %s\n" % self.KNOWN_A)
+
+ 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": self.KNOWN_A})
+ self.assertEqual(out, "checking for foo... %s\n" % self.KNOWN_A)
+
+ config, out, status = self.get_result(
+ 'check_prog("FOO", ("unknown", "known-b", "known c"))',
+ ["FOO=%s" % self.KNOWN_A],
+ )
+ self.assertEqual(status, 0)
+ self.assertEqual(config, {"FOO": self.KNOWN_A})
+ self.assertEqual(out, "checking for foo... %s\n" % self.KNOWN_A)
+
+ path = self.KNOWN_B.replace("known-b", "known-a")
+ config, out, status = self.get_result(
+ 'check_prog("FOO", ("unknown", "known-b", "known c"))', ["FOO=%s" % path]
+ )
+ self.assertEqual(status, 1)
+ self.assertEqual(config, {})
+ self.assertEqual(
+ out,
+ textwrap.dedent(
+ """\
+ checking for foo... not found
+ DEBUG: foo: Looking for %s
+ ERROR: Cannot find foo
+ """
+ )
+ % path,
+ )
+
+ config, out, status = self.get_result(
+ 'check_prog("FOO", ("unknown",))', ["FOO=known c"]
+ )
+ self.assertEqual(status, 0)
+ self.assertEqual(config, {"FOO": fake_short_path(self.KNOWN_C)})
+ self.assertEqual(
+ out, "checking for foo... %s\n" % shell_quote(fake_short_path(self.KNOWN_C))
+ )
+
+ 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,
+ textwrap.dedent(
+ """\
+ checking for foo... not found
+ DEBUG: foo: Looking for unknown
+ ERROR: Cannot find foo
+ """
+ ),
+ )
+
+ def test_check_prog_what(self):
+ config, out, status = self.get_result(
+ 'check_prog("CC", ("known-a",), what="the target C compiler")'
+ )
+ self.assertEqual(status, 0)
+ self.assertEqual(config, {"CC": self.KNOWN_A})
+ self.assertEqual(
+ out, "checking for the target C compiler... %s\n" % self.KNOWN_A
+ )
+
+ config, out, status = self.get_result(
+ 'check_prog("CC", ("unknown", "unknown-2", "unknown 3"),'
+ ' what="the target C compiler")'
+ )
+ self.assertEqual(status, 1)
+ self.assertEqual(config, {})
+ self.assertEqual(
+ out,
+ textwrap.dedent(
+ """\
+ checking for the target C compiler... not found
+ DEBUG: cc: Looking for unknown
+ DEBUG: cc: Looking for unknown-2
+ DEBUG: cc: Looking for 'unknown 3'
+ ERROR: Cannot find the target C compiler
+ """
+ ),
+ )
+
+ def test_check_prog_input(self):
+ config, out, status = self.get_result(
+ textwrap.dedent(
+ """
+ option("--with-ccache", nargs=1, help="ccache")
+ check_prog("CCACHE", ("known-a",), input="--with-ccache")
+ """
+ ),
+ ["--with-ccache=known-b"],
+ )
+ self.assertEqual(status, 0)
+ self.assertEqual(config, {"CCACHE": self.KNOWN_B})
+ self.assertEqual(out, "checking for ccache... %s\n" % self.KNOWN_B)
+
+ script = textwrap.dedent(
+ """
+ option(env="CC", nargs=1, help="compiler")
+ @depends("CC")
+ def compiler(value):
+ return value[0].split()[0] if value else None
+ check_prog("CC", ("known-a",), input=compiler)
+ """
+ )
+ config, out, status = self.get_result(script)
+ self.assertEqual(status, 0)
+ self.assertEqual(config, {"CC": self.KNOWN_A})
+ self.assertEqual(out, "checking for cc... %s\n" % self.KNOWN_A)
+
+ config, out, status = self.get_result(script, ["CC=known-b"])
+ self.assertEqual(status, 0)
+ self.assertEqual(config, {"CC": self.KNOWN_B})
+ self.assertEqual(out, "checking for cc... %s\n" % self.KNOWN_B)
+
+ config, out, status = self.get_result(script, ["CC=known-b -m32"])
+ self.assertEqual(status, 0)
+ self.assertEqual(config, {"CC": self.KNOWN_B})
+ self.assertEqual(out, "checking for cc... %s\n" % self.KNOWN_B)
+
+ def test_check_prog_progs(self):
+ config, out, status = self.get_result('check_prog("FOO", ())')
+ self.assertEqual(status, 0)
+ self.assertEqual(config, {})
+ self.assertEqual(out, "")
+
+ config, out, status = self.get_result('check_prog("FOO", ())', ["FOO=known-a"])
+ self.assertEqual(status, 0)
+ self.assertEqual(config, {"FOO": self.KNOWN_A})
+ self.assertEqual(out, "checking for foo... %s\n" % self.KNOWN_A)
+
+ script = textwrap.dedent(
+ """
+ option(env="TARGET", nargs=1, default="linux", help="target")
+ @depends("TARGET")
+ def compiler(value):
+ if value:
+ if value[0] == "linux":
+ return ("gcc", "clang")
+ if value[0] == "winnt":
+ return ("cl", "clang-cl")
+ check_prog("CC", compiler)
+ """
+ )
+ config, out, status = self.get_result(script)
+ self.assertEqual(status, 1)
+ self.assertEqual(config, {})
+ self.assertEqual(
+ out,
+ textwrap.dedent(
+ """\
+ checking for cc... not found
+ DEBUG: cc: Looking for gcc
+ DEBUG: cc: Looking for clang
+ ERROR: Cannot find cc
+ """
+ ),
+ )
+
+ config, out, status = self.get_result(script, ["TARGET=linux"])
+ self.assertEqual(status, 1)
+ self.assertEqual(config, {})
+ self.assertEqual(
+ out,
+ textwrap.dedent(
+ """\
+ checking for cc... not found
+ DEBUG: cc: Looking for gcc
+ DEBUG: cc: Looking for clang
+ ERROR: Cannot find cc
+ """
+ ),
+ )
+
+ config, out, status = self.get_result(script, ["TARGET=winnt"])
+ self.assertEqual(status, 1)
+ self.assertEqual(config, {})
+ self.assertEqual(
+ out,
+ textwrap.dedent(
+ """\
+ checking for cc... not found
+ DEBUG: cc: Looking for cl
+ DEBUG: cc: Looking for clang-cl
+ ERROR: Cannot find cc
+ """
+ ),
+ )
+
+ config, out, status = self.get_result(script, ["TARGET=none"])
+ self.assertEqual(status, 0)
+ self.assertEqual(config, {})
+ self.assertEqual(out, "")
+
+ config, out, status = self.get_result(script, ["TARGET=winnt", "CC=known-a"])
+ self.assertEqual(status, 0)
+ self.assertEqual(config, {"CC": self.KNOWN_A})
+ self.assertEqual(out, "checking for cc... %s\n" % self.KNOWN_A)
+
+ config, out, status = self.get_result(script, ["TARGET=none", "CC=known-a"])
+ self.assertEqual(status, 0)
+ self.assertEqual(config, {"CC": self.KNOWN_A})
+ self.assertEqual(out, "checking for cc... %s\n" % self.KNOWN_A)
+
+ def test_check_prog_configure_error(self):
+ with self.assertRaises(ConfigureError) as e:
+ self.get_result('check_prog("FOO", "foo")')
+
+ self.assertEqual(str(e.exception), "progs must resolve to a list or tuple!")
+
+ with self.assertRaises(ConfigureError) as e:
+ self.get_result(
+ 'foo = depends(when=True)(lambda: ("a", "b"))\n'
+ 'check_prog("FOO", ("known-a",), input=foo)'
+ )
+
+ self.assertEqual(
+ str(e.exception),
+ "input must resolve to a tuple or a list with a "
+ "single element, or a string",
+ )
+
+ with self.assertRaises(ConfigureError) as e:
+ self.get_result(
+ 'foo = depends(when=True)(lambda: {"a": "b"})\n'
+ 'check_prog("FOO", ("known-a",), input=foo)'
+ )
+
+ self.assertEqual(
+ str(e.exception),
+ "input must resolve to a tuple or a list with a "
+ "single element, or a string",
+ )
+
+ def test_check_prog_with_path(self):
+ config, out, status = self.get_result(
+ 'check_prog("A", ("known-a",), paths=["/some/path"])'
+ )
+ self.assertEqual(status, 1)
+ self.assertEqual(config, {})
+ self.assertEqual(
+ out,
+ textwrap.dedent(
+ """\
+ checking for a... not found
+ DEBUG: a: Looking for known-a
+ ERROR: Cannot find a
+ """
+ ),
+ )
+
+ config, out, status = self.get_result(
+ 'check_prog("A", ("known-a",), paths=["%s"])'
+ % os.path.dirname(self.OTHER_A)
+ )
+ self.assertEqual(status, 0)
+ self.assertEqual(config, {"A": self.OTHER_A})
+ self.assertEqual(
+ out,
+ textwrap.dedent(
+ """\
+ checking for a... %s
+ """
+ % self.OTHER_A
+ ),
+ )
+
+ dirs = map(mozpath.dirname, (self.OTHER_A, self.KNOWN_A))
+ config, out, status = self.get_result(
+ textwrap.dedent(
+ """\
+ check_prog("A", ("known-a",), paths=["%s"])
+ """
+ % os.pathsep.join(dirs)
+ )
+ )
+ self.assertEqual(status, 0)
+ self.assertEqual(config, {"A": self.OTHER_A})
+ self.assertEqual(
+ out,
+ textwrap.dedent(
+ """\
+ checking for a... %s
+ """
+ % self.OTHER_A
+ ),
+ )
+
+ dirs = map(mozpath.dirname, (self.KNOWN_A, self.KNOWN_B))
+ config, out, status = self.get_result(
+ textwrap.dedent(
+ """\
+ check_prog("A", ("known-a",), paths=["%s", "%s"])
+ """
+ % (os.pathsep.join(dirs), self.OTHER_A)
+ )
+ )
+ self.assertEqual(status, 0)
+ self.assertEqual(config, {"A": self.KNOWN_A})
+ self.assertEqual(
+ out,
+ textwrap.dedent(
+ """\
+ checking for a... %s
+ """
+ % self.KNOWN_A
+ ),
+ )
+
+ config, out, status = self.get_result(
+ 'check_prog("A", ("known-a",), paths="%s")' % os.path.dirname(self.OTHER_A)
+ )
+
+ self.assertEqual(status, 1)
+ self.assertEqual(config, {})
+ self.assertEqual(
+ out,
+ textwrap.dedent(
+ """\
+ checking for a... """ # noqa # trailing whitespace...
+ """
+ DEBUG: a: Looking for known-a
+ ERROR: Paths provided to find_program must be a list of strings, not %r
+ """
+ % mozpath.dirname(self.OTHER_A)
+ ),
+ )
+
+ @unittest.skipIf(
+ not sys.platform.startswith("linux"),
+ "Linux-only test, assumes Java is located from a $PATH",
+ )
+ def test_java_tool_checks_linux(self):
+ def run_configure_java(
+ mock_fs_paths, mock_java_home=None, mock_path=None, args=[]
+ ):
+ script = textwrap.dedent(
+ """\
+ @depends('--help')
+ def host(_):
+ return namespace(os='unknown', kernel='unknown')
+ toolchains_base_dir = depends(when=True)(lambda: '/mozbuild')
+ include('%(topsrcdir)s/build/moz.configure/java.configure')
+ """
+ % {"topsrcdir": topsrcdir}
+ )
+
+ # Don't let system JAVA_HOME influence the test
+ original_java_home = os.environ.pop("JAVA_HOME", None)
+ configure_environ = {}
+
+ if mock_java_home:
+ os.environ["JAVA_HOME"] = mock_java_home
+ configure_environ["JAVA_HOME"] = mock_java_home
+
+ if mock_path:
+ configure_environ["PATH"] = mock_path
+
+ # * Even if the real file sysphabtem has a symlink at the mocked path, don't let
+ # realpath follow it, as it may influence the test.
+ # * When finding a binary, check the mock paths rather than the real filesystem.
+ # Note: Python doesn't allow the different "with" bits to be put in parenthesis,
+ # because then it thinks it's an un-with-able tuple. Additionally, if this is cleanly
+ # lined up with "\", black removes them and autoformats them to the block that is
+ # below.
+ result = self.get_result(
+ args=args,
+ command=script,
+ extra_paths=paths,
+ environ=configure_environ,
+ )
+
+ if original_java_home:
+ os.environ["JAVA_HOME"] = original_java_home
+ return result
+
+ java = mozpath.abspath("/usr/bin/java")
+ javac = mozpath.abspath("/usr/bin/javac")
+ paths = {java: None, javac: None}
+ expected_error_message = (
+ "ERROR: Could not locate Java at /mozbuild/jdk/jdk-17.0.7+7/bin, "
+ "please run ./mach bootstrap --no-system-changes\n"
+ )
+
+ config, out, status = run_configure_java(paths)
+ self.assertEqual(status, 1)
+ self.assertEqual(config, {})
+ self.assertEqual(out, expected_error_message)
+
+ # An alternative valid set of tools referred to by JAVA_HOME.
+ alt_java = mozpath.abspath("/usr/local/bin/java")
+ alt_javac = mozpath.abspath("/usr/local/bin/javac")
+ alt_java_home = mozpath.dirname(mozpath.dirname(alt_java))
+ paths = {alt_java: None, alt_javac: None, java: None, javac: None}
+
+ alt_path = mozpath.dirname(java)
+ config, out, status = run_configure_java(paths, alt_java_home, alt_path)
+ self.assertEqual(status, 1)
+ self.assertEqual(config, {})
+ self.assertEqual(out, expected_error_message)
+
+ # We can use --with-java-bin-path instead of JAVA_HOME to similar
+ # effect.
+ config, out, status = run_configure_java(
+ paths,
+ mock_path=mozpath.dirname(java),
+ args=["--with-java-bin-path=%s" % mozpath.dirname(alt_java)],
+ )
+ self.assertEqual(status, 0)
+ self.assertEqual(config, {"JAVA": alt_java, "MOZ_JAVA_CODE_COVERAGE": False})
+ self.assertEqual(
+ out,
+ textwrap.dedent(
+ """\
+ checking for java... %s
+ """
+ % alt_java
+ ),
+ )
+
+ # If --with-java-bin-path and JAVA_HOME are both set,
+ # --with-java-bin-path takes precedence.
+ config, out, status = run_configure_java(
+ paths,
+ mock_java_home=mozpath.dirname(mozpath.dirname(java)),
+ mock_path=mozpath.dirname(java),
+ args=["--with-java-bin-path=%s" % mozpath.dirname(alt_java)],
+ )
+ self.assertEqual(status, 0)
+ self.assertEqual(config, {"JAVA": alt_java, "MOZ_JAVA_CODE_COVERAGE": False})
+ self.assertEqual(
+ out,
+ textwrap.dedent(
+ """\
+ checking for java... %s
+ """
+ % alt_java
+ ),
+ )
+
+ # --enable-java-coverage should set MOZ_JAVA_CODE_COVERAGE.
+ alt_java_home = mozpath.dirname(mozpath.dirname(java))
+ config, out, status = run_configure_java(
+ paths,
+ mock_java_home=alt_java_home,
+ mock_path=mozpath.dirname(java),
+ args=["--enable-java-coverage"],
+ )
+ self.assertEqual(status, 1)
+ self.assertEqual(config, {})
+
+ # Any missing tool is fatal when these checks run.
+ paths = {}
+ config, out, status = run_configure_java(
+ mock_fs_paths={},
+ mock_path=mozpath.dirname(java),
+ args=["--enable-java-coverage"],
+ )
+ self.assertEqual(status, 1)
+ self.assertEqual(config, {})
+ self.assertEqual(out, expected_error_message)
+
+ def test_pkg_check_modules(self):
+ mock_pkg_config_version = "0.10.0"
+ mock_pkg_config_path = mozpath.abspath("/usr/bin/pkg-config")
+
+ seen_flags = set()
+
+ def mock_pkg_config(_, args):
+ if "--dont-define-prefix" in args:
+ args = list(args)
+ seen_flags.add(args.pop(args.index("--dont-define-prefix")))
+ args = tuple(args)
+ if args[0:2] == ("--errors-to-stdout", "--print-errors"):
+ assert len(args) == 3
+ package = args[2]
+ if package == "unknown":
+ return (
+ 1,
+ "Package unknown was not found in the pkg-config search path.\n"
+ "Perhaps you should add the directory containing `unknown.pc'\n"
+ "to the PKG_CONFIG_PATH environment variable\n"
+ "No package 'unknown' found",
+ "",
+ )
+ if package == "valid":
+ return 0, "", ""
+ if package == "new > 1.1":
+ return 1, "Requested 'new > 1.1' but version of new is 1.1", ""
+ if args[0] == "--cflags":
+ assert len(args) == 2
+ return 0, "-I/usr/include/%s" % args[1], ""
+ if args[0] == "--libs":
+ assert len(args) == 2
+ return 0, "-l%s" % args[1], ""
+ if args[0] == "--version":
+ return 0, mock_pkg_config_version, ""
+ if args[0] == "--about":
+ return 1, "Unknown option --about", ""
+ self.fail("Unexpected arguments to mock_pkg_config: %s" % (args,))
+
+ def mock_pkgconf(_, args):
+ if args[0] == "--shared":
+ seen_flags.add(args[0])
+ args = args[1:]
+ if args[0] == "--about":
+ return 0, "pkgconf {}".format(mock_pkg_config_version), ""
+ return mock_pkg_config(_, args)
+
+ def get_result(cmd, args=[], bootstrapped_sysroot=False, extra_paths=None):
+ return self.get_result(
+ textwrap.dedent(
+ """\
+ option('--disable-compile-environment', help='compile env')
+ compile_environment = depends(when='--enable-compile-environment')(lambda: True)
+ toolchain_prefix = depends(when=True)(lambda: None)
+ target_multiarch_dir = depends(when=True)(lambda: None)
+ target_sysroot = depends(when=True)(lambda: %(sysroot)s)
+ target = depends(when=True)(lambda: None)
+ include('%(topsrcdir)s/build/moz.configure/util.configure')
+ include('%(topsrcdir)s/build/moz.configure/checks.configure')
+ # Skip bootstrapping.
+ @template
+ def check_prog(*args, **kwargs):
+ del kwargs["bootstrap"]
+ return check_prog(*args, **kwargs)
+ include('%(topsrcdir)s/build/moz.configure/pkg.configure')
+ """
+ % {
+ "topsrcdir": topsrcdir,
+ "sysroot": "namespace(bootstrapped=True)"
+ if bootstrapped_sysroot
+ else "None",
+ }
+ )
+ + cmd,
+ args=args,
+ extra_paths=extra_paths,
+ includes=(),
+ )
+
+ extra_paths = {mock_pkg_config_path: mock_pkg_config}
+
+ config, output, status = get_result("pkg_check_modules('MOZ_VALID', 'valid')")
+ self.assertEqual(status, 1)
+ self.assertEqual(
+ output,
+ textwrap.dedent(
+ """\
+ checking for pkg_config... not found
+ ERROR: *** The pkg-config script could not be found. Make sure it is
+ *** in your path, or set the PKG_CONFIG environment variable
+ *** to the full path to pkg-config.
+ """
+ ),
+ )
+
+ for pkg_config, version, bootstrapped_sysroot, is_pkgconf in (
+ (mock_pkg_config, "0.10.0", False, False),
+ (mock_pkg_config, "0.30.0", False, False),
+ (mock_pkg_config, "0.30.0", True, False),
+ (mock_pkgconf, "1.1.0", True, True),
+ (mock_pkgconf, "1.6.0", False, True),
+ (mock_pkgconf, "1.8.0", False, True),
+ (mock_pkgconf, "1.8.0", True, True),
+ ):
+ seen_flags = set()
+ mock_pkg_config_version = version
+ config, output, status = get_result(
+ "pkg_check_modules('MOZ_VALID', 'valid')",
+ bootstrapped_sysroot=bootstrapped_sysroot,
+ extra_paths={mock_pkg_config_path: pkg_config},
+ )
+ self.assertEqual(status, 0)
+ self.assertEqual(
+ output,
+ textwrap.dedent(
+ """\
+ checking for pkg_config... %s
+ checking for pkg-config version... %s
+ checking whether pkg-config is pkgconf... %s
+ checking for valid... yes
+ checking MOZ_VALID_CFLAGS... -I/usr/include/valid
+ checking MOZ_VALID_LIBS... -lvalid
+ """
+ % (
+ mock_pkg_config_path,
+ mock_pkg_config_version,
+ "yes" if is_pkgconf else "no",
+ )
+ ),
+ )
+ self.assertEqual(
+ config,
+ {
+ "PKG_CONFIG": mock_pkg_config_path,
+ "MOZ_VALID_CFLAGS": ("-I/usr/include/valid",),
+ "MOZ_VALID_LIBS": ("-lvalid",),
+ },
+ )
+ if version == "1.8.0" and bootstrapped_sysroot:
+ self.assertEqual(seen_flags, set(["--shared", "--dont-define-prefix"]))
+ elif version == "1.8.0":
+ self.assertEqual(seen_flags, set(["--shared"]))
+ elif version in ("1.6.0", "0.30.0") and bootstrapped_sysroot:
+ self.assertEqual(seen_flags, set(["--dont-define-prefix"]))
+ else:
+ self.assertEqual(seen_flags, set())
+
+ config, output, status = get_result(
+ "pkg_check_modules('MOZ_UKNOWN', 'unknown')", extra_paths=extra_paths
+ )
+ self.assertEqual(status, 1)
+ self.assertEqual(
+ output,
+ textwrap.dedent(
+ """\
+ checking for pkg_config... %s
+ checking for pkg-config version... %s
+ checking whether pkg-config is pkgconf... no
+ checking for unknown... no
+ ERROR: Package unknown was not found in the pkg-config search path.
+ ERROR: Perhaps you should add the directory containing `unknown.pc'
+ ERROR: to the PKG_CONFIG_PATH environment variable
+ ERROR: No package 'unknown' found
+ """
+ % (mock_pkg_config_path, mock_pkg_config_version)
+ ),
+ )
+ self.assertEqual(config, {"PKG_CONFIG": mock_pkg_config_path})
+
+ config, output, status = get_result(
+ "pkg_check_modules('MOZ_NEW', 'new > 1.1')", extra_paths=extra_paths
+ )
+ self.assertEqual(status, 1)
+ self.assertEqual(
+ output,
+ textwrap.dedent(
+ """\
+ checking for pkg_config... %s
+ checking for pkg-config version... %s
+ checking whether pkg-config is pkgconf... no
+ checking for new > 1.1... no
+ ERROR: Requested 'new > 1.1' but version of new is 1.1
+ """
+ % (mock_pkg_config_path, mock_pkg_config_version)
+ ),
+ )
+ self.assertEqual(config, {"PKG_CONFIG": mock_pkg_config_path})
+
+ # allow_missing makes missing packages non-fatal.
+ cmd = textwrap.dedent(
+ """\
+ have_new_module = pkg_check_modules('MOZ_NEW', 'new > 1.1', allow_missing=True)
+ @depends(have_new_module)
+ def log_new_module_error(mod):
+ if mod is not True:
+ log.info('Module not found.')
+ """
+ )
+
+ config, output, status = get_result(cmd, extra_paths=extra_paths)
+ self.assertEqual(status, 0)
+ self.assertEqual(
+ output,
+ textwrap.dedent(
+ """\
+ checking for pkg_config... %s
+ checking for pkg-config version... %s
+ checking whether pkg-config is pkgconf... no
+ checking for new > 1.1... no
+ WARNING: Requested 'new > 1.1' but version of new is 1.1
+ Module not found.
+ """
+ % (mock_pkg_config_path, mock_pkg_config_version)
+ ),
+ )
+ self.assertEqual(config, {"PKG_CONFIG": mock_pkg_config_path})
+
+ config, output, status = get_result(
+ cmd, args=["--disable-compile-environment"], extra_paths=extra_paths
+ )
+ self.assertEqual(status, 0)
+ self.assertEqual(output, "Module not found.\n")
+ self.assertEqual(config, {})
+
+ def mock_old_pkg_config(_, args):
+ if args[0] == "--version":
+ return 0, "0.8.10", ""
+ if args[0] == "--about":
+ return 1, "Unknown option --about", ""
+ self.fail("Unexpected arguments to mock_old_pkg_config: %s" % args)
+
+ extra_paths = {mock_pkg_config_path: mock_old_pkg_config}
+
+ config, output, status = get_result(
+ "pkg_check_modules('MOZ_VALID', 'valid')", extra_paths=extra_paths
+ )
+ self.assertEqual(status, 1)
+ self.assertEqual(
+ output,
+ textwrap.dedent(
+ """\
+ checking for pkg_config... %s
+ checking for pkg-config version... 0.8.10
+ checking whether pkg-config is pkgconf... no
+ ERROR: *** Your version of pkg-config is too old. You need version 0.9.0 or newer.
+ """
+ % mock_pkg_config_path
+ ),
+ )
+
+ def test_simple_keyfile(self):
+ includes = ("util.configure", "checks.configure", "keyfiles.configure")
+
+ config, output, status = self.get_result(
+ "simple_keyfile('Mozilla API')", includes=includes
+ )
+ self.assertEqual(status, 0)
+ self.assertEqual(
+ output,
+ textwrap.dedent(
+ """\
+ checking for the Mozilla API key... no
+ """
+ ),
+ )
+ self.assertEqual(config, {"MOZ_MOZILLA_API_KEY": "no-mozilla-api-key"})
+
+ config, output, status = self.get_result(
+ "simple_keyfile('Mozilla API')",
+ args=["--with-mozilla-api-keyfile=/foo/bar/does/not/exist"],
+ includes=includes,
+ )
+ self.assertEqual(status, 1)
+ self.assertEqual(
+ output,
+ textwrap.dedent(
+ """\
+ checking for the Mozilla API key... no
+ ERROR: '/foo/bar/does/not/exist': No such file or directory.
+ """
+ ),
+ )
+ self.assertEqual(config, {})
+
+ with MockedOpen({"key": ""}):
+ config, output, status = self.get_result(
+ "simple_keyfile('Mozilla API')",
+ args=["--with-mozilla-api-keyfile=key"],
+ includes=includes,
+ )
+ self.assertEqual(status, 1)
+ self.assertEqual(
+ output,
+ textwrap.dedent(
+ """\
+ checking for the Mozilla API key... no
+ ERROR: 'key' is empty.
+ """
+ ),
+ )
+ self.assertEqual(config, {})
+
+ with MockedOpen({"key": "fake-key\n"}):
+ config, output, status = self.get_result(
+ "simple_keyfile('Mozilla API')",
+ args=["--with-mozilla-api-keyfile=key"],
+ includes=includes,
+ )
+ self.assertEqual(status, 0)
+ self.assertEqual(
+ output,
+ textwrap.dedent(
+ """\
+ checking for the Mozilla API key... yes
+ """
+ ),
+ )
+ self.assertEqual(config, {"MOZ_MOZILLA_API_KEY": "fake-key"})
+
+ with MockedOpen({"default": "default-key\n"}):
+ config, output, status = self.get_result(
+ "simple_keyfile('Mozilla API', default='default')", includes=includes
+ )
+ self.assertEqual(status, 0)
+ self.assertEqual(
+ output,
+ textwrap.dedent(
+ """\
+ checking for the Mozilla API key... yes
+ """
+ ),
+ )
+ self.assertEqual(config, {"MOZ_MOZILLA_API_KEY": "default-key"})
+
+ with MockedOpen({"default": "default-key\n", "key": "fake-key\n"}):
+ config, output, status = self.get_result(
+ "simple_keyfile('Mozilla API', default='key')", includes=includes
+ )
+ self.assertEqual(status, 0)
+ self.assertEqual(
+ output,
+ textwrap.dedent(
+ """\
+ checking for the Mozilla API key... yes
+ """
+ ),
+ )
+ self.assertEqual(config, {"MOZ_MOZILLA_API_KEY": "fake-key"})
+
+ def test_id_and_secret_keyfile(self):
+ includes = ("util.configure", "checks.configure", "keyfiles.configure")
+
+ config, output, status = self.get_result(
+ "id_and_secret_keyfile('Bing API')", includes=includes
+ )
+ self.assertEqual(status, 0)
+ self.assertEqual(
+ output,
+ textwrap.dedent(
+ """\
+ checking for the Bing API key... no
+ """
+ ),
+ )
+ self.assertEqual(
+ config,
+ {
+ "MOZ_BING_API_CLIENTID": "no-bing-api-clientid",
+ "MOZ_BING_API_KEY": "no-bing-api-key",
+ },
+ )
+
+ config, output, status = self.get_result(
+ "id_and_secret_keyfile('Bing API')",
+ args=["--with-bing-api-keyfile=/foo/bar/does/not/exist"],
+ includes=includes,
+ )
+ self.assertEqual(status, 1)
+ self.assertEqual(
+ output,
+ textwrap.dedent(
+ """\
+ checking for the Bing API key... no
+ ERROR: '/foo/bar/does/not/exist': No such file or directory.
+ """
+ ),
+ )
+ self.assertEqual(config, {})
+
+ with MockedOpen({"key": ""}):
+ config, output, status = self.get_result(
+ "id_and_secret_keyfile('Bing API')",
+ args=["--with-bing-api-keyfile=key"],
+ includes=includes,
+ )
+ self.assertEqual(status, 1)
+ self.assertEqual(
+ output,
+ textwrap.dedent(
+ """\
+ checking for the Bing API key... no
+ ERROR: 'key' is empty.
+ """
+ ),
+ )
+ self.assertEqual(config, {})
+
+ with MockedOpen({"key": "fake-id fake-key\n"}):
+ config, output, status = self.get_result(
+ "id_and_secret_keyfile('Bing API')",
+ args=["--with-bing-api-keyfile=key"],
+ includes=includes,
+ )
+ self.assertEqual(status, 0)
+ self.assertEqual(
+ output,
+ textwrap.dedent(
+ """\
+ checking for the Bing API key... yes
+ """
+ ),
+ )
+ self.assertEqual(
+ config,
+ {"MOZ_BING_API_CLIENTID": "fake-id", "MOZ_BING_API_KEY": "fake-key"},
+ )
+
+ with MockedOpen({"key": "fake-key\n"}):
+ config, output, status = self.get_result(
+ "id_and_secret_keyfile('Bing API')",
+ args=["--with-bing-api-keyfile=key"],
+ includes=includes,
+ )
+ self.assertEqual(status, 1)
+ self.assertEqual(
+ output,
+ textwrap.dedent(
+ """\
+ checking for the Bing API key... no
+ ERROR: Bing API key file has an invalid format.
+ """
+ ),
+ )
+ self.assertEqual(config, {})
+
+ with MockedOpen({"default-key": "default-id default-key\n"}):
+ config, output, status = self.get_result(
+ "id_and_secret_keyfile('Bing API', default='default-key')",
+ includes=includes,
+ )
+ self.assertEqual(status, 0)
+ self.assertEqual(
+ output,
+ textwrap.dedent(
+ """\
+ checking for the Bing API key... yes
+ """
+ ),
+ )
+ self.assertEqual(
+ config,
+ {
+ "MOZ_BING_API_CLIENTID": "default-id",
+ "MOZ_BING_API_KEY": "default-key",
+ },
+ )
+
+ with MockedOpen(
+ {"default-key": "default-id default-key\n", "key": "fake-id fake-key\n"}
+ ):
+ config, output, status = self.get_result(
+ "id_and_secret_keyfile('Bing API', default='default-key')",
+ args=["--with-bing-api-keyfile=key"],
+ includes=includes,
+ )
+ self.assertEqual(status, 0)
+ self.assertEqual(
+ output,
+ textwrap.dedent(
+ """\
+ checking for the Bing API key... yes
+ """
+ ),
+ )
+ self.assertEqual(
+ config,
+ {"MOZ_BING_API_CLIENTID": "fake-id", "MOZ_BING_API_KEY": "fake-key"},
+ )
+
+
+if __name__ == "__main__":
+ main()