Bug 1874684 - Part 28: Return DateDuration from DifferenceISODateTime. r=mgaudet
[gecko.git] / python / mozbuild / mozbuild / test / test_base.py
blobc75a71ef5dd8a10979ff34c81bcbf4b85cb4f2b7
1 # This Source Code Form is subject to the terms of the Mozilla Public
2 # License, v. 2.0. If a copy of the MPL was not distributed with this
3 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
5 import json
6 import os
7 import shutil
8 import sys
9 import tempfile
10 import unittest
12 import mozpack.path as mozpath
13 from buildconfig import topobjdir, topsrcdir
14 from mach.logging import LoggingManager
15 from mozfile.mozfile import NamedTemporaryFile
16 from mozunit import main
17 from six import StringIO
19 from mozbuild.backend.configenvironment import ConfigEnvironment
20 from mozbuild.base import (
21 BadEnvironmentException,
22 MachCommandBase,
23 MozbuildObject,
24 PathArgument,
26 from mozbuild.test.common import prepare_tmp_topsrcdir
28 curdir = os.path.dirname(__file__)
29 log_manager = LoggingManager()
32 class TestMozbuildObject(unittest.TestCase):
33 def setUp(self):
34 self._old_cwd = os.getcwd()
35 self._old_env = dict(os.environ)
36 os.environ.pop("MOZCONFIG", None)
37 os.environ.pop("MOZ_OBJDIR", None)
39 def tearDown(self):
40 os.chdir(self._old_cwd)
41 os.environ.clear()
42 os.environ.update(self._old_env)
44 def get_base(self, topobjdir=None):
45 return MozbuildObject(topsrcdir, None, log_manager, topobjdir=topobjdir)
47 def test_objdir_config_guess(self):
48 base = self.get_base()
50 with NamedTemporaryFile(mode="wt") as mozconfig:
51 os.environ["MOZCONFIG"] = mozconfig.name
53 self.assertIsNotNone(base.topobjdir)
54 self.assertEqual(len(base.topobjdir.split()), 1)
55 config_guess = base.resolve_config_guess()
56 self.assertTrue(base.topobjdir.endswith(config_guess))
57 self.assertTrue(os.path.isabs(base.topobjdir))
58 self.assertTrue(base.topobjdir.startswith(base.topsrcdir))
60 def test_objdir_trailing_slash(self):
61 """Trailing slashes in topobjdir should be removed."""
62 base = self.get_base()
64 with NamedTemporaryFile(mode="wt") as mozconfig:
65 mozconfig.write("mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/foo/")
66 mozconfig.flush()
67 os.environ["MOZCONFIG"] = mozconfig.name
69 self.assertEqual(base.topobjdir, mozpath.join(base.topsrcdir, "foo"))
70 self.assertTrue(base.topobjdir.endswith("foo"))
72 def test_objdir_config_status(self):
73 """Ensure @CONFIG_GUESS@ is handled when loading mozconfig."""
74 base = self.get_base()
75 guess = base.resolve_config_guess()
77 # There may be symlinks involved, so we use real paths to ensure
78 # path consistency.
79 d = os.path.realpath(tempfile.mkdtemp())
80 try:
81 mozconfig = os.path.join(d, "mozconfig")
82 with open(mozconfig, "wt") as fh:
83 fh.write("mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/foo/@CONFIG_GUESS@")
84 print("Wrote mozconfig %s" % mozconfig)
86 topobjdir = os.path.join(d, "foo", guess)
87 os.makedirs(topobjdir)
89 # Create a fake topsrcdir.
90 prepare_tmp_topsrcdir(d)
92 mozinfo = os.path.join(topobjdir, "mozinfo.json")
93 with open(mozinfo, "wt") as fh:
94 json.dump(
95 dict(
96 topsrcdir=d,
97 mozconfig=mozconfig,
99 fh,
102 os.environ["MOZCONFIG"] = mozconfig
103 os.chdir(topobjdir)
105 obj = MozbuildObject.from_environment(detect_virtualenv_mozinfo=False)
107 self.assertEqual(obj.topobjdir, mozpath.normsep(topobjdir))
108 finally:
109 os.chdir(self._old_cwd)
110 shutil.rmtree(d)
112 def test_relative_objdir(self):
113 """Relative defined objdirs are loaded properly."""
114 d = os.path.realpath(tempfile.mkdtemp())
115 try:
116 mozconfig = os.path.join(d, "mozconfig")
117 with open(mozconfig, "wt") as fh:
118 fh.write("mk_add_options MOZ_OBJDIR=./objdir")
120 topobjdir = mozpath.join(d, "objdir")
121 os.mkdir(topobjdir)
123 mozinfo = os.path.join(topobjdir, "mozinfo.json")
124 with open(mozinfo, "wt") as fh:
125 json.dump(
126 dict(
127 topsrcdir=d,
128 mozconfig=mozconfig,
133 os.environ["MOZCONFIG"] = mozconfig
134 child = os.path.join(topobjdir, "foo", "bar")
135 os.makedirs(child)
136 os.chdir(child)
138 obj = MozbuildObject.from_environment(detect_virtualenv_mozinfo=False)
140 self.assertEqual(obj.topobjdir, topobjdir)
142 finally:
143 os.chdir(self._old_cwd)
144 shutil.rmtree(d)
146 @unittest.skipIf(
147 not hasattr(os, "symlink") or os.name == "nt", "symlinks not available."
149 def test_symlink_objdir(self):
150 """Objdir that is a symlink is loaded properly."""
151 d = os.path.realpath(tempfile.mkdtemp())
152 try:
153 topobjdir_real = os.path.join(d, "objdir")
154 topobjdir_link = os.path.join(d, "objlink")
156 os.mkdir(topobjdir_real)
157 os.symlink(topobjdir_real, topobjdir_link)
159 mozconfig = os.path.join(d, "mozconfig")
160 with open(mozconfig, "wt") as fh:
161 fh.write("mk_add_options MOZ_OBJDIR=%s" % topobjdir_link)
163 mozinfo = os.path.join(topobjdir_real, "mozinfo.json")
164 with open(mozinfo, "wt") as fh:
165 json.dump(
166 dict(
167 topsrcdir=d,
168 mozconfig=mozconfig,
173 os.chdir(topobjdir_link)
174 obj = MozbuildObject.from_environment(detect_virtualenv_mozinfo=False)
175 self.assertEqual(obj.topobjdir, topobjdir_real)
177 os.chdir(topobjdir_real)
178 obj = MozbuildObject.from_environment(detect_virtualenv_mozinfo=False)
179 self.assertEqual(obj.topobjdir, topobjdir_real)
181 finally:
182 os.chdir(self._old_cwd)
183 shutil.rmtree(d)
185 def test_mach_command_base_inside_objdir(self):
186 """Ensure a MachCommandBase constructed from inside the objdir works."""
188 d = os.path.realpath(tempfile.mkdtemp())
190 try:
191 topobjdir = os.path.join(d, "objdir")
192 os.makedirs(topobjdir)
194 topsrcdir = os.path.join(d, "srcdir")
195 prepare_tmp_topsrcdir(topsrcdir)
197 mozinfo = os.path.join(topobjdir, "mozinfo.json")
198 with open(mozinfo, "wt") as fh:
199 json.dump(
200 dict(
201 topsrcdir=topsrcdir,
206 os.chdir(topobjdir)
208 class MockMachContext(object):
209 pass
211 context = MockMachContext()
212 context.cwd = topobjdir
213 context.topdir = topsrcdir
214 context.settings = None
215 context.log_manager = None
216 context.detect_virtualenv_mozinfo = False
218 o = MachCommandBase(context, None)
220 self.assertEqual(o.topobjdir, mozpath.normsep(topobjdir))
221 self.assertEqual(o.topsrcdir, mozpath.normsep(topsrcdir))
223 finally:
224 os.chdir(self._old_cwd)
225 shutil.rmtree(d)
227 def test_objdir_is_srcdir_rejected(self):
228 """Ensure the srcdir configurations are rejected."""
229 d = os.path.realpath(tempfile.mkdtemp())
231 try:
232 # The easiest way to do this is to create a mozinfo.json with data
233 # that will never happen.
234 mozinfo = os.path.join(d, "mozinfo.json")
235 with open(mozinfo, "wt") as fh:
236 json.dump({"topsrcdir": d}, fh)
238 os.chdir(d)
240 with self.assertRaises(BadEnvironmentException):
241 MozbuildObject.from_environment(detect_virtualenv_mozinfo=False)
243 finally:
244 os.chdir(self._old_cwd)
245 shutil.rmtree(d)
247 def test_objdir_mismatch(self):
248 """Ensure MachCommandBase throwing on objdir mismatch."""
249 d = os.path.realpath(tempfile.mkdtemp())
251 try:
252 real_topobjdir = os.path.join(d, "real-objdir")
253 os.makedirs(real_topobjdir)
255 topobjdir = os.path.join(d, "objdir")
256 os.makedirs(topobjdir)
258 topsrcdir = os.path.join(d, "srcdir")
259 prepare_tmp_topsrcdir(topsrcdir)
261 mozconfig = os.path.join(d, "mozconfig")
262 with open(mozconfig, "wt") as fh:
263 fh.write(
264 "mk_add_options MOZ_OBJDIR=%s" % real_topobjdir.replace("\\", "/")
267 mozinfo = os.path.join(topobjdir, "mozinfo.json")
268 with open(mozinfo, "wt") as fh:
269 json.dump(
270 dict(
271 topsrcdir=topsrcdir,
272 mozconfig=mozconfig,
277 os.chdir(topobjdir)
279 class MockMachContext(object):
280 pass
282 context = MockMachContext()
283 context.cwd = topobjdir
284 context.topdir = topsrcdir
285 context.settings = None
286 context.log_manager = None
287 context.detect_virtualenv_mozinfo = False
289 stdout = sys.stdout
290 sys.stdout = StringIO()
291 try:
292 with self.assertRaises(SystemExit):
293 MachCommandBase(context, None)
295 self.assertTrue(
296 sys.stdout.getvalue().startswith(
297 "Ambiguous object directory detected."
300 finally:
301 sys.stdout = stdout
303 finally:
304 os.chdir(self._old_cwd)
305 shutil.rmtree(d)
307 def test_config_environment(self):
308 d = os.path.realpath(tempfile.mkdtemp())
310 try:
311 with open(os.path.join(d, "config.status"), "w") as fh:
312 fh.write("# coding=utf-8\n")
313 fh.write("from __future__ import unicode_literals\n")
314 fh.write("topobjdir = '%s'\n" % mozpath.normsep(d))
315 fh.write("topsrcdir = '%s'\n" % topsrcdir)
316 fh.write("mozconfig = None\n")
317 fh.write("defines = { 'FOO': 'foo' }\n")
318 fh.write("substs = { 'QUX': 'qux' }\n")
319 fh.write(
320 "__all__ = ['topobjdir', 'topsrcdir', 'defines', "
321 "'substs', 'mozconfig']"
324 base = self.get_base(topobjdir=d)
326 ce = base.config_environment
327 self.assertIsInstance(ce, ConfigEnvironment)
329 self.assertEqual(base.defines, ce.defines)
330 self.assertEqual(base.substs, ce.substs)
332 self.assertEqual(base.defines, {"FOO": "foo"})
333 self.assertEqual(
334 base.substs,
336 "ACDEFINES": "-DFOO=foo",
337 "ALLEMPTYSUBSTS": "",
338 "ALLSUBSTS": "ACDEFINES = -DFOO=foo\nQUX = qux",
339 "QUX": "qux",
342 finally:
343 shutil.rmtree(d)
345 def test_get_binary_path(self):
346 base = self.get_base(topobjdir=topobjdir)
348 platform = sys.platform
350 # We should ideally use the config.status from the build. Let's install
351 # a fake one.
352 substs = [
353 ("MOZ_APP_NAME", "awesomeapp"),
354 ("MOZ_BUILD_APP", "awesomeapp"),
356 if sys.platform.startswith("darwin"):
357 substs.append(("OS_ARCH", "Darwin"))
358 substs.append(("BIN_SUFFIX", ""))
359 substs.append(("MOZ_MACBUNDLE_NAME", "Nightly.app"))
360 elif sys.platform.startswith(("win32", "cygwin")):
361 substs.append(("OS_ARCH", "WINNT"))
362 substs.append(("BIN_SUFFIX", ".exe"))
363 else:
364 substs.append(("OS_ARCH", "something"))
365 substs.append(("BIN_SUFFIX", ""))
367 base._config_environment = ConfigEnvironment(
368 base.topsrcdir, base.topobjdir, substs=substs
371 p = base.get_binary_path("xpcshell", False)
372 if platform.startswith("darwin"):
373 self.assertTrue(p.endswith("Contents/MacOS/xpcshell"))
374 elif platform.startswith(("win32", "cygwin")):
375 self.assertTrue(p.endswith("xpcshell.exe"))
376 else:
377 self.assertTrue(p.endswith("dist/bin/xpcshell"))
379 p = base.get_binary_path(validate_exists=False)
380 if platform.startswith("darwin"):
381 self.assertTrue(p.endswith("Contents/MacOS/awesomeapp"))
382 elif platform.startswith(("win32", "cygwin")):
383 self.assertTrue(p.endswith("awesomeapp.exe"))
384 else:
385 self.assertTrue(p.endswith("dist/bin/awesomeapp"))
387 p = base.get_binary_path(validate_exists=False, where="staged-package")
388 if platform.startswith("darwin"):
389 self.assertTrue(
390 p.endswith("awesomeapp/Nightly.app/Contents/MacOS/awesomeapp")
392 elif platform.startswith(("win32", "cygwin")):
393 self.assertTrue(p.endswith("awesomeapp\\awesomeapp.exe"))
394 else:
395 self.assertTrue(p.endswith("awesomeapp/awesomeapp"))
397 self.assertRaises(Exception, base.get_binary_path, where="somewhere")
399 p = base.get_binary_path("foobar", validate_exists=False)
400 if platform.startswith("win32"):
401 self.assertTrue(p.endswith("foobar.exe"))
402 else:
403 self.assertTrue(p.endswith("foobar"))
406 class TestPathArgument(unittest.TestCase):
407 def test_path_argument(self):
408 # Absolute path
409 p = PathArgument("/obj/foo", "/src", "/obj", "/src")
410 self.assertEqual(p.relpath(), "foo")
411 self.assertEqual(p.srcdir_path(), "/src/foo")
412 self.assertEqual(p.objdir_path(), "/obj/foo")
414 # Relative path within srcdir
415 p = PathArgument("foo", "/src", "/obj", "/src")
416 self.assertEqual(p.relpath(), "foo")
417 self.assertEqual(p.srcdir_path(), "/src/foo")
418 self.assertEqual(p.objdir_path(), "/obj/foo")
420 # Relative path within subdirectory
421 p = PathArgument("bar", "/src", "/obj", "/src/foo")
422 self.assertEqual(p.relpath(), "foo/bar")
423 self.assertEqual(p.srcdir_path(), "/src/foo/bar")
424 self.assertEqual(p.objdir_path(), "/obj/foo/bar")
426 # Relative path within objdir
427 p = PathArgument("foo", "/src", "/obj", "/obj")
428 self.assertEqual(p.relpath(), "foo")
429 self.assertEqual(p.srcdir_path(), "/src/foo")
430 self.assertEqual(p.objdir_path(), "/obj/foo")
432 # "." path
433 p = PathArgument(".", "/src", "/obj", "/src/foo")
434 self.assertEqual(p.relpath(), "foo")
435 self.assertEqual(p.srcdir_path(), "/src/foo")
436 self.assertEqual(p.objdir_path(), "/obj/foo")
438 # Nested src/obj directories
439 p = PathArgument("bar", "/src", "/src/obj", "/src/obj/foo")
440 self.assertEqual(p.relpath(), "foo/bar")
441 self.assertEqual(p.srcdir_path(), "/src/foo/bar")
442 self.assertEqual(p.objdir_path(), "/src/obj/foo/bar")
445 if __name__ == "__main__":
446 main()