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/.
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
,
26 from mozbuild
.test
.common
import prepare_tmp_topsrcdir
28 curdir
= os
.path
.dirname(__file__
)
29 log_manager
= LoggingManager()
32 class TestMozbuildObject(unittest
.TestCase
):
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)
40 os
.chdir(self
._old
_cwd
)
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/")
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
79 d
= os
.path
.realpath(tempfile
.mkdtemp())
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
:
102 os
.environ
["MOZCONFIG"] = mozconfig
105 obj
= MozbuildObject
.from_environment(detect_virtualenv_mozinfo
=False)
107 self
.assertEqual(obj
.topobjdir
, mozpath
.normsep(topobjdir
))
109 os
.chdir(self
._old
_cwd
)
112 def test_relative_objdir(self
):
113 """Relative defined objdirs are loaded properly."""
114 d
= os
.path
.realpath(tempfile
.mkdtemp())
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")
123 mozinfo
= os
.path
.join(topobjdir
, "mozinfo.json")
124 with
open(mozinfo
, "wt") as fh
:
133 os
.environ
["MOZCONFIG"] = mozconfig
134 child
= os
.path
.join(topobjdir
, "foo", "bar")
138 obj
= MozbuildObject
.from_environment(detect_virtualenv_mozinfo
=False)
140 self
.assertEqual(obj
.topobjdir
, topobjdir
)
143 os
.chdir(self
._old
_cwd
)
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())
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
:
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
)
182 os
.chdir(self
._old
_cwd
)
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())
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
:
208 class MockMachContext(object):
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
))
224 os
.chdir(self
._old
_cwd
)
227 def test_objdir_is_srcdir_rejected(self
):
228 """Ensure the srcdir configurations are rejected."""
229 d
= os
.path
.realpath(tempfile
.mkdtemp())
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
)
240 with self
.assertRaises(BadEnvironmentException
):
241 MozbuildObject
.from_environment(detect_virtualenv_mozinfo
=False)
244 os
.chdir(self
._old
_cwd
)
247 def test_objdir_mismatch(self
):
248 """Ensure MachCommandBase throwing on objdir mismatch."""
249 d
= os
.path
.realpath(tempfile
.mkdtemp())
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
:
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
:
279 class MockMachContext(object):
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
290 sys
.stdout
= StringIO()
292 with self
.assertRaises(SystemExit):
293 MachCommandBase(context
, None)
296 sys
.stdout
.getvalue().startswith(
297 "Ambiguous object directory detected."
304 os
.chdir(self
._old
_cwd
)
307 def test_config_environment(self
):
308 d
= os
.path
.realpath(tempfile
.mkdtemp())
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")
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"})
336 "ACDEFINES": "-DFOO=foo",
337 "ALLEMPTYSUBSTS": "",
338 "ALLSUBSTS": "ACDEFINES = -DFOO=foo\nQUX = qux",
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
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"))
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"))
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"))
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"):
390 p
.endswith("awesomeapp/Nightly.app/Contents/MacOS/awesomeapp")
392 elif platform
.startswith(("win32", "cygwin")):
393 self
.assertTrue(p
.endswith("awesomeapp\\awesomeapp.exe"))
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"))
403 self
.assertTrue(p
.endswith("foobar"))
406 class TestPathArgument(unittest
.TestCase
):
407 def test_path_argument(self
):
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")
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__":