1# Copyright 2018 Palantir Technologies, Inc. 2# pylint: disable=redefined-outer-name 3from io import BytesIO 4import datetime 5import os 6import sys 7import mock 8import pytest 9 10from pyls_jsonrpc.streams import JsonRpcStreamReader, JsonRpcStreamWriter 11 12 13@pytest.fixture() 14def rfile(): 15 return BytesIO() 16 17 18@pytest.fixture() 19def wfile(): 20 return BytesIO() 21 22 23@pytest.fixture() 24def reader(rfile): 25 return JsonRpcStreamReader(rfile) 26 27 28@pytest.fixture() 29def writer(wfile): 30 return JsonRpcStreamWriter(wfile, sort_keys=True) 31 32 33def test_reader(rfile, reader): 34 rfile.write( 35 b'Content-Length: 49\r\n' 36 b'Content-Type: application/vscode-jsonrpc; charset=utf8\r\n' 37 b'\r\n' 38 b'{"id": "hello", "method": "method", "params": {}}' 39 ) 40 rfile.seek(0) 41 42 consumer = mock.Mock() 43 reader.listen(consumer) 44 45 consumer.assert_called_once_with({ 46 'id': 'hello', 47 'method': 'method', 48 'params': {} 49 }) 50 51 52def test_reader_bad_message(rfile, reader): 53 rfile.write(b'Hello world') 54 rfile.seek(0) 55 56 # Ensure the listener doesn't throw 57 consumer = mock.Mock() 58 reader.listen(consumer) 59 consumer.assert_not_called() 60 61 62def test_reader_bad_json(rfile, reader): 63 rfile.write( 64 b'Content-Length: 8\r\n' 65 b'Content-Type: application/vscode-jsonrpc; charset=utf8\r\n' 66 b'\r\n' 67 b'{hello}}' 68 ) 69 rfile.seek(0) 70 71 # Ensure the listener doesn't throw 72 consumer = mock.Mock() 73 reader.listen(consumer) 74 consumer.assert_not_called() 75 76 77def test_writer(wfile, writer): 78 writer.write({ 79 'id': 'hello', 80 'method': 'method', 81 'params': {} 82 }) 83 84 if os.name == 'nt': 85 assert wfile.getvalue() == ( 86 b'Content-Length: 49\r\n' 87 b'Content-Type: application/vscode-jsonrpc; charset=utf8\r\n' 88 b'\r\n' 89 b'{"id": "hello", "method": "method", "params": {}}' 90 ) 91 else: 92 assert wfile.getvalue() == ( 93 b'Content-Length: 44\r\n' 94 b'Content-Type: application/vscode-jsonrpc; charset=utf8\r\n' 95 b'\r\n' 96 b'{"id":"hello","method":"method","params":{}}' 97 ) 98 99 100class JsonDatetime(datetime.datetime): 101 """Monkey path json datetime.""" 102 def __json__(self): 103 if sys.version_info.major == 3: 104 dif = int(self.timestamp()) 105 else: 106 dif = int((self - datetime.datetime(1970, 1, 1)).total_seconds()) 107 return '{0}'.format(dif) 108 109 110def test_writer_bad_message(wfile, writer): 111 # A datetime isn't serializable(or poorly serializable), 112 # ensure the write method doesn't throw, but the result could be empty 113 # or the correct datetime 114 datetime.datetime = JsonDatetime 115 writer.write(datetime.datetime( 116 year=2019, 117 month=1, 118 day=1, 119 hour=1, 120 minute=1, 121 second=1, 122 )) 123 124 assert wfile.getvalue() in [ 125 b'', 126 b'Content-Length: 10\r\n' 127 b'Content-Type: application/vscode-jsonrpc; charset=utf8\r\n' 128 b'\r\n' 129 b'1546304461' 130 ] 131