mirror of
https://github.com/MaskRay/ccls.git
synced 2024-11-25 17:11:59 +00:00
168 lines
3.5 KiB
Python
168 lines
3.5 KiB
Python
import json
|
|
import shlex
|
|
from subprocess import Popen, PIPE
|
|
|
|
# Content-Length: ...\r\n
|
|
# \r\n
|
|
# {
|
|
# "jsonrpc": "2.0",
|
|
# "id": 1,
|
|
# "method": "textDocument/didOpen",
|
|
# "params": {
|
|
# ...
|
|
# }
|
|
# }
|
|
|
|
# We write test files in python. The test runner collects all python files in
|
|
# the directory and executes them. The test function just creates a test object
|
|
# which specifies expected stdin/stdout.
|
|
#
|
|
# Test functions are automatically discovered; they just need to be in the
|
|
# global environment and start with `Test_`.
|
|
|
|
class TestBuilder:
|
|
def __init__(self):
|
|
self.files = []
|
|
self.sent = []
|
|
self.received = []
|
|
|
|
def WithFile(self, filename, contents):
|
|
"""
|
|
Writes the file contents to disk so that the language server can access it.
|
|
"""
|
|
self.files.append((filename, contents))
|
|
return self
|
|
|
|
def Send(self, stdin):
|
|
"""
|
|
Send the given message to the language server.
|
|
"""
|
|
stdin['jsonrpc'] = '2.0'
|
|
self.sent.append(stdin)
|
|
return self
|
|
|
|
def Expect(self, stdout):
|
|
"""
|
|
Expect a message from the language server.
|
|
"""
|
|
self.received.append(stdout)
|
|
return self
|
|
|
|
def SetupCommonInit(self):
|
|
"""
|
|
Add initialize/initialized messages.
|
|
"""
|
|
self.Send({
|
|
'id': 0,
|
|
'method': 'initialize',
|
|
'params': {
|
|
'processId': 123,
|
|
'rootPath': 'cquery',
|
|
'capabilities': {},
|
|
'trace': 'off'
|
|
}
|
|
})
|
|
self.Expect({
|
|
'id': 0,
|
|
'method': 'initialized',
|
|
'result': {}
|
|
})
|
|
return self
|
|
|
|
def _ExecuteTest(name, func):
|
|
"""
|
|
Executes a specific test.
|
|
|
|
|func| must return a TestBuilder object.
|
|
"""
|
|
test_builder = func()
|
|
if not isinstance(test_builder, TestBuilder):
|
|
raise Exception('%s does not return a TestBuilder instance' % name)
|
|
|
|
test_builder.Send({ 'method': 'exit' })
|
|
|
|
# Possible test runner implementation
|
|
cmd = "x64/Debug/indexer.exe --language-server"
|
|
process = Popen(shlex.split(cmd), stdin=PIPE, stdout=PIPE, stderr=PIPE, universal_newlines=True)
|
|
|
|
stdin = ''
|
|
for message in test_builder.sent:
|
|
payload = json.dumps(message)
|
|
wrapped = 'Content-Length: %s\r\n\r\n%s' % (len(payload), payload)
|
|
stdin += wrapped
|
|
|
|
print('## %s ##' % name)
|
|
print('== STDIN ==')
|
|
print(stdin)
|
|
(stdout, stderr) = process.communicate(stdin)
|
|
if stdout:
|
|
print('== STDOUT ==')
|
|
print(stdout)
|
|
if stderr:
|
|
print('== STDERR ==')
|
|
print(stderr)
|
|
|
|
# TODO: Actually verify stdout.
|
|
|
|
exit_code = process.wait()
|
|
|
|
def _DiscoverTests():
|
|
"""
|
|
Discover and return all tests.
|
|
"""
|
|
for name, value in globals().items():
|
|
if not callable(value):
|
|
continue
|
|
if not name.startswith('Test_'):
|
|
continue
|
|
yield (name, value)
|
|
|
|
def _RunTests():
|
|
"""
|
|
Executes all tests.
|
|
"""
|
|
for name, func in _DiscoverTests():
|
|
print('Running test function %s' % name)
|
|
_ExecuteTest(name, func)
|
|
|
|
|
|
|
|
|
|
class lsSymbolKind:
|
|
Function = 1
|
|
|
|
def lsSymbolInfo(name, position, kind):
|
|
return {
|
|
'name': name,
|
|
'position': position,
|
|
'kind': kind
|
|
}
|
|
|
|
def Test_Init():
|
|
return (TestBuilder()
|
|
.SetupCommonInit()
|
|
)
|
|
|
|
def _Test_Outline():
|
|
return (TestBuilder()
|
|
.SetupCommonInit()
|
|
.WithFile("foo.cc",
|
|
"""
|
|
void main() {}
|
|
"""
|
|
)
|
|
.Send({
|
|
'id': 1,
|
|
'method': 'textDocument/documentSymbol',
|
|
'params': {}
|
|
})
|
|
.Expect({
|
|
'id': 1,
|
|
'result': [
|
|
lsSymbolInfo('void main()', (1, 1), lsSymbolKind.Function)
|
|
]
|
|
}))
|
|
|
|
|
|
if __name__ == '__main__':
|
|
_RunTests() |