diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/lint_tests/lint_tutil.py | 10 | ||||
-rw-r--r-- | tests/lint_tests/test_lint_dcpy.py | 64 | ||||
-rw-r--r-- | tests/lint_tests/test_lint_dctrl.py | 265 | ||||
-rw-r--r-- | tests/lint_tests/test_lint_dpatches_series.py | 152 | ||||
-rw-r--r-- | tests/lsp_tests/test_lsp_dpatches_series.py | 59 | ||||
-rw-r--r-- | tests/plugin_tests/grantlee_test.py | 34 |
6 files changed, 571 insertions, 13 deletions
diff --git a/tests/lint_tests/lint_tutil.py b/tests/lint_tests/lint_tutil.py index 26df505..65fe0ad 100644 --- a/tests/lint_tests/lint_tutil.py +++ b/tests/lint_tests/lint_tutil.py @@ -3,8 +3,8 @@ from typing import List, Optional, Mapping, Any, Callable import pytest +from debputy.filesystem_scan import VirtualPathBase from debputy.linting.lint_util import ( - LinterImpl, LinterPositionCodec, LintStateImpl, LintState, @@ -44,6 +44,7 @@ class LintWrapper: self.dctrl_lines: Optional[List[str]] = None self.path = path self._dctrl_parser = dctrl_parser + self.source_root: Optional[VirtualPathBase] = None self.lint_style_preference_table = StylePreferenceTable({}, {}) self.effective_preference: Optional[EffectivePreference] = None @@ -57,11 +58,13 @@ class LintWrapper: dctrl_lines, ignore_errors=True ) ) + source_root = self.source_root + debian_dir = source_root.get("debian") if source_root is not None else None state = LintStateImpl( self._debputy_plugin_feature_set, self.lint_style_preference_table, - None, - None, + source_root, + debian_dir, self.path, "".join(dctrl_lines) if dctrl_lines is not None else "", lines, @@ -84,6 +87,7 @@ def check_diagnostics( if diagnostics: for diagnostic in diagnostics: assert diagnostic.severity is not None + assert diagnostic.source is not None return diagnostics diff --git a/tests/lint_tests/test_lint_dcpy.py b/tests/lint_tests/test_lint_dcpy.py new file mode 100644 index 0000000..f827d3e --- /dev/null +++ b/tests/lint_tests/test_lint_dcpy.py @@ -0,0 +1,64 @@ +import textwrap + +import pytest + +from debputy.lsp.lsp_debian_copyright import _lint_debian_copyright +from debputy.packages import DctrlParser +from debputy.plugin.api.feature_set import PluginProvidedFeatureSet +from lint_tests.lint_tutil import ( + group_diagnostics_by_severity, + LintWrapper, +) + +try: + from lsprotocol.types import Diagnostic, DiagnosticSeverity +except ImportError: + pass + + +@pytest.fixture +def line_linter( + debputy_plugin_feature_set: PluginProvidedFeatureSet, + lint_dctrl_parser: DctrlParser, +) -> LintWrapper: + return LintWrapper( + "/nowhere/debian/copyright", + _lint_debian_copyright, + debputy_plugin_feature_set, + lint_dctrl_parser, + ) + + +def test_dcpy_files_lint(line_linter: LintWrapper) -> None: + lines = textwrap.dedent( + """\ + Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ + + Files: foo .//unnecessary///many/slashes + Copyright: Noone <noone@example.com> + License: something + yada yada yada + """ + ).splitlines(keepends=True) + + diagnostics = line_linter(lines) + by_severity = group_diagnostics_by_severity(diagnostics) + assert DiagnosticSeverity.Warning in by_severity + + assert DiagnosticSeverity.Error not in by_severity + assert DiagnosticSeverity.Hint not in by_severity + assert DiagnosticSeverity.Information not in by_severity + + warnings = by_severity[DiagnosticSeverity.Warning] + print(warnings) + assert len(warnings) == 2 + + first_warn, second_warn = warnings + + msg = 'Unnecessary prefix ".//"' + assert first_warn.message == msg + assert f"{first_warn.range}" == "2:11-2:14" + + msg = 'Simplify to a single "/"' + assert second_warn.message == msg + assert f"{second_warn.range}" == "2:25-2:28" diff --git a/tests/lint_tests/test_lint_dctrl.py b/tests/lint_tests/test_lint_dctrl.py index bcb1613..7e9477e 100644 --- a/tests/lint_tests/test_lint_dctrl.py +++ b/tests/lint_tests/test_lint_dctrl.py @@ -4,6 +4,7 @@ from typing import List, Optional import pytest from debputy.lsp.lsp_debian_control import _lint_debian_control +from debputy.lsp.lsp_debian_control_reference_data import CURRENT_STANDARDS_VERSION from debputy.packages import DctrlParser from debputy.plugin.api.feature_set import PluginProvidedFeatureSet from lint_tests.lint_tutil import ( @@ -18,9 +19,6 @@ except ImportError: pass -STANDARDS_VERSION = "4.7.0" - - class DctrlLintWrapper(LintWrapper): def __call__(self, lines: List[str]) -> Optional[List["Diagnostic"]]: @@ -104,7 +102,7 @@ def test_dctrl_lint_typos(line_linter: LintWrapper) -> None: lines = textwrap.dedent( f"""\ Source: foo - Standards-Version: {STANDARDS_VERSION} + Standards-Version: {CURRENT_STANDARDS_VERSION} Priority: optional Section: devel Maintainer: Jane Developer <jane@example.com> @@ -137,7 +135,7 @@ def test_dctrl_lint_mx_value_with_typo(line_linter: LintWrapper) -> None: lines = textwrap.dedent( f"""\ Source: foo - Standards-Version: {STANDARDS_VERSION} + Standards-Version: {CURRENT_STANDARDS_VERSION} Priority: optional Section: devel Maintainer: Jane Developer <jane@example.com> @@ -176,7 +174,7 @@ def test_dctrl_lint_mx_value(line_linter: LintWrapper) -> None: lines = textwrap.dedent( f"""\ Source: foo - Standards-Version: {STANDARDS_VERSION} + Standards-Version: {CURRENT_STANDARDS_VERSION} Priority: optional Section: devel Maintainer: Jane Developer <jane@example.com> @@ -205,7 +203,7 @@ def test_dctrl_lint_mx_value(line_linter: LintWrapper) -> None: lines = textwrap.dedent( f"""\ Source: foo - Standards-Version: {STANDARDS_VERSION} + Standards-Version: {CURRENT_STANDARDS_VERSION} Priority: optional Section: devel Maintainer: Jane Developer <jane@example.com> @@ -238,14 +236,14 @@ def test_dctrl_lint_dup_sep(line_linter: LintWrapper) -> None: Source: foo Section: devel Priority: optional - Standards-Version: {STANDARDS_VERSION} + Standards-Version: {CURRENT_STANDARDS_VERSION} Maintainer: Jane Developer <jane@example.com> Build-Depends: debhelper-compat (= 13) Package: foo Architecture: all - Depends: foo, - , bar + Depends: bar, + , baz Description: Some very interesting synopsis A very interesting description that spans multiple lines @@ -263,3 +261,250 @@ def test_dctrl_lint_dup_sep(line_linter: LintWrapper) -> None: assert error.message == msg assert f"{error.range}" == "10:1-10:2" assert error.severity == DiagnosticSeverity.Error + + +def test_dctrl_lint_ma(line_linter: LintWrapper) -> None: + lines = textwrap.dedent( + f"""\ + Source: foo + Section: devel + Priority: optional + Standards-Version: {CURRENT_STANDARDS_VERSION} + Maintainer: Jane Developer <jane@example.com> + Build-Depends: debhelper-compat (= 13) + + Package: foo + Architecture: all + Multi-Arch: same + Depends: bar, baz + Description: Some very interesting synopsis + A very interesting description + that spans multiple lines + . + Just so be clear, this is for a test. + """ + ).splitlines(keepends=True) + + diagnostics = line_linter(lines) + print(diagnostics) + assert diagnostics and len(diagnostics) == 1 + error = diagnostics[0] + + msg = "Multi-Arch: same is not valid for Architecture: all packages. Maybe you want foreign?" + assert error.message == msg + assert f"{error.range}" == "9:12-9:16" + assert error.severity == DiagnosticSeverity.Error + + +def test_dctrl_lint_udeb(line_linter: LintWrapper) -> None: + lines = textwrap.dedent( + f"""\ + Source: foo + Section: devel + Priority: optional + Standards-Version: {CURRENT_STANDARDS_VERSION} + Maintainer: Jane Developer <jane@example.com> + Build-Depends: debhelper-compat (= 13) + + Package: foo + Architecture: all + XB-Installer-Menu-Item: 1234 + Depends: bar, baz + Description: Some very interesting synopsis + A very interesting description + that spans multiple lines + . + Just so be clear, this is for a test. + + Package: bar-udeb + Architecture: all + Section: debian-installer + Package-Type: udeb + XB-Installer-Menu-Item: golf + Description: Some very interesting synopsis + A very interesting description + that spans multiple lines + . + Just so be clear, this is for a test. + """ + ).splitlines(keepends=True) + + diagnostics = line_linter(lines) + print(diagnostics) + assert diagnostics and len(diagnostics) == 2 + first, second = diagnostics + + msg = "The XB-Installer-Menu-Item field is only applicable to udeb packages (`Package-Type: udeb`)" + assert first.message == msg + assert f"{first.range}" == "9:0-9:22" + assert first.severity == DiagnosticSeverity.Warning + + msg = r'The value "golf" does not match the regex ^[1-9]\d{3,4}$.' + assert second.message == msg + assert f"{second.range}" == "21:24-21:28" + assert second.severity == DiagnosticSeverity.Error + + +def test_dctrl_lint_arch_only_fields(line_linter: LintWrapper) -> None: + lines = textwrap.dedent( + f"""\ + Source: foo + Section: devel + Priority: optional + Standards-Version: {CURRENT_STANDARDS_VERSION} + Maintainer: Jane Developer <jane@example.com> + Build-Depends: debhelper-compat (= 13) + + Package: foo + Architecture: all + X-DH-Build-For-Type: target + Depends: bar, baz + Description: Some very interesting synopsis + A very interesting description + that spans multiple lines + . + Just so be clear, this is for a test. + """ + ).splitlines(keepends=True) + + diagnostics = line_linter(lines) + print(diagnostics) + assert diagnostics and len(diagnostics) == 1 + issue = diagnostics[0] + + msg = "The X-DH-Build-For-Type field is not applicable to arch:all packages (`Architecture: all`)" + assert issue.message == msg + assert f"{issue.range}" == "9:0-9:19" + assert issue.severity == DiagnosticSeverity.Warning + + +def test_dctrl_lint_sv(line_linter: LintWrapper) -> None: + lines = textwrap.dedent( + f"""\ + Source: foo + Section: devel + Priority: optional + Standards-Version: 4.6.2 + Maintainer: Jane Developer <jane@example.com> + Build-Depends: debhelper-compat (= 13) + + Package: foo + Architecture: all + Depends: bar, baz + Description: Some very interesting synopsis + A very interesting description + that spans multiple lines + . + Just so be clear, this is for a test. + """ + ).splitlines(keepends=True) + + diagnostics = line_linter(lines) + print(diagnostics) + assert diagnostics and len(diagnostics) == 1 + issue = diagnostics[0] + + msg = f"Latest Standards-Version is {CURRENT_STANDARDS_VERSION}" + assert issue.message == msg + assert f"{issue.range}" == "3:19-3:24" + assert issue.severity == DiagnosticSeverity.Information + + lines = textwrap.dedent( + f"""\ + Source: foo + Section: devel + Priority: optional + Standards-Version: Golf + Maintainer: Jane Developer <jane@example.com> + Build-Depends: debhelper-compat (= 13) + + Package: foo + Architecture: all + Depends: bar, baz + Description: Some very interesting synopsis + A very interesting description + that spans multiple lines + . + Just so be clear, this is for a test. + """ + ).splitlines(keepends=True) + + diagnostics = line_linter(lines) + print(diagnostics) + assert diagnostics and len(diagnostics) == 1 + issue = diagnostics[0] + + msg = f'Not a valid version. Current version is "{CURRENT_STANDARDS_VERSION}"' + assert issue.message == msg + assert f"{issue.range}" == "3:19-3:23" + assert issue.severity == DiagnosticSeverity.Warning + + lines = textwrap.dedent( + f"""\ + Source: foo + Section: devel + Priority: optional + Standards-Version: {CURRENT_STANDARDS_VERSION}.0 + Maintainer: Jane Developer <jane@example.com> + Build-Depends: debhelper-compat (= 13) + + Package: foo + Architecture: all + Depends: bar, baz + Description: Some very interesting synopsis + A very interesting description + that spans multiple lines + . + Just so be clear, this is for a test. + """ + ).splitlines(keepends=True) + + diagnostics = line_linter(lines) + print(diagnostics) + assert diagnostics and len(diagnostics) == 1 + issue = diagnostics[0] + + msg = "Unnecessary version segment. This part of the version is only used for editorial changes" + assert issue.message == msg + assert f"{issue.range}" == "3:24-3:26" + assert issue.severity == DiagnosticSeverity.Information + + +def test_dctrl_lint_multiple_vcs(line_linter: LintWrapper) -> None: + lines = textwrap.dedent( + f"""\ + Source: foo + Section: devel + Priority: optional + Standards-Version: {CURRENT_STANDARDS_VERSION} + Maintainer: Jane Developer <jane@example.com> + Build-Depends: debhelper-compat (= 13) + Vcs-Git: https://salsa.debian.org/debian/foo + Vcs-Svn: https://svn.debian.org/debian/foo + Vcs-Browser: https://salsa.debian.org/debian/foo + + Package: foo + Architecture: all + Depends: bar, baz + Description: Some very interesting synopsis + A very interesting description + that spans multiple lines + . + Just so be clear, this is for a test. + """ + ).splitlines(keepends=True) + + diagnostics = line_linter(lines) + print(diagnostics) + assert diagnostics and len(diagnostics) == 2 + first_issue, second_issue = diagnostics + + msg = f'Multiple Version Control fields defined ("Vcs-Git")' + assert first_issue.message == msg + assert f"{first_issue.range}" == "6:0-7:0" + assert first_issue.severity == DiagnosticSeverity.Warning + + msg = f'Multiple Version Control fields defined ("Vcs-Svn")' + assert second_issue.message == msg + assert f"{second_issue.range}" == "7:0-8:0" + assert second_issue.severity == DiagnosticSeverity.Warning diff --git a/tests/lint_tests/test_lint_dpatches_series.py b/tests/lint_tests/test_lint_dpatches_series.py new file mode 100644 index 0000000..ed2a802 --- /dev/null +++ b/tests/lint_tests/test_lint_dpatches_series.py @@ -0,0 +1,152 @@ +import textwrap + +import pytest + +from debputy.lsp.lsp_debian_patches_series import _lint_debian_patches_series +from debputy.packages import DctrlParser +from debputy.plugin.api.feature_set import PluginProvidedFeatureSet +from debputy.plugin.api.test_api import build_virtual_file_system +from lint_tests.lint_tutil import ( + LintWrapper, +) + +try: + from lsprotocol.types import Diagnostic, DiagnosticSeverity +except ImportError: + pass + + +@pytest.fixture +def line_linter( + debputy_plugin_feature_set: PluginProvidedFeatureSet, + lint_dctrl_parser: DctrlParser, +) -> LintWrapper: + return LintWrapper( + "/nowhere/debian/patches/series", + _lint_debian_patches_series, + debputy_plugin_feature_set, + lint_dctrl_parser, + ) + + +def test_dpatches_series_files_lint(line_linter: LintWrapper) -> None: + lines = textwrap.dedent( + """\ + # Some leading comment + + ../some.patch + + .//.//./subdir/another-delta.diff # foo + + subdir/no-issues.patch # bar + """ + ).splitlines(keepends=True) + + fs = build_virtual_file_system( + [ + "./debian/patches/series", + "./debian/some.patch", + "./debian/patches/subdir/another-delta.diff", + "./debian/patches/subdir/no-issues.patch", + ] + ) + + line_linter.source_root = fs + + diagnostics = line_linter(lines) + print(diagnostics) + assert len(diagnostics) == 2 + + first_issue, second_issue = diagnostics + + msg = 'Disallowed prefix "../"' + assert first_issue.message == msg + assert f"{first_issue.range}" == "2:0-2:3" + assert first_issue.severity == DiagnosticSeverity.Error + + msg = 'Unnecessary prefix ".//.//./"' + assert second_issue.message == msg + assert f"{second_issue.range}" == "4:0-4:8" + assert second_issue.severity == DiagnosticSeverity.Warning + + +def test_dpatches_series_files_file_mismatch_lint(line_linter: LintWrapper) -> None: + lines = textwrap.dedent( + """\ + # Some leading comment + + some/used-twice.patch + + some/missing-file.patch + + some/used-twice.patch + """ + ).splitlines(keepends=True) + + fs = build_virtual_file_system( + [ + "./debian/patches/series", + "./debian/ignored.patch", + "./debian/patches/some/unused-file.diff", + "./debian/patches/some/used-twice.patch", + ] + ) + + line_linter.source_root = fs + + diagnostics = line_linter(lines) + print(diagnostics) + assert len(diagnostics) == 3 + + first_issue, second_issue, third_issue = diagnostics + + msg = 'Non-existing patch "some/missing-file.patch"' + assert first_issue.message == msg + assert f"{first_issue.range}" == "4:0-4:23" + assert first_issue.severity == DiagnosticSeverity.Error + + msg = 'Duplicate patch: "some/used-twice.patch"' + assert second_issue.message == msg + assert f"{second_issue.range}" == "6:0-6:21" + assert second_issue.severity == DiagnosticSeverity.Error + + msg = 'Unused patch: "some/unused-file.diff"' + assert third_issue.message == msg + assert f"{third_issue.range}" == "0:0-7:22" + assert third_issue.severity == DiagnosticSeverity.Warning + + +def test_dpatches_series_files_ext_lint(line_linter: LintWrapper) -> None: + lines = textwrap.dedent( + """\ + # Some leading comment + + some/ok.diff + + some/ok.patch + + some/no-extension + """ + ).splitlines(keepends=True) + + fs = build_virtual_file_system( + [ + "./debian/patches/series", + "./debian/patches/some/ok.diff", + "./debian/patches/some/ok.patch", + "./debian/patches/some/no-extension", + ] + ) + + line_linter.source_root = fs + + diagnostics = line_linter(lines) + print(diagnostics) + assert len(diagnostics) == 1 + + issue = diagnostics[0] + + msg = 'Patch not using ".patch" or ".diff" as extension: "some/no-extension"' + assert issue.message == msg + assert f"{issue.range}" == "6:0-6:17" + assert issue.severity == DiagnosticSeverity.Hint diff --git a/tests/lsp_tests/test_lsp_dpatches_series.py b/tests/lsp_tests/test_lsp_dpatches_series.py new file mode 100644 index 0000000..e7a1275 --- /dev/null +++ b/tests/lsp_tests/test_lsp_dpatches_series.py @@ -0,0 +1,59 @@ +import textwrap + +from debputy.lsp.debputy_ls import DebputyLanguageServer + +try: + from lsprotocol.types import ( + CompletionParams, + TextDocumentIdentifier, + HoverParams, + MarkupContent, + SemanticTokensParams, + ) + + from debputy.lsp.lsp_debian_patches_series import ( + _debian_patches_semantic_tokens_full, + _debian_patches_series_completions, + ) + + from pygls.server import LanguageServer +except ImportError: + pass +from lsp_tests.lsp_tutil import ( + put_doc_no_cursor, + resolve_semantic_tokens, + resolved_semantic_token, +) + + +def test_dpatches_series_semantic_tokens(ls: "DebputyLanguageServer") -> None: + doc_uri = "file:///nowhere/debian/patches/series" + put_doc_no_cursor( + ls, + doc_uri, + "debian/patches/series", + textwrap.dedent( + """\ + # Some leading comment + + some.patch + + another-delta.diff # foo +""" + ), + ) + + semantic_tokens = _debian_patches_semantic_tokens_full( + ls, + SemanticTokensParams(TextDocumentIdentifier(doc_uri)), + ) + resolved_semantic_tokens = resolve_semantic_tokens(semantic_tokens) + assert resolved_semantic_tokens is not None + assert resolved_semantic_tokens == [ + resolved_semantic_token(0, 0, len("# Some leading comment"), "comment"), + resolved_semantic_token(2, 0, len("some.patch"), "string"), + resolved_semantic_token(4, 0, len("another-delta.diff"), "string"), + resolved_semantic_token( + 4, len("another-delta.diff") + 1, len("# foo"), "comment" + ), + ] diff --git a/tests/plugin_tests/grantlee_test.py b/tests/plugin_tests/grantlee_test.py new file mode 100644 index 0000000..2cbcd2c --- /dev/null +++ b/tests/plugin_tests/grantlee_test.py @@ -0,0 +1,34 @@ +from debputy.plugin.api.test_api import ( + initialize_plugin_under_test, + build_virtual_file_system, + package_metadata_context, +) + + +def test_grantlee_dependencies(amd64_dpkg_architecture_variables) -> None: + plugin = initialize_plugin_under_test() + fs = build_virtual_file_system([]) + context = package_metadata_context(package_fields={"Architecture": "all"}) + metadata = plugin.run_metadata_detector("detect-grantlee-dependencies", fs, context) + assert "grantlee:Depends" not in metadata.substvars + + context = package_metadata_context( + package_fields={"Architecture": "any"}, + host_arch=amd64_dpkg_architecture_variables.current_host_arch, + ) + madir = amd64_dpkg_architecture_variables.current_host_multiarch + fs = build_virtual_file_system( + [ + f"usr/lib/{madir}/grantlee/random-dir", + ] + ) + metadata = plugin.run_metadata_detector("detect-grantlee-dependencies", fs, context) + assert "grantlee:Depends" not in metadata.substvars + + fs = build_virtual_file_system( + [ + f"usr/lib/{madir}/grantlee/5.0/foo.so", + ] + ) + metadata = plugin.run_metadata_detector("detect-grantlee-dependencies", fs, context) + assert metadata.substvars["grantlee:Depends"] == "grantlee5-templates-5-0" |