troubadix 25.7.0__tar.gz → 25.7.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {troubadix-25.7.0 → troubadix-25.7.2}/PKG-INFO +1 -1
- {troubadix-25.7.0 → troubadix-25.7.2}/pyproject.toml +1 -1
- troubadix-25.7.2/tests/helper/test_if_block_parser.py +216 -0
- troubadix-25.7.2/tests/helper/test_remove_comments.py +81 -0
- troubadix-25.7.2/tests/helper/test_text_utils.py +168 -0
- troubadix-25.7.2/tests/manual_tests/comment_removal_diff.py +62 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_using_display.py +52 -15
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_valid_oid.py +15 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/standalone_plugins/test_dependency_graph.py +77 -57
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/standalone_plugins/test_file_extensions.py +14 -13
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/__version__.py +1 -1
- troubadix-25.7.2/troubadix/helper/if_block_parser.py +200 -0
- troubadix-25.7.2/troubadix/helper/remove_comments.py +39 -0
- troubadix-25.7.2/troubadix/helper/text_utils.py +80 -0
- troubadix-25.7.2/troubadix/plugins/using_display.py +110 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/plugins/valid_oid.py +2 -2
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/standalone_plugins/dependency_graph/dependency_graph.py +12 -14
- troubadix-25.7.0/troubadix/plugins/using_display.py +0 -121
- {troubadix-25.7.0 → troubadix-25.7.2}/LICENSE +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/README.md +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/__init__.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/helper/__init__.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/helper/test_date_format.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/helper/test_linguistic_exception_handler.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/helper/test_patterns.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/__init__.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/fail.nasl +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/fail2.nasl +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test.nasl +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_badwords.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_copyright_text.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_copyright_year.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_creation_date.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_cve_format.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_cvss_format.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_dependencies.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_dependency_category_order.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_deprecated_dependency.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_deprecated_functions.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_double_end_points.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_duplicate_oid.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_duplicated_script_tags.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_encoding.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_files/fail_bad_new_line.nasl +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_files/fail_badwords.nasl +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_files/fail_name_and_copyright_newline.nasl +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_files/fail_name_newline.nasl +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_files/fail_permissions.nasl +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_files/fail_spelling.nasl +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_files/nasl/21.04/fail.nasl +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_files/nasl/21.04/fail_badwords.nasl +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_files/nasl/21.04/fail_name_and_copyright_newline.nasl +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_files/nasl/21.04/fail_name_newline.nasl +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_files/nasl/21.04/fail_solution_template.nasl +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_files/nasl/21.04/runner/fail.nasl +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_files/nasl/21.04/runner/fail2.nasl +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_files/nasl/21.04/runner/test.nasl +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_files/nasl/21.04/runner/test_valid_oid.nasl +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_files/nasl/21.04/test.inc +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_files/nasl/21.04/test.nasl +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_files/nasl/warning.nasl +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_files/ok_permissions.nasl +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_files/test_oid.nasl +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_forking_nasl_functions.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_get_kb_on_services.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_grammar.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_http_links_in_tags.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_illegal_characters.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_log_messages.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_malformed_dependencies.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_misplaced_compare_in_if.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_missing_desc_exit.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_missing_tag_solution.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_multiple_re_parameters.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_newlines.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_overlong_description_lines.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_overlong_script_tags.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_prod_svc_detect_in_vulnvt.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_qod.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_reporting_consistency.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_script_add_preference_type.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_script_calls_empty_values.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_script_calls_recommended.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_script_category.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_script_copyright.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_script_family.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_script_tag_form.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_script_tag_whitespaces.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_script_tags_mandatory.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_script_version_and_last_modification_tags.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_script_xref_form.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_script_xref_url.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_security_messages.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_set_get_kb_calls.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_severity_date.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_severity_format.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_severity_origin.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_solution_text.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_solution_type.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_spaces_before_dots.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_spaces_in_filename.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_spelling.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_tabs.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_todo_tbd.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_trailing_spaces_tabs.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_valid_script_tag_names.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_variable_redefinition_in_foreach.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_vt_file_permissions.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/plugins/test_vt_placement.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/standalone_plugins/__init__.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/standalone_plugins/changed_packages/__init__.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/standalone_plugins/changed_packages/markers/__init__.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/standalone_plugins/changed_packages/markers/test_added_epoch.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/standalone_plugins/changed_packages/markers/test_added_release.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/standalone_plugins/changed_packages/markers/test_added_udeb.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/standalone_plugins/changed_packages/markers/test_changed_update.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/standalone_plugins/changed_packages/markers/test_dropped_architecture.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/standalone_plugins/changed_packages/test_changed_packages.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/standalone_plugins/changed_packages/test_package.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/standalone_plugins/nasl/21.04/21_script.nasl +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/standalone_plugins/nasl/22.04/22_script.nasl +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/standalone_plugins/nasl/common/bar.nasl +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/standalone_plugins/nasl/common/foo.nasl +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/standalone_plugins/nasl/common/foobar.nasl +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/standalone_plugins/nasl/common/gsf/enterprise_script.nasl +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/standalone_plugins/test_changed_creation_date.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/standalone_plugins/test_changed_cves.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/standalone_plugins/test_changed_oid.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/standalone_plugins/test_deprecate_vts.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/standalone_plugins/test_last_modification.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/standalone_plugins/test_no_solution.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/standalone_plugins/test_version_updated.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/test_argparser.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/test_helper.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/test_naslinter.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/test_reporter.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/test_results.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/tests/test_runner.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/__init__.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/argparser.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/codespell/codespell.additions +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/codespell/codespell.exclude +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/codespell/codespell.ignore +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/helper/__init__.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/helper/date_format.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/helper/helper.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/helper/linguistic_exception_handler.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/helper/patterns.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/plugin.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/plugins/__init__.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/plugins/badwords.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/plugins/copyright_text.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/plugins/copyright_year.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/plugins/creation_date.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/plugins/cve_format.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/plugins/cvss_format.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/plugins/dependencies.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/plugins/dependency_category_order.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/plugins/deprecated_dependency.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/plugins/deprecated_functions.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/plugins/double_end_points.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/plugins/duplicate_oid.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/plugins/duplicated_script_tags.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/plugins/encoding.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/plugins/forking_nasl_functions.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/plugins/get_kb_on_services.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/plugins/grammar.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/plugins/http_links_in_tags.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/plugins/illegal_characters.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/plugins/log_messages.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/plugins/malformed_dependencies.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/plugins/misplaced_compare_in_if.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/plugins/missing_desc_exit.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/plugins/missing_tag_solution.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/plugins/multiple_re_parameters.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/plugins/newlines.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/plugins/overlong_description_lines.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/plugins/overlong_script_tags.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/plugins/prod_svc_detect_in_vulnvt.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/plugins/qod.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/plugins/reporting_consistency.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/plugins/script_add_preference_type.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/plugins/script_calls_empty_values.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/plugins/script_calls_recommended.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/plugins/script_category.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/plugins/script_copyright.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/plugins/script_family.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/plugins/script_tag_form.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/plugins/script_tag_whitespaces.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/plugins/script_tags_mandatory.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/plugins/script_version_and_last_modification_tags.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/plugins/script_xref_form.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/plugins/script_xref_url.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/plugins/security_messages.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/plugins/set_get_kb_calls.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/plugins/severity_date.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/plugins/severity_format.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/plugins/severity_origin.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/plugins/solution_text.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/plugins/solution_type.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/plugins/spaces_before_dots.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/plugins/spaces_in_filename.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/plugins/spelling.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/plugins/tabs.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/plugins/todo_tbd.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/plugins/trailing_spaces_tabs.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/plugins/valid_script_tag_names.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/plugins/variable_assigned_in_if.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/plugins/variable_redefinition_in_foreach.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/plugins/vt_file_permissions.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/plugins/vt_placement.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/reporter.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/results.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/runner.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/standalone_plugins/__init__.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/standalone_plugins/allowed_rev_diff.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/standalone_plugins/changed_creation_date.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/standalone_plugins/changed_cves.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/standalone_plugins/changed_oid.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/standalone_plugins/changed_packages/changed_packages.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/standalone_plugins/changed_packages/marker/__init__.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/standalone_plugins/changed_packages/marker/added_epoch.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/standalone_plugins/changed_packages/marker/added_release.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/standalone_plugins/changed_packages/marker/added_udeb.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/standalone_plugins/changed_packages/marker/changed_update.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/standalone_plugins/changed_packages/marker/dropped_architecture.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/standalone_plugins/changed_packages/marker/marker.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/standalone_plugins/changed_packages/package.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/standalone_plugins/common.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/standalone_plugins/dependency_graph/__init__.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/standalone_plugins/dependency_graph/checks.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/standalone_plugins/dependency_graph/cli.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/standalone_plugins/dependency_graph/models.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/standalone_plugins/deprecate_vts.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/standalone_plugins/file_extensions.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/standalone_plugins/last_modification.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/standalone_plugins/no_solution.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/standalone_plugins/util.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/standalone_plugins/version_updated.py +0 -0
- {troubadix-25.7.0 → troubadix-25.7.2}/troubadix/troubadix.py +0 -0
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
2
|
+
# SPDX-FileCopyrightText: 2025 Greenbone AG
|
|
3
|
+
|
|
4
|
+
import unittest
|
|
5
|
+
|
|
6
|
+
from troubadix.helper.if_block_parser import find_if_statements
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class FindIfStatementsTestCase(unittest.TestCase):
|
|
10
|
+
def test_empty_input(self):
|
|
11
|
+
result = find_if_statements("")
|
|
12
|
+
self.assertEqual(len(result), 0)
|
|
13
|
+
|
|
14
|
+
def test_inline_single_expression(self):
|
|
15
|
+
content = 'if(TRUE) display("inline");'
|
|
16
|
+
result = find_if_statements(content)
|
|
17
|
+
|
|
18
|
+
self.assertEqual(1, len(result))
|
|
19
|
+
self.assertEqual("TRUE", result[0].condition)
|
|
20
|
+
self.assertEqual('display("inline")', result[0].statement)
|
|
21
|
+
# Check that position is correct (start at 'if', end at semicolon)
|
|
22
|
+
self.assertEqual(0, result[0].if_start)
|
|
23
|
+
self.assertEqual(len(content), result[0].if_end)
|
|
24
|
+
|
|
25
|
+
def test_single_line_with_newline(self):
|
|
26
|
+
content = 'if(TRUE)\n display("single line");'
|
|
27
|
+
result = find_if_statements(content)
|
|
28
|
+
|
|
29
|
+
self.assertEqual(1, len(result))
|
|
30
|
+
self.assertEqual("TRUE", result[0].condition)
|
|
31
|
+
self.assertEqual('display("single line")', result[0].statement)
|
|
32
|
+
|
|
33
|
+
def test_standard_block(self):
|
|
34
|
+
content = 'if(TRUE) {\n display("block");\n}'
|
|
35
|
+
result = find_if_statements(content)
|
|
36
|
+
|
|
37
|
+
self.assertEqual(1, len(result))
|
|
38
|
+
self.assertEqual("TRUE", result[0].condition)
|
|
39
|
+
self.assertEqual('display("block");', result[0].statement)
|
|
40
|
+
# Check position spans from 'if' to the closing brace
|
|
41
|
+
self.assertEqual(0, result[0].if_start)
|
|
42
|
+
self.assertEqual(len(content), result[0].if_end)
|
|
43
|
+
|
|
44
|
+
def test_block_brace_on_newline(self):
|
|
45
|
+
content = 'if(TRUE)\n{\n display("block");\n}'
|
|
46
|
+
result = find_if_statements(content)
|
|
47
|
+
|
|
48
|
+
self.assertEqual(1, len(result))
|
|
49
|
+
self.assertEqual("TRUE", result[0].condition)
|
|
50
|
+
self.assertEqual('display("block");', result[0].statement)
|
|
51
|
+
|
|
52
|
+
def test_empty_block(self):
|
|
53
|
+
content = "if(TRUE)\n{\n}"
|
|
54
|
+
result = find_if_statements(content)
|
|
55
|
+
|
|
56
|
+
self.assertEqual(1, len(result))
|
|
57
|
+
self.assertEqual("TRUE", result[0].condition)
|
|
58
|
+
self.assertEqual("", result[0].statement.strip())
|
|
59
|
+
|
|
60
|
+
def test_compact_block(self):
|
|
61
|
+
content = "if(TRUE){}"
|
|
62
|
+
result = find_if_statements(content)
|
|
63
|
+
|
|
64
|
+
self.assertEqual(1, len(result))
|
|
65
|
+
self.assertEqual("TRUE", result[0].condition)
|
|
66
|
+
self.assertEqual("", result[0].statement)
|
|
67
|
+
|
|
68
|
+
def test_multiple_if_statements(self):
|
|
69
|
+
content = """
|
|
70
|
+
if(cond1) display("one");
|
|
71
|
+
if(cond2) {
|
|
72
|
+
display("two");
|
|
73
|
+
}
|
|
74
|
+
if(cond3)
|
|
75
|
+
display("three");
|
|
76
|
+
"""
|
|
77
|
+
result = find_if_statements(content)
|
|
78
|
+
self.assertEqual(3, len(result))
|
|
79
|
+
|
|
80
|
+
self.assertEqual("cond1", result[0].condition)
|
|
81
|
+
self.assertEqual('display("one")', result[0].statement)
|
|
82
|
+
|
|
83
|
+
self.assertEqual("cond2", result[1].condition)
|
|
84
|
+
self.assertEqual('display("two");', result[1].statement)
|
|
85
|
+
|
|
86
|
+
self.assertEqual("cond3", result[2].condition)
|
|
87
|
+
self.assertEqual('display("three")', result[2].statement)
|
|
88
|
+
|
|
89
|
+
def test_nested_if_statements(self):
|
|
90
|
+
content = """
|
|
91
|
+
if(outer) {
|
|
92
|
+
if(inner1) {
|
|
93
|
+
display("nested block");
|
|
94
|
+
}
|
|
95
|
+
if(inner2) display("nested inline");
|
|
96
|
+
}
|
|
97
|
+
"""
|
|
98
|
+
result = find_if_statements(content)
|
|
99
|
+
self.assertEqual(3, len(result))
|
|
100
|
+
|
|
101
|
+
self.assertEqual("outer", result[0].condition)
|
|
102
|
+
self.assertIn("if(inner1)", result[0].statement)
|
|
103
|
+
self.assertIn("if(inner2)", result[0].statement)
|
|
104
|
+
|
|
105
|
+
self.assertEqual("inner1", result[1].condition)
|
|
106
|
+
self.assertIn('display("nested block")', result[1].statement)
|
|
107
|
+
|
|
108
|
+
self.assertEqual("inner2", result[2].condition)
|
|
109
|
+
self.assertEqual('display("nested inline")', result[2].statement)
|
|
110
|
+
|
|
111
|
+
def test_complex_condition(self):
|
|
112
|
+
content = (
|
|
113
|
+
'if (a == 1 && b > 2 || c != "string") { display("complex"); }'
|
|
114
|
+
)
|
|
115
|
+
result = find_if_statements(content)
|
|
116
|
+
|
|
117
|
+
self.assertEqual(1, len(result))
|
|
118
|
+
self.assertEqual(
|
|
119
|
+
'a == 1 && b > 2 || c != "string"', result[0].condition
|
|
120
|
+
)
|
|
121
|
+
self.assertEqual('display("complex");', result[0].statement)
|
|
122
|
+
|
|
123
|
+
def test_if_with_problematic_stuff(self):
|
|
124
|
+
# escape single quote and backslash, function call in condition
|
|
125
|
+
content = r"if(some_func('\'\\')) display('\'test\\');"
|
|
126
|
+
result = find_if_statements(content)
|
|
127
|
+
|
|
128
|
+
self.assertEqual(1, len(result))
|
|
129
|
+
self.assertEqual(r"some_func('\'\\')", result[0].condition)
|
|
130
|
+
self.assertEqual(r"display('\'test\\')", result[0].statement)
|
|
131
|
+
|
|
132
|
+
def test_unclosed_parenthesis(self):
|
|
133
|
+
content = "if(unclosed condition\ndisplay();"
|
|
134
|
+
with self.assertRaises(ValueError) as cm:
|
|
135
|
+
find_if_statements(content)
|
|
136
|
+
self.assertEqual(
|
|
137
|
+
"Unclosed parenthesis in if statement at line 1",
|
|
138
|
+
str(cm.exception),
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
def test_no_statement_after_condition(self):
|
|
142
|
+
content = "if(condition)"
|
|
143
|
+
with self.assertRaises(ValueError) as cm:
|
|
144
|
+
find_if_statements(content)
|
|
145
|
+
self.assertEqual(
|
|
146
|
+
"Missing statement after if condition at line 1",
|
|
147
|
+
str(cm.exception),
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
def test_useless_semicolon(self):
|
|
151
|
+
content = "if(condition);"
|
|
152
|
+
with self.assertRaises(ValueError) as cm:
|
|
153
|
+
find_if_statements(content)
|
|
154
|
+
self.assertEqual(
|
|
155
|
+
"Semicolon after if condition at line 1 makes following block always execute."
|
|
156
|
+
" Remove semicolon to fix.",
|
|
157
|
+
str(cm.exception),
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
def test_unclosed_block_brace(self):
|
|
161
|
+
content = "if(condition) {\ndisplay();\n# Missing closing brace"
|
|
162
|
+
with self.assertRaises(ValueError) as cm:
|
|
163
|
+
find_if_statements(content)
|
|
164
|
+
self.assertEqual(
|
|
165
|
+
"Unclosed brace in if statement at line 1",
|
|
166
|
+
str(cm.exception),
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
def test_no_semicolon_in_single_expression(self):
|
|
170
|
+
content = "if(condition) display()" # Missing semicolon
|
|
171
|
+
with self.assertRaises(ValueError) as cm:
|
|
172
|
+
find_if_statements(content)
|
|
173
|
+
self.assertEqual(
|
|
174
|
+
"Missing expression after if condition at line 1",
|
|
175
|
+
str(cm.exception),
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
def test_complex_condition_with_unmatched_brace(self):
|
|
179
|
+
content = "if(func(1, 2) || check(a) { display(); }" # Missing closing ) in condition
|
|
180
|
+
with self.assertRaises(ValueError) as cm:
|
|
181
|
+
find_if_statements(content)
|
|
182
|
+
self.assertEqual(
|
|
183
|
+
"Unclosed parenthesis in if statement at line 1",
|
|
184
|
+
str(cm.exception),
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
def test_position_info_in_error_message(self):
|
|
188
|
+
content = "# Some comment\nif(bad) something" # No semicolon
|
|
189
|
+
with self.assertRaises(ValueError) as cm:
|
|
190
|
+
find_if_statements(content)
|
|
191
|
+
error_msg = str(cm.exception)
|
|
192
|
+
self.assertIn("at line 2", error_msg)
|
|
193
|
+
|
|
194
|
+
def test_condition_and_statement_positions_block(self):
|
|
195
|
+
content = 'if(TRUE) {\n display("block");\n}'
|
|
196
|
+
result = find_if_statements(content)
|
|
197
|
+
|
|
198
|
+
self.assertEqual(1, len(result))
|
|
199
|
+
# Check condition position (inside parentheses)
|
|
200
|
+
self.assertEqual(3, result[0].condition_start)
|
|
201
|
+
self.assertEqual(7, result[0].condition_end)
|
|
202
|
+
# Check statement position (inside braces)
|
|
203
|
+
self.assertEqual(10, result[0].statement_start)
|
|
204
|
+
self.assertEqual(31, result[0].statement_end)
|
|
205
|
+
|
|
206
|
+
def test_condition_and_statement_positions_single(self):
|
|
207
|
+
content = 'if(num > 5) display("inline");'
|
|
208
|
+
result = find_if_statements(content)
|
|
209
|
+
|
|
210
|
+
self.assertEqual(1, len(result))
|
|
211
|
+
# Check condition position (inside parentheses)
|
|
212
|
+
self.assertEqual(3, result[0].condition_start)
|
|
213
|
+
self.assertEqual(10, result[0].condition_end)
|
|
214
|
+
# Check statement position (after parenthesis to semicolon)
|
|
215
|
+
self.assertEqual(12, result[0].statement_start)
|
|
216
|
+
self.assertEqual(29, result[0].statement_end)
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
2
|
+
# SPDX-FileCopyrightText: 2025 Greenbone AG
|
|
3
|
+
|
|
4
|
+
import unittest
|
|
5
|
+
|
|
6
|
+
from troubadix.helper.remove_comments import remove_comments
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class RemoveCommentsTestCase(unittest.TestCase):
|
|
10
|
+
def test_empty_string(self):
|
|
11
|
+
input_content = ""
|
|
12
|
+
expected_output = ""
|
|
13
|
+
self.assertEqual(remove_comments(input_content), expected_output)
|
|
14
|
+
|
|
15
|
+
def test_no_comments(self):
|
|
16
|
+
input_content = (
|
|
17
|
+
"function detect_archlinux(sock, port, SCRIPT_DESC, is_pfsense) {"
|
|
18
|
+
)
|
|
19
|
+
expected_output = input_content
|
|
20
|
+
self.assertEqual(remove_comments(input_content), expected_output)
|
|
21
|
+
|
|
22
|
+
def test_full_line_comments(self):
|
|
23
|
+
input_content = "# comment\nfunction hello() {\n # Another comment\n return 42;"
|
|
24
|
+
expected_output = "\nfunction hello() {\n\n return 42;"
|
|
25
|
+
self.assertEqual(remove_comments(input_content), expected_output)
|
|
26
|
+
|
|
27
|
+
def test_inline_comments(self):
|
|
28
|
+
input_content = (
|
|
29
|
+
"function hello(){ # A function\n return 42; # The answer"
|
|
30
|
+
)
|
|
31
|
+
expected_output = "function hello(){ \n return 42; "
|
|
32
|
+
self.assertEqual(remove_comments(input_content), expected_output)
|
|
33
|
+
|
|
34
|
+
def test_hash_in_strings(self):
|
|
35
|
+
input_content = "message = 'This # is not a comment';\nurl = \"http://example.com/#anchor\";"
|
|
36
|
+
expected_output = input_content
|
|
37
|
+
self.assertEqual(remove_comments(input_content), expected_output)
|
|
38
|
+
|
|
39
|
+
def test_mixed_quotes_and_comments(self):
|
|
40
|
+
input_content = (
|
|
41
|
+
"display('Hash: #'); # Real comment\n"
|
|
42
|
+
's = "My string with # character"; # Another comment'
|
|
43
|
+
)
|
|
44
|
+
expected_output = (
|
|
45
|
+
"display('Hash: #'); \ns = \"My string with # character\"; "
|
|
46
|
+
)
|
|
47
|
+
self.assertEqual(remove_comments(input_content), expected_output)
|
|
48
|
+
|
|
49
|
+
def test_complex_scenario(self):
|
|
50
|
+
# ruff does not allow whitespace at end of lines so this looks a bit weird
|
|
51
|
+
input_content = """function hello(){
|
|
52
|
+
# Comment at start
|
|
53
|
+
if (TRUE) {# inline comment
|
|
54
|
+
display('Hello # not a comment');
|
|
55
|
+
# Full comment line
|
|
56
|
+
display("Hash: #");# end comment
|
|
57
|
+
}
|
|
58
|
+
}"""
|
|
59
|
+
|
|
60
|
+
expected_output = """function hello(){
|
|
61
|
+
|
|
62
|
+
if (TRUE) {
|
|
63
|
+
display('Hello # not a comment');
|
|
64
|
+
|
|
65
|
+
display("Hash: #");
|
|
66
|
+
}
|
|
67
|
+
}"""
|
|
68
|
+
|
|
69
|
+
self.assertEqual(remove_comments(input_content), expected_output)
|
|
70
|
+
|
|
71
|
+
def test_indented_comments(self):
|
|
72
|
+
input_content = (
|
|
73
|
+
"function func() {\n # Indented comment\n return 0;\n}"
|
|
74
|
+
)
|
|
75
|
+
expected_output = "function func() {\n\n return 0;\n}"
|
|
76
|
+
self.assertEqual(remove_comments(input_content), expected_output)
|
|
77
|
+
|
|
78
|
+
def test_backslash_double_quotes(self):
|
|
79
|
+
input_content = r'display("\"); # This is a comment'
|
|
80
|
+
expected_output = r'display("\"); '
|
|
81
|
+
self.assertEqual(remove_comments(input_content), expected_output)
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
2
|
+
# SPDX-FileCopyrightText: 2025 Greenbone AG
|
|
3
|
+
|
|
4
|
+
import unittest
|
|
5
|
+
|
|
6
|
+
from troubadix.helper.text_utils import (
|
|
7
|
+
StringState,
|
|
8
|
+
index_to_linecol,
|
|
9
|
+
is_position_in_string,
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class TestStringState(unittest.TestCase):
|
|
14
|
+
def test_process_normal_char_outside_strings(self):
|
|
15
|
+
state = StringState()
|
|
16
|
+
state.process_next_char("a")
|
|
17
|
+
self.assertFalse(state.escape_next)
|
|
18
|
+
self.assertFalse(state.in_string)
|
|
19
|
+
|
|
20
|
+
def test_enter_double_quotes(self):
|
|
21
|
+
state = StringState()
|
|
22
|
+
state.process_next_char('"')
|
|
23
|
+
self.assertFalse(state.escape_next)
|
|
24
|
+
self.assertTrue(state.in_double_quote)
|
|
25
|
+
self.assertTrue(state.in_string)
|
|
26
|
+
|
|
27
|
+
def test_exit_double_quotes(self):
|
|
28
|
+
state = StringState(in_double_quote=True)
|
|
29
|
+
state.process_next_char('"')
|
|
30
|
+
self.assertFalse(state.escape_next)
|
|
31
|
+
self.assertFalse(state.in_string)
|
|
32
|
+
|
|
33
|
+
def test_enter_single_quotes(self):
|
|
34
|
+
state = StringState()
|
|
35
|
+
state.process_next_char("'")
|
|
36
|
+
self.assertFalse(state.escape_next)
|
|
37
|
+
self.assertTrue(state.in_single_quote)
|
|
38
|
+
self.assertTrue(state.in_string)
|
|
39
|
+
|
|
40
|
+
def test_exit_single_quotes(self):
|
|
41
|
+
state = StringState(in_single_quote=True)
|
|
42
|
+
state.process_next_char("'")
|
|
43
|
+
self.assertFalse(state.escape_next)
|
|
44
|
+
self.assertFalse(state.in_string)
|
|
45
|
+
|
|
46
|
+
def test_escape_in_single_quotes(self):
|
|
47
|
+
state = StringState(in_single_quote=True)
|
|
48
|
+
state.process_next_char("\\")
|
|
49
|
+
self.assertTrue(state.escape_next)
|
|
50
|
+
self.assertTrue(state.in_single_quote)
|
|
51
|
+
self.assertTrue(state.in_string)
|
|
52
|
+
|
|
53
|
+
def test_escaped_single_quote_in_single_quotes(self):
|
|
54
|
+
state = StringState(escape_next=True, in_single_quote=True)
|
|
55
|
+
state.process_next_char("'")
|
|
56
|
+
self.assertFalse(state.escape_next)
|
|
57
|
+
self.assertTrue(state.in_single_quote)
|
|
58
|
+
self.assertTrue(state.in_string)
|
|
59
|
+
|
|
60
|
+
def test_ignore_single_quotes_in_double_quotes(self):
|
|
61
|
+
state = StringState(in_double_quote=True)
|
|
62
|
+
state.process_next_char("'")
|
|
63
|
+
self.assertFalse(state.escape_next)
|
|
64
|
+
self.assertTrue(state.in_double_quote)
|
|
65
|
+
self.assertTrue(state.in_string)
|
|
66
|
+
|
|
67
|
+
def test_ignore_double_quotes_in_single_quotes(self):
|
|
68
|
+
state = StringState(in_single_quote=True)
|
|
69
|
+
state.process_next_char('"')
|
|
70
|
+
self.assertFalse(state.escape_next)
|
|
71
|
+
self.assertTrue(state.in_single_quote)
|
|
72
|
+
self.assertTrue(state.in_string)
|
|
73
|
+
|
|
74
|
+
def test_nasl_backslash_string_sequence(self):
|
|
75
|
+
# Test the sequence "\" in NASL - a valid string where escaping is ignored
|
|
76
|
+
state = StringState()
|
|
77
|
+
|
|
78
|
+
# Enter double quote
|
|
79
|
+
state.process_next_char('"')
|
|
80
|
+
self.assertFalse(state.escape_next)
|
|
81
|
+
self.assertTrue(state.in_double_quote)
|
|
82
|
+
|
|
83
|
+
# Process backslash in double quotes (should not set escape flag)
|
|
84
|
+
state.process_next_char("\\")
|
|
85
|
+
self.assertFalse(state.escape_next)
|
|
86
|
+
self.assertTrue(state.in_double_quote)
|
|
87
|
+
|
|
88
|
+
# Exit double quote
|
|
89
|
+
state.process_next_char('"')
|
|
90
|
+
self.assertFalse(state.escape_next)
|
|
91
|
+
self.assertFalse(state.in_string)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
class TestIndexToLinecol(unittest.TestCase):
|
|
95
|
+
def test_start_of_file(self):
|
|
96
|
+
line, col = index_to_linecol("hello\nworld", 0)
|
|
97
|
+
self.assertEqual((line, col), (1, 1))
|
|
98
|
+
|
|
99
|
+
def test_middle_of_first_line(self):
|
|
100
|
+
line, col = index_to_linecol("hello\nworld", 2)
|
|
101
|
+
self.assertEqual((line, col), (1, 3))
|
|
102
|
+
|
|
103
|
+
def test_end_of_first_line(self):
|
|
104
|
+
line, col = index_to_linecol("hello\nworld", 5)
|
|
105
|
+
self.assertEqual((line, col), (1, 6))
|
|
106
|
+
|
|
107
|
+
def test_start_of_second_line(self):
|
|
108
|
+
line, col = index_to_linecol("hello\nworld", 6)
|
|
109
|
+
self.assertEqual((line, col), (2, 1))
|
|
110
|
+
|
|
111
|
+
def test_end_of_file(self):
|
|
112
|
+
line, col = index_to_linecol("hello\nworld", 10)
|
|
113
|
+
self.assertEqual((line, col), (2, 5))
|
|
114
|
+
|
|
115
|
+
def test_multiline_file(self):
|
|
116
|
+
text = "line1\nline2\nline3"
|
|
117
|
+
line, col = index_to_linecol(text, 10)
|
|
118
|
+
self.assertEqual((line, col), (2, 5))
|
|
119
|
+
|
|
120
|
+
def test_empty_file(self):
|
|
121
|
+
self.assertRaises(ValueError, index_to_linecol, "", 0)
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
class TestIsPositionInString(unittest.TestCase):
|
|
125
|
+
def test_no_strings(self):
|
|
126
|
+
text = "x = 5; y = 10;"
|
|
127
|
+
self.assertFalse(is_position_in_string(text, 0))
|
|
128
|
+
self.assertFalse(is_position_in_string(text, 7))
|
|
129
|
+
|
|
130
|
+
def test_position_before_string(self):
|
|
131
|
+
text = 'x = "hello";'
|
|
132
|
+
self.assertFalse(is_position_in_string(text, 0))
|
|
133
|
+
self.assertFalse(is_position_in_string(text, 3))
|
|
134
|
+
|
|
135
|
+
def test_position_inside_double_quote_string(self):
|
|
136
|
+
text = 'x = "hello";'
|
|
137
|
+
self.assertTrue(is_position_in_string(text, 5)) # inside "hello"
|
|
138
|
+
self.assertTrue(is_position_in_string(text, 9)) # inside "hello"
|
|
139
|
+
|
|
140
|
+
def test_position_inside_single_quote_string(self):
|
|
141
|
+
text = "x = 'world';"
|
|
142
|
+
self.assertTrue(is_position_in_string(text, 5)) # inside 'world'
|
|
143
|
+
self.assertTrue(is_position_in_string(text, 9)) # inside 'world'
|
|
144
|
+
|
|
145
|
+
def test_position_after_string(self):
|
|
146
|
+
text = 'x = "hello";'
|
|
147
|
+
self.assertFalse(is_position_in_string(text, 11)) # after string
|
|
148
|
+
|
|
149
|
+
def test_escaped_quote_in_single_quotes(self):
|
|
150
|
+
text = "x = 'don\\'t';"
|
|
151
|
+
self.assertTrue(is_position_in_string(text, 8)) # inside the string
|
|
152
|
+
self.assertTrue(
|
|
153
|
+
is_position_in_string(text, 10)
|
|
154
|
+
) # after the escaped quote
|
|
155
|
+
|
|
156
|
+
def test_mixed_quotes(self):
|
|
157
|
+
text = 'a = "it\'s ok"; b = \'say "hi"\';'
|
|
158
|
+
self.assertTrue(is_position_in_string(text, 6)) # inside "it's ok"
|
|
159
|
+
self.assertTrue(is_position_in_string(text, 22)) # inside 'say "hi"'
|
|
160
|
+
self.assertFalse(is_position_in_string(text, 15)) # between strings
|
|
161
|
+
|
|
162
|
+
def test_position_at_quote_characters(self):
|
|
163
|
+
# This checks that the implementation considers only characters before the current index,
|
|
164
|
+
# so the opening quote is not inside the string,
|
|
165
|
+
# but the closing quote is still considered inside.
|
|
166
|
+
text = 'x = "hello";'
|
|
167
|
+
self.assertFalse(is_position_in_string(text, 4)) # at opening quote
|
|
168
|
+
self.assertTrue(is_position_in_string(text, 10)) # at closing quote
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
2
|
+
# SPDX-FileCopyrightText: 2025 Greenbone AG
|
|
3
|
+
|
|
4
|
+
import sys
|
|
5
|
+
|
|
6
|
+
from troubadix.helper import CURRENT_ENCODING
|
|
7
|
+
from troubadix.helper.remove_comments import remove_comments
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
# poetry run python tests/manual_tests/comment_removal_diff.py <path_to_nasl_file>
|
|
11
|
+
def test_comment_removal(input_file):
|
|
12
|
+
"""
|
|
13
|
+
Test the remove_comments function and show all lines with their status.
|
|
14
|
+
|
|
15
|
+
Args:
|
|
16
|
+
input_file: Path to the NASL file to test
|
|
17
|
+
"""
|
|
18
|
+
try:
|
|
19
|
+
with open(input_file, "r", encoding=CURRENT_ENCODING) as f:
|
|
20
|
+
original_content = f.read()
|
|
21
|
+
except Exception as e:
|
|
22
|
+
print(f"Error reading file: {e}")
|
|
23
|
+
return
|
|
24
|
+
|
|
25
|
+
processed_content = remove_comments(original_content)
|
|
26
|
+
|
|
27
|
+
original_lines = original_content.splitlines()
|
|
28
|
+
processed_lines = processed_content.splitlines()
|
|
29
|
+
|
|
30
|
+
print("\nFull comparison between original and processed file:")
|
|
31
|
+
print("----------------------------------------------------")
|
|
32
|
+
|
|
33
|
+
max_len = max(len(original_lines), len(processed_lines))
|
|
34
|
+
|
|
35
|
+
for i in range(max_len):
|
|
36
|
+
if i < len(original_lines) and i < len(processed_lines):
|
|
37
|
+
if original_lines[i] == processed_lines[i]:
|
|
38
|
+
status = " " # Unchanged
|
|
39
|
+
else:
|
|
40
|
+
status = "! " # Changed
|
|
41
|
+
print(f"{i + 1:4d} {status}{original_lines[i]}")
|
|
42
|
+
if status == "! ":
|
|
43
|
+
print(f" -> {processed_lines[i]}")
|
|
44
|
+
|
|
45
|
+
print("\nSummary:")
|
|
46
|
+
print(f"Original file lines: {len(original_lines)}")
|
|
47
|
+
print(f"Processed file lines: {len(processed_lines)}")
|
|
48
|
+
|
|
49
|
+
comment_lines = 0
|
|
50
|
+
for line in original_lines:
|
|
51
|
+
stripped = line.lstrip()
|
|
52
|
+
if stripped.startswith("#"):
|
|
53
|
+
comment_lines += 1
|
|
54
|
+
print(f"Full-line comments: {comment_lines}")
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
if __name__ == "__main__":
|
|
58
|
+
if len(sys.argv) != 2:
|
|
59
|
+
print(f"Usage: {sys.argv[0]} <nasl_file>")
|
|
60
|
+
sys.exit(1)
|
|
61
|
+
|
|
62
|
+
test_comment_removal(sys.argv[1])
|
|
@@ -38,7 +38,7 @@ class CheckUsingDisplayTestCase(PluginTestCase):
|
|
|
38
38
|
|
|
39
39
|
results = list(plugin.run())
|
|
40
40
|
|
|
41
|
-
self.assertEqual(len(results)
|
|
41
|
+
self.assertEqual(0, len(results))
|
|
42
42
|
|
|
43
43
|
def test_using_display(self):
|
|
44
44
|
path = Path("some/file.nasl")
|
|
@@ -55,10 +55,10 @@ class CheckUsingDisplayTestCase(PluginTestCase):
|
|
|
55
55
|
|
|
56
56
|
results = list(plugin.run())
|
|
57
57
|
|
|
58
|
-
self.assertEqual(len(results)
|
|
58
|
+
self.assertEqual(1, len(results))
|
|
59
59
|
self.assertIsInstance(results[0], LinterError)
|
|
60
60
|
self.assertEqual(
|
|
61
|
-
'VT
|
|
61
|
+
'VT is using a display() without any if statement at line 3: display("FOO");',
|
|
62
62
|
results[0].message,
|
|
63
63
|
)
|
|
64
64
|
|
|
@@ -77,14 +77,13 @@ class CheckUsingDisplayTestCase(PluginTestCase):
|
|
|
77
77
|
|
|
78
78
|
results = list(plugin.run())
|
|
79
79
|
|
|
80
|
-
self.assertEqual(len(results)
|
|
80
|
+
self.assertEqual(1, len(results))
|
|
81
81
|
self.assertIsInstance(results[0], LinterWarning)
|
|
82
|
-
self.
|
|
83
|
-
"VT is using a display()
|
|
84
|
-
"protected by a comment or an if statement at: "
|
|
85
|
-
'if (0) display("FOO");.',
|
|
82
|
+
self.assertIn(
|
|
83
|
+
"VT is using a display() inside an if statement but without debug check",
|
|
86
84
|
results[0].message,
|
|
87
85
|
)
|
|
86
|
+
self.assertIn('if (0) display("FOO");', results[0].message)
|
|
88
87
|
|
|
89
88
|
def test_using_comment_display(self):
|
|
90
89
|
path = Path("some/file.nasl")
|
|
@@ -101,11 +100,49 @@ class CheckUsingDisplayTestCase(PluginTestCase):
|
|
|
101
100
|
|
|
102
101
|
results = list(plugin.run())
|
|
103
102
|
|
|
104
|
-
|
|
105
|
-
self.
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
103
|
+
# Comments are removed, so display() won't be found
|
|
104
|
+
self.assertEqual(0, len(results))
|
|
105
|
+
|
|
106
|
+
def test_using_debug_if_display(self):
|
|
107
|
+
"""Test that display() inside a debug if statement is allowed"""
|
|
108
|
+
path = Path("some/file.nasl")
|
|
109
|
+
content = (
|
|
110
|
+
' script_tag(name:"cvss_base", value:"4.0");\n'
|
|
111
|
+
'if (debug) display("FOO");\n'
|
|
111
112
|
)
|
|
113
|
+
fake_context = self.create_file_plugin_context(
|
|
114
|
+
nasl_file=path, file_content=content
|
|
115
|
+
)
|
|
116
|
+
plugin = CheckUsingDisplay(fake_context)
|
|
117
|
+
|
|
118
|
+
results = list(plugin.run())
|
|
119
|
+
|
|
120
|
+
# Should be OK because it's in a debug if
|
|
121
|
+
self.assertEqual(0, len(results))
|
|
122
|
+
|
|
123
|
+
def test_display_in_string_ignored(self):
|
|
124
|
+
path = Path("some/file.nasl")
|
|
125
|
+
content = "str = 'display(\"FOO\")';\n"
|
|
126
|
+
fake_context = self.create_file_plugin_context(
|
|
127
|
+
nasl_file=path, file_content=content
|
|
128
|
+
)
|
|
129
|
+
plugin = CheckUsingDisplay(fake_context)
|
|
130
|
+
|
|
131
|
+
results = list(plugin.run())
|
|
132
|
+
|
|
133
|
+
self.assertEqual(0, len(results))
|
|
134
|
+
|
|
135
|
+
def test_propagate_if_parser_error(self):
|
|
136
|
+
path = Path("some/file.nasl")
|
|
137
|
+
content = "if (Foo);\ndisplay('Foo');"
|
|
138
|
+
fake_context = self.create_file_plugin_context(
|
|
139
|
+
nasl_file=path, file_content=content
|
|
140
|
+
)
|
|
141
|
+
plugin = CheckUsingDisplay(fake_context)
|
|
142
|
+
|
|
143
|
+
results = list(plugin.run())
|
|
144
|
+
|
|
145
|
+
# only one result for if parser error,
|
|
146
|
+
# display call not part of result due to early exit of entire run.
|
|
147
|
+
self.assertEqual(1, len(results))
|
|
148
|
+
self.assertIn("Semicolon after if condition", results[0].message)
|
|
@@ -300,6 +300,21 @@ class CheckValidOIDTestCase(PluginTestCase):
|
|
|
300
300
|
|
|
301
301
|
self.assertEqual(len(results), 0)
|
|
302
302
|
|
|
303
|
+
def test_amazon_with_optional_identifier(self):
|
|
304
|
+
path = Path("some/file.nasl")
|
|
305
|
+
content = (
|
|
306
|
+
' script_oid("1.3.6.1.4.1.25623.1.1.5.1.2012.2256");\n'
|
|
307
|
+
' script_family("Amazon Linux Local Security Checks");\n'
|
|
308
|
+
)
|
|
309
|
+
fake_context = self.create_file_plugin_context(
|
|
310
|
+
nasl_file=path, file_content=content
|
|
311
|
+
)
|
|
312
|
+
plugin = CheckValidOID(fake_context)
|
|
313
|
+
|
|
314
|
+
results = list(plugin.run())
|
|
315
|
+
|
|
316
|
+
self.assertEqual(len(results), 0)
|
|
317
|
+
|
|
303
318
|
def test_amazon(self):
|
|
304
319
|
path = Path("some/file.nasl")
|
|
305
320
|
content = (
|