Add a token refresh test that exhibits an API race issue
parent
5dac8fa44d
commit
5339f754a1
|
@ -2,15 +2,19 @@
|
||||||
Questrade broker testing
|
Questrade broker testing
|
||||||
"""
|
"""
|
||||||
import time
|
import time
|
||||||
|
import logging
|
||||||
|
|
||||||
import trio
|
import trio
|
||||||
import tractor
|
|
||||||
from trio.testing import trio_test
|
from trio.testing import trio_test
|
||||||
|
import tractor
|
||||||
from tractor.testing import tractor_test
|
from tractor.testing import tractor_test
|
||||||
from piker.brokers import questrade as qt
|
from piker.brokers import questrade as qt
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
|
log = tractor.get_logger('tests')
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(autouse=True)
|
@pytest.fixture(autouse=True)
|
||||||
def check_qt_conf_section(brokerconf):
|
def check_qt_conf_section(brokerconf):
|
||||||
"""Skip this module's tests if we have not quetrade API creds.
|
"""Skip this module's tests if we have not quetrade API creds.
|
||||||
|
@ -101,6 +105,49 @@ def match_packet(symbols, quotes, feed_type='stock'):
|
||||||
assert not quotes
|
assert not quotes
|
||||||
|
|
||||||
|
|
||||||
|
async def intermittently_refresh_tokens():
|
||||||
|
async with qt.get_client() as client:
|
||||||
|
try:
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
log.info("REFRESHING TOKENS!")
|
||||||
|
await client.ensure_access(force_refresh=True)
|
||||||
|
await trio.sleep(0.3)
|
||||||
|
except Exception:
|
||||||
|
log.exception("Token refresh failed")
|
||||||
|
finally:
|
||||||
|
with trio.open_cancel_scope(shield=True):
|
||||||
|
async with qt.get_client() as client:
|
||||||
|
await client.ensure_access(force_refresh=True)
|
||||||
|
|
||||||
|
|
||||||
|
# XXX: demonstrates the shoddy API QT serves
|
||||||
|
@pytest.mark.skip
|
||||||
|
@tractor_test
|
||||||
|
async def test_concurrent_tokens_refresh(us_symbols, loglevel):
|
||||||
|
async with qt.get_client() as client:
|
||||||
|
|
||||||
|
# async with tractor.open_nursery() as n:
|
||||||
|
# await n.run_in_actor('other', intermittently_refresh_tokens)
|
||||||
|
|
||||||
|
async with trio.open_nursery() as n:
|
||||||
|
n.start_soon(intermittently_refresh_tokens)
|
||||||
|
|
||||||
|
quoter = await qt.stock_quoter(client, us_symbols)
|
||||||
|
|
||||||
|
async def get_quotes():
|
||||||
|
for tries in range(10):
|
||||||
|
log.info(f"{tries}: GETTING QUOTES!")
|
||||||
|
quotes = await quoter(us_symbols)
|
||||||
|
await trio.sleep(0.1)
|
||||||
|
|
||||||
|
await get_quotes()
|
||||||
|
|
||||||
|
# shutdown
|
||||||
|
# await n.cancel()
|
||||||
|
n.cancel_scope.cancel()
|
||||||
|
|
||||||
|
|
||||||
@trio_test
|
@trio_test
|
||||||
async def test_batched_stock_quote(us_symbols):
|
async def test_batched_stock_quote(us_symbols):
|
||||||
"""Use the client stock quote api and verify quote response format.
|
"""Use the client stock quote api and verify quote response format.
|
||||||
|
@ -201,13 +248,13 @@ async def stream_option_chain(portal, symbols):
|
||||||
broker='questrade',
|
broker='questrade',
|
||||||
symbols=[sub],
|
symbols=[sub],
|
||||||
feed_type='option',
|
feed_type='option',
|
||||||
rate=4,
|
rate=3,
|
||||||
diff_cached=False,
|
diff_cached=False,
|
||||||
)
|
)
|
||||||
# latency arithmetic
|
# latency arithmetic
|
||||||
loops = 8
|
loops = 8
|
||||||
rate = 1/3. # 3 rps
|
period = 1/3. # 3 rps
|
||||||
timeout = loops / rate
|
timeout = loops / period
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# wait on the data streamer to actually start
|
# wait on the data streamer to actually start
|
||||||
|
|
Loading…
Reference in New Issue