Skip to content

Commit d7446d6

Browse files
Added parse --status test cases
1 parent d3594d8 commit d7446d6

File tree

7 files changed

+212
-1
lines changed

7 files changed

+212
-1
lines changed

analyzer/codechecker_analyzer/cli/parse.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,7 @@ def get_report_dir_status(compile_commands: List[dict[str, str]],
299299
for c in compile_commands:
300300
for analyzer in supported_analyzers:
301301
file, directory, cmd = c["file"], c["directory"], c["command"]
302+
file = os.path.abspath(file)
302303

303304
filename = os.path.basename(file)
304305
action_hash = analyzer_action_hash(file, directory, cmd)
@@ -411,7 +412,7 @@ def print_status(report_dir: str,
411412
compile_commands = list(
412413
filter(lambda c: c["file"] in files_filter, compile_commands))
413414

414-
if not compile_commands:
415+
if not compile_commands and not export:
415416
LOG.warning("File not found in the compilation database!")
416417

417418
status = get_report_dir_status(compile_commands, report_dir, detailed_flag)
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# coding=utf-8
2+
# -------------------------------------------------------------------------
3+
#
4+
# Part of the CodeChecker project, under the Apache License v2.0 with
5+
# LLVM Exceptions. See LICENSE for license information.
6+
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+
#
8+
# -------------------------------------------------------------------------
9+
10+
# This file is empty, and is only present so that this directory will form a
11+
# package.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
default: a.o b.o
2+
3+
a.o: a.cpp
4+
$(CXX) -c a.cpp -o /dev/null
5+
6+
b.o: b.cpp
7+
$(CXX) -c b.cpp -o /dev/null
8+
9+
clean:
10+
rm -f a.o b.o
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#include "lib.h"
2+
3+
void foo() {
4+
myDiv(1);
5+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#include "lib.h"
2+
3+
void bar() {
4+
myDiv(2);
5+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#ifndef LIB_H
2+
#define LIB_H
3+
4+
int myDiv(int x)
5+
{
6+
return x / 0;
7+
}
8+
9+
10+
#endif
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
#
2+
# -------------------------------------------------------------------------
3+
#
4+
# Part of the CodeChecker project, under the Apache License v2.0 with
5+
# LLVM Exceptions. See LICENSE for license information.
6+
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+
#
8+
# -------------------------------------------------------------------------
9+
10+
"""
11+
Test parse --status command.
12+
"""
13+
14+
import os
15+
import re
16+
import json
17+
import shutil
18+
import subprocess
19+
import unittest
20+
21+
from libtest import env
22+
23+
24+
class TestParseStatus(unittest.TestCase):
25+
_ccClient = None
26+
27+
def setup_class(self):
28+
"""Setup the environment for the tests."""
29+
30+
global TEST_WORKSPACE
31+
TEST_WORKSPACE = env.get_workspace('skip')
32+
33+
report_dir = os.path.join(TEST_WORKSPACE, 'reports')
34+
os.makedirs(report_dir)
35+
36+
os.environ['TEST_WORKSPACE'] = TEST_WORKSPACE
37+
38+
def teardown_class(self):
39+
"""Delete the workspace associated with this test"""
40+
41+
# TODO: If environment variable is set keep the workspace
42+
# and print out the path.
43+
global TEST_WORKSPACE
44+
45+
print("Removing: " + TEST_WORKSPACE)
46+
shutil.rmtree(TEST_WORKSPACE)
47+
48+
def setup_method(self, _):
49+
50+
# TEST_WORKSPACE is automatically set by test package __init__.py .
51+
self.test_workspace = os.environ['TEST_WORKSPACE']
52+
53+
test_class = self.__class__.__name__
54+
print('Running ' + test_class + ' tests in ' + self.test_workspace)
55+
56+
# Get the CodeChecker cmd if needed for the tests.
57+
self._codechecker_cmd = env.codechecker_cmd()
58+
self._tu_collector_cmd = env.tu_collector_cmd()
59+
self.report_dir = os.path.join(self.test_workspace, "reports")
60+
self.test_dir = os.path.join(os.path.dirname(__file__), 'test_files')
61+
62+
def __run_cmd(self, cmd):
63+
process = subprocess.Popen(
64+
cmd,
65+
stdout=subprocess.PIPE,
66+
stderr=subprocess.PIPE,
67+
cwd=self.test_dir,
68+
encoding="utf-8",
69+
errors="ignore")
70+
out, err = process.communicate()
71+
72+
print(out)
73+
print(err)
74+
75+
output = out.splitlines(True)
76+
processed_output = []
77+
for line in output:
78+
# replace timestamps
79+
line = re.sub(r'\[\w+ \d{4}-\d{2}-\d{2} \d{2}:\d{2}\]',
80+
'[]', line)
81+
processed_output.append(line)
82+
83+
return ''.join(processed_output)
84+
85+
def __log_and_analyze(self):
86+
""" Log and analyze the test project. """
87+
build_json = os.path.join(self.test_workspace, "build.json")
88+
89+
clean_cmd = ["make", "clean"]
90+
out = subprocess.check_output(clean_cmd,
91+
cwd=self.test_dir,
92+
encoding="utf-8", errors="ignore")
93+
print(out)
94+
95+
# Create and run log command.
96+
log_cmd = [self._codechecker_cmd, "log", "-b", "make",
97+
"-o", build_json]
98+
out = subprocess.check_output(log_cmd,
99+
cwd=self.test_dir,
100+
encoding="utf-8", errors="ignore")
101+
print(out)
102+
103+
# Create and run analyze command.
104+
analyze_cmd = [
105+
self._codechecker_cmd, "analyze", "-c", build_json,
106+
"--analyzers", "clangsa", "-o", self.report_dir]
107+
108+
self.__run_cmd(analyze_cmd)
109+
110+
def test_parse_status_summary(self):
111+
self.__log_and_analyze()
112+
113+
parse_status_cmd = [self._codechecker_cmd, "parse",
114+
"--status", self.report_dir]
115+
out = self.__run_cmd(parse_status_cmd)
116+
117+
expected_output = """[] - ----==== Summary ====----
118+
[] - Up-to-date analysis results
119+
[] - clangsa: 2
120+
[] - Outdated analysis results
121+
[] - Failed to analyze
122+
[] - Missing analysis results
123+
[] - clang-tidy: 2
124+
[] - cppcheck: 2
125+
[] - gcc: 2
126+
[] - infer: 2
127+
[] - Total analyzed compilation commands: 2
128+
[] - Total available compilation commands: 2
129+
[] - ----=================----
130+
"""
131+
self.assertEqual(out, expected_output)
132+
133+
def test_parse_status_summary_json(self):
134+
self.__log_and_analyze()
135+
136+
parse_status_cmd = [self._codechecker_cmd, "parse",
137+
"--status", "-e", "json", self.report_dir]
138+
out = self.__run_cmd(parse_status_cmd)
139+
140+
parsed_json = json.loads(out)
141+
142+
def get_summary_count(analyzer, summary_type):
143+
return parsed_json["analyzers"][analyzer]["summary"][summary_type]
144+
145+
self.assertEqual(get_summary_count("clangsa", "up-to-date"), 2)
146+
self.assertEqual(get_summary_count("clang-tidy", "up-to-date"), 0)
147+
self.assertEqual(get_summary_count("clang-tidy", "missing"), 2)
148+
149+
def test_parse_status_detailed_json(self):
150+
self.__log_and_analyze()
151+
152+
parse_status_cmd = [self._codechecker_cmd, "parse",
153+
"--status", "-e", "json", "--detailed",
154+
self.report_dir]
155+
out = self.__run_cmd(parse_status_cmd)
156+
157+
parsed_json = json.loads(out)
158+
159+
def get_file_list(analyzer, list_type):
160+
return list(map(
161+
os.path.basename,
162+
parsed_json["analyzers"][analyzer][list_type]))
163+
164+
self.assertListEqual(get_file_list("clangsa", "up-to-date"),
165+
["a.cpp", "b.cpp"])
166+
self.assertListEqual(get_file_list("clang-tidy", "up-to-date"),
167+
[])
168+
self.assertListEqual(get_file_list("clang-tidy", "missing"),
169+
["a.cpp", "b.cpp"])

0 commit comments

Comments
 (0)