blob: ab8702b083df6b3bc760f9b95db1a968fe349094 [file] [log] [blame]
#!/usr/bin/env fuchsia-vendored-python
# Copyright 2022 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import unittest
import sys
from pathlib import Path
from unittest import mock
from typing import Any, Sequence
import cxx
def _strs(items: Sequence[Any]) -> Sequence[str]:
return [str(i) for i in items]
def _paths(items: Sequence[Any]) -> Sequence[Path]:
if isinstance(items, list):
return [Path(i) for i in items]
elif isinstance(items, set):
return {Path(i) for i in items}
elif isinstance(items, tuple):
return tuple(Path(i) for i in items)
t = type(items)
raise TypeError(f"Unhandled sequence type: {t}")
class CxxActionTests(unittest.TestCase):
def test_help_unwanted(self):
source = Path('hello.cc')
output = Path('hello.o')
for opt in (
'-h',
'--help',
'-hwasan-record-stack-history=libcall',
'-hello-world-is-ignored',
):
with mock.patch.object(sys, 'exit') as mock_exit:
c = cxx.CxxAction(
_strs(['clang++', opt, '-c', source, '-o', output]))
preprocess, compile = c.split_preprocessing()
mock_exit.assert_not_called()
def test_simple_clang_cxx(self):
source = Path('hello.cc')
ii_file = Path('hello.ii')
output = Path('hello.o')
c = cxx.CxxAction(_strs(['clang++', '-c', source, '-o', output]))
self.assertEqual(c.output_file, output)
self.assertEqual(
c.compiler,
cxx.CompilerTool(tool=Path('clang++'), type=cxx.Compiler.CLANG))
self.assertTrue(c.compiler_is_clang)
self.assertFalse(c.compiler_is_gcc)
self.assertEqual(c.target, '')
self.assertEqual(
c.sources,
[cxx.Source(file=source, dialect=cxx.SourceLanguage.CXX)])
self.assertTrue(c.dialect_is_cxx)
self.assertFalse(c.dialect_is_c)
self.assertIsNone(c.depfile)
self.assertIsNone(c.sysroot)
self.assertIsNone(c.profile_list)
self.assertEqual(list(c.input_files()), [source])
self.assertEqual(list(c.output_files()), [output])
self.assertEqual(list(c.output_dirs()), [])
self.assertFalse(c.uses_macos_sdk)
self.assertIsNone(c.crash_diagnostics_dir)
self.assertEqual(c.preprocessed_output, ii_file)
preprocess, compile = c.split_preprocessing()
self.assertEqual(
preprocess,
_strs(
['clang++', '-c', source, '-o', ii_file, '-E', '-fno-blocks']),
)
self.assertEqual(
compile,
_strs(['clang++', '-c', ii_file, '-o', output]),
)
def test_simple_clang_c(self):
source = Path('hello.c')
i_file = Path('hello.i')
output = Path('hello.o')
c = cxx.CxxAction(_strs(['clang', '-c', source, '-o', output]))
self.assertEqual(c.output_file, output)
self.assertEqual(
c.compiler,
cxx.CompilerTool(tool=Path('clang'), type=cxx.Compiler.CLANG))
self.assertTrue(c.compiler_is_clang)
self.assertFalse(c.compiler_is_gcc)
self.assertEqual(c.target, '')
self.assertEqual(
c.sources, [cxx.Source(file=source, dialect=cxx.SourceLanguage.C)])
self.assertFalse(c.dialect_is_cxx)
self.assertTrue(c.dialect_is_c)
self.assertIsNone(c.depfile)
self.assertIsNone(c.sysroot)
self.assertIsNone(c.profile_list)
self.assertEqual(list(c.input_files()), [source])
self.assertEqual(list(c.output_files()), [output])
self.assertEqual(list(c.output_dirs()), [])
self.assertIsNone(c.crash_diagnostics_dir)
self.assertEqual(c.preprocessed_output, i_file)
preprocess, compile = c.split_preprocessing()
self.assertEqual(
preprocess,
_strs(['clang', '-c', source, '-o', i_file, '-E', '-fno-blocks']),
)
self.assertEqual(
compile,
_strs(['clang', '-c', i_file, '-o', output]),
)
def test_simple_clang_asm(self):
source = Path('hello.s')
i_file = Path('hello.i')
output = Path('hello.o')
c = cxx.CxxAction(_strs(['clang', '-c', source, '-o', output]))
self.assertEqual(c.output_file, output)
self.assertEqual(
c.compiler,
cxx.CompilerTool(tool=Path('clang'), type=cxx.Compiler.CLANG))
self.assertTrue(c.compiler_is_clang)
self.assertFalse(c.compiler_is_gcc)
self.assertEqual(c.target, '')
self.assertEqual(
c.sources,
[cxx.Source(file=source, dialect=cxx.SourceLanguage.ASM)])
self.assertFalse(c.dialect_is_cxx)
self.assertFalse(c.dialect_is_c)
self.assertIsNone(c.crash_diagnostics_dir)
def test_simple_clang_asm_pp(self):
source = Path('hello.S')
i_file = Path('hello.i')
output = Path('hello.o')
c = cxx.CxxAction(_strs(['clang', '-c', source, '-o', output]))
self.assertEqual(c.output_file, output)
self.assertEqual(
c.compiler,
cxx.CompilerTool(tool=Path('clang'), type=cxx.Compiler.CLANG))
self.assertTrue(c.compiler_is_clang)
self.assertFalse(c.compiler_is_gcc)
self.assertEqual(c.target, '')
self.assertEqual(
c.sources,
[cxx.Source(file=source, dialect=cxx.SourceLanguage.ASM)])
self.assertFalse(c.dialect_is_cxx)
self.assertFalse(c.dialect_is_c)
self.assertIsNone(c.crash_diagnostics_dir)
def test_simple_gcc_cxx(self):
source = Path('hello.cc')
output = Path('hello.o')
ii_file = Path('hello.ii')
c = cxx.CxxAction(_strs(['g++', '-c', source, '-o', output]))
self.assertEqual(c.output_file, output)
self.assertEqual(
c.compiler,
cxx.CompilerTool(tool=Path('g++'), type=cxx.Compiler.GCC))
self.assertFalse(c.compiler_is_clang)
self.assertTrue(c.compiler_is_gcc)
self.assertEqual(c.target, '')
self.assertEqual(
c.sources,
[cxx.Source(file=source, dialect=cxx.SourceLanguage.CXX)])
self.assertTrue(c.dialect_is_cxx)
self.assertFalse(c.dialect_is_c)
self.assertIsNone(c.depfile)
self.assertIsNone(c.crash_diagnostics_dir)
self.assertEqual(c.preprocessed_output, ii_file)
preprocess, compile = c.split_preprocessing()
self.assertEqual(
preprocess,
_strs(['g++', '-c', source, '-o', ii_file, '-E']),
)
self.assertEqual(
compile,
_strs(['g++', '-c', ii_file, '-o', output]),
)
def test_simple_gcc_c(self):
source = Path('hello.c')
i_file = Path('hello.i')
output = Path('hello.o')
c = cxx.CxxAction(_strs(['gcc', '-c', source, '-o', output]))
self.assertEqual(c.output_file, output)
self.assertEqual(
c.compiler,
cxx.CompilerTool(tool=Path('gcc'), type=cxx.Compiler.GCC))
self.assertFalse(c.compiler_is_clang)
self.assertTrue(c.compiler_is_gcc)
self.assertEqual(c.target, '')
self.assertEqual(
c.sources, [cxx.Source(file=source, dialect=cxx.SourceLanguage.C)])
self.assertFalse(c.dialect_is_cxx)
self.assertTrue(c.dialect_is_c)
self.assertIsNone(c.depfile)
self.assertIsNone(c.crash_diagnostics_dir)
self.assertEqual(c.preprocessed_output, i_file)
preprocess, compile = c.split_preprocessing()
self.assertEqual(
preprocess,
_strs(['gcc', '-c', source, '-o', i_file, '-E']),
)
self.assertEqual(
compile,
_strs(['gcc', '-c', i_file, '-o', output]),
)
def test_clang_target(self):
c = cxx.CxxAction(
[
'clang++', '--target=powerpc-apple-darwin8', '-c', 'hello.cc',
'-o', 'hello.o'
])
self.assertEqual(c.target, 'powerpc-apple-darwin8')
def test_clang_crash_diagnostics_dir(self):
crash_dir = Path('/tmp/graveyard')
c = cxx.CxxAction(
[
'clang++', f'-fcrash-diagnostics-dir={crash_dir}', '-c',
'hello.cc', '-o', 'hello.o'
])
self.assertEqual(c.crash_diagnostics_dir, crash_dir)
self.assertEqual(set(c.output_dirs()), {crash_dir})
def test_profile_list(self):
source = Path('hello.cc')
ii_file = Path('hello.ii')
output = Path('hello.o')
profile = Path('my/online/profile.list')
c = cxx.CxxAction(
_strs(
[
'clang++', '-c', source, '-o', output,
f'-fprofile-list={profile}'
]))
self.assertEqual(c.profile_list, profile)
self.assertEqual(set(c.input_files()), {source, profile})
def test_uses_macos_sdk(self):
sysroot = Path('/Library/Developer/blah')
c = cxx.CxxAction(
[
'clang++', f'--sysroot={sysroot}', '-c', 'hello.cc', '-o',
'hello.o'
])
self.assertEqual(c.sysroot, sysroot)
self.assertTrue(c.uses_macos_sdk)
def test_split_preprocessing(self):
source = Path('hello.cc')
ii_file = Path('hello.ii')
output = Path('hello.o')
depfile = Path('hello.d')
c = cxx.CxxAction(
_strs(
[
'clang++', '-DNDEBUG', '-I/opt/include', '-stdlib=libc++',
'-M', '-MF', depfile, '-c', source, '-o', output
]))
self.assertEqual(c.depfile, depfile)
preprocess, compile = c.split_preprocessing()
self.assertEqual(
preprocess,
_strs(
[
'clang++', '-DNDEBUG', '-I/opt/include', '-stdlib=libc++',
'-M', '-MF', depfile, '-c', source, '-o', ii_file, '-E',
'-fno-blocks'
]),
)
self.assertEqual(
compile,
_strs(['clang++', '-c', ii_file, '-o', output]),
)
if __name__ == '__main__':
unittest.main()