async def test_startup_errors_should_halt_ready(): """ Ensure that a failure to connect aborts ready futures. """ network = Network() network.set_config(url="http://nowhere.at.all.localdomain:6865/", connect_timeout=1) client = network.aio_party("SillyParty") # place the ready() call BEFORE the run f = ensure_future(wait_for(client.ready(), 2)) try: await network.aio_run(keep_open=False) except Exception: pass try: await f raise AssertionError( "client.ready() should not have ended because there is nothing to connect to" ) except asyncio.TimeoutError: raise AssertionError( "client.ready() did not abort with an appropriate exception and was killed because " "it was taking too long") except CancelledError: LOG.info("Successfully terminated because ready() was cancelled.")
async def test_package_events(sandbox): initial_events = [] follow_up_events = [] network = Network() network.set_config(url=sandbox) client = network.aio_new_party() async def upload_dars_and_verify(): # make sure the client is "ready" before uploading DARs, because we are explicitly # checking to make sure proper reporting of packages that are uploaded after a # client is running and # operational await client.ready() await upload_test_dars(network) await (await network.aio_global().metadata()).package_loader.load_all() # give the client some time to pick up the new packages; unfortunately there isn't # much more to do here except wait await sleep(10) client.add_ledger_packages_added(lambda _: initial_events.append(_), initial=True) client.add_ledger_packages_added(lambda _: follow_up_events.append(_)) await network.aio_run(upload_dars_and_verify(), keep_open=False) assert len(initial_events) == 2 assert len(follow_up_events) == 1
class Setup: def __init__(self, url, dar): self.url = url self.party = None self.dar = dar self.network = None def run(self): # upload our DAR and allocate our Party in a completely separate thread as to try to avoid # polluting the current context t = Thread(target=self._main) t.start() t.join() return self.party def _main(self): # create a private event loop just for us set_event_loop(new_event_loop()) self.network = Network() self.network.set_config(url=self.url) client = self.network.aio_new_party() self.party = client.party self.network.run_until_complete(self.upload_dar()) async def upload_dar(self): await self.network.aio_global().ensure_dar(self.dar)
def test_global_url_propagates_to_parties(): config = NetworkConfig.parse_kwargs(url='http://nowhere/') network = Network() network.set_config(config) client = network.aio_party('Bob') party_config = client.resolved_config() assert party_config.url == 'http://nowhere/'
def _main(self): # create a private event loop just for us set_event_loop(new_event_loop()) self.network = Network() self.network.set_config(url=self.url) client = self.network.aio_new_party() self.party = client.party self.network.run_until_complete(self.upload_dar())
class Stage1LedgerInit: def __init__(self): self.network = Network() self.operator_party = None self.user_parties = None self.done = None self.evt_count = 0 def run(self, url): set_event_loop(new_event_loop()) self.done = asyncio.Event() self.network.set_config(url=url) # TODO: These should be party allocations instead of just random strings. self.user_parties = frozenset( Party(str(uuid.uuid4())) for _ in range(0, PARTY_COUNT)) operator = self.network.aio_new_party() operator.add_ledger_ready(self.on_ready) operator.add_ledger_created(Simple.OperatorRole, self.on_operator) operator.add_ledger_created(Simple.OperatorNotification, self.on_notification) self.operator_party = operator.party self.network.run_until_complete(self.done.wait()) async def on_ready(self, event): await self.network.aio_global().ensure_dar(SimpleDar) while not event.package_store.resolve_template(Simple.OperatorRole): await sleep(1) return create(Simple.OperatorRole, {'operator': event.party}) @staticmethod def on_operator(event): return [ exercise(event.cid, 'Publish', {"text": n}) for n in range(0, NOTIFICATION_COUNT) ] def on_notification(self, event): if self.evt_count == 25: self.done.set() else: self.evt_count += 1 missing_parties = self.user_parties.difference( event.cdata['theObservers']) if missing_parties: return exercise( event.cid, 'Share', {'sharingParty': random.choice(list(missing_parties))})
def __init__(self, url): self.manager1 = Network() self.manager1.set_config(url=url) self.manager2 = Network() self.manager2.set_config(url=url) self.manager1.aio_party(PARTY).add_ledger_ready(self._handle_ready_1) self.manager2.aio_party(PARTY).add_ledger_ready(self._handle_ready_2) self.manager1.aio_party(PARTY).add_ledger_created( 'Main.PostmanRole', self._handle_postman_role_1) self.manager2.aio_party(PARTY).add_ledger_created( 'Main.PostmanRole', self._handle_postman_role_2)
def test_some_party_receives_public_contract(self): some_party_cids = [] publisher_cids = [] with sandbox(AllParty, extra_args=None) as proc: network = Network() network.set_config(url=proc.url, party_groups=[ALL_PARTY]) some_client = network.aio_party(SOME_PARTY) some_client.add_ledger_ready( lambda _: create(PrivateContract, {'someParty': SOME_PARTY})) publisher_client = network.aio_party(PUBLISHER) publisher_client.add_ledger_ready( lambda _: create(PublicContract, { 'publisher': PUBLISHER, '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.run_until_complete() print( f'got to the end with some_party contracts: {some_party_cids} and publisher contracts: {publisher_cids}' ) self.assertEqual(len(some_party_cids), 2) self.assertEqual(len(publisher_cids), 1)
def test_parties_can_be_added_after_run_forever(self): with sandbox(daml_path=DAML_PATH) as proc: network = Network() network.set_config(url=proc.url) operator = network.aio_party('Operator') party_a = network.aio_party('Party A') party_b = network.aio_party('Party B') @operator.ledger_ready() def _(event): return create('Main.PostmanRole', {'postman': 'Operator'}) @operator.ledger_created('Main.PostmanRole') def __(event): return [ exercise(event.cid, 'InviteParticipant', { 'party': party, 'address': 'whatevs' }) for party in ('Party A', 'Party B', 'Party C') ] @party_a.ledger_created('Main.InviteAuthorRole') async def _(event): party_c = network.aio_party('Party C') @party_c.ledger_created('Main.AuthorRole') def ___(event): network.shutdown() cid, cdata = await party_c.find_one('Main.InviteAuthorRole') party_c.submit_exercise(cid, 'AcceptInviteAuthorRole') network.run_forever()
async def client_main( network: Network, server_port: int, alice: "Party", bob: "Party", carol: "Party" ): """ The main method of a client running against the server endpoint exposed by the dazl app above. """ LOG.info("client_main: started.") try: async with ClientSession() as session: await wait_for_ready(session, server_port, [alice, bob, carol]) # start Bob from the administration endpoint bots_response = await session.get(f"http://localhost:{server_port}/bots") bots = await bots_response.json() bobs_bots = [bot for bot in bots["bots"] if bot["party"] == bob] for bobs_bot in bobs_bots: await session.post( f'http://localhost:{server_port}/bots/{bobs_bot["id"]}/state/resume' ) # now make sure Alice received Bob's message, and not Carol's (because Carol was never started) alice_client = network.aio_party(alice) _, cdata = await alice_client.find_one("TestServer:Message") LOG.info("Received message from %r: %r", cdata["sender"], cdata["text"]) all_messages = alice_client.find("TestServer:Message") LOG.info("Alice has a total of %d message(s).", len(all_messages)) if len(all_messages) > 1: raise AssertionError("Alice was only supposed to have one message") LOG.info("client_main: finished.") except Exception: LOG.exception("client_main: failed.")
def register_pingpong_handler(network: dazl.Network, party): party_client = network.aio_party(party) @party_client.ledger_ready() async def init(event: ReadyEvent): cmds = [] pings = event.acs_find_active( 'PingPong.Ping', match=lambda cdata: cdata['receiver'] == party) for pingCid, pingData in pings.items(): cmds.append(send(party, pingCid, 'RespondPong', pingData['count'])) pongs = event.acs_find_active( 'PingPong.Pong', match=lambda cdata: cdata['receiver'] == party) for pongCid, pongData in pongs.items(): cmds.append(send(party, pongCid, 'RespondPing', pongData['count'])) return cmds @party_client.ledger_created('PingPong.Ping') async def ping(event: ContractCreateEvent): if event.cdata['receiver'] == party: await sleep(1) return send(party, event.cid, 'RespondPong', event.cdata['count']) @party_client.ledger_created('PingPong.Pong') async def pong(event: ContractCreateEvent): if event.cdata['receiver'] == party: await sleep(1) return send(party, event.cid, 'RespondPing', event.cdata['count'])
async def client_main(network: Network, server_port: int): """ The main method of a client running against the server endpoint exposed by the dazl app above. """ LOG.info('client_main: started.') try: async with ClientSession() as session: await wait_for_ready(session, server_port, [Alice, Bob, Carol]) # start Bob from the administration endpoint bots_response = await session.get( f'http://localhost:{server_port}/bots') bots = await bots_response.json() bobs_bots = [bot for bot in bots['bots'] if bot['party'] == Bob] for bobs_bot in bobs_bots: await session.post( f'http://localhost:{server_port}/bots/{bobs_bot["id"]}/state/resume' ) # now make sure Alice received Bob's message, and not Carol's (because Carol was never started) alice = network.aio_party(Alice) _, cdata = await alice.find_one('TestServer:Message') LOG.info('Received message from %r: %r', cdata['sender'], cdata['text']) all_messages = alice.find('TestServer:Message') LOG.info('Alice has a total of %d message(s).', len(all_messages)) if len(all_messages) > 1: raise AssertionError( 'Alice was only supposed to have one message') LOG.info('client_main: finished.') except Exception: LOG.exception('client_main: failed.')
def run_test(url, keepalive=False): start_time = datetime.now() members = [dict(party=f'Member {i}', address=address(i)) for i in range(0, MEMBER_PARTY_COUNT)] network = Network() network.set_config(url=url, server_port=8105) postman_client = network.aio_party(POSTMAN_PARTY) member_clients = [network.aio_party(m['party']) for m in members] post_office = PostOffice() postman_client.add_ledger_ready(lambda event: create('Main.PostmanRole', dict(postman=POSTMAN_PARTY))) postman_client.add_ledger_created('Main.PostmanRole', lambda event: [exercise(event.cid, 'InviteParticipant', m) for m in members]) postman_client.add_ledger_created('Main.UnsortedLetter', post_office.sort_and_deliver_letter) postman_client.add_ledger_created('Main.ReceiverRole', post_office.register_address) postman_client.add_ledger_created('Main.SortedLetter', lambda event: exercise(event.cid, 'Deliver')) @postman_client.ledger_exercised('Main.PostmanRole', 'InviteParticipant') def log(event): LOG.info('Observing the exercise of an InviteParticipant: %s', event) for member_client in member_clients: bot = PartyBot(member_client.party) # every member automatically accepts member_client.add_ledger_created('Main.InviteAuthorRole', lambda event: exercise(event.cid, 'AcceptInviteAuthorRole')) member_client.add_ledger_created('Main.InviteReceiverRole', lambda event: exercise(event.cid, 'AcceptInviteReceiverRole')) # every member, upon joining, sends messages to five of their best friends member_client.add_ledger_created('Main.AuthorRole', bot.send_to_five_friends) try: if not keepalive: network.run_until_complete() else: network.run_forever() ledger_run_failed = False except: LOG.exception('The run failed!') ledger_run_failed = True # Display everything, including archived contracts if we terminated for an unexpected reason. write_acs(sys.stdout, network, include_archived=ledger_run_failed) LOG.info('%s letters were received before the recipients were known.', post_office._unsorted_letter_count) LOG.info('Test finished in %s.', datetime.now() - start_time)
def test_select_template_retrieves_contracts(self): number_of_contracts = 10 with sandbox(Pending) as proc: network = Network() network.set_config(url=proc.url) party_client = network.aio_party(PARTY) party_client.add_ledger_ready(lambda _: [ create(Counter, { 'owner': PARTY, 'value': 0 }), *[ create(AccountRequest, {'owner': PARTY}) for i in range(number_of_contracts) ], ]) @party_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') ] network.run_until_complete() data = party_client.find_active(Account) self.assertEqual(len(data), number_of_contracts)
def test_static_dump_and_tail(self): with sandbox(daml_path=DAML_PATH) as proc: seen_contracts = [] network = Network() network.set_config(url=proc.url) client = network.simple_party('PARTY') @client.ledger_ready() def print_initial_state(event): print(event.acs_find_active('*')) @client.ledger_created('*') def print_create(event): print(event.cid, event.cdata) seen_contracts.append(event.cid) async def publish_some_contracts(): aclient = network.aio_party('PARTY') for i in range(0, 5): sleep_interval = random() print(f'Publishing contract {i}, then sleeping for {sleep_interval} seconds...') await aclient.submit_create('Main.PostmanRole', {'postman': 'PARTY'}) await sleep(sleep_interval) network.shutdown() network.run_forever(publish_some_contracts())
def test_select_reflects_archive_events(self): 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)) with sandbox(Simple) as proc: network = Network() network.set_config(url=proc.url) party_client = network.aio_party(PARTY) party_client.add_ledger_ready( lambda e: create(OperatorRole, {'operator': PARTY})) party_client.add_ledger_created( OperatorRole, lambda e: exercise(e.cid, 'PublishMany', dict(count=3))) party_client.add_ledger_created( OperatorNotification, lambda e: exercise(e.cid, 'Archive')) party_client.add_ledger_created(OperatorNotification, on_notification_contract) network.run_until_complete() final_select_count = len( party_client.find_active(OperatorNotification)) self.assertEqual(actual_select_count, expected_select_count) self.assertEqual(0, final_select_count)
def test_package_events(): set_event_loop(new_event_loop()) initial_events = [] follow_up_events = [] with sandbox([]) as proc: network = Network() network.set_config(url=proc.url) client = network.aio_party('TestParty') async def upload_dars_and_verify(): # make sure the client is "ready" before uploading DARs, because we are explicitly # checking to make sure proper reporting of packages that are uploaded after a # client is running and # operational await client.ready() await upload_test_dars(network) # give the client some time to pick up the new packages; unfortunately there isn't # much more to do here except wait await sleep(10) client.add_ledger_packages_added(initial_events.append, initial=True) client.add_ledger_packages_added(follow_up_events.append) network.run_until_complete(upload_dars_and_verify()) assert len(initial_events) == 2 assert len(follow_up_events) == 1
async def test_dar_uploads_near_startup(sandbox): package_ids = [] network = Network() network.set_config(url=sandbox) async def upload_dars_and_verify(): await upload_test_dars(network) metadata = await network.aio_global().metadata() package_ids.extend(network.lookup.package_ids()) await network.aio_run(upload_dars_and_verify(), keep_open=False) # Because we use a single sandbox process, it's somewhat difficult to assert that the specific # DAR we are attempting to upload has indeed been uploaded, because packages are global and # other tests will upload packages as well. However, we know that we HAVE indeed uploaded # SOMETHING, and the Sandbox tests are started without any packages at all. So assume that a # non-zero package ID list means that DAR uploading works. assert len(package_ids) > 0
def run(self, url): network = Network() network.set_config(url=url) operator = network.aio_party(OPERATOR_PARTY) operator.add_ledger_ready(lambda _: create(Simple.OperatorRole, {'operator': OPERATOR_PARTY})) operator.add_ledger_created(Simple.OperatorRole, self.on_operator) operator.add_ledger_created(Simple.OperatorNotification, self.on_notification) network.run_until_complete(asyncio.sleep(15))
def run(self, url): network = Network() network.set_config(url=url) operator = network.aio_party(OPERATOR_PARTY) operator.add_ledger_ready(self.on_ready) operator.add_ledger_created(Simple.OperatorNotification, self.on_notification_created) operator.add_ledger_archived(Simple.OperatorNotification, self.on_notification_archived) network.run_until_complete() self.events.append(('finished', (), ()))
def main(url: str): network = Network() network.set_config(url=url) test_party = network.aio_party('TestA') test_party.add_ledger_ready(ready) test_party.add_ledger_created('Main:PostmanRole', created) other_party = network.aio_party('TestB') other_party.add_ledger_ready(ready) dump_state() network.run_forever()
def init(network: dazl.Network, owner): sender_client = network.aio_party(owner) @sender_client.ledger_ready() async def init(event: ReadyEvent): assets = event.acs_find_active( 'Main.DonorConfig', match=lambda cdata: cdata['owner'] == owner) if len(assets) == 0: logging.info("Initializing DonorConfig for " + owner) return dazl.create('Main.DonorConfig', { 'owner': owner, 'donateTo': 'Alice' })
def register_handler(network: dazl.Network, party): party_client = network.aio_party(party) @party_client.ledger_ready() async def init(event: ReadyEvent): cmds = [] donateTo = None donor_config = event.acs_find_active( 'Main.DonorConfig', match=lambda cdata: cdata['owner'] == party) for donorCid, donorData in donor_config.items(): donateTo = donorData['donateTo'] logging.info("Party: {} is configured to donate to: {}".format( party, donateTo)) assets = event.acs_find_active( 'Main.Asset', match=lambda cdata: cdata['owner'] == party) for assetCid, assetData in assets.items(): if party != donateTo: cmds.append( send(party, assetCid, 'Give', donateTo, assetData['name'])) return cmds @party_client.ledger_created('Main.Asset') async def ping(event: ContractCreateEvent): cmds = [] if event.cdata['owner'] == party: logging.info("New asset created for {}: {}".format( event.cdata['owner'], event.cdata['name'])) #await sleep(1) #return send(party, event.cid, 'RespondPong', event.cdata['count']) donateTo = None donor_config = event.acs_find_active( 'Main.DonorConfig', match=lambda cdata: cdata['owner'] == party) for donorCid, donorData in donor_config.items(): donateTo = donorData['donateTo'] logging.info("Party: {} is configured to donate to: {}".format( party, donateTo)) assets = event.acs_find_active( 'Main.Asset', match=lambda cdata: cdata['owner'] == party) for assetCid, assetData in assets.items(): if party != donateTo: cmds.append( send(party, assetCid, 'Give', donateTo, assetData['name'])) return cmds
def test_select_unknown_template_retrieves_empty_set(self): with sandbox(Simple) as proc: network = Network() network.set_config(url=proc.url) party_client = network.aio_party(PARTY) party_client.add_ledger_ready( lambda e: create(OperatorRole, {'operator': PARTY})) network.run_until_complete() data = party_client.find_active('NonExistentTemplate') self.assertEqual(len(data), 0)
def test_select_template_retrieves_contracts(): with sandbox(Simple) as proc: network = Network() network.set_config(url=proc.url) party_client = network.aio_party(PARTY) party_client.add_ledger_ready( lambda e: create(OperatorRole, {'operator': PARTY})) network.run_until_complete() data = party_client.find_active(OperatorRole) assert len(data) == 1
def _sandbox_test(self, extra_args=None): cids = [] with sandbox(Simple, extra_args=extra_args) as proc: network = Network() network.set_config(url=proc.url) party_client = network.aio_party(PARTY) party_client.add_ledger_ready(lambda _: create(OperatorRole, {'operator': PARTY})) party_client.add_ledger_created(OperatorRole, lambda e: cids.append(e.cid)) network.run_until_complete() print('got to the end with contracts: ', cids) self.assertEqual(len(cids), 1)
def bot_main(sandbox_url, server_port): """ The 'dazl app' being tested. """ network = Network() network.set_config(url=sandbox_url, server_port=server_port) network.aio_party(Alice) bob = network.aio_party(Bob) carol = network.aio_party(Carol) # 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._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.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 network.run_until_complete(client_main(network, server_port))
def init_pingpong(network: dazl.Network, sender, receiver): sender_client = network.aio_party(sender) @sender_client.ledger_ready() async def init(event: ReadyEvent): pings = event.acs_find_active( 'PingPong.Ping', match=lambda cdata: cdata['sender'] == sender) pongs = event.acs_find_active( 'PingPong.Pong', match=lambda cdata: cdata['receiver'] == sender) if len(pings) == 0 and len(pongs) == 0: logging.info("Initializing Ping for " + sender) return dazl.create('PingPong.Ping', { 'sender': sender, 'receiver': receiver, 'count': 0 })
def run(self, url, operator_party): set_event_loop(new_event_loop()) network = Network() network.set_config(url=url) operator = network.aio_party(operator_party) operator.add_ledger_ready(self.on_ready) operator.add_ledger_created(Simple.OperatorNotification, self.on_notification_created) operator.add_ledger_archived(Simple.OperatorNotification, self.on_notification_archived) network.run_until_complete() self.events.append(("finished", (), ()))
def main(): DAML_FILE = Path(__file__).parent.parent.parent / '_template' / 'Main.daml' with sandbox(DAML_FILE, extra_args=['-w', '--jdbcurl', 'jdbc:h2:file:sandbox.db']) as proc: network = Network() network.set_config(url=proc.url) test_party = network.aio_party('TestA') test_party.add_ledger_ready(ready) test_party.add_ledger_created('Main.PostmanRole', created) other_party = network.aio_party('TestB') other_party.add_ledger_ready(ready) dump_state() network.run_forever()