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