Skip to content

Commit

Permalink
LOBSTER-Cpptest tool to use configuration files
Browse files Browse the repository at this point in the history
- Replaced command-line arguments with a YAML-based configuration file for improved usability and maintainability.
- Simplifies parameter management and enhances readability.
  • Loading branch information
SurajBDeore committed Dec 5, 2024
1 parent 0a90610 commit c945916
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 49 deletions.
51 changes: 25 additions & 26 deletions lobster/tools/cpptest/cpptest.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import sys
import argparse
import os.path
import yaml
from copy import copy
from enum import Enum

Expand Down Expand Up @@ -65,19 +66,19 @@ class RequirementTypes(Enum):

def parse_config_file(file_name: str) -> dict:
"""
Parse the configuration dictionary from given config file.
Parse the configuration dictionary from the given YAML config file.
The configuration dictionary for cpptest must contain the OUTPUT and
CODEBEAMER_URL keys.
Each output configuration dictionary contains a file name as key and
a value dictionary containing the keys MARKERS and KIND.
The supported values for the MARKERS list are specified in
The configuration dictionary for cpptest must contain the `output` and
`codebeamer_url` keys.
Each output configuration dictionary contains a file name as a key and
a value dictionary containing the keys `markers` and `kind`.
The supported values for the `markers` list are specified in
SUPPORTED_REQUIREMENTS.
Parameters
----------
file_name : str
The file name of the cpptest config file.
The file name of the cpptest YAML config file.
Returns
-------
Expand All @@ -87,17 +88,17 @@ def parse_config_file(file_name: str) -> dict:
Raises
------
Exception
If the config dict does not contain the required keys
or contains not supported values.
If the config dictionary does not contain the required keys
or is improperly formatted.
"""
if not os.path.isfile(file_name):
raise ValueError(f'{file_name} is not an existing file!')

with open(file_name, "r", encoding='utf-8') as file:
config_dict: dict = json.loads(file.read())
config_dict = yaml.safe_load(file)

if (OUTPUT not in config_dict.keys() or
CODEBEAMER_URL not in config_dict.keys()):
if not config_dict or OUTPUT not in config_dict or \
CODEBEAMER_URL not in config_dict:
raise ValueError(f'Please follow the right config file structure! '
f'Missing attribute "{OUTPUT}" and '
f'"{CODEBEAMER_URL}"')
Expand All @@ -106,17 +107,16 @@ def parse_config_file(file_name: str) -> dict:

supported_markers = ', '.join(SUPPORTED_REQUIREMENTS)
for output_file, output_file_config_dict in output_config_dict.items():
if MARKERS not in output_file_config_dict.keys():
if MARKERS not in output_file_config_dict:
raise ValueError(f'Please follow the right config file structure! '
f'Missing attribute "{MARKERS}" for output file '
f'"{output_file}"')
if KIND not in output_file_config_dict.keys():
if KIND not in output_file_config_dict:
raise ValueError(f'Please follow the right config file structure! '
f'Missing attribute "{KIND}" for output file '
f'"{output_file}"')

output_file_marker_list = output_file_config_dict.get(MARKERS)
for output_file_marker in output_file_marker_list:
for output_file_marker in output_file_config_dict.get(MARKERS, []):
if output_file_marker not in SUPPORTED_REQUIREMENTS:
raise ValueError(f'"{output_file_marker}" is not a supported '
f'"{MARKERS}" value '
Expand Down Expand Up @@ -374,20 +374,19 @@ def main():
"""
# lobster-trace: cpptest_req.Dummy_Requirement
ap = argparse.ArgumentParser()
ap.add_argument("files",
nargs="+",
metavar="FILE|DIR")
ap.add_argument("--config-file",
help="path of the config file, it consists of "
"a requirement types as keys and "
"output filenames as value",
required=True,
default=None)
ap.add_argument("--config",
help=("Path to YAML file with arguments, "
"by default (cpptest-config.yaml)"),
default="cpptest-config.yaml"
)

options = ap.parse_args()

try:
config_dict = parse_config_file(options.config_file)
config_dict = parse_config_file(options.config)

options.files = config_dict.get("files", ["."])
config_dict.pop("files", None)

lobster_cpptest(
file_dir_list=options.files,
Expand Down
54 changes: 34 additions & 20 deletions packages/lobster-tool-cpptest/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ from the provided comments in cpp files
* `lobster-cpptest`: Extract requirements with dynamic refrences
from comments.

## Configuration

The tool requires a YAML configuration file to define its settings.
You must provide this file when running the tool to specify parameters to process.

## Usage

This tool supports C/C++ code.
Expand All @@ -29,28 +34,37 @@ For this you can provide some cpp file with these comments:
*/
TEST(RequirementTagTest1, RequirementsAsMultipleComments) {}
```
You can also provide a config-file which determines which markers
should be extracted in which files. In addition you have to provide
the codebeamer-url:
```config
{
"output": {
"unit_tests.lobster" :
{
"markers": ["@requirement"],
"kind": "req"
},
"components_tests.lobster" :
{
"markers": ["@requiredby", "@requirement"],
"kind": "imp"
}
},
"codebeamer_url": "https://codebeamer.example.com/test"
}
You can also provide parameters to specify which markers should be extracted from which files.
Additionally, you need to provide the Codebeamer URL.
Examples:
```yaml
output:
component_tests.lobster:
markers:
- "@requirement"
kind: "req"
unit_tests.lobster:
markers:
- "@requiredby"
kind: "req"
other_tests.lobster:
markers: []
kind: ""
codebeamer_url: "https://codebeamer.com"
```
You can also include CPP files in the YAML configuration file.

```yaml
files:
- 'path/to/source1.cpp'
- 'path/to/source2.cpp'
```
Note: File paths are accepted only in single quotes.
## Copyright & License information
Expand Down
11 changes: 11 additions & 0 deletions tests-unit/lobster-cpptest/data/cpptest-config_1.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
output:
component_tests.lobster:
markers: ["@requirement", "@requiredby"]
kind: "req"

other_tests.lobster:
markers: []

kind: ""

codebeamer_url: "https://codebeamer.com"
17 changes: 17 additions & 0 deletions tests-unit/lobster-cpptest/data/cpptest-config_2.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
output:
component_tests.lobster:
markers:
- "@requirement"
kind: "req"

unit_tests.lobster:
markers:
- "@requiredby"
kind: "req"

other_tests.lobster:
markers: []

kind: ""

codebeamer_url: "https://codebeamer.com"
8 changes: 5 additions & 3 deletions tests-unit/lobster-cpptest/test_cpptest.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ def setUp(self):
self.test_case_file = str(Path(dirname(__file__), "data", "test_case.cpp"))
self.test_config_1 = str(Path(dirname(__file__), "data", "test_1.config"))
self.test_config_2 = str(Path(dirname(__file__), "data", "test_2.config"))
self.test_config_3 = str(Path(dirname(__file__), "data", "cpptest-config_1.yaml"))
self.test_config_4 = str(Path(dirname(__file__), "data", "cpptest-config_2.yaml"))

self.req_test_type = [RequirementTypes.REQS.value]
self.req_by_test_type = [RequirementTypes.REQ_BY.value]
Expand All @@ -45,7 +47,7 @@ def setUp(self):
self.component_test_lobster_file, self.other_test_lobster_file]

def test_parse_config_file_with_two_markers_for_two_outputs(self):
config_dict = parse_config_file(self.test_config_1)
config_dict = parse_config_file(self.test_config_4)
self.assertIsNotNone(config_dict)
self.assertIsInstance(config_dict, dict)
self.assertEqual(2, len(config_dict))
Expand Down Expand Up @@ -113,7 +115,7 @@ def test_parse_config_file_with_two_markers_for_two_outputs(self):
self.assertEqual('', other_test_kind_value)

def test_parse_config_file_with_two_markers_for_one_output(self):
config_dict = parse_config_file(self.test_config_2)
config_dict = parse_config_file(self.test_config_3)
self.assertIsNotNone(config_dict)
self.assertIsInstance(config_dict, dict)
self.assertEqual(2, len(config_dict))
Expand Down Expand Up @@ -304,7 +306,7 @@ def test_not_existing_file_dir(self):

def test_separate_output_config(self):
file_dir_list = [self.test_case_file]
config_dict: dict = parse_config_file(self.test_config_1)
config_dict: dict = parse_config_file(self.test_config_4)

lobster_cpptest(
file_dir_list=file_dir_list,
Expand Down

0 comments on commit c945916

Please sign in to comment.