Source code
Revision control
Copy as Markdown
Other Tools
Test Info:
# 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
import os
import textwrap
import unittest
import mozpack.path as mozpath
from buildconfig import topsrcdir
from mozunit import main
from six import StringIO
from test_toolchain_helpers import FakeCompiler
from common import ConfigureTestSandbox
class BaseCompileChecks(unittest.TestCase):
def get_mock_compiler(self, expected_test_content=None, expected_flags=None):
expected_flags = expected_flags or []
def mock_compiler(stdin, args):
if args != ["--version"]:
test_file = [a for a in args if not a.startswith("-")]
self.assertEqual(len(test_file), 1)
test_file = test_file[0]
args = [a for a in args if a.startswith("-")]
self.assertIn("-c", args)
for flag in expected_flags:
self.assertIn(flag, args)
if expected_test_content:
with open(test_file) as fh:
test_content = fh.read()
self.assertEqual(test_content, expected_test_content)
return FakeCompiler()(None, args)
return mock_compiler
def do_compile_test(self, command, expected_test_content=None, expected_flags=None):
paths = {
os.path.abspath("/usr/bin/mockcc"): self.get_mock_compiler(
expected_test_content=expected_test_content,
expected_flags=expected_flags,
),
}
base_dir = os.path.join(topsrcdir, "build", "moz.configure")
mock_compiler_defs = textwrap.dedent(
"""\
@depends(when=True)
def extra_toolchain_flags():
return []
@depends(when=True)
def linker_ldflags():
return []
target = depends(when=True)(lambda: True)
@depends(when=True)
def configure_cache():
class ConfigureCache(dict):
pass
cache_data = {}
cache = ConfigureCache(cache_data)
cache.version_checked_compilers = set()
return cache
include('%s/compilers-util.configure')
@template
def wrap_compiler(compiler):
return compiler_class(compiler, False)
@wrap_compiler
@depends(when=True)
def c_compiler():
return namespace(
flags=[],
type='gcc',
compiler=os.path.abspath('/usr/bin/mockcc'),
wrapper=[],
language='C',
)
@wrap_compiler
@depends(when=True)
def host_c_compiler():
return namespace(
flags=[],
type='gcc',
compiler=os.path.abspath('/usr/bin/mockcc'),
wrapper=[],
language='C',
)
@wrap_compiler
@depends(when=True)
def cxx_compiler():
return namespace(
flags=[],
type='gcc',
compiler=os.path.abspath('/usr/bin/mockcc'),
wrapper=[],
language='C++',
)
@wrap_compiler
@depends(when=True)
def host_cxx_compiler():
return namespace(
flags=[],
type='gcc',
compiler=os.path.abspath('/usr/bin/mockcc'),
wrapper=[],
language='C++',
)
"""
% mozpath.normsep(base_dir)
)
config = {}
out = StringIO()
sandbox = ConfigureTestSandbox(paths, config, {}, ["/bin/configure"], out, out)
sandbox.include_file(os.path.join(base_dir, "util.configure"))
sandbox.include_file(os.path.join(base_dir, "checks.configure"))
exec(mock_compiler_defs, sandbox)
sandbox.include_file(os.path.join(base_dir, "compile-checks.configure"))
status = 0
try:
exec(command, sandbox)
sandbox.run()
except SystemExit as e:
status = e.code
return config, out.getvalue(), status
class TestHeaderChecks(BaseCompileChecks):
def test_try_compile_include(self):
expected_test_content = textwrap.dedent(
"""\
#include <foo.h>
#include <bar.h>
int
main(void)
{
;
return 0;
}
"""
)
cmd = textwrap.dedent(
"""\
try_compile(['foo.h', 'bar.h'], language='C')
"""
)
config, out, status = self.do_compile_test(cmd, expected_test_content)
self.assertEqual(status, 0)
self.assertEqual(config, {})
def test_try_compile_flags(self):
expected_flags = ["--extra", "--flags"]
cmd = textwrap.dedent(
"""\
try_compile(language='C++', flags=['--flags', '--extra'])
"""
)
config, out, status = self.do_compile_test(cmd, expected_flags=expected_flags)
self.assertEqual(status, 0)
self.assertEqual(config, {})
def test_try_compile_failure(self):
cmd = textwrap.dedent(
"""\
have_fn = try_compile(body='somefn();', flags=['-funknown-flag'])
set_config('HAVE_SOMEFN', have_fn)
have_another = try_compile(body='anotherfn();', language='C')
set_config('HAVE_ANOTHERFN', have_another)
"""
)
config, out, status = self.do_compile_test(cmd)
self.assertEqual(status, 0)
self.assertEqual(
config,
{
"HAVE_ANOTHERFN": True,
},
)
def test_try_compile_msg(self):
cmd = textwrap.dedent(
"""\
known_flag = try_compile(language='C++', flags=['-fknown-flag'],
check_msg='whether -fknown-flag works')
set_config('HAVE_KNOWN_FLAG', known_flag)
"""
)
config, out, status = self.do_compile_test(cmd)
self.assertEqual(status, 0)
self.assertEqual(config, {"HAVE_KNOWN_FLAG": True})
self.assertEqual(
out,
textwrap.dedent(
"""\
checking whether -fknown-flag works... yes
"""
),
)
def test_check_header(self):
expected_test_content = textwrap.dedent(
"""\
#include <foo.h>
int
main(void)
{
;
return 0;
}
"""
)
cmd = textwrap.dedent(
"""\
check_header('foo.h')
"""
)
config, out, status = self.do_compile_test(
cmd, expected_test_content=expected_test_content
)
self.assertEqual(status, 0)
self.assertEqual(config, {"DEFINES": {"HAVE_FOO_H": True}})
self.assertEqual(
out,
textwrap.dedent(
"""\
checking for foo.h... yes
"""
),
)
def test_check_header_conditional(self):
cmd = textwrap.dedent(
"""\
check_headers('foo.h', 'bar.h', when=never)
"""
)
config, out, status = self.do_compile_test(cmd)
self.assertEqual(status, 0)
self.assertEqual(out, "")
self.assertEqual(config, {"DEFINES": {}})
def test_check_header_include(self):
expected_test_content = textwrap.dedent(
"""\
#include <std.h>
#include <bar.h>
#include <foo.h>
int
main(void)
{
;
return 0;
}
"""
)
cmd = textwrap.dedent(
"""\
have_foo = check_header('foo.h', includes=['std.h', 'bar.h'])
set_config('HAVE_FOO_H', have_foo)
"""
)
config, out, status = self.do_compile_test(
cmd, expected_test_content=expected_test_content
)
self.assertEqual(status, 0)
self.assertEqual(
config,
{
"HAVE_FOO_H": True,
"DEFINES": {
"HAVE_FOO_H": True,
},
},
)
self.assertEqual(
out,
textwrap.dedent(
"""\
checking for foo.h... yes
"""
),
)
def test_check_headers_multiple(self):
cmd = textwrap.dedent(
"""\
baz_bar, quux_bar = check_headers('baz/foo-bar.h', 'baz-quux/foo-bar.h')
set_config('HAVE_BAZ_BAR', baz_bar)
set_config('HAVE_QUUX_BAR', quux_bar)
"""
)
config, out, status = self.do_compile_test(cmd)
self.assertEqual(status, 0)
self.assertEqual(
config,
{
"HAVE_BAZ_BAR": True,
"HAVE_QUUX_BAR": True,
"DEFINES": {
"HAVE_BAZ_FOO_BAR_H": True,
"HAVE_BAZ_QUUX_FOO_BAR_H": True,
},
},
)
self.assertEqual(
out,
textwrap.dedent(
"""\
checking for baz/foo-bar.h... yes
checking for baz-quux/foo-bar.h... yes
"""
),
)
def test_check_headers_not_found(self):
cmd = textwrap.dedent(
"""\
baz_bar, quux_bar = check_headers('baz/foo-bar.h', 'baz-quux/foo-bar.h',
flags=['-funknown-flag'])
set_config('HAVE_BAZ_BAR', baz_bar)
set_config('HAVE_QUUX_BAR', quux_bar)
"""
)
config, out, status = self.do_compile_test(cmd)
self.assertEqual(status, 0)
self.assertEqual(config, {"DEFINES": {}})
self.assertEqual(
out,
textwrap.dedent(
"""\
checking for baz/foo-bar.h... no
checking for baz-quux/foo-bar.h... no
"""
),
)
class TestWarningChecks(BaseCompileChecks):
def get_warnings(self):
return textwrap.dedent(
"""\
set_config('_WARNINGS_CFLAGS', warnings_flags.cflags)
set_config('_WARNINGS_CXXFLAGS', warnings_flags.cxxflags)
"""
)
def test_check_and_add_warning(self):
for flag, expected_flags in (
("-Wfoo", ["-Werror", "-Wfoo"]),
("-Wno-foo", ["-Werror", "-Wfoo"]),
("-Werror=foo", ["-Werror=foo"]),
("-Wno-error=foo", ["-Wno-error=foo"]),
):
cmd = (
textwrap.dedent(
"""\
check_and_add_warning('%s')
"""
% flag
)
+ self.get_warnings()
)
config, out, status = self.do_compile_test(
cmd, expected_flags=expected_flags
)
self.assertEqual(status, 0)
self.assertEqual(
config,
{
"_WARNINGS_CFLAGS": [flag],
"_WARNINGS_CXXFLAGS": [flag],
},
)
self.assertEqual(
out,
textwrap.dedent(
"""\
checking whether the C compiler supports {flag}... yes
checking whether the C++ compiler supports {flag}... yes
""".format(
flag=flag
)
),
)
def test_check_and_add_warning_one(self):
cmd = (
textwrap.dedent(
"""\
check_and_add_warning('-Wfoo', cxx_compiler)
"""
)
+ self.get_warnings()
)
config, out, status = self.do_compile_test(cmd)
self.assertEqual(status, 0)
self.assertEqual(
config,
{
"_WARNINGS_CFLAGS": [],
"_WARNINGS_CXXFLAGS": ["-Wfoo"],
},
)
self.assertEqual(
out,
textwrap.dedent(
"""\
checking whether the C++ compiler supports -Wfoo... yes
"""
),
)
def test_check_and_add_warning_when(self):
cmd = (
textwrap.dedent(
"""\
@depends(when=True)
def never():
return False
check_and_add_warning('-Wfoo', cxx_compiler, when=never)
"""
)
+ self.get_warnings()
)
config, out, status = self.do_compile_test(cmd)
self.assertEqual(status, 0)
self.assertEqual(
config,
{
"_WARNINGS_CFLAGS": [],
"_WARNINGS_CXXFLAGS": [],
},
)
self.assertEqual(out, "")
cmd = (
textwrap.dedent(
"""\
@depends(when=True)
def always():
return True
check_and_add_warning('-Wfoo', cxx_compiler, when=always)
"""
)
+ self.get_warnings()
)
config, out, status = self.do_compile_test(cmd)
self.assertEqual(status, 0)
self.assertEqual(
config,
{
"_WARNINGS_CFLAGS": [],
"_WARNINGS_CXXFLAGS": ["-Wfoo"],
},
)
self.assertEqual(
out,
textwrap.dedent(
"""\
checking whether the C++ compiler supports -Wfoo... yes
"""
),
)
def test_add_warning(self):
cmd = (
textwrap.dedent(
"""\
add_warning('-Wfoo')
"""
)
+ self.get_warnings()
)
config, out, status = self.do_compile_test(cmd)
self.assertEqual(status, 0)
self.assertEqual(
config,
{
"_WARNINGS_CFLAGS": ["-Wfoo"],
"_WARNINGS_CXXFLAGS": ["-Wfoo"],
},
)
self.assertEqual(out, "")
def test_add_warning_one(self):
cmd = (
textwrap.dedent(
"""\
add_warning('-Wfoo', c_compiler)
"""
)
+ self.get_warnings()
)
config, out, status = self.do_compile_test(cmd)
self.assertEqual(status, 0)
self.assertEqual(
config,
{
"_WARNINGS_CFLAGS": ["-Wfoo"],
"_WARNINGS_CXXFLAGS": [],
},
)
self.assertEqual(out, "")
def test_add_warning_when(self):
cmd = (
textwrap.dedent(
"""\
@depends(when=True)
def never():
return False
add_warning('-Wfoo', c_compiler, when=never)
"""
)
+ self.get_warnings()
)
config, out, status = self.do_compile_test(cmd)
self.assertEqual(status, 0)
self.assertEqual(
config,
{
"_WARNINGS_CFLAGS": [],
"_WARNINGS_CXXFLAGS": [],
},
)
self.assertEqual(out, "")
cmd = (
textwrap.dedent(
"""\
@depends(when=True)
def always():
return True
add_warning('-Wfoo', c_compiler, when=always)
"""
)
+ self.get_warnings()
)
config, out, status = self.do_compile_test(cmd)
self.assertEqual(status, 0)
self.assertEqual(
config,
{
"_WARNINGS_CFLAGS": ["-Wfoo"],
"_WARNINGS_CXXFLAGS": [],
},
)
self.assertEqual(out, "")
if __name__ == "__main__":
main()