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