From 3bb2ffddfa6b703846722cb79887ee351ac7ab81 Mon Sep 17 00:00:00 2001 From: Matthew Burket Date: Wed, 14 Feb 2024 15:22:39 -0600 Subject: [PATCH 1/3] Add new test cces-removed.py This test ensures that any assigned CCE isn't in the respective avail file. --- tests/CMakeLists.txt | 17 +++++++++++ tests/cces-removed.py | 68 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+) create mode 100755 tests/cces-removed.py diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 78344868f7c..37bf905db8b 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -105,6 +105,7 @@ endmacro() mypy_test("utils/import_srg_spreadsheet.py" "normal") mypy_test("utils/check_eof.py" "normal") +mypy_test("tests/cces-removed.py" "normal") if(PYTHON_VERSION_MAJOR GREATER 2 AND PYTHON_VERSION_MINOR GREATER 7 AND PY_TRESTLE AND PY_LXML) mypy_test("utils/oscal/" "skip") @@ -326,3 +327,19 @@ add_test( COMMAND env "PYTHONPATH=$ENV{PYTHONPATH}" "${PYTHON_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/test_components.py" --build-dir "${CMAKE_BINARY_DIR}" --source-dir "${CMAKE_SOURCE_DIR}" --product "rhel9" ) endif() + +macro(cce_avail_check TEST_NAME_SUFFIX PRODUCTS CCE_LIST_PATH) + if(PYTHON_VERSION_MAJOR GREATER 2) + add_test( + NAME "cce_avail_check-${TEST_NAME_SUFFIX}" + COMMAND env "PYTHONPATH=$ENV{PYTHONPATH}" "${PYTHON_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/cces-removed.py" --root "${CMAKE_SOURCE_DIR}" --json "${CMAKE_SOURCE_DIR}/build/rule_dirs.json" --products "${PRODUCTS}" --cee-list "${CCE_LIST_PATH}" + ) + set_tests_properties("cce_avail_check-${TEST_NAME_SUFFIX}" PROPERTIES FIXTURES_REQUIRED "rule-dir-json") + set_tests_properties("cce_avail_check-${TEST_NAME_SUFFIX}" PROPERTIES DEPENDS "test-rule-dir-json") + set_tests_properties("cce_avail_check-${TEST_NAME_SUFFIX}" PROPERTIES LABELS quick) + endif() +endmacro() + +cce_avail_check("rhel-all" "rhel7,rhel8,rhel9" "${CMAKE_SOURCE_DIR}/shared/references/cce-redhat-avail.txt") +cce_avail_check("sle12" "sle12" "${CMAKE_SOURCE_DIR}/shared/references/cce-sle12-avail.txt") +cce_avail_check("sle15" "sle15" "${CMAKE_SOURCE_DIR}/shared/references/cce-sle12-avail.txt") diff --git a/tests/cces-removed.py b/tests/cces-removed.py new file mode 100755 index 00000000000..abef74203f1 --- /dev/null +++ b/tests/cces-removed.py @@ -0,0 +1,68 @@ +#! /usr/bin/python3 + +import argparse +import json +import os +from typing import Set +import sys + +SSG_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "..")) +JSON_PATH = os.path.join(SSG_ROOT, "build", "rule_dirs.json") + + +def _parse_args() -> argparse.Namespace: + parser = argparse.ArgumentParser( + description="Given a list of products and CCE available list error and output if an " + "assigned CCE is in the available list. This scripts needs rule_dirs.json to " + "run.") + parser.add_argument('-p', '--products', required=True, + help='Comma separated list (no spaces) of products to check') + parser.add_argument('-l', '--cee-list', type=str, required=True, + help='Path to cce avail list') + parser.add_argument('-j', '--json', type=str, default=JSON_PATH, + help='Path to rule_dirs.json file') + parser.add_argument('-r', '--root', type=str, default=SSG_ROOT, + help='Path to the root of the content repo') + return parser.parse_args() + + +def _get_cces_in_use(data, products) -> Set[str]: + cces_in_use: Set[str] = set() + for rule_id, rule_obj in data.items(): + for identifier_key, identifier_value in rule_obj['identifiers'].items(): + for product in products.split(","): + if identifier_key.endswith(product): + cces_in_use.add(identifier_value) + return cces_in_use + + +def _get_avail_cces(args) -> Set[str]: + avail_cces: Set[str] = set() + with open(args.cee_list) as f: + for line in f.readlines(): + avail_cces.add(line.strip()) + return avail_cces + + +def main(): + args = _parse_args() + products = args.products + with open(args.json) as f: + data = json.load(f) + cces_in_use = _get_cces_in_use(data, products) + + if len(cces_in_use) == 0: + print(f"Test is useless, no CCEs were found for products in {','.join(products)}") + exit(2) + + avail_cces = _get_avail_cces(args) + + not_removed = avail_cces.intersection(cces_in_use) + if len(not_removed) != 0: + for cce in not_removed: + print(f"CCE {cce} not removed from {args.cee_list}.", file=sys.stderr) + exit(1) + + +if __name__ == '__main__': + main() From 495176385e0bf731b23b5fa8239179629fa6c234 Mon Sep 17 00:00:00 2001 From: Matthew Burket Date: Wed, 14 Feb 2024 16:05:17 -0600 Subject: [PATCH 2/3] Code climate fix for tests/cces-removed.py --- tests/cces-removed.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/tests/cces-removed.py b/tests/cces-removed.py index abef74203f1..c13ae7e0c6e 100755 --- a/tests/cces-removed.py +++ b/tests/cces-removed.py @@ -26,13 +26,17 @@ def _parse_args() -> argparse.Namespace: return parser.parse_args() +def _process_rule(cces_in_use, products, rule_obj): + for identifier_key, identifier_value in rule_obj['identifiers'].items(): + for product in products.split(","): + if identifier_key.endswith(product): + cces_in_use.add(identifier_value) + + def _get_cces_in_use(data, products) -> Set[str]: cces_in_use: Set[str] = set() for rule_id, rule_obj in data.items(): - for identifier_key, identifier_value in rule_obj['identifiers'].items(): - for product in products.split(","): - if identifier_key.endswith(product): - cces_in_use.add(identifier_value) + _process_rule(cces_in_use, products, rule_obj) return cces_in_use From dc857413785cc1d3c5cf5945c7d58ec3eb5f06d9 Mon Sep 17 00:00:00 2001 From: Matthew Burket Date: Thu, 15 Feb 2024 07:39:58 -0600 Subject: [PATCH 3/3] Fix reviewer comments in #11590 --- tests/CMakeLists.txt | 4 ++-- tests/cces-removed.py | 20 ++++++++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 37bf905db8b..7f5d559b376 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -332,7 +332,7 @@ macro(cce_avail_check TEST_NAME_SUFFIX PRODUCTS CCE_LIST_PATH) if(PYTHON_VERSION_MAJOR GREATER 2) add_test( NAME "cce_avail_check-${TEST_NAME_SUFFIX}" - COMMAND env "PYTHONPATH=$ENV{PYTHONPATH}" "${PYTHON_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/cces-removed.py" --root "${CMAKE_SOURCE_DIR}" --json "${CMAKE_SOURCE_DIR}/build/rule_dirs.json" --products "${PRODUCTS}" --cee-list "${CCE_LIST_PATH}" + COMMAND env "PYTHONPATH=$ENV{PYTHONPATH}" "${PYTHON_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/cces-removed.py" --root "${CMAKE_SOURCE_DIR}" --json "${CMAKE_SOURCE_DIR}/build/rule_dirs.json" --products "${PRODUCTS}" --cce-list "${CCE_LIST_PATH}" ) set_tests_properties("cce_avail_check-${TEST_NAME_SUFFIX}" PROPERTIES FIXTURES_REQUIRED "rule-dir-json") set_tests_properties("cce_avail_check-${TEST_NAME_SUFFIX}" PROPERTIES DEPENDS "test-rule-dir-json") @@ -342,4 +342,4 @@ endmacro() cce_avail_check("rhel-all" "rhel7,rhel8,rhel9" "${CMAKE_SOURCE_DIR}/shared/references/cce-redhat-avail.txt") cce_avail_check("sle12" "sle12" "${CMAKE_SOURCE_DIR}/shared/references/cce-sle12-avail.txt") -cce_avail_check("sle15" "sle15" "${CMAKE_SOURCE_DIR}/shared/references/cce-sle12-avail.txt") +cce_avail_check("sle15" "sle15" "${CMAKE_SOURCE_DIR}/shared/references/cce-sle15-avail.txt") diff --git a/tests/cces-removed.py b/tests/cces-removed.py index c13ae7e0c6e..d4705dfd1aa 100755 --- a/tests/cces-removed.py +++ b/tests/cces-removed.py @@ -1,10 +1,10 @@ -#! /usr/bin/python3 +#!/usr/bin/python3 import argparse import json import os -from typing import Set import sys +from typing import Set SSG_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "..")) JSON_PATH = os.path.join(SSG_ROOT, "build", "rule_dirs.json") @@ -17,7 +17,7 @@ def _parse_args() -> argparse.Namespace: "run.") parser.add_argument('-p', '--products', required=True, help='Comma separated list (no spaces) of products to check') - parser.add_argument('-l', '--cee-list', type=str, required=True, + parser.add_argument('-l', '--cce-list', type=str, required=True, help='Path to cce avail list') parser.add_argument('-j', '--json', type=str, default=JSON_PATH, help='Path to rule_dirs.json file') @@ -26,23 +26,23 @@ def _parse_args() -> argparse.Namespace: return parser.parse_args() -def _process_rule(cces_in_use, products, rule_obj): +def _process_rule(cces_in_use: Set[str], products: str, rule_obj: dict): for identifier_key, identifier_value in rule_obj['identifiers'].items(): for product in products.split(","): if identifier_key.endswith(product): cces_in_use.add(identifier_value) -def _get_cces_in_use(data, products) -> Set[str]: +def _get_cces_in_use(data: dict, products: str) -> Set[str]: cces_in_use: Set[str] = set() - for rule_id, rule_obj in data.items(): + for _, rule_obj in data.items(): _process_rule(cces_in_use, products, rule_obj) return cces_in_use -def _get_avail_cces(args) -> Set[str]: +def _get_avail_cces(cce_list: str) -> Set[str]: avail_cces: Set[str] = set() - with open(args.cee_list) as f: + with open(cce_list) as f: for line in f.readlines(): avail_cces.add(line.strip()) return avail_cces @@ -59,12 +59,12 @@ def main(): print(f"Test is useless, no CCEs were found for products in {','.join(products)}") exit(2) - avail_cces = _get_avail_cces(args) + avail_cces = _get_avail_cces(args.cce_list) not_removed = avail_cces.intersection(cces_in_use) if len(not_removed) != 0: for cce in not_removed: - print(f"CCE {cce} not removed from {args.cee_list}.", file=sys.stderr) + print(f"CCE {cce} not removed from {args.cce_list}.", file=sys.stderr) exit(1)