async def test_parties_can_be_added_after_run_forever(sandbox): async with async_network(url=sandbox, dars=PostOffice) as network: operator_client = network.aio_new_party() party_a_client = network.aio_new_party() party_b_client = network.aio_new_party() # TODO: Introduce a Party allocation API separate from client creation party_c_party = str(uuid.uuid4()) @operator_client.ledger_ready() def operator_ready(event): return create("Main:PostmanRole", {"postman": event.party}) @operator_client.ledger_created("Main:PostmanRole") def operator_role_created(event): return [ exercise(event.cid, "InviteParticipant", { "party": party, "address": "whatevs" }) for party in (party_a_client.party, party_b_client.party, party_c_party) ] @party_a_client.ledger_created("Main:InviteAuthorRole") async def party_a_accept_invite(_): party_c = network.aio_party(party_c_party) @party_c.ledger_created("Main:AuthorRole") def party_c_role_created(_): network.shutdown() cid, cdata = await party_c.find_one("Main:InviteAuthorRole") party_c.submit_exercise(cid, "AcceptInviteAuthorRole") network.start()
async def test_cancelled_write(sandbox): async with async_network(url=sandbox, dars=Pending) as network: client = network.aio_new_party() network.start() # Submit a command, but _immediately_ cancel it. Because there are no awaits, this code # cannot have possibly been interrupted by the coroutine responsible for scheduling a write # to the server, so the command should be cancelled. fut = client.create("Pending:Counter", { "owner": client.party, "value": 66 }) ensure_future(fut).cancel() # Immediately afterwards, schedule another command submission; this time, we wait for it. fut = client.create("Pending:Counter", { "owner": client.party, "value": 7 }) await fut data = client.find_active("Pending:Counter") assert len(data) == 1 assert list(data.values())[0]["value"] == 7
async def test_variant_dotted_fields_submit(sandbox): async with async_network(url=sandbox, dars=DottedFields) as network: client = network.aio_new_party() network.start() await client.ready() await client.submit_create( "DottedFields:Person", { "person": client.party, "address.US.address": "1 Test Place", "address.US.city": "Somewhere", "address.US.state": "ZZ", "address.US.zip": "99999", "address.UK.address": "", "address.UK.locality": "", "address.UK.city": "", "address.UK.state": "", "address.UK.postcode": "", }, ) items = client.find_active("DottedFields:Person") assert len(items) == 1
async def test_select_template_retrieves_contracts(sandbox): number_of_contracts = 10 async with async_network(url=sandbox, dars=Pending) as network: client = network.aio_new_party() client.add_ledger_ready(lambda _: [ CreateCommand(Counter, { "owner": client.party, "value": 0 }), *[ CreateCommand(AccountRequest, {"owner": client.party}) for _ in range(number_of_contracts) ], ]) @client.ledger_created(AccountRequest) async def on_account_request(event): counter_cid, counter_cdata = await event.acs_find_one(Counter) return [ ExerciseCommand(event.cid, "CreateAccount", dict(accountId=counter_cdata["value"])), ExerciseCommand(counter_cid, "Increment"), ] await network.aio_run(keep_open=False) data = client.find_active(Account) assert len(data) == number_of_contracts
async def test_server_endpoint(sandbox): SERVER_PORT = 53390 async with async_network(url=sandbox, dars=TestServerDar) as network: network.set_config(server_port=SERVER_PORT) alice_client = network.aio_new_party() alice = alice_client.party bob_client = network.aio_new_party() bob = bob_client.party carol_client = network.aio_new_party() carol = carol_client.party # create Person contracts for each party for party in [alice, bob, carol]: ensure_person_contract(network, party) # have Bob start up "suspended"; we'll start up Bob from the outside bob_bot = bob_client._impl.bots.add_new("Bob's Bot") bob_bot.pause() @bob_bot.ledger_created('TestServer:Person') def bob_sends_a_message(_): return exercise_by_key( 'TestServer:Person', bob, 'SayHello', {'receiver': alice, 'text': "Bob's ultra secret message"}) @carol_client.ledger_created('TestServer:Person') def carol_sends_a_message(_): return exercise_by_key( 'TestServer:Person', carol, 'SayHello', {'receiver': alice, 'text': "Carol's gonna Carol"}) # Carol will start Bob only once Alice has processed three events await network.aio_run(client_main(network, SERVER_PORT, alice, bob, carol), keep_open=False)
async def test_select_reflects_archive_events(sandbox): notification_count = 3 # we expect that, upon each on_created notification of an OperatorNotification contract, # when we query the ACS, we get precisely the same number of contracts. expected_select_count = notification_count * notification_count actual_select_count = 0 def on_notification_contract(event): nonlocal actual_select_count actual_select_count += len(event.acs_find_active(OperatorNotification)) async with async_network(url=sandbox, dars=Simple) as network: client = network.aio_new_party() client.add_ledger_ready( lambda e: create(OperatorRole, {'operator': client.party})) client.add_ledger_created( OperatorRole, lambda e: exercise(e.cid, 'PublishMany', dict(count=3))) client.add_ledger_created(OperatorNotification, lambda e: exercise(e.cid, 'Archive')) client.add_ledger_created(OperatorNotification, on_notification_contract) network.start() final_select_count = len(client.find_active(OperatorNotification)) assert actual_select_count == expected_select_count assert 0 == final_select_count
async def test_select_template_retrieves_contracts(sandbox): number_of_contracts = 10 async with async_network(url=sandbox, dars=Pending) as network: client = network.aio_new_party() client.add_ledger_ready(lambda _: [ create(Counter, { 'owner': client.party, 'value': 0 }), *[ create(AccountRequest, {'owner': client.party}) for i in range(number_of_contracts) ], ]) @client.ledger_created(AccountRequest) async def on_account_request(event): counter_cid, counter_cdata = await event.acs_find_one(Counter) return [ exercise(event.cid, 'CreateAccount', dict(accountId=counter_cdata['value'])), exercise(counter_cid, 'Increment') ] await network.aio_run(keep_open=False) data = client.find_active(Account) assert len(data) == number_of_contracts
async def test_complicated_map_support(sandbox): # This test will be re-enabled when GenMap support lands in DAML-LF 1.9 async with async_network(url=sandbox, dars=MapSupport) as network: client = network.aio_new_party() await client.ready() await client.create( "MapSupport:ComplicatedSample", { "party": "Test", # Note: Python `dict`s are not hashable, so the only way to write this out # is to create a special dict as a key "keyIsMap": { frozendict(A="b"): "mmm" }, "keyIsRecord": { frozendict(x=2, y=4): "rrr" }, "keyIsRecordWithTypeParam": { frozendict(x=2, y=4): "rrr" }, "keyIsVariant": { frozendict(Apple=""): "ttt" }, }, ) assert len(client.find_active("*")) == 1
async def test_complicated_map_support(sandbox): # This test will be re-enabled when GenMap support lands in DAML-LF 1.9 async with async_network(url=sandbox, dars=MapSupport) as network: client = network.aio_new_party() await client.ready() await client.submit_create( 'MapSupport:ComplicatedSample', { 'party': 'Test', # Note: Python `dict`s are not hashable, so the only way to write this out # is to create a special dict as a key 'keyIsMap': { frozendict(A='b'): 'mmm' }, 'keyIsRecord': { frozendict(x=2, y=4): 'rrr' }, 'keyIsRecordWithTypeParam': { frozendict(x=2, y=4): 'rrr' }, 'keyIsVariant': { frozendict(Apple=''): 'ttt' } }) assert len(client.find_active('*')) == 1
async def test_maps(sandbox): async with async_network(url=sandbox, dars=AllKindsOf) as network: client = network.aio_new_party() network.start() await client.submit_create( "AllKindsOf:MappyContract", {"operator": client.party, "value": {"Map_internal": []}} )
async def test_select_star_on_empty_ledger_retrieves_nothing(sandbox): async with async_network(url=sandbox, dars=Simple) as network: client = network.aio_new_party() network.start() data = client.find_active("*") assert len(data) == 0
async def test_event_handler_exceptions(sandbox): async with async_network(url=sandbox, dars=PostOffice) as network: client = network.aio_new_party() def throw_error(event: ReadyEvent): raise MagicException(event.ledger_id) client.add_ledger_ready(throw_error) network.start()
async def test_select_unknown_template_retrieves_empty_set(sandbox): async with async_network(url=sandbox, dars=Simple) as network: client = network.aio_new_party() network.start() await client.submit_create(OperatorRole, {'operator': client.party}) data = client.find_active('NonExistentModule:NonExistentTemplate') assert len(data) == 0
async def test_select_template_retrieves_contracts(sandbox): async with async_network(url=sandbox, dars=Simple) as network: client = network.aio_new_party() network.start() await client.submit_create(OperatorRole, {'operator': client.party}) data = client.find_active(OperatorRole) assert len(data) == 1
async def test_maps(sandbox): async with async_network(url=sandbox, dars=AllKindsOf) as network: client = network.aio_new_party() network.start() await client.submit_create('AllKindsOf:MappyContract', { 'operator': client.party, 'value': { 'Map_internal': [] } })
async def test_select_unknown_template_retrieves_empty_set(sandbox): async with async_network(url=sandbox, dars=Simple) as network: client = network.aio_new_party() network.start() await client.create(OperatorRole, {"operator": client.party}) with pytest.warns(UnknownTemplateWarning): data = client.find_active("NonExistentModule:NonExistentTemplate") assert len(data) == 0
async def test_map_support(sandbox): async with async_network(url=sandbox, dars=MapSupport) as network: client = network.aio_new_party() network.start() await client.ready() await client.submit_create( "MapSupport:Sample", {"party": client.party, "mappings": {"65": "A", "97": "a"}, "text": None}, ) assert len(client.find_active("*")) == 1
async def test_template_filtering(sandbox): # First, create a few contracts stretching across two DARs and validate that all of those # contracts show up in the active contract set. async_network will supply the list of DARs to # dazl. async with async_network(url=sandbox, dars=[AllParty, PostOffice]) as network: client = network.aio_new_party() # Remember the party, because we're going to reconnect as this party, but with a restricted # set of DARs. party = client.party network.start() await client.submit([ create('AllParty:PrivateContract', {'someParty': party}), create('AllParty:PrivateContract', {'someParty': party}), create('AllParty:PrivateContract', {'someParty': party}), create('Main:PostmanRole', {'postman': party}), create('Main:PostmanRole', {'postman': party}), ]) # The ACS should only contain the five contracts we created: two from Post Office, and three # from AllKindsOf. contracts = client.find_active("*") assert len(contracts) == 5 # Now create a new client to the same sandbox, but with less DARs async with async_network(url=sandbox, dars=[PostOffice]) as network: client = network.aio_party(party) network.start() await client.ready() # The ACS should only contain the two contracts we created that were part of the Post Office # model. contracts = client.find_active("*") assert len(contracts) == 2
async def test_select_template_retrieves_contracts(sandbox): seen_notifications = [] async with async_network(url=sandbox, dars=Simple) as network: client = network.aio_new_party() client.add_ledger_created( OperatorNotification, lambda event: seen_notifications.append(event.cid)) await network.aio_run(async_test_case(client), keep_open=False) data = client.find_active(OperatorNotification) assert len(data) == 5 assert len(seen_notifications) == 8
async def test_package_loading(sandbox): d = {} with DarFile(AllKindsOf) as dar: expected_package_ids = dar.get_package_provider().get_package_ids() async with async_network(url=sandbox, dars=AllKindsOf) as network: client = network.aio_new_party() client.add_ledger_ready(lambda event: setitem(d, 'metadata', event.package_store)) network.start() store: PackageStore = d['metadata'] actual_package_ids = store.package_ids() assert set(expected_package_ids).issubset(set(actual_package_ids))
async def test_map_support(sandbox): async with async_network(url=sandbox, dars=MapSupport) as network: client = network.aio_new_party() network.start() await client.ready() await client.submit_create( 'MapSupport:Sample', { 'party': client.party, 'mappings': { '65': 'A', '97': 'a' }, 'text': None }) assert len(client.find_active('*')) == 1
async def test_record_dotted_fields_submit(sandbox): async with async_network(url=sandbox, dars=DottedFields) as network: client = network.aio_new_party() network.start() await client.ready() await client.submit_create( 'DottedFields:American', { 'person': client.party, 'address.address': '1 Test Place', 'address.city': 'Somewhere', 'address.state': 'ZZ', 'address.zip': '99999' }) items = client.find_active('DottedFields:American') assert len(items) == 1
async def test_record_dotted_fields_submit(sandbox): async with async_network(url=sandbox, dars=DottedFields) as network: client = network.aio_new_party() network.start() await client.ready() await client.submit_create( "DottedFields:American", { "person": client.party, "address.address": "1 Test Place", "address.city": "Somewhere", "address.state": "ZZ", "address.zip": "99999", }, ) items = client.find_active("DottedFields:American") assert len(items) == 1
async def test_complicated_types(sandbox): recorded_data = dict() async with async_network(url=sandbox, dars=ComplicatedDar) as network: party_client = network.aio_new_party() party_client.add_ledger_ready(lambda event: create( Complicated.OperatorRole, {"operator": event.party})) party_client.add_ledger_created(Complicated.OperatorRole, _create_empty_notification) party_client.add_ledger_created(Complicated.OperatorRole, _create_complicated_notifications) party_client.add_ledger_created( Complicated.OperatorFormulaNotification, lambda e: setitem(recorded_data, e.cid, e.cdata), ) network.start() logging.info("got to the end with contracts: %s", recorded_data) assert len(recorded_data) == 4
async def test_all_types(sandbox): async with async_network(url=sandbox, dars=AllKindsOf) as network: client = network.aio_new_party() test_case = AllTypesTestCase(client.party) client.add_ledger_ready(test_case.create_one_of_everything) client.add_ledger_created(TEMPLATE, test_case.on_one_of_everything) network.start() assert test_case.found_instance is not None, "Expected to find an instance of OneOfEverything!" assert (SOME_ARGS.keys() == test_case.found_instance.keys() ), "There are either extra fields or missing fields!" for key in SOME_ARGS: if key != "operator": expected = SOME_ARGS.get(key) actual = test_case.found_instance.get(key) assert expected == actual, f"Failed to compare types for key: {key}"
async def test_some_party_receives_public_contract(sandbox): some_party_cids = [] publisher_cids = [] # TODO: Switch to a Party allocation API when available. all_party = Party(str(uuid.uuid4())) async with async_network(url=sandbox, dars=AllPartyDar) as network: network.set_config(party_groups=[all_party]) some_client = network.aio_new_party() some_client.add_ledger_ready(lambda _: some_client.create( PrivateContract, {"someParty": some_client.party})) publisher_client = network.aio_new_party() publisher_client.add_ledger_ready( lambda _: publisher_client.create(PublicContract, { "publisher": publisher_client.party, "allParty": all_party })) some_client.add_ledger_created(PublicContract, lambda e: some_party_cids.append(e.cid)) some_client.add_ledger_created(PrivateContract, lambda e: some_party_cids.append(e.cid)) publisher_client.add_ledger_created( PublicContract, lambda e: publisher_cids.append(e.cid)) publisher_client.add_ledger_created( PrivateContract, lambda e: publisher_cids.append(e.cid)) network.start() logging.info( "got to the end with some_party contracts: %s and publisher contracts: %s", some_party_cids, publisher_cids, ) assert len(some_party_cids) == 2 assert len(publisher_cids) == 1
async def test_static_dump_and_tail(sandbox): async with async_network(url=sandbox, dars=PostOffice) as network: client = network.aio_new_party() seen_contracts = [] @client.ledger_ready() def print_initial_state(event): LOG.info("Current ACS: %s", event.acs_find_active("*")) @client.ledger_created("*") def print_create(event): LOG.info("Seen cid: %s, cdata: %s", event.cid, event.cdata) seen_contracts.append(event.cid) network.start() await client.ready() for i in range(0, 5): await client.create("Main:PostmanRole", {"postman": client.party}) assert len(seen_contracts) == 5
async def test_select_operates_on_acs_before_event_handlers(sandbox): notification_count = 3 # we expect that, upon each on_created notification of an OperatorNotification contract, # when we query the ACS, we get precisely the same number of contracts. expected_select_count = notification_count * notification_count actual_select_count = 0 def on_notification_contract(_): nonlocal actual_select_count actual_select_count += len(client.find_active(OperatorNotification)) async with async_network(url=sandbox, dars=Simple) as network: client = network.aio_new_party() client.add_ledger_ready(lambda e: client.create(OperatorRole, {"operator": client.party})) client.add_ledger_created( OperatorRole, lambda e: client.exercise(e.cid, "PublishMany", dict(count=3)) ) client.add_ledger_created(OperatorNotification, on_notification_contract) network.start() assert actual_select_count == expected_select_count
async def test_variant_dotted_fields_submit(sandbox): async with async_network(url=sandbox, dars=DottedFields) as network: client = network.aio_new_party() network.start() await client.ready() await client.submit_create( 'DottedFields:Person', { 'person': client.party, 'address.US.address': '1 Test Place', 'address.US.city': 'Somewhere', 'address.US.state': 'ZZ', 'address.US.zip': '99999', 'address.UK.address': '', 'address.UK.locality': '', 'address.UK.city': '', 'address.UK.state': '', 'address.UK.postcode': '', }) items = client.find_active('DottedFields:Person') assert len(items) == 1