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 libear 7import libscanbuild.report as sut 8import unittest 9import os 10import os.path 11 12 13def run_bug_parse(content): 14 with libear.TemporaryDirectory() as tmpdir: 15 file_name = os.path.join(tmpdir, 'test.html') 16 with open(file_name, 'w') as handle: 17 handle.writelines(content) 18 for bug in sut.parse_bug_html(file_name): 19 return bug 20 21 22def run_crash_parse(content, preproc): 23 with libear.TemporaryDirectory() as tmpdir: 24 file_name = os.path.join(tmpdir, preproc + '.info.txt') 25 with open(file_name, 'w') as handle: 26 handle.writelines(content) 27 return sut.parse_crash(file_name) 28 29 30class ParseFileTest(unittest.TestCase): 31 32 def test_parse_bug(self): 33 content = [ 34 "some header\n", 35 "<!-- BUGDESC Division by zero -->\n", 36 "<!-- BUGTYPE Division by zero -->\n", 37 "<!-- BUGCATEGORY Logic error -->\n", 38 "<!-- BUGFILE xx -->\n", 39 "<!-- BUGLINE 5 -->\n", 40 "<!-- BUGCOLUMN 22 -->\n", 41 "<!-- BUGPATHLENGTH 4 -->\n", 42 "<!-- BUGMETAEND -->\n", 43 "<!-- REPORTHEADER -->\n", 44 "some tails\n"] 45 result = run_bug_parse(content) 46 self.assertEqual(result['bug_category'], 'Logic error') 47 self.assertEqual(result['bug_path_length'], 4) 48 self.assertEqual(result['bug_line'], 5) 49 self.assertEqual(result['bug_description'], 'Division by zero') 50 self.assertEqual(result['bug_type'], 'Division by zero') 51 self.assertEqual(result['bug_file'], 'xx') 52 53 def test_parse_bug_empty(self): 54 content = [] 55 result = run_bug_parse(content) 56 self.assertEqual(result['bug_category'], 'Other') 57 self.assertEqual(result['bug_path_length'], 1) 58 self.assertEqual(result['bug_line'], 0) 59 60 def test_parse_crash(self): 61 content = [ 62 "/some/path/file.c\n", 63 "Some very serious Error\n", 64 "bla\n", 65 "bla-bla\n"] 66 result = run_crash_parse(content, 'file.i') 67 self.assertEqual(result['source'], content[0].rstrip()) 68 self.assertEqual(result['problem'], content[1].rstrip()) 69 self.assertEqual(os.path.basename(result['file']), 70 'file.i') 71 self.assertEqual(os.path.basename(result['info']), 72 'file.i.info.txt') 73 self.assertEqual(os.path.basename(result['stderr']), 74 'file.i.stderr.txt') 75 76 def test_parse_real_crash(self): 77 import libscanbuild.analyze as sut2 78 import re 79 with libear.TemporaryDirectory() as tmpdir: 80 filename = os.path.join(tmpdir, 'test.c') 81 with open(filename, 'w') as handle: 82 handle.write('int main() { return 0') 83 # produce failure report 84 opts = { 85 'clang': 'clang', 86 'directory': os.getcwd(), 87 'flags': [], 88 'file': filename, 89 'output_dir': tmpdir, 90 'language': 'c', 91 'error_type': 'other_error', 92 'error_output': 'some output', 93 'exit_code': 13 94 } 95 sut2.report_failure(opts) 96 # find the info file 97 pp_file = None 98 for root, _, files in os.walk(tmpdir): 99 keys = [os.path.join(root, name) for name in files] 100 for key in keys: 101 if re.match(r'^(.*/)+clang(.*)\.i$', key): 102 pp_file = key 103 self.assertIsNot(pp_file, None) 104 # read the failure report back 105 result = sut.parse_crash(pp_file + '.info.txt') 106 self.assertEqual(result['source'], filename) 107 self.assertEqual(result['problem'], 'Other Error') 108 self.assertEqual(result['file'], pp_file) 109 self.assertEqual(result['info'], pp_file + '.info.txt') 110 self.assertEqual(result['stderr'], pp_file + '.stderr.txt') 111 112 113class ReportMethodTest(unittest.TestCase): 114 115 def test_chop(self): 116 self.assertEqual('file', sut.chop('/prefix', '/prefix/file')) 117 self.assertEqual('file', sut.chop('/prefix/', '/prefix/file')) 118 self.assertEqual('lib/file', sut.chop('/prefix/', '/prefix/lib/file')) 119 self.assertEqual('/prefix/file', sut.chop('', '/prefix/file')) 120 121 def test_chop_when_cwd(self): 122 self.assertEqual('../src/file', sut.chop('/cwd', '/src/file')) 123 self.assertEqual('../src/file', sut.chop('/prefix/cwd', 124 '/prefix/src/file')) 125 126 127class GetPrefixFromCompilationDatabaseTest(unittest.TestCase): 128 129 def test_with_different_filenames(self): 130 self.assertEqual( 131 sut.commonprefix(['/tmp/a.c', '/tmp/b.c']), '/tmp') 132 133 def test_with_different_dirnames(self): 134 self.assertEqual( 135 sut.commonprefix(['/tmp/abs/a.c', '/tmp/ack/b.c']), '/tmp') 136 137 def test_no_common_prefix(self): 138 self.assertEqual( 139 sut.commonprefix(['/tmp/abs/a.c', '/usr/ack/b.c']), '/') 140 141 def test_with_single_file(self): 142 self.assertEqual( 143 sut.commonprefix(['/tmp/a.c']), '/tmp') 144 145 def test_empty(self): 146 self.assertEqual( 147 sut.commonprefix([]), '') 148