summaryrefslogtreecommitdiffstats
path: root/python/mozbuild/mozbuild/test/test_base.py
diff options
context:
space:
mode:
Diffstat (limited to 'python/mozbuild/mozbuild/test/test_base.py')
-rw-r--r--python/mozbuild/mozbuild/test/test_base.py446
1 files changed, 446 insertions, 0 deletions
diff --git a/python/mozbuild/mozbuild/test/test_base.py b/python/mozbuild/mozbuild/test/test_base.py
new file mode 100644
index 0000000000..c75a71ef5d
--- /dev/null
+++ b/python/mozbuild/mozbuild/test/test_base.py
@@ -0,0 +1,446 @@
+# 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 json
+import os
+import shutil
+import sys
+import tempfile
+import unittest
+
+import mozpack.path as mozpath
+from buildconfig import topobjdir, topsrcdir
+from mach.logging import LoggingManager
+from mozfile.mozfile import NamedTemporaryFile
+from mozunit import main
+from six import StringIO
+
+from mozbuild.backend.configenvironment import ConfigEnvironment
+from mozbuild.base import (
+ BadEnvironmentException,
+ MachCommandBase,
+ MozbuildObject,
+ PathArgument,
+)
+from mozbuild.test.common import prepare_tmp_topsrcdir
+
+curdir = os.path.dirname(__file__)
+log_manager = LoggingManager()
+
+
+class TestMozbuildObject(unittest.TestCase):
+ def setUp(self):
+ self._old_cwd = os.getcwd()
+ self._old_env = dict(os.environ)
+ os.environ.pop("MOZCONFIG", None)
+ os.environ.pop("MOZ_OBJDIR", None)
+
+ def tearDown(self):
+ os.chdir(self._old_cwd)
+ os.environ.clear()
+ os.environ.update(self._old_env)
+
+ def get_base(self, topobjdir=None):
+ return MozbuildObject(topsrcdir, None, log_manager, topobjdir=topobjdir)
+
+ def test_objdir_config_guess(self):
+ base = self.get_base()
+
+ with NamedTemporaryFile(mode="wt") as mozconfig:
+ os.environ["MOZCONFIG"] = mozconfig.name
+
+ self.assertIsNotNone(base.topobjdir)
+ self.assertEqual(len(base.topobjdir.split()), 1)
+ config_guess = base.resolve_config_guess()
+ self.assertTrue(base.topobjdir.endswith(config_guess))
+ self.assertTrue(os.path.isabs(base.topobjdir))
+ self.assertTrue(base.topobjdir.startswith(base.topsrcdir))
+
+ def test_objdir_trailing_slash(self):
+ """Trailing slashes in topobjdir should be removed."""
+ base = self.get_base()
+
+ with NamedTemporaryFile(mode="wt") as mozconfig:
+ mozconfig.write("mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/foo/")
+ mozconfig.flush()
+ os.environ["MOZCONFIG"] = mozconfig.name
+
+ self.assertEqual(base.topobjdir, mozpath.join(base.topsrcdir, "foo"))
+ self.assertTrue(base.topobjdir.endswith("foo"))
+
+ def test_objdir_config_status(self):
+ """Ensure @CONFIG_GUESS@ is handled when loading mozconfig."""
+ base = self.get_base()
+ guess = base.resolve_config_guess()
+
+ # There may be symlinks involved, so we use real paths to ensure
+ # path consistency.
+ d = os.path.realpath(tempfile.mkdtemp())
+ try:
+ mozconfig = os.path.join(d, "mozconfig")
+ with open(mozconfig, "wt") as fh:
+ fh.write("mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/foo/@CONFIG_GUESS@")
+ print("Wrote mozconfig %s" % mozconfig)
+
+ topobjdir = os.path.join(d, "foo", guess)
+ os.makedirs(topobjdir)
+
+ # Create a fake topsrcdir.
+ prepare_tmp_topsrcdir(d)
+
+ mozinfo = os.path.join(topobjdir, "mozinfo.json")
+ with open(mozinfo, "wt") as fh:
+ json.dump(
+ dict(
+ topsrcdir=d,
+ mozconfig=mozconfig,
+ ),
+ fh,
+ )
+
+ os.environ["MOZCONFIG"] = mozconfig
+ os.chdir(topobjdir)
+
+ obj = MozbuildObject.from_environment(detect_virtualenv_mozinfo=False)
+
+ self.assertEqual(obj.topobjdir, mozpath.normsep(topobjdir))
+ finally:
+ os.chdir(self._old_cwd)
+ shutil.rmtree(d)
+
+ def test_relative_objdir(self):
+ """Relative defined objdirs are loaded properly."""
+ d = os.path.realpath(tempfile.mkdtemp())
+ try:
+ mozconfig = os.path.join(d, "mozconfig")
+ with open(mozconfig, "wt") as fh:
+ fh.write("mk_add_options MOZ_OBJDIR=./objdir")
+
+ topobjdir = mozpath.join(d, "objdir")
+ os.mkdir(topobjdir)
+
+ mozinfo = os.path.join(topobjdir, "mozinfo.json")
+ with open(mozinfo, "wt") as fh:
+ json.dump(
+ dict(
+ topsrcdir=d,
+ mozconfig=mozconfig,
+ ),
+ fh,
+ )
+
+ os.environ["MOZCONFIG"] = mozconfig
+ child = os.path.join(topobjdir, "foo", "bar")
+ os.makedirs(child)
+ os.chdir(child)
+
+ obj = MozbuildObject.from_environment(detect_virtualenv_mozinfo=False)
+
+ self.assertEqual(obj.topobjdir, topobjdir)
+
+ finally:
+ os.chdir(self._old_cwd)
+ shutil.rmtree(d)
+
+ @unittest.skipIf(
+ not hasattr(os, "symlink") or os.name == "nt", "symlinks not available."
+ )
+ def test_symlink_objdir(self):
+ """Objdir that is a symlink is loaded properly."""
+ d = os.path.realpath(tempfile.mkdtemp())
+ try:
+ topobjdir_real = os.path.join(d, "objdir")
+ topobjdir_link = os.path.join(d, "objlink")
+
+ os.mkdir(topobjdir_real)
+ os.symlink(topobjdir_real, topobjdir_link)
+
+ mozconfig = os.path.join(d, "mozconfig")
+ with open(mozconfig, "wt") as fh:
+ fh.write("mk_add_options MOZ_OBJDIR=%s" % topobjdir_link)
+
+ mozinfo = os.path.join(topobjdir_real, "mozinfo.json")
+ with open(mozinfo, "wt") as fh:
+ json.dump(
+ dict(
+ topsrcdir=d,
+ mozconfig=mozconfig,
+ ),
+ fh,
+ )
+
+ os.chdir(topobjdir_link)
+ obj = MozbuildObject.from_environment(detect_virtualenv_mozinfo=False)
+ self.assertEqual(obj.topobjdir, topobjdir_real)
+
+ os.chdir(topobjdir_real)
+ obj = MozbuildObject.from_environment(detect_virtualenv_mozinfo=False)
+ self.assertEqual(obj.topobjdir, topobjdir_real)
+
+ finally:
+ os.chdir(self._old_cwd)
+ shutil.rmtree(d)
+
+ def test_mach_command_base_inside_objdir(self):
+ """Ensure a MachCommandBase constructed from inside the objdir works."""
+
+ d = os.path.realpath(tempfile.mkdtemp())
+
+ try:
+ topobjdir = os.path.join(d, "objdir")
+ os.makedirs(topobjdir)
+
+ topsrcdir = os.path.join(d, "srcdir")
+ prepare_tmp_topsrcdir(topsrcdir)
+
+ mozinfo = os.path.join(topobjdir, "mozinfo.json")
+ with open(mozinfo, "wt") as fh:
+ json.dump(
+ dict(
+ topsrcdir=topsrcdir,
+ ),
+ fh,
+ )
+
+ os.chdir(topobjdir)
+
+ class MockMachContext(object):
+ pass
+
+ context = MockMachContext()
+ context.cwd = topobjdir
+ context.topdir = topsrcdir
+ context.settings = None
+ context.log_manager = None
+ context.detect_virtualenv_mozinfo = False
+
+ o = MachCommandBase(context, None)
+
+ self.assertEqual(o.topobjdir, mozpath.normsep(topobjdir))
+ self.assertEqual(o.topsrcdir, mozpath.normsep(topsrcdir))
+
+ finally:
+ os.chdir(self._old_cwd)
+ shutil.rmtree(d)
+
+ def test_objdir_is_srcdir_rejected(self):
+ """Ensure the srcdir configurations are rejected."""
+ d = os.path.realpath(tempfile.mkdtemp())
+
+ try:
+ # The easiest way to do this is to create a mozinfo.json with data
+ # that will never happen.
+ mozinfo = os.path.join(d, "mozinfo.json")
+ with open(mozinfo, "wt") as fh:
+ json.dump({"topsrcdir": d}, fh)
+
+ os.chdir(d)
+
+ with self.assertRaises(BadEnvironmentException):
+ MozbuildObject.from_environment(detect_virtualenv_mozinfo=False)
+
+ finally:
+ os.chdir(self._old_cwd)
+ shutil.rmtree(d)
+
+ def test_objdir_mismatch(self):
+ """Ensure MachCommandBase throwing on objdir mismatch."""
+ d = os.path.realpath(tempfile.mkdtemp())
+
+ try:
+ real_topobjdir = os.path.join(d, "real-objdir")
+ os.makedirs(real_topobjdir)
+
+ topobjdir = os.path.join(d, "objdir")
+ os.makedirs(topobjdir)
+
+ topsrcdir = os.path.join(d, "srcdir")
+ prepare_tmp_topsrcdir(topsrcdir)
+
+ mozconfig = os.path.join(d, "mozconfig")
+ with open(mozconfig, "wt") as fh:
+ fh.write(
+ "mk_add_options MOZ_OBJDIR=%s" % real_topobjdir.replace("\\", "/")
+ )
+
+ mozinfo = os.path.join(topobjdir, "mozinfo.json")
+ with open(mozinfo, "wt") as fh:
+ json.dump(
+ dict(
+ topsrcdir=topsrcdir,
+ mozconfig=mozconfig,
+ ),
+ fh,
+ )
+
+ os.chdir(topobjdir)
+
+ class MockMachContext(object):
+ pass
+
+ context = MockMachContext()
+ context.cwd = topobjdir
+ context.topdir = topsrcdir
+ context.settings = None
+ context.log_manager = None
+ context.detect_virtualenv_mozinfo = False
+
+ stdout = sys.stdout
+ sys.stdout = StringIO()
+ try:
+ with self.assertRaises(SystemExit):
+ MachCommandBase(context, None)
+
+ self.assertTrue(
+ sys.stdout.getvalue().startswith(
+ "Ambiguous object directory detected."
+ )
+ )
+ finally:
+ sys.stdout = stdout
+
+ finally:
+ os.chdir(self._old_cwd)
+ shutil.rmtree(d)
+
+ def test_config_environment(self):
+ d = os.path.realpath(tempfile.mkdtemp())
+
+ try:
+ with open(os.path.join(d, "config.status"), "w") as fh:
+ fh.write("# coding=utf-8\n")
+ fh.write("from __future__ import unicode_literals\n")
+ fh.write("topobjdir = '%s'\n" % mozpath.normsep(d))
+ fh.write("topsrcdir = '%s'\n" % topsrcdir)
+ fh.write("mozconfig = None\n")
+ fh.write("defines = { 'FOO': 'foo' }\n")
+ fh.write("substs = { 'QUX': 'qux' }\n")
+ fh.write(
+ "__all__ = ['topobjdir', 'topsrcdir', 'defines', "
+ "'substs', 'mozconfig']"
+ )
+
+ base = self.get_base(topobjdir=d)
+
+ ce = base.config_environment
+ self.assertIsInstance(ce, ConfigEnvironment)
+
+ self.assertEqual(base.defines, ce.defines)
+ self.assertEqual(base.substs, ce.substs)
+
+ self.assertEqual(base.defines, {"FOO": "foo"})
+ self.assertEqual(
+ base.substs,
+ {
+ "ACDEFINES": "-DFOO=foo",
+ "ALLEMPTYSUBSTS": "",
+ "ALLSUBSTS": "ACDEFINES = -DFOO=foo\nQUX = qux",
+ "QUX": "qux",
+ },
+ )
+ finally:
+ shutil.rmtree(d)
+
+ def test_get_binary_path(self):
+ base = self.get_base(topobjdir=topobjdir)
+
+ platform = sys.platform
+
+ # We should ideally use the config.status from the build. Let's install
+ # a fake one.
+ substs = [
+ ("MOZ_APP_NAME", "awesomeapp"),
+ ("MOZ_BUILD_APP", "awesomeapp"),
+ ]
+ if sys.platform.startswith("darwin"):
+ substs.append(("OS_ARCH", "Darwin"))
+ substs.append(("BIN_SUFFIX", ""))
+ substs.append(("MOZ_MACBUNDLE_NAME", "Nightly.app"))
+ elif sys.platform.startswith(("win32", "cygwin")):
+ substs.append(("OS_ARCH", "WINNT"))
+ substs.append(("BIN_SUFFIX", ".exe"))
+ else:
+ substs.append(("OS_ARCH", "something"))
+ substs.append(("BIN_SUFFIX", ""))
+
+ base._config_environment = ConfigEnvironment(
+ base.topsrcdir, base.topobjdir, substs=substs
+ )
+
+ p = base.get_binary_path("xpcshell", False)
+ if platform.startswith("darwin"):
+ self.assertTrue(p.endswith("Contents/MacOS/xpcshell"))
+ elif platform.startswith(("win32", "cygwin")):
+ self.assertTrue(p.endswith("xpcshell.exe"))
+ else:
+ self.assertTrue(p.endswith("dist/bin/xpcshell"))
+
+ p = base.get_binary_path(validate_exists=False)
+ if platform.startswith("darwin"):
+ self.assertTrue(p.endswith("Contents/MacOS/awesomeapp"))
+ elif platform.startswith(("win32", "cygwin")):
+ self.assertTrue(p.endswith("awesomeapp.exe"))
+ else:
+ self.assertTrue(p.endswith("dist/bin/awesomeapp"))
+
+ p = base.get_binary_path(validate_exists=False, where="staged-package")
+ if platform.startswith("darwin"):
+ self.assertTrue(
+ p.endswith("awesomeapp/Nightly.app/Contents/MacOS/awesomeapp")
+ )
+ elif platform.startswith(("win32", "cygwin")):
+ self.assertTrue(p.endswith("awesomeapp\\awesomeapp.exe"))
+ else:
+ self.assertTrue(p.endswith("awesomeapp/awesomeapp"))
+
+ self.assertRaises(Exception, base.get_binary_path, where="somewhere")
+
+ p = base.get_binary_path("foobar", validate_exists=False)
+ if platform.startswith("win32"):
+ self.assertTrue(p.endswith("foobar.exe"))
+ else:
+ self.assertTrue(p.endswith("foobar"))
+
+
+class TestPathArgument(unittest.TestCase):
+ def test_path_argument(self):
+ # Absolute path
+ p = PathArgument("/obj/foo", "/src", "/obj", "/src")
+ self.assertEqual(p.relpath(), "foo")
+ self.assertEqual(p.srcdir_path(), "/src/foo")
+ self.assertEqual(p.objdir_path(), "/obj/foo")
+
+ # Relative path within srcdir
+ p = PathArgument("foo", "/src", "/obj", "/src")
+ self.assertEqual(p.relpath(), "foo")
+ self.assertEqual(p.srcdir_path(), "/src/foo")
+ self.assertEqual(p.objdir_path(), "/obj/foo")
+
+ # Relative path within subdirectory
+ p = PathArgument("bar", "/src", "/obj", "/src/foo")
+ self.assertEqual(p.relpath(), "foo/bar")
+ self.assertEqual(p.srcdir_path(), "/src/foo/bar")
+ self.assertEqual(p.objdir_path(), "/obj/foo/bar")
+
+ # Relative path within objdir
+ p = PathArgument("foo", "/src", "/obj", "/obj")
+ self.assertEqual(p.relpath(), "foo")
+ self.assertEqual(p.srcdir_path(), "/src/foo")
+ self.assertEqual(p.objdir_path(), "/obj/foo")
+
+ # "." path
+ p = PathArgument(".", "/src", "/obj", "/src/foo")
+ self.assertEqual(p.relpath(), "foo")
+ self.assertEqual(p.srcdir_path(), "/src/foo")
+ self.assertEqual(p.objdir_path(), "/obj/foo")
+
+ # Nested src/obj directories
+ p = PathArgument("bar", "/src", "/src/obj", "/src/obj/foo")
+ self.assertEqual(p.relpath(), "foo/bar")
+ self.assertEqual(p.srcdir_path(), "/src/foo/bar")
+ self.assertEqual(p.objdir_path(), "/src/obj/foo/bar")
+
+
+if __name__ == "__main__":
+ main()