Skip to content

Commit

Permalink
Add broad spectrum tests for python (#273)
Browse files Browse the repository at this point in the history
  • Loading branch information
karthiknadig authored Sep 15, 2023
1 parent e547d3d commit 05a4341
Show file tree
Hide file tree
Showing 3 changed files with 154 additions and 0 deletions.
3 changes: 3 additions & 0 deletions noxfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ def tests(session: nox.Session):
"""Run tests for generator and generated code in all languages."""
_install_requirements(session)

session.log("Running test data generator.")
session.run("python", "-m", "generator", "--plugin", "testdata")

session.log("Running tests: generator and generated Python code.")
session.run("pytest", "./tests")

Expand Down
117 changes: 117 additions & 0 deletions packages/python/lsprotocol/_hooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -634,6 +634,88 @@ def _notebook_sync_option_selector_hook(
object_, lsp_types.NotebookDocumentSyncOptionsNotebookSelectorType2
)

def _semantic_token_registration_options_hook(
object_: Any, _: type
) -> Optional[
Union[OptionalPrimitive, lsp_types.SemanticTokensRegistrationOptionsFullType1]
]:
if object_ is None:
return None
if isinstance(object_, (bool, int, str, float)):
return object_
return converter.structure(
object_, lsp_types.SemanticTokensRegistrationOptionsFullType1
)

def _inline_completion_provider_hook(
object_: Any, _: type
) -> Optional[Union[OptionalPrimitive, lsp_types.InlineCompletionOptions]]:
if object_ is None:
return None
if isinstance(object_, (bool, int, str, float)):
return object_
return converter.structure(object_, lsp_types.InlineCompletionOptions)

def _inline_completion_list_hook(
object_: Any, _: type
) -> Optional[
Union[lsp_types.InlineCompletionList, List[lsp_types.InlineCompletionItem]]
]:
if object_ is None:
return None
if isinstance(object_, list):
return [
converter.structure(item, lsp_types.InlineCompletionItem)
for item in object_
]
return converter.structure(object_, lsp_types.InlineCompletionList)

def _string_value_hook(
object_: Any, _: type
) -> Union[OptionalPrimitive, lsp_types.StringValue]:
if object_ is None:
return None
if isinstance(object_, (bool, int, str, float)):
return object_
return converter.structure(object_, lsp_types.StringValue)

def _symbol_list_hook(
object_: Any, _: type
) -> Optional[
Union[List[lsp_types.SymbolInformation], List[lsp_types.WorkspaceSymbol]]
]:
if object_ is None:
return None
assert isinstance(object_, list)
if len(object_) == 0:
return [] # type: ignore[return-value]
if "location" in object_[0]:
return [
converter.structure(item, lsp_types.SymbolInformation)
for item in object_
]
else:
return [
converter.structure(item, lsp_types.WorkspaceSymbol) for item in object_
]

def _notebook_sync_registration_option_selector_hook(
object_: Any, _: type
) -> Union[
lsp_types.NotebookDocumentSyncRegistrationOptionsNotebookSelectorType1,
lsp_types.NotebookDocumentSyncRegistrationOptionsNotebookSelectorType2,
]:
if "notebook" in object_:
return converter.structure(
object_,
lsp_types.NotebookDocumentSyncRegistrationOptionsNotebookSelectorType1,
)
else:
return converter.structure(
object_,
lsp_types.NotebookDocumentSyncRegistrationOptionsNotebookSelectorType2,
)

structure_hooks = [
(
Optional[
Expand Down Expand Up @@ -940,6 +1022,41 @@ def _notebook_sync_option_selector_hook(
],
_position_encoding_hook,
),
(
Optional[Union[bool, lsp_types.SemanticTokensRegistrationOptionsFullType1]],
_semantic_token_registration_options_hook,
),
(
Optional[Union[bool, lsp_types.InlineCompletionOptions]],
_inline_completion_provider_hook,
),
(
Optional[
Union[
lsp_types.InlineCompletionList, List[lsp_types.InlineCompletionItem]
]
],
_inline_completion_list_hook,
),
(
Union[str, lsp_types.StringValue],
_string_value_hook,
),
(
Optional[
Union[
List[lsp_types.SymbolInformation], List[lsp_types.WorkspaceSymbol]
]
],
_symbol_list_hook,
),
(
Union[
lsp_types.NotebookDocumentSyncRegistrationOptionsNotebookSelectorType1,
lsp_types.NotebookDocumentSyncRegistrationOptionsNotebookSelectorType2,
],
_notebook_sync_registration_option_selector_hook,
),
]
for type_, hook in structure_hooks:
converter.register_structure_hook(type_, hook)
Expand Down
34 changes: 34 additions & 0 deletions tests/python/test_generated_data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.

import json
import pathlib
from typing import Generator, List, Union

import pytest

import lsprotocol.converters as cv
import lsprotocol.types as lsp

TEST_DATA_ROOT = pathlib.Path(__file__).parent.parent.parent / "packages" / "testdata"


def get_all_json_files(root: Union[pathlib.Path, str]) -> List[pathlib.Path]:
root_path = pathlib.Path(root)
return list(root_path.glob("**/*.json"))


converter = cv.get_converter()


@pytest.mark.parametrize("json_file", get_all_json_files(TEST_DATA_ROOT))
def test_generated_data(json_file: str) -> None:
type_name, result_type, _ = json_file.name.split("-", 2)
lsp_type = getattr(lsp, type_name)
data = json.loads(json_file.read_text(encoding="utf-8"))

try:
converter.structure(data, lsp_type)
assert result_type == "True", "Expected error, but succeeded structuring"
except Exception as e:
assert result_type == "False", "Expected success, but failed structuring"

0 comments on commit 05a4341

Please sign in to comment.