195 lines
6.5 KiB
Python
195 lines
6.5 KiB
Python
import asyncio
|
|
import os
|
|
import sys
|
|
|
|
# Assuming the structure of test_shared_methods based on common unittest methods
|
|
|
|
root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))))
|
|
sys.path.append(root)
|
|
|
|
from ccxt import ExchangeClosedByUser
|
|
from ccxt.async_support.base.ws.future import Future
|
|
|
|
# Helper functions
|
|
async def resolve_later(future, result, delay):
|
|
await asyncio.sleep(delay)
|
|
future.resolve(result)
|
|
|
|
async def cancel_later(future, delay):
|
|
await asyncio.sleep(delay)
|
|
future.cancel()
|
|
|
|
async def reject_later(future, err, delay):
|
|
await asyncio.sleep(delay)
|
|
future.reject(err)
|
|
|
|
async def test_resolve_before():
|
|
print("test_resolve")
|
|
future = Future()
|
|
expected_result = "test"
|
|
future.resolve(expected_result)
|
|
assert future.done(), "Future is not marked as done"
|
|
assert future.result() == expected_result, f"Expected result '{expected_result}', got '{future.result()}'"
|
|
|
|
async def test_reject():
|
|
print("test_reject")
|
|
future = Future()
|
|
test_exception = Exception("test error")
|
|
future.reject(test_exception)
|
|
assert future.done(), "Future is not marked as done"
|
|
try:
|
|
future.result()
|
|
assert False, "Expected an exception but none was raised"
|
|
except Exception as e:
|
|
assert str(e) == "test error", f"Expected 'test error', got '{str(e)}'"
|
|
|
|
async def test_race_success_before():
|
|
print("test_race_success")
|
|
future1 = Future()
|
|
future2 = Future()
|
|
race_future = Future.race([future1, future2])
|
|
future1.resolve("first")
|
|
result = await race_future
|
|
future2.cancel()
|
|
assert result == "first", f"Expected 'first', got '{result}'"
|
|
|
|
async def test_race_success_after():
|
|
print("test_race_success")
|
|
future1 = Future()
|
|
future2 = Future()
|
|
race_future = Future.race([future1, future2])
|
|
asyncio.create_task(resolve_later(future1, "first", 0.01))
|
|
result = await race_future
|
|
future2.cancel()
|
|
assert result == "first", f"Expected 'first', got '{result}'"
|
|
|
|
async def test_race_return_first_exception():
|
|
print("test_race_return_first_exception")
|
|
future1 = Future()
|
|
race_future = Future.race([future1])
|
|
future1.reject(Exception("Error in future1"))
|
|
try:
|
|
await race_future
|
|
assert False, "Expected an exception but none was raised"
|
|
except Exception as e:
|
|
assert str(e) == "Error in future1", f"Expected 'Error in future1', got '{str(e)}'"
|
|
|
|
async def test_await_canceled_future():
|
|
print("test_await_canceled_future")
|
|
future = Future()
|
|
try:
|
|
future.cancel()
|
|
await future
|
|
assert False, "Expected an exception but none was raised"
|
|
except asyncio.CancelledError as e:
|
|
assert isinstance(e, asyncio.CancelledError), "Expected asyncio.CancelledError"
|
|
|
|
async def test_cancel():
|
|
print("test_cancel")
|
|
future = Future()
|
|
asyncio.create_task(cancel_later(future, 0.1))
|
|
try:
|
|
await future
|
|
assert False, "Expected an exception but none was raised"
|
|
except asyncio.CancelledError as e:
|
|
assert isinstance(e, asyncio.CancelledError), "Expected asyncio.CancelledError"
|
|
|
|
async def test_race_cancel():
|
|
print("test_race_cancel")
|
|
try:
|
|
future1 = Future()
|
|
future2 = Future()
|
|
race_future = Future.race([future1, future2])
|
|
race_future.cancel()
|
|
future1.resolve("success")
|
|
await race_future
|
|
assert False, "Expected a cancelledError"
|
|
except asyncio.CancelledError:
|
|
assert True
|
|
|
|
async def test_race_mixed_outcomes():
|
|
print("test_race_mixed_outcome")
|
|
future1 = Future()
|
|
future2 = Future()
|
|
race_future = Future.race([future1, future2])
|
|
future1.resolve("first")
|
|
task = asyncio.create_task(reject_later(future2, Exception("Error in future2"), 0.1))
|
|
result = await race_future
|
|
assert result == "first", f"Expected 'first', got '{result}'"
|
|
task.cancel()
|
|
future2.cancel()
|
|
|
|
async def test_race_with_wait_for_timeout():
|
|
print("test_race_with_wait_for_timeout")
|
|
future1 = Future()
|
|
|
|
task = asyncio.create_task(resolve_later(future1, "completed first", 2))
|
|
|
|
# Attempt to race the futures with a timeout shorter than their resolution time
|
|
try:
|
|
race_future = Future.race([future1])
|
|
await asyncio.wait_for(race_future, timeout=1) # Timeout is set deliberately short
|
|
assert False, "Expected a timeout but race_future completed"
|
|
except asyncio.TimeoutError:
|
|
# Expected outcome, the race_future should not complete within the timeout
|
|
assert True
|
|
await task
|
|
|
|
async def test_race_with_wait_for_completion():
|
|
print("test_race_with_wait_for_completion")
|
|
future1 = Future()
|
|
future2 = Future()
|
|
|
|
task = asyncio.create_task(resolve_later(future1, "completed first", 0.1))
|
|
|
|
# Race the futures with a timeout longer than necessary
|
|
try:
|
|
race_future = Future.race([future1, future2])
|
|
result = await asyncio.wait_for(race_future, timeout=1)
|
|
assert result == "completed first", f"Unexpected race result: {result}"
|
|
except asyncio.TimeoutError:
|
|
assert False, "Did not expect a timeout"
|
|
await task
|
|
|
|
async def test_race_with_precompleted_future():
|
|
print("test_race_with_precompleted_future")
|
|
future1 = Future()
|
|
future2 = Future()
|
|
future1.resolve("immediate success")
|
|
# Immediately resolved future before race call
|
|
race_future = Future.race([future1, future2])
|
|
result = await race_future
|
|
assert result == "immediate success", "Race did not correctly prioritize already completed future."
|
|
|
|
async def test_closed_by_user():
|
|
print("test_closed_by_user")
|
|
future1 = Future()
|
|
future2 = Future()
|
|
race_future = Future.race([future1, future2])
|
|
task1 = asyncio.create_task(reject_later(future1, ExchangeClosedByUser(), 0.1))
|
|
task2 = asyncio.create_task(reject_later(future2, ExchangeClosedByUser(), 0.1))
|
|
try:
|
|
await race_future
|
|
assert False, "Expected an ExchangeClosedByUser"
|
|
except ExchangeClosedByUser:
|
|
assert True
|
|
assert task1.done()
|
|
assert task2.done()
|
|
except Exception as e:
|
|
assert False, f"Received Exception {e}"
|
|
|
|
async def test_ws_future():
|
|
await test_resolve_before()
|
|
await test_reject()
|
|
await test_race_success_before()
|
|
await test_race_return_first_exception()
|
|
await test_cancel()
|
|
await test_await_canceled_future()
|
|
await test_race_cancel()
|
|
await test_race_mixed_outcomes()
|
|
await test_race_with_wait_for_timeout()
|
|
await test_race_with_wait_for_completion()
|
|
await test_race_with_precompleted_future()
|
|
await test_closed_by_user()
|
|
|