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