xref: /llvm-project/clang/tools/scan-build-py/tests/unit/test_compilation.py (revision dd3c26a045c081620375a878159f536758baba6e)
1# -*- coding: utf-8 -*-
2# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3# See https://llvm.org/LICENSE.txt for license information.
4# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5
6import libscanbuild.compilation as sut
7import unittest
8
9
10class CompilerTest(unittest.TestCase):
11    def test_is_compiler_call(self):
12        self.assertIsNotNone(sut.compiler_language(["clang"]))
13        self.assertIsNotNone(sut.compiler_language(["clang-3.6"]))
14        self.assertIsNotNone(sut.compiler_language(["clang++"]))
15        self.assertIsNotNone(sut.compiler_language(["clang++-3.5.1"]))
16        self.assertIsNotNone(sut.compiler_language(["cc"]))
17        self.assertIsNotNone(sut.compiler_language(["c++"]))
18        self.assertIsNotNone(sut.compiler_language(["gcc"]))
19        self.assertIsNotNone(sut.compiler_language(["g++"]))
20        self.assertIsNotNone(sut.compiler_language(["/usr/local/bin/gcc"]))
21        self.assertIsNotNone(sut.compiler_language(["/usr/local/bin/g++"]))
22        self.assertIsNotNone(sut.compiler_language(["/usr/local/bin/clang"]))
23        self.assertIsNotNone(sut.compiler_language(["armv7_neno-linux-gnueabi-g++"]))
24
25        self.assertIsNone(sut.compiler_language([]))
26        self.assertIsNone(sut.compiler_language([""]))
27        self.assertIsNone(sut.compiler_language(["ld"]))
28        self.assertIsNone(sut.compiler_language(["as"]))
29        self.assertIsNone(sut.compiler_language(["/usr/local/bin/compiler"]))
30
31
32class SplitTest(unittest.TestCase):
33    def test_detect_cxx_from_compiler_name(self):
34        def test(cmd):
35            result = sut.split_command([cmd, "-c", "src.c"])
36            self.assertIsNotNone(result, "wrong input for test")
37            return result.compiler == "c++"
38
39        self.assertFalse(test("cc"))
40        self.assertFalse(test("gcc"))
41        self.assertFalse(test("clang"))
42
43        self.assertTrue(test("c++"))
44        self.assertTrue(test("g++"))
45        self.assertTrue(test("g++-5.3.1"))
46        self.assertTrue(test("clang++"))
47        self.assertTrue(test("clang++-3.7.1"))
48        self.assertTrue(test("armv7_neno-linux-gnueabi-g++"))
49
50    def test_action(self):
51        self.assertIsNotNone(sut.split_command(["clang", "source.c"]))
52        self.assertIsNotNone(sut.split_command(["clang", "-c", "source.c"]))
53        self.assertIsNotNone(
54            sut.split_command(["clang", "-c", "source.c", "-MF", "a.d"])
55        )
56
57        self.assertIsNone(sut.split_command(["clang", "-E", "source.c"]))
58        self.assertIsNone(sut.split_command(["clang", "-c", "-E", "source.c"]))
59        self.assertIsNone(sut.split_command(["clang", "-c", "-M", "source.c"]))
60        self.assertIsNone(sut.split_command(["clang", "-c", "-MM", "source.c"]))
61
62    def test_source_file(self):
63        def test(expected, cmd):
64            self.assertEqual(expected, sut.split_command(cmd).files)
65
66        test(["src.c"], ["clang", "src.c"])
67        test(["src.c"], ["clang", "-c", "src.c"])
68        test(["src.C"], ["clang", "-x", "c", "src.C"])
69        test(["src.cpp"], ["clang++", "-c", "src.cpp"])
70        test(["s1.c", "s2.c"], ["clang", "-c", "s1.c", "s2.c"])
71        test(["s1.c", "s2.c"], ["cc", "s1.c", "s2.c", "-ldep", "-o", "a.out"])
72        test(["src.c"], ["clang", "-c", "-I", "./include", "src.c"])
73        test(["src.c"], ["clang", "-c", "-I", "/opt/me/include", "src.c"])
74        test(["src.c"], ["clang", "-c", "-D", "config=file.c", "src.c"])
75
76        self.assertIsNone(sut.split_command(["cc", "this.o", "that.o", "-o", "a.out"]))
77        self.assertIsNone(sut.split_command(["cc", "this.o", "-lthat", "-o", "a.out"]))
78
79    def test_filter_flags(self):
80        def test(expected, flags):
81            command = ["clang", "-c", "src.c"] + flags
82            self.assertEqual(expected, sut.split_command(command).flags)
83
84        def same(expected):
85            test(expected, expected)
86
87        def filtered(flags):
88            test([], flags)
89
90        same([])
91        same(["-I", "/opt/me/include", "-DNDEBUG", "-ULIMITS"])
92        same(["-O", "-O2"])
93        same(["-m32", "-mmms"])
94        same(["-Wall", "-Wno-unused", "-g", "-funroll-loops"])
95
96        filtered([])
97        filtered(["-lclien", "-L/opt/me/lib", "-L", "/opt/you/lib"])
98        filtered(["-static"])
99        filtered(["-MD", "-MT", "something"])
100        filtered(["-MMD", "-MF", "something"])
101
102
103class SourceClassifierTest(unittest.TestCase):
104    def test_sources(self):
105        self.assertIsNone(sut.classify_source("file.o"))
106        self.assertIsNone(sut.classify_source("file.exe"))
107        self.assertIsNone(sut.classify_source("/path/file.o"))
108        self.assertIsNone(sut.classify_source("clang"))
109
110        self.assertEqual("c", sut.classify_source("file.c"))
111        self.assertEqual("c", sut.classify_source("./file.c"))
112        self.assertEqual("c", sut.classify_source("/path/file.c"))
113        self.assertEqual("c++", sut.classify_source("file.c", False))
114        self.assertEqual("c++", sut.classify_source("./file.c", False))
115        self.assertEqual("c++", sut.classify_source("/path/file.c", False))
116