From d7bcbac214776445b4a8ddb55ef93bf656df02da Mon Sep 17 00:00:00 2001 From: "F.Tibor" Date: Mon, 24 Nov 2025 18:03:27 +0100 Subject: [PATCH 1/8] Create Test case for config files --- test/unit/config/BUILD | 110 +++++++++++++++++++++++ test/unit/config/__init__.py | 0 test/unit/config/config.json | 7 ++ test/unit/config/config.yaml | 5 ++ test/unit/config/test_config.py | 154 ++++++++++++++++++++++++++++++++ test/unit/config/zero_div.cc | 21 +++++ 6 files changed, 297 insertions(+) create mode 100644 test/unit/config/BUILD create mode 100644 test/unit/config/__init__.py create mode 100644 test/unit/config/config.json create mode 100644 test/unit/config/config.yaml create mode 100644 test/unit/config/test_config.py create mode 100644 test/unit/config/zero_div.cc diff --git a/test/unit/config/BUILD b/test/unit/config/BUILD new file mode 100644 index 00000000..2e86facc --- /dev/null +++ b/test/unit/config/BUILD @@ -0,0 +1,110 @@ +# Copyright 2023 Ericsson AB +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# cc_binary for simple C++ tests +load( + "@rules_cc//cc:defs.bzl", + "cc_binary", +) + +# codechecker rules +load( + "@bazel_codechecker//src:codechecker.bzl", + "codechecker", + "codechecker_test", + "codechecker_config", +) + +# C++ binary containing a division by zero bug +cc_binary( + name = "test_zero", + srcs = ["zero_div.cc"], +) + +# The config files should disable check for the bug found in `zero_div.cc` +filegroup( + name = "json_config_file", + srcs = [":config.json"], +) + +codechecker_config( + name = "config_json", + config_file = "json_config_file", +) + +filegroup( + name = "yaml_config_file", + srcs = [":config.yaml"], +) + +codechecker_config( + name = "config_yaml", + config_file = "yaml_config_file", +) + +# None of these codechecker rules should find any issues +codechecker( + name = "codechecker_json", + config = "config_json", + targets = [ + "test_zero", + ], +) + +codechecker( + name = "codechecker_yaml", + config = "config_yaml", + targets = [ + "test_zero", + ], +) + +codechecker_test( + name = "codechecker_test_json", + config = "config_json", + targets = [ + "test_zero", + ], + tags = ["manual"] +) + +codechecker_test( + name = "codechecker_test_yaml", + config = "config_yaml", + targets = [ + "test_zero", + ], + tags = ["manual"] +) + +codechecker_test( + name = "per_file_test_json", + config = "config_json", + targets = [ + "test_zero", + ], + tags = ["manual"], + per_file = True, +) + +codechecker_test( + name = "per_file_test_yaml", + config = "config_yaml", + targets = [ + "test_zero", + ], + tags = ["manual"], + per_file = True, +) + diff --git a/test/unit/config/__init__.py b/test/unit/config/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/test/unit/config/config.json b/test/unit/config/config.json new file mode 100644 index 00000000..e671ccf8 --- /dev/null +++ b/test/unit/config/config.json @@ -0,0 +1,7 @@ +{ + "analyze": [ + "--disable=core.DivideZero", + "--disable=core.CallAndMessage", + "--disable=cppcheck-zerodiv" + ] +} diff --git a/test/unit/config/config.yaml b/test/unit/config/config.yaml new file mode 100644 index 00000000..ddc28459 --- /dev/null +++ b/test/unit/config/config.yaml @@ -0,0 +1,5 @@ +--- +analyze: + - "--disable=core.DivideZero" + - "--disable=core.CallAndMessage" + - "--disable=cppcheck-zerodiv" diff --git a/test/unit/config/test_config.py b/test/unit/config/test_config.py new file mode 100644 index 00000000..64885f45 --- /dev/null +++ b/test/unit/config/test_config.py @@ -0,0 +1,154 @@ +# Copyright 2023 Ericsson AB +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +""" +Tests involving config files +""" +import os +import unittest +from typing import final +from common.base import TestBase + + +class TestConfig(TestBase): + """Test whether config files are getting passed to CodeChecker correctly""" + + # Set working directory + __test_path__ = os.path.dirname(os.path.abspath(__file__)) + BAZEL_BIN_DIR = os.path.join( + "../../..", "bazel-bin", "test", "unit", "config" + ) + BAZEL_TESTLOGS_DIR = os.path.join( + "../../..", "bazel-testlogs", "test", "unit", "config" + ) + + def test_codechecker_json(self): + """Test: bazel build //test/unit/config:codechecker_json""" + ret, _, _ = self.run_command( + "bazel build //test/unit/config:codechecker_json" + ) + self.assertEqual(ret, 0) + copied_config = os.path.join( + self.BAZEL_BIN_DIR, # type: ignore + "codechecker_json", + "codechecker_config.json" # TODO: Change to config.json + ) + self.assertTrue(os.path.exists(copied_config)) + with open('config.json', 'r') as f: + og_config_cont = f.read() + with open(copied_config, 'r') as f: + cp_config_cont = f.read() + self.assertEqual(og_config_cont, cp_config_cont) + + def test_codechecker_yaml(self): + """Test: bazel build //test/unit/config:codechecker_yaml""" + ret, _, _ = self.run_command( + "bazel build //test/unit/config:codechecker_yaml" + ) + self.assertEqual(ret, 0) + copied_config = os.path.join( + self.BAZEL_BIN_DIR, # type: ignore + "codechecker_yaml", + "config.yaml" + ) + self.assertFalse(os.path.exists(copied_config)) # TODO: Set to True + return # TODO: remove + with open('config.yaml', 'r') as f: + og_config_cont = f.read() + with open(copied_config, 'r') as f: + cp_config_cont = f.read() + self.assertEqual(og_config_cont, cp_config_cont) + + def test_codechecker_test_json(self): + """Test: bazel test //test/unit/config:codechecker_test_json""" + ret, _, _ = self.run_command( + "bazel test //test/unit/config:codechecker_test_json" + ) + # Should not find the division by zero bug + self.assertEqual(ret, 0) + copied_config = os.path.join( + self.BAZEL_BIN_DIR, # type: ignore + "codechecker_test_json", + "codechecker_config.json" # TODO: Change to config.json + ) + self.assertTrue(os.path.exists(copied_config)) + with open('config.json', 'r') as f: + og_config_cont = f.read() + with open(copied_config, 'r') as f: + cp_config_cont = f.read() + self.assertEqual(og_config_cont, cp_config_cont) + + def test_codechecker_test_yaml(self): + """Test: bazel test //test/unit/config:codechecker_test_yaml""" + ret, _, _ = self.run_command( + "bazel test //test/unit/config:codechecker_test_yaml" + ) + # Should not find the division by zero bug + self.assertEqual(ret, 3) # TODO: Set to 0 + copied_config = os.path.join( + self.BAZEL_BIN_DIR, # type: ignore + "codechecker_test_yaml", + "config.yaml" + ) + self.assertFalse(os.path.exists(copied_config)) # TODO: Set to True + return # TODO: Remove + with open('config.yaml', 'r') as f: + og_config_cont = f.read() + with open(copied_config, 'r') as f: + cp_config_cont = f.read() + self.assertEqual(og_config_cont, cp_config_cont) + + def test_per_file_test_json(self): + """Test: bazel test //test/unit/config:per_file_test_json""" + ret, _, _ = self.run_command( + "bazel test //test/unit/config:per_file_test_json" + ) + # Should not find the division by zero bug + self.assertEqual(ret, 3) # TODO: Change to 0 + copied_config = os.path.join( + self.BAZEL_BIN_DIR, # type: ignore + "per_file_test_json", + "config.json" + ) + self.assertFalse(os.path.exists(copied_config)) # TODO: Set to True + return # TODO: Remove + with open('config.json', 'r') as f: + og_config_cont = f.read() + with open(copied_config, 'r') as f: + cp_config_cont = f.read() + self.assertEqual(og_config_cont, cp_config_cont) + + def test_per_file_test_yaml(self): + """Test: bazel test //test/unit/config:per_file_test_yaml""" + ret, _, _ = self.run_command( + "bazel test //test/unit/config:per_file_test_yaml" + ) + # Should not find the division by zero bug + self.assertEqual(ret, 3) # TODO: Change to 0 + copied_config = os.path.join( + self.BAZEL_BIN_DIR, # type: ignore + "per_file_test_yaml", + "config.yaml" + ) + self.assertFalse(os.path.exists(copied_config)) # TODO: Set to True + return # TODO: Remove + with open('config.yaml', 'r') as f: + og_config_cont = f.read() + with open(copied_config, 'r') as f: + cp_config_cont = f.read() + self.assertEqual(og_config_cont, cp_config_cont) + + +if __name__ == "__main__": + unittest.main(buffer=True) diff --git a/test/unit/config/zero_div.cc b/test/unit/config/zero_div.cc new file mode 100644 index 00000000..fa78acc8 --- /dev/null +++ b/test/unit/config/zero_div.cc @@ -0,0 +1,21 @@ +/* + * Copyright 2023 Ericsson AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +int main(){ + int y = 0; + int x = 0/y; + return x; +} From 320c6b6baf04872a582e475a23b31950870e91e5 Mon Sep 17 00:00:00 2001 From: "F.Tibor" Date: Mon, 24 Nov 2025 18:33:30 +0100 Subject: [PATCH 2/8] Remove cpp check argument --- test/unit/config/config.json | 3 +-- test/unit/config/config.yaml | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/test/unit/config/config.json b/test/unit/config/config.json index e671ccf8..2aae3833 100644 --- a/test/unit/config/config.json +++ b/test/unit/config/config.json @@ -1,7 +1,6 @@ { "analyze": [ "--disable=core.DivideZero", - "--disable=core.CallAndMessage", - "--disable=cppcheck-zerodiv" + "--disable=core.CallAndMessage" ] } diff --git a/test/unit/config/config.yaml b/test/unit/config/config.yaml index ddc28459..0d2b55af 100644 --- a/test/unit/config/config.yaml +++ b/test/unit/config/config.yaml @@ -2,4 +2,3 @@ analyze: - "--disable=core.DivideZero" - "--disable=core.CallAndMessage" - - "--disable=cppcheck-zerodiv" From d1db9593d1ff2b7f764bc9e34d76098bb420c72a Mon Sep 17 00:00:00 2001 From: "F.Tibor" Date: Mon, 1 Dec 2025 15:03:01 +0100 Subject: [PATCH 3/8] Add comments --- test/unit/config/test_config.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/test/unit/config/test_config.py b/test/unit/config/test_config.py index 64885f45..033c6d39 100644 --- a/test/unit/config/test_config.py +++ b/test/unit/config/test_config.py @@ -43,6 +43,8 @@ def test_codechecker_json(self): self.BAZEL_BIN_DIR, # type: ignore "codechecker_json", "codechecker_config.json" # TODO: Change to config.json + # After the path the file name will change + # from codechecker_config.json to config.json ) self.assertTrue(os.path.exists(copied_config)) with open('config.json', 'r') as f: @@ -63,6 +65,7 @@ def test_codechecker_yaml(self): "config.yaml" ) self.assertFalse(os.path.exists(copied_config)) # TODO: Set to True + # Before the patch config.yaml won't be generated return # TODO: remove with open('config.yaml', 'r') as f: og_config_cont = f.read() @@ -81,6 +84,8 @@ def test_codechecker_test_json(self): self.BAZEL_BIN_DIR, # type: ignore "codechecker_test_json", "codechecker_config.json" # TODO: Change to config.json + # After the path the file name will change + # from codechecker_config.json to config.json ) self.assertTrue(os.path.exists(copied_config)) with open('config.json', 'r') as f: @@ -95,13 +100,15 @@ def test_codechecker_test_yaml(self): "bazel test //test/unit/config:codechecker_test_yaml" ) # Should not find the division by zero bug - self.assertEqual(ret, 3) # TODO: Set to 0 + self.assertEqual(ret, 3) # TODO: Set to 0, + # since CodeChecker won't find the division by zero bug copied_config = os.path.join( self.BAZEL_BIN_DIR, # type: ignore "codechecker_test_yaml", "config.yaml" ) self.assertFalse(os.path.exists(copied_config)) # TODO: Set to True + # Before the patch config.yaml won't be generated return # TODO: Remove with open('config.yaml', 'r') as f: og_config_cont = f.read() @@ -116,12 +123,14 @@ def test_per_file_test_json(self): ) # Should not find the division by zero bug self.assertEqual(ret, 3) # TODO: Change to 0 + # since CodeChecker won't find the division by zero bug copied_config = os.path.join( self.BAZEL_BIN_DIR, # type: ignore "per_file_test_json", "config.json" ) self.assertFalse(os.path.exists(copied_config)) # TODO: Set to True + # Before the patch config files aren't supported in per_file return # TODO: Remove with open('config.json', 'r') as f: og_config_cont = f.read() @@ -136,12 +145,14 @@ def test_per_file_test_yaml(self): ) # Should not find the division by zero bug self.assertEqual(ret, 3) # TODO: Change to 0 + # since CodeChecker won't find the division by zero bug copied_config = os.path.join( self.BAZEL_BIN_DIR, # type: ignore "per_file_test_yaml", "config.yaml" ) self.assertFalse(os.path.exists(copied_config)) # TODO: Set to True + # Before the patch config files aren't supported in per_file return # TODO: Remove with open('config.yaml', 'r') as f: og_config_cont = f.read() From fe0ac9a992fd4221bd3dbb219234150bdaf32bf6 Mon Sep 17 00:00:00 2001 From: "F.Tibor" Date: Mon, 1 Dec 2025 15:19:40 +0100 Subject: [PATCH 4/8] Reorder comments to try avoid errors --- test/unit/config/test_config.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/unit/config/test_config.py b/test/unit/config/test_config.py index 033c6d39..163b3b21 100644 --- a/test/unit/config/test_config.py +++ b/test/unit/config/test_config.py @@ -43,9 +43,9 @@ def test_codechecker_json(self): self.BAZEL_BIN_DIR, # type: ignore "codechecker_json", "codechecker_config.json" # TODO: Change to config.json - # After the path the file name will change - # from codechecker_config.json to config.json ) + # After the path the file name will change + # from codechecker_config.json to config.json self.assertTrue(os.path.exists(copied_config)) with open('config.json', 'r') as f: og_config_cont = f.read() @@ -84,9 +84,9 @@ def test_codechecker_test_json(self): self.BAZEL_BIN_DIR, # type: ignore "codechecker_test_json", "codechecker_config.json" # TODO: Change to config.json - # After the path the file name will change - # from codechecker_config.json to config.json ) + # After the path the file name will change + # from codechecker_config.json to config.json self.assertTrue(os.path.exists(copied_config)) with open('config.json', 'r') as f: og_config_cont = f.read() From 2ef91d89a483fc24aabb7a79c93797b6bf24e776 Mon Sep 17 00:00:00 2001 From: "F.Tibor" Date: Mon, 1 Dec 2025 15:23:30 +0100 Subject: [PATCH 5/8] Fix errors --- test/unit/config/BUILD | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/unit/config/BUILD b/test/unit/config/BUILD index 2e86facc..3d2f3212 100644 --- a/test/unit/config/BUILD +++ b/test/unit/config/BUILD @@ -90,7 +90,8 @@ codechecker_test( codechecker_test( name = "per_file_test_json", - config = "config_json", + #config = "config_json", #TODO: uncomment + # complains that per_file doesn't have a config attribute targets = [ "test_zero", ], @@ -100,7 +101,8 @@ codechecker_test( codechecker_test( name = "per_file_test_yaml", - config = "config_yaml", + #config = "config_yaml", #TODO: uncomment + # complains that per_file doesn't have a config attribute targets = [ "test_zero", ], From 63d2d6f9d5910d68976c956a2766eb773c3fda4c Mon Sep 17 00:00:00 2001 From: "F.Tibor" Date: Mon, 1 Dec 2025 15:31:49 +0100 Subject: [PATCH 6/8] Change file name to correct (have been changed during refactoring) --- test/unit/config/test_config.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/test/unit/config/test_config.py b/test/unit/config/test_config.py index 163b3b21..b1c424ad 100644 --- a/test/unit/config/test_config.py +++ b/test/unit/config/test_config.py @@ -42,10 +42,8 @@ def test_codechecker_json(self): copied_config = os.path.join( self.BAZEL_BIN_DIR, # type: ignore "codechecker_json", - "codechecker_config.json" # TODO: Change to config.json + "config.json" ) - # After the path the file name will change - # from codechecker_config.json to config.json self.assertTrue(os.path.exists(copied_config)) with open('config.json', 'r') as f: og_config_cont = f.read() @@ -83,7 +81,7 @@ def test_codechecker_test_json(self): copied_config = os.path.join( self.BAZEL_BIN_DIR, # type: ignore "codechecker_test_json", - "codechecker_config.json" # TODO: Change to config.json + "config.json" ) # After the path the file name will change # from codechecker_config.json to config.json From 18947f2ee98fe015198c73434200b2320fa051c8 Mon Sep 17 00:00:00 2001 From: "F.Tibor" Date: Mon, 1 Dec 2025 15:39:56 +0100 Subject: [PATCH 7/8] Remove config file content comparision --- test/unit/config/test_config.py | 34 --------------------------------- 1 file changed, 34 deletions(-) diff --git a/test/unit/config/test_config.py b/test/unit/config/test_config.py index b1c424ad..8f5628f1 100644 --- a/test/unit/config/test_config.py +++ b/test/unit/config/test_config.py @@ -45,11 +45,6 @@ def test_codechecker_json(self): "config.json" ) self.assertTrue(os.path.exists(copied_config)) - with open('config.json', 'r') as f: - og_config_cont = f.read() - with open(copied_config, 'r') as f: - cp_config_cont = f.read() - self.assertEqual(og_config_cont, cp_config_cont) def test_codechecker_yaml(self): """Test: bazel build //test/unit/config:codechecker_yaml""" @@ -64,12 +59,6 @@ def test_codechecker_yaml(self): ) self.assertFalse(os.path.exists(copied_config)) # TODO: Set to True # Before the patch config.yaml won't be generated - return # TODO: remove - with open('config.yaml', 'r') as f: - og_config_cont = f.read() - with open(copied_config, 'r') as f: - cp_config_cont = f.read() - self.assertEqual(og_config_cont, cp_config_cont) def test_codechecker_test_json(self): """Test: bazel test //test/unit/config:codechecker_test_json""" @@ -86,11 +75,6 @@ def test_codechecker_test_json(self): # After the path the file name will change # from codechecker_config.json to config.json self.assertTrue(os.path.exists(copied_config)) - with open('config.json', 'r') as f: - og_config_cont = f.read() - with open(copied_config, 'r') as f: - cp_config_cont = f.read() - self.assertEqual(og_config_cont, cp_config_cont) def test_codechecker_test_yaml(self): """Test: bazel test //test/unit/config:codechecker_test_yaml""" @@ -107,12 +91,6 @@ def test_codechecker_test_yaml(self): ) self.assertFalse(os.path.exists(copied_config)) # TODO: Set to True # Before the patch config.yaml won't be generated - return # TODO: Remove - with open('config.yaml', 'r') as f: - og_config_cont = f.read() - with open(copied_config, 'r') as f: - cp_config_cont = f.read() - self.assertEqual(og_config_cont, cp_config_cont) def test_per_file_test_json(self): """Test: bazel test //test/unit/config:per_file_test_json""" @@ -129,12 +107,6 @@ def test_per_file_test_json(self): ) self.assertFalse(os.path.exists(copied_config)) # TODO: Set to True # Before the patch config files aren't supported in per_file - return # TODO: Remove - with open('config.json', 'r') as f: - og_config_cont = f.read() - with open(copied_config, 'r') as f: - cp_config_cont = f.read() - self.assertEqual(og_config_cont, cp_config_cont) def test_per_file_test_yaml(self): """Test: bazel test //test/unit/config:per_file_test_yaml""" @@ -151,12 +123,6 @@ def test_per_file_test_yaml(self): ) self.assertFalse(os.path.exists(copied_config)) # TODO: Set to True # Before the patch config files aren't supported in per_file - return # TODO: Remove - with open('config.yaml', 'r') as f: - og_config_cont = f.read() - with open(copied_config, 'r') as f: - cp_config_cont = f.read() - self.assertEqual(og_config_cont, cp_config_cont) if __name__ == "__main__": From 6ab1b11e57e6099610ff121893999f4fbbbe94d5 Mon Sep 17 00:00:00 2001 From: "F.Tibor" Date: Tue, 2 Dec 2025 12:14:05 +0100 Subject: [PATCH 8/8] Comment nit update --- test/unit/config/test_config.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/unit/config/test_config.py b/test/unit/config/test_config.py index 8f5628f1..133db19b 100644 --- a/test/unit/config/test_config.py +++ b/test/unit/config/test_config.py @@ -72,7 +72,7 @@ def test_codechecker_test_json(self): "codechecker_test_json", "config.json" ) - # After the path the file name will change + # After the fix the file name will change # from codechecker_config.json to config.json self.assertTrue(os.path.exists(copied_config)) @@ -83,7 +83,7 @@ def test_codechecker_test_yaml(self): ) # Should not find the division by zero bug self.assertEqual(ret, 3) # TODO: Set to 0, - # since CodeChecker won't find the division by zero bug + # based on the config file won't find the division by zero bug copied_config = os.path.join( self.BAZEL_BIN_DIR, # type: ignore "codechecker_test_yaml",