From 4a7dc652f496b21b7cc2a98bcb214f3963f7cb8a Mon Sep 17 00:00:00 2001 From: "Tannaz Vahidi (ext.)" Date: Mon, 23 Sep 2024 14:50:38 +0200 Subject: [PATCH] apply review --- lobster/tools/coda/coda.py | 81 +++++-- lobster/tools/coda/parser/constants.py | 25 ++- .../tools/coda/parser/requirements_parser.py | 4 +- lobster/tools/coda/parser/test_case.py | 200 ++++++++++++------ lobster_adp_report.config | 8 - 5 files changed, 217 insertions(+), 101 deletions(-) delete mode 100644 lobster_adp_report.config diff --git a/lobster/tools/coda/coda.py b/lobster/tools/coda/coda.py index 59de9880..63ca180d 100644 --- a/lobster/tools/coda/coda.py +++ b/lobster/tools/coda/coda.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # # lobster_coda - Extract C/C++ tracing tags from commands for LOBSTER -# Copyright (C) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +# Copyright (C) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as @@ -68,7 +68,8 @@ def parse_config_file(file_name: str) -> dict: The configuration dictionary for coda must contain the OUTPUT key. 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 SUPPORTED_REQUIREMENTS. + The supported values for the MARKERS list are specified in + SUPPORTED_REQUIREMENTS. Parameters ---------- @@ -102,15 +103,18 @@ def parse_config_file(file_name: str) -> dict: for output_file, output_file_config_dict in output_config_dict.items(): if MARKERS not in output_file_config_dict.keys(): raise Exception(f'Please follow the right config file structure! ' - f'Missing attribute "{MARKERS}" for output file "{output_file}"') + f'Missing attribute "{MARKERS}" for output file ' + f'"{output_file}"') if KIND not in output_file_config_dict.keys(): raise Exception(f'Please follow the right config file structure! ' - f'Missing attribute "{KIND}" for output file "{output_file}"') + 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: if output_file_marker not in SUPPORTED_REQUIREMENTS: - raise Exception(f'"{output_file_marker}" is not a supported "{MARKERS}" value ' + raise Exception(f'"{output_file_marker}" is not a supported ' + f'"{MARKERS}" value ' f'for output file "{output_file}". ' f'Supported values are: "{supported_markers}"') @@ -121,14 +125,17 @@ def get_test_file_list(file_dir_list: list, extension_list: list) -> list: """ Gets the list of test files. - Given file names are added to the test file list without validating against the extension list. - From given directory names only file names will be added to the test file list if their extension matches - against the extension list. + Given file names are added to the test file list without + validating against the extension list. + From given directory names only file names will be added + to the test file list if their extension matches against + the extension list. Parameters ---------- file_dir_list : list - A list containing file names and/or directory names to parse for file names. + A list containing file names and/or directory names + to parse for file names. extension_list : list The list of file name extensions. @@ -178,13 +185,18 @@ def collect_test_cases_from_test_files(test_file_list: list) -> list: The list of test cases. """ parser = ParserForRequirements() - test_case_list = parser.collect_test_cases_for_test_files(test_files=test_file_list) + test_case_list = parser.collect_test_cases_for_test_files( + test_files=test_file_list + ) return test_case_list -def create_lobster_items_output_dict_from_test_cases(test_case_list: list, config_dict: dict) -> dict: +def create_lobster_items_output_dict_from_test_cases( + test_case_list: list, + config_dict: dict) -> dict: """ - Creates the lobster items dictionary for the given test cases grouped by configured output. + Creates the lobster items dictionary for the given test cases grouped by + configured output. Parameters ---------- @@ -196,7 +208,8 @@ def create_lobster_items_output_dict_from_test_cases(test_case_list: list, confi Returns ------- dict - The lobster items dictionary for the given test cases grouped by configured output. + The lobster items dictionary for the given test cases + grouped by configured output. """ prefix = os.getcwd() lobster_items_output_dict = {} @@ -235,17 +248,25 @@ def create_lobster_items_output_dict_from_test_cases(test_case_list: list, confi ) contains_no_tracing_target = True - for output_file_name, output_config_dict in marker_output_config_dict.items(): + for output_file_name, output_config_dict in ( + marker_output_config_dict.items()): tracing_target_list = [] tracing_target_kind = output_config_dict.get(KIND) for marker in output_config_dict.get(MARKERS): if marker not in map_test_type_to_key_name.keys(): continue - for test_case_marker_value in getattr(test_case, map_test_type_to_key_name.get(marker)): + for test_case_marker_value in getattr( + test_case, + map_test_type_to_key_name.get(marker) + ): if MISSING not in test_case_marker_value: - test_case_marker_value = test_case_marker_value.replace(CB_PREFIX, "") - tracing_target = Tracing_Tag(tracing_target_kind, test_case_marker_value) + test_case_marker_value = ( + test_case_marker_value.replace(CB_PREFIX, "")) + tracing_target = Tracing_Tag( + tracing_target_kind, + test_case_marker_value + ) tracing_target_list.append(tracing_target) if len(tracing_target_list) >= 1: @@ -254,10 +275,12 @@ def create_lobster_items_output_dict_from_test_cases(test_case_list: list, confi for tracing_target in tracing_target_list: lobster_item.add_tracing_target(tracing_target) - lobster_items_output_dict.get(output_file_name)[key] = lobster_item + lobster_items_output_dict.get(output_file_name)[key] = ( + lobster_item) if contains_no_tracing_target: - lobster_items_output_dict.get(no_marker_output_file_name)[key] = activity + lobster_items_output_dict.get(no_marker_output_file_name)[key] = ( + activity) return lobster_items_output_dict @@ -279,11 +302,22 @@ def write_lobster_items_output_dict(lobster_items_output_dict: dict): if output_file_name: with open(output_file_name, "w", encoding="UTF-8") as output_file: - lobster_write(output_file, Activity, LOBSTER_GENERATOR, lobster_items.values()) - print(f'Written {item_count} lobster items to "{output_file_name}".') + lobster_write( + output_file, + Activity, + LOBSTER_GENERATOR, + lobster_items.values() + ) + print(f'Written {item_count} lobster items to ' + f'"{output_file_name}".') else: - lobster_write(sys.stdout, Activity, LOBSTER_GENERATOR, lobster_items.values()) + lobster_write( + sys.stdout, + Activity, + LOBSTER_GENERATOR, + lobster_items.values() + ) print(f'Written {item_count} lobster items to stdout.') @@ -324,7 +358,8 @@ def lobster_coda(file_dir_list: list, config_dict: dict): def main(): """ - Main function to parse arguments, read configuration and launch lobster_coda. + Main function to parse arguments, read configuration + and launch lobster_coda. """ ap = argparse.ArgumentParser() ap.add_argument("files", diff --git a/lobster/tools/coda/parser/constants.py b/lobster/tools/coda/parser/constants.py index 9c220cea..9da10202 100644 --- a/lobster/tools/coda/parser/constants.py +++ b/lobster/tools/coda/parser/constants.py @@ -29,30 +29,39 @@ "TM_CONDITION", "TM_REQUIREMENT", "TM_TABLE", - "TM_BOUNDARY", ] # Regex -TEST_CASE_INTRO = re.compile(r"^\s*(" + "|".join(VALID_TEST_MACROS) + r")\s*\(") +TEST_CASE_INTRO = re.compile(r"^\s*(" + + "|".join(VALID_TEST_MACROS) + + r")\s*\(") TEST_CASE_INFO = re.compile( - r"^\s*(" + "|".join(VALID_TEST_MACROS) + r")\s*\(\s*(?P\w+),\s*(?P\w+)\)" + r"^\s*(" + "|".join(VALID_TEST_MACROS) + + r")\s*\(\s*(?P\w+),\s*(?P\w+)\)" ) CODEBEAMER_LINK = CODEBEMAER_URL + "/issue/" -REQUIREMENT = re.compile(r".*[@\\]requirement\s+([\s*/]*(((CB-#)|({}))\d+)\s*,?)+".format(CODEBEAMER_LINK)) +REQUIREMENT = re.compile(r".*[@\\]requirement\s+" + r"([\s*/]*(((CB-#)|({}))\d+)\s*,?)+" + .format(CODEBEAMER_LINK)) REQUIREMENT_TAG = r"(CB-#\d+)" -REQUIREMENT_TAG_HTTP = r"([@\\]requirement(\s+(CB-#\d+\s+)*({}\d+\s*,?\s*/*\*?)+)+)".format(CODEBEAMER_LINK) +REQUIREMENT_TAG_HTTP = ((r"([@\\]requirement(\s+" + r"(CB-#\d+\s+)*({}\d+\s*,?\s*/*\*?)+)+)") + .format(CODEBEAMER_LINK)) REQUIREMENT_TAG_HTTP_NAMED = r"({}(?P\d+))".format(CODEBEAMER_LINK) REQUIRED_BY = re.compile(r".*[@\\]requiredby\s+([\s*/]*(\w*::\w+),?\s*)+") REQUIRED_BY_TAG = r"(\w*::\w+)" DEFECT = re.compile( - r"(@defect\s+)(((?:(CB-#\d+)|(OCT-#\d+)),?\s*)+)" + r"(?:///|/)\s+(((?:(CB-#\d+)|(OCT-#\d+)),?\s)+)?" + r"(@defect\s+)(((?:(CB-#\d+)|(OCT-#\d+)),?\s*)+)" + + r"(?:///|/)\s+(((?:(CB-#\d+)|(OCT-#\d+)),?\s)+)?" ) BRIEF = re.compile(r"(@brief\s+)([^@]+)") VERSION = re.compile(r"(@version\s+)(\d+([,]? \d+)*)+") OCT_TAG = r"(OCT-#\d+)" TESTMETHODS = re.compile(r"(@testmethods\s+)([^@]+)") # unmatch whole testmethod if invalid method is used -# TESTMETHODS = re.compile(r"(@testmethods\s+)((" + "|".join(VALID_TESTMETHODS) + ")([,]? (" + "|".join(VALID_TESTMETHODS) + "))*)+") -TEST = re.compile(r"(@test\s+)([^@]+)") \ No newline at end of file +# TESTMETHODS = re.compile(r"(@testmethods\s+ +# )((" + "|".join(VALID_TESTMETHODS) + +# ")([,]? (" + "|".join(VALID_TESTMETHODS) + "))*)+") +TEST = re.compile(r"(@test\s+)([^@]+)") diff --git a/lobster/tools/coda/parser/requirements_parser.py b/lobster/tools/coda/parser/requirements_parser.py index 9a718e4d..dfbae759 100644 --- a/lobster/tools/coda/parser/requirements_parser.py +++ b/lobster/tools/coda/parser/requirements_parser.py @@ -1,5 +1,6 @@ """ -This script verifies if the test files of a given target contains @requirement tag or not +This script verifies if the test files of a given +target contains @requirement tag or not """ import logging from pathlib import Path @@ -65,4 +66,3 @@ def collect_test_cases(file: Path) -> List[TestCase]: if test_case: test_cases.append(test_case) return test_cases - diff --git a/lobster/tools/coda/parser/test_case.py b/lobster/tools/coda/parser/test_case.py index 686fdf4d..f0a9a7b2 100644 --- a/lobster/tools/coda/parser/test_case.py +++ b/lobster/tools/coda/parser/test_case.py @@ -1,49 +1,72 @@ import re from typing import List -from lobster.tools.coda.parser.constants import NON_EXISTING_INFO, TEST_CASE_INFO, \ - REQUIREMENT_TAG, REQUIREMENT_TAG_HTTP, REQUIRED_BY, REQUIREMENT, REQUIREMENT_TAG_HTTP_NAMED, REQUIRED_BY_TAG, \ - OCT_TAG, TEST, BRIEF, TESTMETHODS, VALID_TESTMETHODS, VERSION, TEST_CASE_INTRO, DEFECT +from lobster.tools.coda.parser.constants import ( + NON_EXISTING_INFO, TEST_CASE_INFO, REQUIREMENT_TAG, + REQUIREMENT_TAG_HTTP, REQUIRED_BY, REQUIREMENT, + REQUIREMENT_TAG_HTTP_NAMED, REQUIRED_BY_TAG, + OCT_TAG, TEST, BRIEF, TESTMETHODS, VALID_TESTMETHODS, + VERSION, TEST_CASE_INTRO, DEFECT) class TestCase: """ Class to represent a test case. - In case of a c/c++ file a test case is considered to be the combination of a - gtest macro, e.g. TEST(TestSuite, TestName) and its corresponding doxygen style documentation. - The documentation is assumed to contain references to requirements and related - test cases. + In case of a c/c++ file a test case is considered + to be the combination of a gtest macro, e.g. + TEST(TestSuite, TestName) and its corresponding doxygen + style documentation. + The documentation is assumed to contain references to + requirements and related test cases. Limitations on the tag usage: - - @requirement, @requiredby & @defect can be used multiple times in the test documentation and can be written on multiple lines - - @brief, @test, @testmethods and @version can be written on multiple lines but only used once as tag + - @requirement, @requiredby & @defect can be used multiple + times in the test documentation and can be written on + multiple lines + - @brief, @test, @testmethods and @version can be written + on multiple lines but only used once as tag """ def __init__(self, file: str, lines: List[str], start_idx: int): - self.file_name = file # File_name where the test case is located - self.suite_name = NON_EXISTING_INFO # TestSuite from TEST(TestSuite, TestName) - self.test_name = NON_EXISTING_INFO # TestName from TEST(TestSuite, TestName) - self.docu_start_line = 1 # First line of the doxygen style doc for the test case - self.docu_end_line = 1 # Last line of the doxygen style + # File_name where the test case is located + self.file_name = file + # TestSuite from TEST(TestSuite, TestName) + self.suite_name = NON_EXISTING_INFO + # TestName from TEST(TestSuite, TestName) + self.test_name = NON_EXISTING_INFO + # First line of the doxygen style doc for the test case + self.docu_start_line = 1 + # Last line of the doxygen style + self.docu_end_line = 1 + # First line of the implementation (typically the line + # TEST(TestSuite, TestName)) self.definition_start_line = ( - 1 # First line of the implementation (typically the line TEST(TestSuite, TestName)) + 1 ) - self.definition_end_line = 1 # Last line of the implementation - self.requirements = [] # List of @requirement values - self.required_by = [] # List of @requiredby values - self.defect_tracking_ids = [] # List of @defect values - self.version_id = [] # Content of @version - self.test = "" # Content of @test - self.testmethods = [] # Content of @testmethods - self.brief = "" # Content of @brief + # Last line of the implementation + self.definition_end_line = 1 + # List of @requirement values + self.requirements = [] + # List of @requiredby values + self.required_by = [] + # List of @defect values + self.defect_tracking_ids = [] + # Content of @version + self.version_id = [] + # Content of @test + self.test = "" + # Content of @testmethods + self.testmethods = [] + # Content of @brief + self.brief = "" self._set_test_details(lines, start_idx) def _set_test_details(self, lines, start_idx) -> None: """ - Parse the given range of lines for a valid test case. Missing information - are replaced by placeholders. + Parse the given range of lines for a valid test case. + Missing information are replaced by placeholders. file -- path to file that the following lines belong to lines -- lines to parse @@ -65,13 +88,15 @@ def _set_test_details(self, lines, start_idx) -> None: self.docu_start_line = self.docu_range[0] + 1 self.docu_end_line = self.docu_start_line - self.docu_lines = [line.strip() for line in lines[self.docu_range[0] : self.docu_range[1]]] + self.docu_lines = [line.strip() for line in + lines[self.docu_range[0]: self.docu_range[1]]] self.docu_lines = " ".join(self.docu_lines) self._set_base_attributes() def _definition_end(self, lines, start_idx, char=["{", "}"]) -> int: """ - Function to find the last line of test case defintion, i.e. the closing brace. + Function to find the last line of test case definition, + i.e. the closing brace. lines -- lines to parse start_idx -- index into lines where to start parsing @@ -99,21 +124,33 @@ def _set_test_and_suite_name(self, src) -> None: def _set_base_attributes(self) -> None: self._get_requirements_from_docu_lines( - REQUIREMENT, REQUIREMENT_TAG, REQUIREMENT_TAG_HTTP, REQUIREMENT_TAG_HTTP_NAMED + REQUIREMENT, + REQUIREMENT_TAG, + REQUIREMENT_TAG_HTTP, + REQUIREMENT_TAG_HTTP_NAMED ) - self.required_by = self._get_require_tags(REQUIRED_BY.search(self.docu_lines), REQUIRED_BY_TAG) + self.required_by = self._get_require_tags( + REQUIRED_BY.search(self.docu_lines), + REQUIRED_BY_TAG + ) defect_found = DEFECT.search(self.docu_lines) if defect_found: - defect_tracking_cb_ids = self._get_require_tags(defect_found, REQUIREMENT_TAG) + defect_tracking_cb_ids = self._get_require_tags( + defect_found, + REQUIREMENT_TAG + ) cb_list = sorted( [ defect_tracking_id.strip("CB-#") for defect_tracking_id in defect_tracking_cb_ids ] ) - defect_tracking_oct_ids = self._get_require_tags(defect_found, OCT_TAG) + defect_tracking_oct_ids = self._get_require_tags( + defect_found, + OCT_TAG + ) oct_list = sorted( [ defect_tracking_id.strip("CB-#") @@ -126,7 +163,10 @@ def _set_base_attributes(self) -> None: self.testmethods = self._get_testmethod_tag() self.brief = self._add_multiline_attribute(BRIEF) - def _get_requirements_from_docu_lines(self, general_pattern, tag, tag_http, tag_http_named): + def _get_requirements_from_docu_lines(self, + general_pattern, + tag, tag_http, + tag_http_named): """ Function to search for requirements from docu lines @@ -143,13 +183,21 @@ def _get_requirements_from_docu_lines(self, general_pattern, tag, tag_http, tag_ http_requirements = self._get_require_tags(search_result, tag_http) for requirements_listed_behind_one_tag in http_requirements: for requirement in requirements_listed_behind_one_tag: - requirement_uri = self._get_uri_from_requirement_detection(requirement, tag_http_named) - self._add_new_requirement_to_requirement_list(self, requirement_uri, tag_http_named) + requirement_uri = self._get_uri_from_requirement_detection( + requirement, + tag_http_named + ) + self._add_new_requirement_to_requirement_list( + self, + requirement_uri, + tag_http_named + ) def _get_testmethod_tag(self) -> List[str]: """ Returns a list of string of valid test methods - If a test method used in the tag is not valid, the value is dropped from the list + If a test method used in the tag is not valid, + the value is dropped from the list """ test_methods_list = [] test_methods = self._add_multiline_attribute(TESTMETHODS) @@ -162,7 +210,8 @@ def _get_testmethod_tag(self) -> List[str]: def _get_version_tag(self) -> List[int]: """ Returns a list of versions as int - If the number of version specified is less than the number of requirement linked, the last version + If the number of version specified is less + than the number of requirement linked, the last version of the list is added for all requirements """ versions = self._add_multiline_attribute(VERSION) @@ -178,7 +227,9 @@ def _add_multiline_attribute(self, pattern) -> str: field = "" found = pattern.search(self.docu_lines) if found: - field = found.group(2).replace("/", " ").replace("*", " ").replace(",", " ") if found else "" + field = (found.group(2).replace("/", " ") + .replace("*", " ") + .replace(",", " ")) if found else "" field = " ".join(field.split()) return field @@ -191,12 +242,21 @@ def is_line_commented(lines, start_idx) -> bool: @staticmethod def has_no_macro_or_commented(lines, start_idx) -> bool: - return TestCase.has_no_macro_or_commented_general(lines, start_idx, TestCase, TEST_CASE_INTRO) + return TestCase.has_no_macro_or_commented_general( + lines, + start_idx, + TestCase, + TEST_CASE_INTRO + ) @staticmethod - def has_no_macro_or_commented_general(lines, start_idx, case, case_intro) -> bool: + def has_no_macro_or_commented_general(lines, + start_idx, + case, + case_intro) -> bool: """ - Returns True is the test case does not start with an INTRO, or if the test case is commented out + Returns True is the test case does not start with + an INTRO, or if the test case is commented out """ line = lines[start_idx].strip() @@ -212,9 +272,13 @@ def has_no_macro_or_commented_general(lines, start_idx, case, case_intro) -> boo @staticmethod def is_special_case(lines, test_case) -> bool: - if TestCase.notracing_special_case(lines, (test_case.docu_start_line - 1, test_case.docu_end_line)): + if TestCase.notracing_special_case( + lines, + (test_case.docu_start_line - 1, test_case.docu_end_line) + ): return True - elif test_case.suite_name == NON_EXISTING_INFO or test_case.test_name == NON_EXISTING_INFO: + elif (test_case.suite_name == NON_EXISTING_INFO or + test_case.test_name == NON_EXISTING_INFO): return True return False @@ -223,8 +287,8 @@ def is_special_case(lines, test_case) -> bool: def try_parse(file, lines, start_idx): """ Function to parse the given range of lines for a valid test case. - If a valid test case is found a TestCase object is returned, otherwise None - is returned. + If a valid test case is found a TestCase object is returned, + otherwise None is returned. file -- path to file that the following lines belong to lines -- lines to parse @@ -236,8 +300,8 @@ def try_parse(file, lines, start_idx): def try_parse_general(file, lines, start_idx, case): """ Function to parse the given range of lines for a valid general case. - If a valid general case is found a Case object is returned, otherwise None - is returned. + If a valid general case is found a Case object is returned, + otherwise None is returned. file -- path to file that the following lines belong to lines -- lines to parse @@ -261,7 +325,8 @@ def _get_uri_from_requirement_detection(requirement, tag_http_named): Function to get uri itself (without @requirement or similar) requirement -- requirement candidate - tag_http_named -- http pattern to search for uri in requirement candidate + tag_http_named -- http pattern to search for uri in requirement + candidate """ if requirement == "": return None @@ -273,19 +338,30 @@ def _get_uri_from_requirement_detection(requirement, tag_http_named): return requirement_uri.group() @staticmethod - def _add_new_requirement_to_requirement_list(self, requirement_uri, tag_http_named): + def _add_new_requirement_to_requirement_list( + self, + requirement_uri, + tag_http_named + ): """ - Function to add new, non-None requirement to requirement list if not included yet + Function to add new, non-None requirement to requirement + list if not included yet requirement_uri -- uri to requirement - tag_http_named -- named http pattern to get requirement number itself + tag_http_named -- named http pattern to get requirement + number itself """ if requirement_uri is None: return else: - named_requirement_number_match = re.match(tag_http_named, requirement_uri) - requirement_number_dictionary = named_requirement_number_match.groupdict() - requirement_number = requirement_number_dictionary.get("number") + named_requirement_number_match = re.match( + tag_http_named, + requirement_uri + ) + requirement_number_dictionary = ( + named_requirement_number_match.groupdict()) + requirement_number = ( + requirement_number_dictionary.get("number")) requirement_cb = "CB-#" + requirement_number if requirement_cb not in self.requirements: self.requirements.append(requirement_cb) @@ -293,9 +369,10 @@ def _add_new_requirement_to_requirement_list(self, requirement_uri, tag_http_nam @staticmethod def _get_require_tags(match, filter_regex): """ - Function to filter the given re.match. The resulting list will only contain - the objects of the match that correspond to the filter. If the match is - empty an empty list is returned. + Function to filter the given re.match. The + resulting list will only contain the objects + of the match that correspond to the filter. + If the match is empty an empty list is returned. match -- re.match object filter_regex -- filter to apply to the match @@ -309,7 +386,10 @@ def _get_require_tags(match, filter_regex): @staticmethod def notracing_special_case(lines, the_range): notracing_tag = "NOTRACING" - return list(filter(lambda x: notracing_tag in x, lines[the_range[0]: the_range[1]])) + return list(filter( + lambda x: notracing_tag in x, + lines[the_range[0]: the_range[1]] + )) @staticmethod def get_range_for_doxygen_comments(lines, index_of_test_definition): @@ -322,8 +402,8 @@ def get_range_for_doxygen_comments(lines, index_of_test_definition): else: has_at_least_one_comment = False break - start_index = index_pointer if has_at_least_one_comment else index_pointer + 1 + start_index = index_pointer \ + if has_at_least_one_comment \ + else index_pointer + 1 doxygen_comments_line_range = (start_index, index_of_test_definition) return doxygen_comments_line_range - - diff --git a/lobster_adp_report.config b/lobster_adp_report.config deleted file mode 100644 index 171d1d29..00000000 --- a/lobster_adp_report.config +++ /dev/null @@ -1,8 +0,0 @@ -requirements "cb-req"{ - source: "codebeamer.lobster" with valid_status {"Draft", "Content Review", "Discarded", "Approved", "Cancelled", "In Translation"}; -} - -implementation "adp"{ - source: "adp.lobster"; - trace to: "cb-req"; -}