Skip to content

Commit 91d8bdc

Browse files
committed
parser: More tests
1 parent 3cd4b8f commit 91d8bdc

File tree

12 files changed

+230
-28
lines changed

12 files changed

+230
-28
lines changed

parser/snooty/gizaparser/nodes.py

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import re
55
from dataclasses import dataclass, field
66
from pathlib import Path, PurePath
7-
from typing import cast, Any, Callable, Dict, Set, Generic, Optional, \
7+
from typing import cast, Callable, Dict, Set, Generic, Optional, \
88
TypeVar, Tuple, Iterator, Sequence, List, Union
99
from ..flutter import checked
1010
from ..types import Diagnostic, Page, EmbeddedRstParser, SerializableType, ProjectConfig
@@ -242,21 +242,3 @@ def render_heading(self, parse_rst: EmbeddedRstParser) -> Sequence[SerializableT
242242
'position': {'start': {'line': self.line}},
243243
'children': result
244244
},)
245-
246-
247-
def ast_to_testing_string(ast: Any) -> str:
248-
value = ast.get('value', '')
249-
children = ast.get('children', [])
250-
attrs = ' '.join(
251-
'{}="{}"'.format(k, v) for k, v in ast.items() if k not in (
252-
'argument', 'value', 'children', 'type', 'position') and v)
253-
contents = value if value else (''.join(
254-
ast_to_testing_string(child) for child in children)
255-
if children else '')
256-
if 'argument' in ast:
257-
contents = ''.join(ast_to_testing_string(part) for part in ast['argument']) + contents
258-
return '<{}{}>{}</{}>'.format(
259-
ast['type'],
260-
' ' + attrs if attrs else '',
261-
contents,
262-
ast['type'])

parser/snooty/gizaparser/test_extracts.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
from pathlib import Path, PurePath
22
from typing import Dict, Tuple, List
33
from .extracts import GizaExtractsCategory
4-
from .nodes import ast_to_testing_string
54
from ..types import Diagnostic, Page, EmbeddedRstParser, ProjectConfig
65
from ..parser import make_embedded_rst_parser
6+
from ..util import ast_to_testing_string
77

88

99
def test_extract() -> None:
@@ -32,6 +32,7 @@ def add_child_file() -> List[Diagnostic]:
3232
all_diagnostics[path] = add_main_file()
3333
all_diagnostics[child_path] = add_child_file()
3434

35+
assert len(category) == 2
3536
file_id, giza_node = next(category.reify_all_files(all_diagnostics))
3637

3738
def create_page() -> Tuple[Page, EmbeddedRstParser]:

parser/snooty/gizaparser/test_nodes.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ def test_substitution() -> None:
3838
substituted_string = 'testing substitution. test.'
3939
assert nodes.substitute_text(test_string, replacements) == substituted_string
4040

41+
obj = object()
42+
assert nodes.substitute(obj, replacements) is obj
43+
4144
# Test complex substitution
4245
node = SubstitutionTest(
4346
foo=test_string,
@@ -56,3 +59,15 @@ def test_substitution() -> None:
5659
# Ensure the identity of the zero-substitutions case remains the same
5760
test_string = 'foo'
5861
assert nodes.substitute_text(test_string, {}) is test_string
62+
63+
64+
def test_inheritance() -> None:
65+
parent = nodes.Inheritable('parent', {'foo': 'bar', 'old': ''}, source=None, inherit=None)
66+
child = nodes.Inheritable(
67+
'child',
68+
{'bar': 'baz', 'old': 'new'},
69+
source=nodes.Inherit('self.yaml', 'parent'),
70+
inherit=None)
71+
child = nodes.inherit(child, parent)
72+
73+
assert child.replacement == {'foo': 'bar', 'bar': 'baz', 'old': 'new'}

parser/snooty/gizaparser/test_steps.py

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
from pathlib import Path, PurePath
22
from typing import Dict, Tuple, List
33
from .steps import GizaStepsCategory
4-
from .nodes import ast_to_testing_string
54
from ..types import Diagnostic, Page, EmbeddedRstParser, ProjectConfig
65
from ..parser import make_embedded_rst_parser
6+
from ..util import ast_to_testing_string
77

88

99
def test_step() -> None:
@@ -31,6 +31,7 @@ def add_child_file() -> List[Diagnostic]:
3131
all_diagnostics[path] = add_main_file()
3232
all_diagnostics[child_path] = add_child_file()
3333

34+
assert len(category) == 2
3435
file_id, giza_node = next(category.reify_all_files(all_diagnostics))
3536

3637
def create_page() -> Tuple[Page, EmbeddedRstParser]:
@@ -49,17 +50,24 @@ def create_page() -> Tuple[Page, EmbeddedRstParser]:
4950

5051
'<directive name="step"><section><heading><text>Create a </text><literal><text>',
5152
'/etc/apt/sources.list.d/mongodb-org-3.4.list</text></literal><text> file for MongoDB.',
52-
'</text></heading><paragraph><text>Create the list file using the command appropriate for ',
53-
'your version\nof Debian.</text></paragraph></section></directive>',
53+
'</text></heading>',
54+
'<section><heading><text>Optional: action heading</text></heading>'
55+
'<paragraph><text>Create the list file using the command appropriate for ',
56+
'your version\nof Debian.</text></paragraph>',
57+
'<paragraph><text>action-content</text></paragraph>',
58+
'<paragraph><text>action-post</text></paragraph>',
59+
'</section></section></directive>',
5460

5561
'<directive name="step"><section><heading><text>Reload local package database.</text>',
5662
'</heading><paragraph><text>Issue the following command to reload the local package ',
5763
'database:</text></paragraph><code lang="sh" copyable="True">sudo apt-get update\n</code>',
5864
'</section></directive>',
5965

6066
'<directive name="step"><section><heading><text>Install the MongoDB packages.</text>',
61-
'</heading><paragraph><text>You can install either the latest stable version of MongoDB ',
67+
'</heading><paragraph><text>hi</text></paragraph>',
68+
'<paragraph><text>You can install either the latest stable version of MongoDB ',
6269
'or a\nspecific version of MongoDB.</text></paragraph>',
6370
'<directive name="code-block">',
64-
'<text>sh</text><literal></literal></directive></section></directive></directive>'
71+
'<text>sh</text><literal></literal></directive><paragraph><text>bye</text></paragraph>',
72+
'</section></directive></directive>'
6573
))

parser/snooty/language_server.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ class WorkspaceEntry:
162162
document_uri: Uri
163163
diagnostics: List[types.Diagnostic]
164164

165-
def create_lsp_diagnostics(self) -> object:
165+
def create_lsp_diagnostics(self) -> List[object]:
166166
return [{
167167
'range': {
168168
'start': {

parser/snooty/rstparser.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
PAT_EXPLICIT_TILE = re.compile(r'^(?P<label>.+?)\s*(?<!\x00)<(?P<target>.*?)>$', re.DOTALL)
2121
PAT_WHITESPACE = re.compile(r'^\x20*')
2222
PAT_BLOCK_HAS_ARGUMENT = re.compile(r'^\x20*\.\.\x20[^\s]+::\s*\S+')
23-
SPECIAL_DIRECTIVES = {'code-block', 'include', 'tabs-drivers', 'tabs', 'tabs-platforms', 'only'}
23+
SPECIAL_DIRECTIVES = {'code-block', 'include', 'only'}
2424

2525

2626
@checked
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import sys
2+
import time
3+
from dataclasses import dataclass
4+
from pathlib import Path
5+
from . import language_server
6+
from .types import Diagnostic
7+
from .flutter import checked, check_type
8+
9+
10+
@checked
11+
@dataclass
12+
class LSPPosition:
13+
line: int
14+
character: int
15+
16+
17+
@checked
18+
@dataclass
19+
class LSPRange:
20+
start: LSPPosition
21+
end: LSPPosition
22+
23+
24+
@checked
25+
@dataclass
26+
class LSPDiagnostic:
27+
message: str
28+
severity: int
29+
range: LSPRange
30+
31+
32+
def test_debounce() -> None:
33+
bounces = [0]
34+
35+
@language_server.debounce(0.1)
36+
def inc() -> None:
37+
bounces[0] += 1
38+
39+
inc()
40+
inc()
41+
inc()
42+
43+
time.sleep(0.2)
44+
inc()
45+
46+
assert bounces[0] == 1
47+
48+
49+
def test_pid_exists() -> None:
50+
assert language_server.pid_exists(0)
51+
# Test that an invalid PID returns False
52+
assert not language_server.pid_exists(537920)
53+
54+
55+
def test_workspace_entry() -> None:
56+
entry = language_server.WorkspaceEntry('', '', [
57+
Diagnostic.error('foo', 10),
58+
Diagnostic.warning('fo', 10, 12),
59+
])
60+
parsed = [check_type(LSPDiagnostic, diag) for diag in entry.create_lsp_diagnostics()]
61+
assert parsed[0] == LSPDiagnostic('foo', 1, LSPRange(LSPPosition(10, 0), LSPPosition(10, 1000)))
62+
assert parsed[1] == LSPDiagnostic('fo', 2, LSPRange(LSPPosition(10, 0), LSPPosition(12, 1000)))
63+
64+
65+
def test_language_server() -> None:
66+
server = language_server.LanguageServer(sys.stdin.buffer, sys.stdout.buffer)
67+
assert server.uri_to_path('file://foo.rst') == Path('foo.rst')

parser/snooty/test_main.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import builtins
2+
from pathlib import PurePath
3+
from typing import Any, List
4+
from .types import Diagnostic
5+
from . import main
6+
7+
8+
def test_backend() -> None:
9+
messages: List[str] = []
10+
11+
def test_print(*values: Any, **kwargs: Any) -> None:
12+
messages.extend(str(val) for val in values)
13+
14+
backend = main.Backend()
15+
orig_print = builtins.print
16+
builtins.print = test_print
17+
try:
18+
backend.on_diagnostics(PurePath('foo/bar.rst'), [
19+
Diagnostic.error('an error', 10, 12),
20+
Diagnostic.error('another error', (10, 0), (12, 30))])
21+
backend.on_diagnostics(PurePath('foo/foo.rst'), [Diagnostic.warning('a warning', 10)])
22+
assert backend.total_warnings == 3
23+
finally:
24+
builtins.print = orig_print
25+
26+
assert messages == [
27+
'ERROR(foo/bar.rst:10ish): an error',
28+
'ERROR(foo/bar.rst:10ish): another error',
29+
'WARNING(foo/foo.rst:10ish): a warning'
30+
]

parser/snooty/test_parser.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
from pathlib import Path
2+
from . import rstparser
3+
from .util import ast_to_testing_string
4+
from .types import ProjectConfig
5+
from .parser import parse_rst, JSONVisitor
6+
7+
8+
def test_tabs() -> None:
9+
root = Path('test_data')
10+
tabs_path = Path(root).joinpath(Path('test_tabs.rst'))
11+
project_config = ProjectConfig(root, '')
12+
parser = rstparser.Parser(project_config, JSONVisitor)
13+
page, diagnostics = parse_rst(parser, tabs_path, None)
14+
15+
assert ast_to_testing_string(page.ast) == ''.join((
16+
'<root>',
17+
18+
'<directive name="tabs"><directive name="tab"><text>bionic</text>',
19+
'<paragraph><text>Bionic content</text></paragraph></directive>',
20+
21+
'<directive name="tab"><text>xenial</text><paragraph><text>',
22+
'Xenial content</text></paragraph></directive>',
23+
24+
'<directive name="tab"><text>trusty</text><paragraph><text>',
25+
'Trusty content</text></paragraph></directive></directive>',
26+
27+
'<directive name="tabs"><directive name="tab"><text>trusty</text><paragraph><text>',
28+
'Trusty content</text></paragraph></directive>',
29+
30+
'<directive name="tab"><text>xenial</text><paragraph><text>',
31+
'Xenial content</text></paragraph></directive></directive>',
32+
33+
'</root>'
34+
))
35+
36+
assert len(diagnostics) == 1 and \
37+
diagnostics[0].message.startswith('Unexpected field') and \
38+
diagnostics[0].start[0] == 36

parser/snooty/util.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import os
22
import docutils.nodes
33
from pathlib import Path, PurePath
4-
from typing import cast, Container, Optional, Tuple, Iterator
4+
from typing import cast, Any, Container, Optional, Tuple, Iterator
55

66

77
def reroot_path(filename: PurePath,
@@ -46,3 +46,21 @@ def line_of_node(node: docutils.nodes.Node) -> Optional[int]:
4646
node = node.parent
4747

4848
return cast(int, line_of_node(node)) - 1
49+
50+
51+
def ast_to_testing_string(ast: Any) -> str:
52+
value = ast.get('value', '')
53+
children = ast.get('children', [])
54+
attrs = ' '.join(
55+
'{}="{}"'.format(k, v) for k, v in ast.items() if k not in (
56+
'argument', 'value', 'children', 'type', 'position') and v)
57+
contents = value if value else (''.join(
58+
ast_to_testing_string(child) for child in children)
59+
if children else '')
60+
if 'argument' in ast:
61+
contents = ''.join(ast_to_testing_string(part) for part in ast['argument']) + contents
62+
return '<{}{}>{}</{}>'.format(
63+
ast['type'],
64+
' ' + attrs if attrs else '',
65+
contents,
66+
ast['type'])

0 commit comments

Comments
 (0)