xref: /openbsd-src/gnu/llvm/clang/utils/check_cfc/test_check_cfc.py (revision e5dd70708596ae51455a0ffa086a00c5b29f8583)
1*e5dd7070Spatrick#!/usr/bin/env python
2*e5dd7070Spatrick
3*e5dd7070Spatrick"""Test internal functions within check_cfc.py."""
4*e5dd7070Spatrick
5*e5dd7070Spatrickimport check_cfc
6*e5dd7070Spatrickimport os
7*e5dd7070Spatrickimport platform
8*e5dd7070Spatrickimport unittest
9*e5dd7070Spatrick
10*e5dd7070Spatrick
11*e5dd7070Spatrickclass TestCheckCFC(unittest.TestCase):
12*e5dd7070Spatrick
13*e5dd7070Spatrick    def test_flip_dash_g(self):
14*e5dd7070Spatrick        self.assertIn('-g', check_cfc.flip_dash_g(['clang', '-c']))
15*e5dd7070Spatrick        self.assertNotIn('-g', check_cfc.flip_dash_g(['clang', '-c', '-g']))
16*e5dd7070Spatrick        self.assertNotIn(
17*e5dd7070Spatrick            '-g', check_cfc.flip_dash_g(['clang', '-g', '-c', '-g']))
18*e5dd7070Spatrick
19*e5dd7070Spatrick    def test_remove_dir_from_path(self):
20*e5dd7070Spatrick        bin_path = r'/usr/bin'
21*e5dd7070Spatrick        space_path = r'/home/user/space in path'
22*e5dd7070Spatrick        superstring_path = r'/usr/bin/local'
23*e5dd7070Spatrick
24*e5dd7070Spatrick        # Test removing last thing in path
25*e5dd7070Spatrick        self.assertNotIn(
26*e5dd7070Spatrick            bin_path, check_cfc.remove_dir_from_path(bin_path, bin_path))
27*e5dd7070Spatrick
28*e5dd7070Spatrick        # Test removing one entry and leaving others
29*e5dd7070Spatrick        # Also tests removing repeated path
30*e5dd7070Spatrick        path_var = os.pathsep.join(
31*e5dd7070Spatrick            [superstring_path, bin_path, space_path, bin_path])
32*e5dd7070Spatrick        stripped_path_var = check_cfc.remove_dir_from_path(path_var, bin_path)
33*e5dd7070Spatrick        self.assertIn(superstring_path, stripped_path_var)
34*e5dd7070Spatrick        self.assertNotIn(bin_path, stripped_path_var.split(os.pathsep))
35*e5dd7070Spatrick        self.assertIn(space_path, stripped_path_var)
36*e5dd7070Spatrick
37*e5dd7070Spatrick        # Test removing non-canonical path
38*e5dd7070Spatrick        self.assertNotIn(r'/usr//bin',
39*e5dd7070Spatrick                         check_cfc.remove_dir_from_path(r'/usr//bin', bin_path))
40*e5dd7070Spatrick
41*e5dd7070Spatrick        if platform == 'Windows':
42*e5dd7070Spatrick            # Windows is case insensitive so should remove a different case
43*e5dd7070Spatrick            # path
44*e5dd7070Spatrick            self.assertNotIn(
45*e5dd7070Spatrick                bin_path, check_cfc.remove_dir_from_path(path_var, r'/USR/BIN'))
46*e5dd7070Spatrick        else:
47*e5dd7070Spatrick            # Case sensitive so will not remove different case path
48*e5dd7070Spatrick            self.assertIn(
49*e5dd7070Spatrick                bin_path, check_cfc.remove_dir_from_path(path_var, r'/USR/BIN'))
50*e5dd7070Spatrick
51*e5dd7070Spatrick    def test_is_output_specified(self):
52*e5dd7070Spatrick        self.assertTrue(
53*e5dd7070Spatrick            check_cfc.is_output_specified(['clang', '-o', 'test.o']))
54*e5dd7070Spatrick        self.assertTrue(check_cfc.is_output_specified(['clang', '-otest.o']))
55*e5dd7070Spatrick        self.assertFalse(
56*e5dd7070Spatrick            check_cfc.is_output_specified(['clang', '-gline-tables-only']))
57*e5dd7070Spatrick        # Not specified for implied output file name
58*e5dd7070Spatrick        self.assertFalse(check_cfc.is_output_specified(['clang', 'test.c']))
59*e5dd7070Spatrick
60*e5dd7070Spatrick    def test_get_output_file(self):
61*e5dd7070Spatrick        self.assertEqual(
62*e5dd7070Spatrick            check_cfc.get_output_file(['clang', '-o', 'test.o']), 'test.o')
63*e5dd7070Spatrick        self.assertEqual(
64*e5dd7070Spatrick            check_cfc.get_output_file(['clang', '-otest.o']), 'test.o')
65*e5dd7070Spatrick        self.assertIsNone(
66*e5dd7070Spatrick            check_cfc.get_output_file(['clang', '-gline-tables-only']))
67*e5dd7070Spatrick        # Can't get output file if more than one input file
68*e5dd7070Spatrick        self.assertIsNone(
69*e5dd7070Spatrick            check_cfc.get_output_file(['clang', '-c', 'test.cpp', 'test2.cpp']))
70*e5dd7070Spatrick        # No output file specified
71*e5dd7070Spatrick        self.assertIsNone(check_cfc.get_output_file(['clang', '-c', 'test.c']))
72*e5dd7070Spatrick
73*e5dd7070Spatrick    def test_derive_output_file(self):
74*e5dd7070Spatrick        # Test getting implicit output file
75*e5dd7070Spatrick        self.assertEqual(
76*e5dd7070Spatrick            check_cfc.derive_output_file(['clang', '-c', 'test.c']), 'test.o')
77*e5dd7070Spatrick        self.assertEqual(
78*e5dd7070Spatrick            check_cfc.derive_output_file(['clang', '-c', 'test.cpp']), 'test.o')
79*e5dd7070Spatrick        self.assertIsNone(check_cfc.derive_output_file(['clang', '--version']))
80*e5dd7070Spatrick
81*e5dd7070Spatrick    def test_is_normal_compile(self):
82*e5dd7070Spatrick        self.assertTrue(check_cfc.is_normal_compile(
83*e5dd7070Spatrick            ['clang', '-c', 'test.cpp', '-o', 'test2.o']))
84*e5dd7070Spatrick        self.assertTrue(
85*e5dd7070Spatrick            check_cfc.is_normal_compile(['clang', '-c', 'test.cpp']))
86*e5dd7070Spatrick        # Outputting bitcode is not a normal compile
87*e5dd7070Spatrick        self.assertFalse(
88*e5dd7070Spatrick            check_cfc.is_normal_compile(['clang', '-c', 'test.cpp', '-flto']))
89*e5dd7070Spatrick        self.assertFalse(
90*e5dd7070Spatrick            check_cfc.is_normal_compile(['clang', '-c', 'test.cpp', '-emit-llvm']))
91*e5dd7070Spatrick        # Outputting preprocessed output or assembly is not a normal compile
92*e5dd7070Spatrick        self.assertFalse(
93*e5dd7070Spatrick            check_cfc.is_normal_compile(['clang', '-E', 'test.cpp', '-o', 'test.ii']))
94*e5dd7070Spatrick        self.assertFalse(
95*e5dd7070Spatrick            check_cfc.is_normal_compile(['clang', '-S', 'test.cpp', '-o', 'test.s']))
96*e5dd7070Spatrick        # Input of preprocessed or assembly is not a "normal compile"
97*e5dd7070Spatrick        self.assertFalse(
98*e5dd7070Spatrick            check_cfc.is_normal_compile(['clang', '-c', 'test.s', '-o', 'test.o']))
99*e5dd7070Spatrick        self.assertFalse(
100*e5dd7070Spatrick            check_cfc.is_normal_compile(['clang', '-c', 'test.ii', '-o', 'test.o']))
101*e5dd7070Spatrick        # Specifying --version and -c is not a normal compile
102*e5dd7070Spatrick        self.assertFalse(
103*e5dd7070Spatrick            check_cfc.is_normal_compile(['clang', '-c', 'test.cpp', '--version']))
104*e5dd7070Spatrick        self.assertFalse(
105*e5dd7070Spatrick            check_cfc.is_normal_compile(['clang', '-c', 'test.cpp', '--help']))
106*e5dd7070Spatrick        # Outputting dependency files is not a normal compile
107*e5dd7070Spatrick        self.assertFalse(
108*e5dd7070Spatrick            check_cfc.is_normal_compile(['clang', '-c', '-M', 'test.cpp']))
109*e5dd7070Spatrick        self.assertFalse(
110*e5dd7070Spatrick            check_cfc.is_normal_compile(['clang', '-c', '-MM', 'test.cpp']))
111*e5dd7070Spatrick        # Creating a dependency file as a side effect still outputs an object file
112*e5dd7070Spatrick        self.assertTrue(
113*e5dd7070Spatrick            check_cfc.is_normal_compile(['clang', '-c', '-MD', 'test.cpp']))
114*e5dd7070Spatrick        self.assertTrue(
115*e5dd7070Spatrick            check_cfc.is_normal_compile(['clang', '-c', '-MMD', 'test.cpp']))
116*e5dd7070Spatrick
117*e5dd7070Spatrick    def test_replace_output_file(self):
118*e5dd7070Spatrick        self.assertEqual(check_cfc.replace_output_file(
119*e5dd7070Spatrick            ['clang', '-o', 'test.o'], 'testg.o'), ['clang', '-o', 'testg.o'])
120*e5dd7070Spatrick        self.assertEqual(check_cfc.replace_output_file(
121*e5dd7070Spatrick            ['clang', '-otest.o'], 'testg.o'), ['clang', '-otestg.o'])
122*e5dd7070Spatrick        with self.assertRaises(Exception):
123*e5dd7070Spatrick            check_cfc.replace_output_file(['clang'], 'testg.o')
124*e5dd7070Spatrick
125*e5dd7070Spatrick    def test_add_output_file(self):
126*e5dd7070Spatrick        self.assertEqual(check_cfc.add_output_file(
127*e5dd7070Spatrick            ['clang'], 'testg.o'), ['clang', '-o', 'testg.o'])
128*e5dd7070Spatrick
129*e5dd7070Spatrick    def test_set_output_file(self):
130*e5dd7070Spatrick        # Test output not specified
131*e5dd7070Spatrick        self.assertEqual(
132*e5dd7070Spatrick            check_cfc.set_output_file(['clang'], 'test.o'), ['clang', '-o', 'test.o'])
133*e5dd7070Spatrick        # Test output is specified
134*e5dd7070Spatrick        self.assertEqual(check_cfc.set_output_file(
135*e5dd7070Spatrick            ['clang', '-o', 'test.o'], 'testb.o'), ['clang', '-o', 'testb.o'])
136*e5dd7070Spatrick
137*e5dd7070Spatrick    def test_get_input_file(self):
138*e5dd7070Spatrick        # No input file
139*e5dd7070Spatrick        self.assertIsNone(check_cfc.get_input_file(['clang']))
140*e5dd7070Spatrick        # Input C file
141*e5dd7070Spatrick        self.assertEqual(
142*e5dd7070Spatrick            check_cfc.get_input_file(['clang', 'test.c']), 'test.c')
143*e5dd7070Spatrick        # Input C++ file
144*e5dd7070Spatrick        self.assertEqual(
145*e5dd7070Spatrick            check_cfc.get_input_file(['clang', 'test.cpp']), 'test.cpp')
146*e5dd7070Spatrick        # Multiple input files
147*e5dd7070Spatrick        self.assertIsNone(
148*e5dd7070Spatrick            check_cfc.get_input_file(['clang', 'test.c', 'test2.cpp']))
149*e5dd7070Spatrick        self.assertIsNone(
150*e5dd7070Spatrick            check_cfc.get_input_file(['clang', 'test.c', 'test2.c']))
151*e5dd7070Spatrick        # Don't handle preprocessed files
152*e5dd7070Spatrick        self.assertIsNone(check_cfc.get_input_file(['clang', 'test.i']))
153*e5dd7070Spatrick        self.assertIsNone(check_cfc.get_input_file(['clang', 'test.ii']))
154*e5dd7070Spatrick        # Test identifying input file with quotes
155*e5dd7070Spatrick        self.assertEqual(
156*e5dd7070Spatrick            check_cfc.get_input_file(['clang', '"test.c"']), '"test.c"')
157*e5dd7070Spatrick        self.assertEqual(
158*e5dd7070Spatrick            check_cfc.get_input_file(['clang', "'test.c'"]), "'test.c'")
159*e5dd7070Spatrick        # Test multiple quotes
160*e5dd7070Spatrick        self.assertEqual(
161*e5dd7070Spatrick            check_cfc.get_input_file(['clang', "\"'test.c'\""]), "\"'test.c'\"")
162*e5dd7070Spatrick
163*e5dd7070Spatrick    def test_set_input_file(self):
164*e5dd7070Spatrick        self.assertEqual(check_cfc.set_input_file(
165*e5dd7070Spatrick            ['clang', 'test.c'], 'test.s'), ['clang', 'test.s'])
166*e5dd7070Spatrick
167*e5dd7070Spatrickif __name__ == '__main__':
168*e5dd7070Spatrick    unittest.main()
169