|
1 | 1 | import json |
| 2 | +import sys |
2 | 3 | import re |
3 | 4 | import pytest |
4 | 5 | import asyncio |
@@ -114,16 +115,35 @@ async def test_testnet_url(): |
114 | 115 | async def test_message_handling(clientAsync): |
115 | 116 | """Test message handling with various message types""" |
116 | 117 | # Test valid message |
117 | | - valid_msg = {"id": "123", "result": {"test": "data"}} |
118 | | - result = clientAsync.ws_api._handle_message(json.dumps(valid_msg)) |
| 118 | + future = asyncio.Future() |
| 119 | + clientAsync.ws_api._responses["123"] = future |
| 120 | + valid_msg = {"id": "123", "status": 200, "result": {"test": "data"}} |
| 121 | + clientAsync.ws_api._handle_message(json.dumps(valid_msg)) |
| 122 | + result = await clientAsync.ws_api._responses["123"] |
119 | 123 | assert result == valid_msg |
| 124 | + |
| 125 | +@pytest.mark.asyncio |
| 126 | +async def test_message_handling_raise_exception(clientAsync): |
| 127 | + with pytest.raises(BinanceAPIException): |
| 128 | + future = asyncio.Future() |
| 129 | + clientAsync.ws_api._responses["123"] = future |
| 130 | + valid_msg = {"id": "123", "status": 400, "error": {"code": "0", "msg": "error message"}} |
| 131 | + clientAsync.ws_api._handle_message(json.dumps(valid_msg)) |
| 132 | + await future |
| 133 | +@pytest.mark.asyncio |
| 134 | +async def test_message_handling_raise_exception_without_id(clientAsync): |
| 135 | + with pytest.raises(BinanceAPIException): |
| 136 | + future = asyncio.Future() |
| 137 | + clientAsync.ws_api._responses["123"] = future |
| 138 | + valid_msg = {"id": "123", "status": 400, "error": {"code": "0", "msg": "error message"}} |
| 139 | + clientAsync.ws_api._handle_message(json.dumps(valid_msg)) |
| 140 | + await future |
| 141 | + |
| 142 | +@pytest.mark.asyncio |
| 143 | +async def test_message_handling_invalid_json(clientAsync): |
| 144 | + with pytest.raises(json.JSONDecodeError): |
| 145 | + clientAsync.ws_api._handle_message("invalid json") |
120 | 146 |
|
121 | | - # Test message without ID |
122 | | - no_id_msg = {"data": "test"} |
123 | | - result = clientAsync.ws_api._handle_message(json.dumps(no_id_msg)) |
124 | | - assert result == no_id_msg |
125 | | - |
126 | | - # Test invalid JSON |
127 | 147 | with pytest.raises(json.JSONDecodeError): |
128 | 148 | clientAsync.ws_api._handle_message("invalid json") |
129 | 149 |
|
@@ -151,3 +171,51 @@ async def test_cleanup_on_exit(clientAsync): |
151 | 171 | # Check cleanup |
152 | 172 | assert "test" not in clientAsync.ws_api._responses |
153 | 173 | assert future.exception() is not None |
| 174 | + |
| 175 | + |
| 176 | +@pytest.mark.asyncio |
| 177 | +async def test_ws_queue_overflow(clientAsync): |
| 178 | + """WebSocket API should not overflow queue""" |
| 179 | + # |
| 180 | + original_size = clientAsync.ws_api.MAX_QUEUE_SIZE |
| 181 | + clientAsync.ws_api.MAX_QUEUE_SIZE = 1 |
| 182 | + |
| 183 | + try: |
| 184 | + # Request multiple order books concurrently |
| 185 | + symbols = ["BTCUSDT", "ETHUSDT", "BNBUSDT"] |
| 186 | + tasks = [clientAsync.ws_get_order_book(symbol=symbol) for symbol in symbols] |
| 187 | + |
| 188 | + # Execute all requests concurrently and wait for results |
| 189 | + results = await asyncio.gather(*tasks, return_exceptions=True) |
| 190 | + |
| 191 | + # Check that we got valid responses or expected overflow errors |
| 192 | + valid_responses = [r for r in results if not isinstance(r, Exception)] |
| 193 | + assert len(valid_responses) == len(symbols), "Should get at least one valid response" |
| 194 | + |
| 195 | + for result in valid_responses: |
| 196 | + assert_ob(result) |
| 197 | + |
| 198 | + finally: |
| 199 | + # Restore original queue size |
| 200 | + clientAsync.ws_api.MAX_QUEUE_SIZE = original_size |
| 201 | + |
| 202 | +@pytest.mark.skipif(sys.version_info < (3, 8), reason="websockets_proxy Python 3.8+") |
| 203 | +@pytest.mark.asyncio |
| 204 | +async def test_ws_api_with_stream(clientAsync): |
| 205 | + """Test combining WebSocket API requests with stream listening""" |
| 206 | + from binance import BinanceSocketManager |
| 207 | + |
| 208 | + # Create socket manager and trade socket |
| 209 | + bm = BinanceSocketManager(clientAsync) |
| 210 | + ts = bm.trade_socket("BTCUSDT") |
| 211 | + |
| 212 | + async with ts: |
| 213 | + # Make WS API request while stream is active |
| 214 | + order_book = await clientAsync.ws_get_order_book(symbol="BTCUSDT") |
| 215 | + assert_ob(order_book) |
| 216 | + |
| 217 | + # Verify we can still receive stream data |
| 218 | + trade = await ts.recv() |
| 219 | + assert "s" in trade # Symbol |
| 220 | + assert "p" in trade # Price |
| 221 | + assert "q" in trade # Quantity |
0 commit comments