diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
commit | 36d22d82aa202bb199967e9512281e9a53db42c9 (patch) | |
tree | 105e8c98ddea1c1e4784a60a5a6410fa416be2de /python/mozbuild/mozbuild/test/configure/test_checks_configure.py | |
parent | Initial commit. (diff) | |
download | firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip |
Adding upstream version 115.7.0esr.upstream/115.7.0esrupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'python/mozbuild/mozbuild/test/configure/test_checks_configure.py')
-rw-r--r-- | python/mozbuild/mozbuild/test/configure/test_checks_configure.py | 1169 |
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() |