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 7from . import call_and_report 8import unittest 9 10import os.path 11import string 12import glob 13 14 15def prepare_cdb(name, target_dir): 16 target_file = 'build_{0}.json'.format(name) 17 this_dir, _ = os.path.split(__file__) 18 path = os.path.normpath(os.path.join(this_dir, '..', 'src')) 19 source_dir = os.path.join(path, 'compilation_database') 20 source_file = os.path.join(source_dir, target_file + '.in') 21 target_file = os.path.join(target_dir, 'compile_commands.json') 22 with open(source_file, 'r') as in_handle: 23 with open(target_file, 'w') as out_handle: 24 for line in in_handle: 25 temp = string.Template(line) 26 out_handle.write(temp.substitute(path=path)) 27 return target_file 28 29 30def run_analyzer(directory, cdb, args): 31 cmd = ['analyze-build', '--cdb', cdb, '--output', directory] \ 32 + args 33 return call_and_report(cmd, []) 34 35 36class OutputDirectoryTest(unittest.TestCase): 37 def test_regular_keeps_report_dir(self): 38 with libear.TemporaryDirectory() as tmpdir: 39 cdb = prepare_cdb('regular', tmpdir) 40 exit_code, reportdir = run_analyzer(tmpdir, cdb, []) 41 self.assertTrue(os.path.isdir(reportdir)) 42 43 def test_clear_deletes_report_dir(self): 44 with libear.TemporaryDirectory() as tmpdir: 45 cdb = prepare_cdb('clean', tmpdir) 46 exit_code, reportdir = run_analyzer(tmpdir, cdb, []) 47 self.assertFalse(os.path.isdir(reportdir)) 48 49 def test_clear_keeps_report_dir_when_asked(self): 50 with libear.TemporaryDirectory() as tmpdir: 51 cdb = prepare_cdb('clean', tmpdir) 52 exit_code, reportdir = run_analyzer(tmpdir, cdb, ['--keep-empty']) 53 self.assertTrue(os.path.isdir(reportdir)) 54 55 56class ExitCodeTest(unittest.TestCase): 57 def test_regular_does_not_set_exit_code(self): 58 with libear.TemporaryDirectory() as tmpdir: 59 cdb = prepare_cdb('regular', tmpdir) 60 exit_code, __ = run_analyzer(tmpdir, cdb, []) 61 self.assertFalse(exit_code) 62 63 def test_clear_does_not_set_exit_code(self): 64 with libear.TemporaryDirectory() as tmpdir: 65 cdb = prepare_cdb('clean', tmpdir) 66 exit_code, __ = run_analyzer(tmpdir, cdb, []) 67 self.assertFalse(exit_code) 68 69 def test_regular_sets_exit_code_if_asked(self): 70 with libear.TemporaryDirectory() as tmpdir: 71 cdb = prepare_cdb('regular', tmpdir) 72 exit_code, __ = run_analyzer(tmpdir, cdb, ['--status-bugs']) 73 self.assertTrue(exit_code) 74 75 def test_clear_does_not_set_exit_code_if_asked(self): 76 with libear.TemporaryDirectory() as tmpdir: 77 cdb = prepare_cdb('clean', tmpdir) 78 exit_code, __ = run_analyzer(tmpdir, cdb, ['--status-bugs']) 79 self.assertFalse(exit_code) 80 81 def test_regular_sets_exit_code_if_asked_from_plist(self): 82 with libear.TemporaryDirectory() as tmpdir: 83 cdb = prepare_cdb('regular', tmpdir) 84 exit_code, __ = run_analyzer( 85 tmpdir, cdb, ['--status-bugs', '--plist']) 86 self.assertTrue(exit_code) 87 88 def test_clear_does_not_set_exit_code_if_asked_from_plist(self): 89 with libear.TemporaryDirectory() as tmpdir: 90 cdb = prepare_cdb('clean', tmpdir) 91 exit_code, __ = run_analyzer( 92 tmpdir, cdb, ['--status-bugs', '--plist']) 93 self.assertFalse(exit_code) 94 95 96class OutputFormatTest(unittest.TestCase): 97 @staticmethod 98 def get_html_count(directory): 99 return len(glob.glob(os.path.join(directory, 'report-*.html'))) 100 101 @staticmethod 102 def get_plist_count(directory): 103 return len(glob.glob(os.path.join(directory, 'report-*.plist'))) 104 105 @staticmethod 106 def get_sarif_count(directory): 107 return len(glob.glob(os.path.join(directory, 'result-*.sarif'))) 108 109 def test_default_only_creates_html_report(self): 110 with libear.TemporaryDirectory() as tmpdir: 111 cdb = prepare_cdb('regular', tmpdir) 112 exit_code, reportdir = run_analyzer(tmpdir, cdb, []) 113 self.assertTrue( 114 os.path.exists(os.path.join(reportdir, 'index.html'))) 115 self.assertEqual(self.get_html_count(reportdir), 2) 116 self.assertEqual(self.get_plist_count(reportdir), 0) 117 self.assertEqual(self.get_sarif_count(reportdir), 0) 118 119 def test_plist_and_html_creates_html_and_plist_reports(self): 120 with libear.TemporaryDirectory() as tmpdir: 121 cdb = prepare_cdb('regular', tmpdir) 122 exit_code, reportdir = run_analyzer(tmpdir, cdb, ['--plist-html']) 123 self.assertTrue( 124 os.path.exists(os.path.join(reportdir, 'index.html'))) 125 self.assertEqual(self.get_html_count(reportdir), 2) 126 self.assertEqual(self.get_plist_count(reportdir), 5) 127 self.assertEqual(self.get_sarif_count(reportdir), 0) 128 129 def test_plist_only_creates_plist_report(self): 130 with libear.TemporaryDirectory() as tmpdir: 131 cdb = prepare_cdb('regular', tmpdir) 132 exit_code, reportdir = run_analyzer(tmpdir, cdb, ['--plist']) 133 self.assertFalse( 134 os.path.exists(os.path.join(reportdir, 'index.html'))) 135 self.assertEqual(self.get_html_count(reportdir), 0) 136 self.assertEqual(self.get_plist_count(reportdir), 5) 137 self.assertEqual(self.get_sarif_count(reportdir), 0) 138 139 def test_sarif_only_creates_sarif_result(self): 140 with libear.TemporaryDirectory() as tmpdir: 141 cdb = prepare_cdb('regular', tmpdir) 142 exit_code, reportdir = run_analyzer(tmpdir, cdb, ['--sarif']) 143 self.assertFalse( 144 os.path.exists(os.path.join(reportdir, 'index.html'))) 145 self.assertTrue( 146 os.path.exists(os.path.join(reportdir, 'results-merged.sarif'))) 147 self.assertEqual(self.get_html_count(reportdir), 0) 148 self.assertEqual(self.get_plist_count(reportdir), 0) 149 self.assertEqual(self.get_sarif_count(reportdir), 5) 150 151 def test_sarif_and_html_creates_sarif_and_html_reports(self): 152 with libear.TemporaryDirectory() as tmpdir: 153 cdb = prepare_cdb('regular', tmpdir) 154 exit_code, reportdir = run_analyzer(tmpdir, cdb, ['--sarif-html']) 155 self.assertTrue( 156 os.path.exists(os.path.join(reportdir, 'index.html'))) 157 self.assertTrue( 158 os.path.exists(os.path.join(reportdir, 'results-merged.sarif'))) 159 self.assertEqual(self.get_html_count(reportdir), 2) 160 self.assertEqual(self.get_plist_count(reportdir), 0) 161 self.assertEqual(self.get_sarif_count(reportdir), 5) 162 163 164class FailureReportTest(unittest.TestCase): 165 def test_broken_creates_failure_reports(self): 166 with libear.TemporaryDirectory() as tmpdir: 167 cdb = prepare_cdb('broken', tmpdir) 168 exit_code, reportdir = run_analyzer(tmpdir, cdb, []) 169 self.assertTrue( 170 os.path.isdir(os.path.join(reportdir, 'failures'))) 171 172 def test_broken_does_not_creates_failure_reports(self): 173 with libear.TemporaryDirectory() as tmpdir: 174 cdb = prepare_cdb('broken', tmpdir) 175 exit_code, reportdir = run_analyzer( 176 tmpdir, cdb, ['--no-failure-reports']) 177 self.assertFalse( 178 os.path.isdir(os.path.join(reportdir, 'failures'))) 179 180 181class TitleTest(unittest.TestCase): 182 def assertTitleEqual(self, directory, expected): 183 import re 184 patterns = [ 185 re.compile(r'<title>(?P<page>.*)</title>'), 186 re.compile(r'<h1>(?P<head>.*)</h1>') 187 ] 188 result = dict() 189 190 index = os.path.join(directory, 'index.html') 191 with open(index, 'r') as handler: 192 for line in handler.readlines(): 193 for regex in patterns: 194 match = regex.match(line.strip()) 195 if match: 196 result.update(match.groupdict()) 197 break 198 self.assertEqual(result['page'], result['head']) 199 self.assertEqual(result['page'], expected) 200 201 def test_default_title_in_report(self): 202 with libear.TemporaryDirectory() as tmpdir: 203 cdb = prepare_cdb('broken', tmpdir) 204 exit_code, reportdir = run_analyzer(tmpdir, cdb, []) 205 self.assertTitleEqual(reportdir, 'src - analyzer results') 206 207 def test_given_title_in_report(self): 208 with libear.TemporaryDirectory() as tmpdir: 209 cdb = prepare_cdb('broken', tmpdir) 210 exit_code, reportdir = run_analyzer( 211 tmpdir, cdb, ['--html-title', 'this is the title']) 212 self.assertTitleEqual(reportdir, 'this is the title') 213