Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 45 additions & 19 deletions test/common/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,32 +70,32 @@ class TestBase(unittest.TestCase):
@classmethod
def setUpClass(cls):
"""Load module, save environment"""
ErrorCollector: list[str] = []
if cls.__test_path__ == None:
ErrorCollector.append(
error_collector: list[str] = []
if cls.__test_path__ is None:
error_collector.append(
"Test path must be overwritten! Use:"
"\n__test_path__ = os.path.dirname(os.path.abspath(__file__))"
)
if cls.BAZEL_BIN_DIR == None:
ErrorCollector.append(
if cls.BAZEL_BIN_DIR is None:
error_collector.append(
"Bazel bin directory must be overwritten! Use:"
"../../../bazel-bin/test/unit/my_test_folder"
)
if cls.BAZEL_TESTLOGS_DIR == None:
ErrorCollector.append(
if cls.BAZEL_TESTLOGS_DIR is None:
error_collector.append(
"Bazel test logs directory must be overwritten! Use:"
"../../../bazel-testlogs/test/unit/my_test_folder"
)
if ErrorCollector:
raise NotImplementedError("\n".join(ErrorCollector))
if error_collector:
raise NotImplementedError("\n".join(error_collector))
# Enable debug logs for tests if "super verbose" flag is provided
if "-vvv" in sys.argv:
logging.basicConfig(
level=logging.DEBUG, format="[TEST] %(levelname)5s: %(message)s"
)
# Move to test dir
cls.test_dir = cls.__test_path__
os.chdir(cls.test_dir)
os.chdir(cls.test_dir) # pyright: ignore[reportArgumentType]
# Save environment and location
cls.save_env = os.environ
cls.save_cwd = os.getcwd()
Expand All @@ -106,7 +106,7 @@ def tearDownClass(cls):
os.chdir(cls.save_cwd)
os.environ = cls.save_env
try:
assert cls.server_process.poll() != None, "Server not stopped"
assert cls.server_process.poll() is not None, "Server not stopped"
except AttributeError:
pass # if server_process is not set, everything is fine

Expand All @@ -116,7 +116,7 @@ def setUp(self):

@classmethod
def run_command(
self, cmd: str, working_dir: Optional[str] = None
cls, cmd: str, working_dir: Optional[str] = None
) -> tuple[int, str, str]:
"""
Run shell command.
Expand All @@ -138,8 +138,8 @@ def run_command(
cwd=working_dir,
) as process:
stdout, stderr = process.communicate()
logging.debug(f"stdout:\n{stdout}")
logging.debug(f"stderr:\n{stderr}")
logging.debug("stdout:\n %s", stdout)
logging.debug("stderr:\n %s", stderr)
return (
process.returncode,
f"stdout: {stdout}",
Expand Down Expand Up @@ -168,10 +168,14 @@ def contains_regex_in_file(cls, file_path: str, regex: str) -> bool:
"""
Returns a boolean, whether the specified file contains the regex or not.
"""
return cls.grep_file(file_path, regex) != []
return bool(cls.grep_file(file_path, regex))

@classmethod
def start_codechecker_server(cls):
"""
Starts a CodeChecker server instance on port 8001
This server must be shutdown with stop_codechecker_sever
"""
cls.temp_workspace = tempfile.mkdtemp()
server_command = [
"CodeChecker",
Expand All @@ -181,7 +185,9 @@ def start_codechecker_server(cls):
"--port",
"8001", # user running unittest must make this port free!
]
cls.devnull = open(os.devnull, "w")
# pylint: disable=consider-using-with
cls.devnull = open(os.devnull, "w", encoding='utf-8')
# pylint: disable=consider-using-with
cls.server_process: subprocess.Popen = subprocess.Popen(
server_command, stdout=cls.devnull
)
Comment thread
furtib marked this conversation as resolved.
Expand All @@ -191,17 +197,37 @@ def start_codechecker_server(cls):

@classmethod
def stop_codechecker_server(cls):
"""
Stops the CodeChecker server started by start_codechecker_server
"""
os.kill(cls.server_process.pid, signal.SIGTERM)
cls.server_process.wait()
cls.devnull.close()
shutil.rmtree(cls.temp_workspace)

def check_store(self, path : str, name : str):
def check_store(self, path: str, name: str):
"""
Tries to store the results on the codechecker server,
asserts for successful storing.

Args:
path - Path of the result files
name - name of the project to be saved under
"""
ret, _, _ = self.run_command(
f'CodeChecker store {path} -n {name} --url=http://localhost:8001/Default'
f"CodeChecker store {path} -n {name}"
" --url=http://localhost:8001/Default"
)
self.assertEqual(ret, 0)

def check_parse(self, path : str, will_find_bug : bool = True):
def check_parse(self, path: str, will_find_bug: bool = True):
"""
Checks if the parse command finishes correctly on results.

Args:
path - Path of the result files
will_find_bug - Will there be a bug in the result files,
changes on what we assert
"""
ret, _, _ = self.run_command(f"CodeChecker parse {path}")
self.assertEqual(ret, 2 if will_find_bug else 0)
18 changes: 14 additions & 4 deletions test/foss/test_foss.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@
# See the License for the specific language governing permissions and
# limitations under the License.

import logging
import sys
"""
Test the rule integrated into open source projects
"""

import unittest
import os
from types import FunctionType
Expand All @@ -24,6 +26,9 @@


def get_test_dirs() -> list[str]:
"""
Collect directories containing a test project
"""
dirs = []
for entry in os.listdir(ROOT_DIR):
full_path = os.path.join(ROOT_DIR, entry)
Expand All @@ -37,6 +42,9 @@ def get_test_dirs() -> list[str]:

# This will contain the generated tests.
class FOSSTestCollector(TestBase):
"""
Test class for FOSS tests
"""
# Set working directory
__test_path__ = os.path.dirname(os.path.abspath(__file__))
# These are irrelevant for these kind of tests
Expand All @@ -50,13 +58,14 @@ def create_test_method(directory_name: str) -> FunctionType:
"""
Returns a function pointer that points to a function for the given directory
"""

def test_runner(self) -> None:
project_root = os.path.join(ROOT_DIR, directory_name)

self.assertTrue(
os.path.exists(os.path.join(project_root, "init.sh")),
f"Missing 'init.sh' in {directory_name}\n" + \
"Please consult with the README on how to add a new FOSS project",
f"Missing 'init.sh' in {directory_name}\n"
+ "Please consult with the README on how to add a new FOSS project",
)
project_working_dir = os.path.join(project_root, "test-proj")
if not os.path.exists(project_working_dir):
Expand All @@ -73,6 +82,7 @@ def test_runner(self) -> None:

return test_runner


# Dynamically add a test method for each project
# For each project directory it adds a new test function to the class
# This must be outside of the __main__ if, pytest doesn't run it that way
Expand Down
7 changes: 4 additions & 3 deletions test/unit/caching/test_caching.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ def setUp(self):
if os.path.exists("tmp"):
try:
shutil.rmtree("tmp")
# pylint: disable=broad-exception-caught
except Exception as e:
self.fail(f"Failed to clean up the existing tmp directory {e}")
os.mkdir("tmp")
Expand Down Expand Up @@ -77,7 +78,7 @@ def test_bazel_test_codechecker_caching(self):
with open("tmp/secondary.cc", "a", encoding="utf-8") as f:
f.write("//test")
except FileNotFoundError:
self.fail(f"File not found!")
self.fail("File not found!")
ret, _, stderr = self.run_command(f"bazel build {target} --subcommands")
self.assertEqual(ret, 0)
# Since everything in the monolithic rule is a single action,
Expand All @@ -98,7 +99,7 @@ def test_bazel_test_per_file_caching(self):
with open("tmp/secondary.cc", "a", encoding="utf-8") as f:
f.write("//test")
except FileNotFoundError:
self.fail(f"File not found!")
self.fail("File not found!")
ret, _, stderr = self.run_command(f"bazel build {target} --subcommands")
self.assertEqual(ret, 0)
self.assertEqual(
Expand All @@ -117,7 +118,7 @@ def test_bazel_test_per_file_ctu_caching(self):
with open("tmp/secondary.cc", "a", encoding="utf-8") as f:
f.write("//test")
except FileNotFoundError:
self.fail(f"File not found!")
self.fail("File not found!")
ret, _, stderr = self.run_command(f"bazel build {target} --subcommands")
self.assertEqual(ret, 0)
# We expect both files to be reanalyzed, since there is no caching
Expand Down
8 changes: 4 additions & 4 deletions test/unit/compile_flags/test_compile_flags.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,12 @@ def test_bazel_test_compile_commands_filter(self):
exit_code, _, _ = self.run_command(build_cmd)
self.assertEqual(0, exit_code)
compile_commands = os.path.join(
self.BAZEL_BIN_DIR,
self.BAZEL_BIN_DIR, # pyright: ignore
"compile_commands_filter",
"compile_commands.json",
)

with open(compile_commands) as f:
with open(compile_commands, "r", encoding="utf-8") as f:
json_content = json.load(f)
for source in json_content:
if source["file"].endswith(".c"):
Expand Down Expand Up @@ -83,12 +83,12 @@ def test_bazel_test_per_file_filter(self):
exit_code, _, _ = self.run_command(build_cmd)
self.assertEqual(0, exit_code)
compile_commands = os.path.join(
self.BAZEL_BIN_DIR,
self.BAZEL_BIN_DIR, # pyright: ignore
"per_file_filter",
"compile_commands.json",
)
self.assertTrue(os.path.exists(compile_commands))
with open(compile_commands) as f:
with open(compile_commands, "r", encoding="utf-8") as f:
json_content = json.load(f)
for source in json_content:
if source["file"].endswith(".c"):
Expand Down
25 changes: 12 additions & 13 deletions test/unit/config/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
"""
import os
import unittest
from typing import final
from common.base import TestBase


Expand All @@ -40,9 +39,9 @@ def test_codechecker_json(self):
)
self.assertEqual(ret, 0)
copied_config = os.path.join(
self.BAZEL_BIN_DIR, # type: ignore
self.BAZEL_BIN_DIR, # type: ignore
"codechecker_json",
"config.json"
"config.json",
)
self.assertTrue(os.path.exists(copied_config))

Expand All @@ -53,9 +52,9 @@ def test_codechecker_yaml(self):
)
self.assertEqual(ret, 0)
copied_config = os.path.join(
self.BAZEL_BIN_DIR, # type: ignore
self.BAZEL_BIN_DIR, # type: ignore
"codechecker_yaml",
"config.yaml"
"config.yaml",
)
self.assertTrue(os.path.exists(copied_config))

Expand All @@ -67,9 +66,9 @@ def test_codechecker_test_json(self):
# Should not find the division by zero bug
self.assertEqual(ret, 0)
copied_config = os.path.join(
self.BAZEL_BIN_DIR, # type: ignore
self.BAZEL_BIN_DIR, # type: ignore
"codechecker_test_json",
"config.json"
"config.json",
)
# After the fix the file name will change
# from codechecker_config.json to config.json
Expand All @@ -83,9 +82,9 @@ def test_codechecker_test_yaml(self):
# Should not find the division by zero bug
self.assertEqual(ret, 0)
copied_config = os.path.join(
self.BAZEL_BIN_DIR, # type: ignore
self.BAZEL_BIN_DIR, # type: ignore
"codechecker_test_yaml",
"config.yaml"
"config.yaml",
)
self.assertTrue(os.path.exists(copied_config))

Expand All @@ -97,9 +96,9 @@ def test_per_file_test_json(self):
# Should not find the division by zero bug
self.assertEqual(ret, 0)
copied_config = os.path.join(
self.BAZEL_BIN_DIR, # type: ignore
self.BAZEL_BIN_DIR, # type: ignore
"per_file_test_json",
"config.json"
"config.json",
)
self.assertTrue(os.path.exists(copied_config))

Expand All @@ -111,9 +110,9 @@ def test_per_file_test_yaml(self):
# Should not find the division by zero bug
self.assertEqual(ret, 0)
copied_config = os.path.join(
self.BAZEL_BIN_DIR, # type: ignore
self.BAZEL_BIN_DIR, # type: ignore
"per_file_test_yaml",
"config.yaml"
"config.yaml",
)
self.assertTrue(os.path.exists(copied_config))

Expand Down
Loading