Skip to content

Commit 36e543a

Browse files
author
pacrob
committed
async test_contract_data_filters
1 parent d8d2fd9 commit 36e543a

File tree

4 files changed

+270
-41
lines changed

4 files changed

+270
-41
lines changed

tests/core/filtering/conftest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,6 @@ async def async_return_filter(contract=None, args=[]):
204204
return await contract.events[event_name].create_filter(**kwargs)
205205

206206

207-
@pytest_asyncio.fixture()
207+
@pytest_asyncio.fixture(scope="module")
208208
async def async_create_filter(request):
209209
return async_partial(async_return_filter)

tests/core/filtering/test_contract_data_filters.py

Lines changed: 252 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,28 @@
1+
import asyncio
12
import pytest
23

34
from hypothesis import (
45
given,
56
settings,
67
strategies as st,
78
)
9+
import pytest_asyncio
810

9-
from web3 import Web3
11+
from tests.core.filtering.utils import (
12+
_async_emitter_fixture_logic,
13+
_async_w3_fixture_logic,
14+
_emitter_fixture_logic,
15+
_w3_fixture_logic,
16+
)
17+
from tests.utils import (
18+
_async_wait_for_block_fixture_logic,
19+
_async_wait_for_transaction_fixture_logic,
20+
)
1021
from web3._utils.module_testing.emitter_contract import (
1122
CONTRACT_EMITTER_ABI,
1223
CONTRACT_EMITTER_CODE,
1324
CONTRACT_EMITTER_RUNTIME,
1425
)
15-
from web3.middleware import (
16-
local_filter_middleware,
17-
)
18-
from web3.providers.eth_tester import (
19-
EthereumTesterProvider,
20-
)
21-
22-
23-
@pytest.fixture(
24-
scope="module",
25-
params=[True, False],
26-
ids=["local_filter_middleware", "node_based_filter"],
27-
)
28-
def w3(request):
29-
use_filter_middleware = request.param
30-
provider = EthereumTesterProvider()
31-
w3 = Web3(provider)
32-
if use_filter_middleware:
33-
w3.middleware_onion.add(local_filter_middleware)
34-
return w3
3526

3627

3728
@pytest.fixture(scope="module")
@@ -58,25 +49,6 @@ def EMITTER(EMITTER_CODE, EMITTER_RUNTIME, EMITTER_ABI):
5849
}
5950

6051

61-
@pytest.fixture(scope="module")
62-
def Emitter(w3, EMITTER):
63-
return w3.eth.contract(**EMITTER)
64-
65-
66-
@pytest.fixture(scope="module")
67-
def emitter(w3, Emitter, wait_for_transaction, wait_for_block, address_conversion_func):
68-
wait_for_block(w3)
69-
deploy_txn_hash = Emitter.constructor().transact({"gas": 10000000})
70-
deploy_receipt = wait_for_transaction(w3, deploy_txn_hash)
71-
contract_address = address_conversion_func(deploy_receipt["contractAddress"])
72-
73-
bytecode = w3.eth.get_code(contract_address)
74-
assert bytecode == Emitter.bytecode_runtime
75-
_emitter = Emitter(address=contract_address)
76-
assert _emitter.address == contract_address
77-
return _emitter
78-
79-
8052
def not_empty_string(x):
8153
return x != ""
8254

@@ -130,6 +102,30 @@ def array_values(draw):
130102
return (matching, non_matching)
131103

132104

105+
# --- sync --- #
106+
107+
108+
@pytest.fixture(
109+
scope="module",
110+
params=[True, False],
111+
ids=["local_filter_middleware", "node_based_filter"],
112+
)
113+
def w3(request):
114+
return _w3_fixture_logic(request)
115+
116+
117+
@pytest.fixture(scope="module")
118+
def Emitter(w3, EMITTER):
119+
return w3.eth.contract(**EMITTER)
120+
121+
122+
@pytest.fixture(scope="module")
123+
def emitter(w3, Emitter, wait_for_transaction, wait_for_block, address_conversion_func):
124+
return _emitter_fixture_logic(
125+
w3, Emitter, wait_for_transaction, wait_for_block, address_conversion_func
126+
)
127+
128+
133129
@pytest.mark.parametrize("api_style", ("v4", "build_filter"))
134130
@given(vals=dynamic_values())
135131
@settings(max_examples=5, deadline=None)
@@ -284,3 +280,219 @@ def test_data_filters_with_list_arguments(
284280
else:
285281
with pytest.raises(TypeError):
286282
create_filter(emitter, ["LogListArgs", {"filter": {"arg1": matching}}])
283+
284+
285+
# --- async --- #
286+
287+
288+
@pytest_asyncio.fixture(scope="module")
289+
async def async_wait_for_block():
290+
return _async_wait_for_block_fixture_logic
291+
292+
293+
@pytest_asyncio.fixture(scope="module")
294+
async def async_wait_for_transaction():
295+
return _async_wait_for_transaction_fixture_logic
296+
297+
298+
@pytest.fixture(scope="module")
299+
def event_loop():
300+
policy = asyncio.get_event_loop_policy()
301+
loop = policy.new_event_loop()
302+
yield loop
303+
loop.close()
304+
305+
306+
@pytest.fixture(
307+
scope="module",
308+
params=[True, False],
309+
ids=["local_filter_middleware", "node_based_filter"],
310+
)
311+
def async_w3(request):
312+
return _async_w3_fixture_logic(request)
313+
314+
315+
@pytest_asyncio.fixture(scope="module")
316+
def AsyncEmitter(async_w3, EMITTER):
317+
return async_w3.eth.contract(**EMITTER)
318+
319+
320+
@pytest_asyncio.fixture(scope="module")
321+
async def async_emitter(
322+
async_w3,
323+
AsyncEmitter,
324+
async_wait_for_transaction,
325+
async_wait_for_block,
326+
address_conversion_func,
327+
):
328+
return await _async_emitter_fixture_logic(
329+
async_w3,
330+
AsyncEmitter,
331+
async_wait_for_transaction,
332+
async_wait_for_block,
333+
address_conversion_func,
334+
)
335+
336+
337+
@pytest.mark.asyncio
338+
@pytest.mark.parametrize("api_style", ("v4", "build_filter"))
339+
@given(vals=dynamic_values())
340+
@settings(max_examples=5, deadline=None)
341+
async def test_async_data_filters_with_dynamic_arguments(
342+
async_w3,
343+
async_wait_for_transaction,
344+
async_create_filter,
345+
async_emitter,
346+
api_style,
347+
vals,
348+
):
349+
if api_style == "build_filter":
350+
filter_builder = async_emitter.events.LogDynamicArgs.build_filter()
351+
filter_builder.args["arg1"].match_single(vals["matching"])
352+
event_filter = await filter_builder.deploy(async_w3)
353+
else:
354+
event_filter = await async_create_filter(
355+
async_emitter, ["LogDynamicArgs", {"filter": {"arg1": vals["matching"]}}]
356+
)
357+
358+
txn_hashes = [
359+
await async_emitter.functions.logDynamicArgs(
360+
arg0=vals["matching"], arg1=vals["matching"]
361+
).transact(
362+
{"maxFeePerGas": 10**9, "maxPriorityFeePerGas": 10**9, "gas": 400000}
363+
),
364+
await async_emitter.functions.logDynamicArgs(
365+
arg0=vals["non_matching"][0], arg1=vals["non_matching"][0]
366+
).transact(
367+
{"maxFeePerGas": 10**9, "maxPriorityFeePerGas": 10**9, "gas": 400000}
368+
),
369+
]
370+
371+
for txn_hash in txn_hashes:
372+
await async_wait_for_transaction(async_w3, txn_hash)
373+
374+
log_entries = await event_filter.get_new_entries()
375+
assert len(log_entries) == 1
376+
assert log_entries[0]["transactionHash"] == txn_hashes[0]
377+
378+
379+
@pytest.mark.asyncio
380+
@pytest.mark.parametrize("api_style", ("v4", "build_filter"))
381+
@given(vals=fixed_values())
382+
@settings(max_examples=5, deadline=None)
383+
async def test_async_data_filters_with_fixed_arguments(
384+
async_w3,
385+
async_emitter,
386+
async_wait_for_transaction,
387+
async_create_filter,
388+
api_style,
389+
vals,
390+
):
391+
if api_style == "build_filter":
392+
filter_builder = async_emitter.events.LogQuadrupleArg.build_filter()
393+
filter_builder.args["arg0"].match_single(vals["matching"][0])
394+
filter_builder.args["arg1"].match_single(vals["matching"][1])
395+
filter_builder.args["arg2"].match_single(vals["matching"][2])
396+
filter_builder.args["arg3"].match_single(vals["matching"][3])
397+
event_filter = await filter_builder.deploy(async_w3)
398+
else:
399+
event_filter = await async_create_filter(
400+
async_emitter,
401+
[
402+
"LogQuadrupleArg",
403+
{
404+
"filter": {
405+
"arg0": vals["matching"][0],
406+
"arg1": vals["matching"][1],
407+
"arg2": vals["matching"][2],
408+
"arg3": vals["matching"][3],
409+
}
410+
},
411+
],
412+
)
413+
414+
txn_hashes = []
415+
txn_hashes.append(
416+
await async_emitter.functions.logQuadruple(
417+
which=5,
418+
arg0=vals["matching"][0],
419+
arg1=vals["matching"][1],
420+
arg2=vals["matching"][2],
421+
arg3=vals["matching"][3],
422+
).transact(
423+
{"maxFeePerGas": 10**9, "maxPriorityFeePerGas": 10**9, "gas": 100000}
424+
)
425+
)
426+
txn_hashes.append(
427+
await async_emitter.functions.logQuadruple(
428+
which=5,
429+
arg0=vals["non_matching"][0],
430+
arg1=vals["non_matching"][1],
431+
arg2=vals["non_matching"][2],
432+
arg3=vals["non_matching"][3],
433+
).transact(
434+
{"maxFeePerGas": 10**9, "maxPriorityFeePerGas": 10**9, "gas": 100000}
435+
)
436+
)
437+
438+
for txn_hash in txn_hashes:
439+
await async_wait_for_transaction(async_w3, txn_hash)
440+
441+
log_entries = await event_filter.get_new_entries()
442+
assert len(log_entries) == 1
443+
assert log_entries[0]["transactionHash"] == txn_hashes[0]
444+
445+
446+
@pytest.mark.asyncio
447+
@pytest.mark.parametrize("api_style", ("v4", "build_filter"))
448+
@given(vals=array_values())
449+
@settings(max_examples=5, deadline=None)
450+
async def test_async_data_filters_with_list_arguments(
451+
async_w3,
452+
async_emitter,
453+
async_wait_for_transaction,
454+
async_create_filter,
455+
api_style,
456+
vals,
457+
):
458+
matching, non_matching = vals
459+
460+
if api_style == "build_filter":
461+
filter_builder = async_emitter.events.LogListArgs.build_filter()
462+
filter_builder.args["arg1"].match_single(matching)
463+
event_filter = await filter_builder.deploy(async_w3)
464+
465+
txn_hashes = []
466+
txn_hashes.append(
467+
await async_emitter.functions.logListArgs(
468+
arg0=matching, arg1=matching
469+
).transact({"maxFeePerGas": 10**9, "maxPriorityFeePerGas": 10**9})
470+
)
471+
txn_hashes.append(
472+
await async_emitter.functions.logListArgs(
473+
arg0=non_matching, arg1=non_matching
474+
).transact({"maxFeePerGas": 10**9, "maxPriorityFeePerGas": 10**9})
475+
)
476+
txn_hashes.append(
477+
await async_emitter.functions.logListArgs(
478+
arg0=non_matching, arg1=matching
479+
).transact({"maxFeePerGas": 10**9, "maxPriorityFeePerGas": 10**9})
480+
)
481+
txn_hashes.append(
482+
await async_emitter.functions.logListArgs(
483+
arg0=matching, arg1=non_matching
484+
).transact({"maxFeePerGas": 10**9, "maxPriorityFeePerGas": 10**9})
485+
)
486+
487+
for txn_hash in txn_hashes:
488+
await async_wait_for_transaction(async_w3, txn_hash)
489+
490+
log_entries = await event_filter.get_new_entries()
491+
assert len(log_entries) == 2
492+
assert log_entries[0]["transactionHash"] == txn_hashes[0]
493+
assert log_entries[1]["transactionHash"] == txn_hashes[2]
494+
else:
495+
with pytest.raises(TypeError):
496+
await async_create_filter(
497+
async_emitter, ["LogListArgs", {"filter": {"arg1": matching}}]
498+
)

tests/core/filtering/test_contract_on_event_filtering.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import asyncio
12
import pytest
23

34
from eth_utils import (
@@ -217,6 +218,14 @@ def test_on_sync_filter_with_topic_filter_options_on_old_apis(
217218
# --- async --- #
218219

219220

221+
@pytest.fixture(scope="module")
222+
def event_loop():
223+
policy = asyncio.get_event_loop_policy()
224+
loop = policy.new_event_loop()
225+
yield loop
226+
loop.close()
227+
228+
220229
@pytest.mark.asyncio
221230
@pytest.mark.parametrize("call_as_instance", (True, False))
222231
async def test_async_create_filter_address_parameter(

tests/core/filtering/test_contract_past_event_filtering.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import asyncio
12
import pytest
23

34
from eth_utils import (
@@ -89,6 +90,13 @@ def test_get_all_entries_returned_block_data(
8990

9091
# --- async --- #
9192

93+
@pytest.fixture(scope="module")
94+
def event_loop():
95+
policy = asyncio.get_event_loop_policy()
96+
loop = policy.new_event_loop()
97+
yield loop
98+
loop.close()
99+
92100

93101
@pytest.mark.asyncio
94102
@pytest.mark.parametrize("call_as_instance", (True, False))

0 commit comments

Comments
 (0)