Skip to content

Commit c1ee6fa

Browse files
author
Joe Stubbs
committed
fix race in execution_delete, new test for alias nonce permissions, initial events tests
1 parent 81436d5 commit c1ee6fa

File tree

1 file changed

+214
-2
lines changed

1 file changed

+214
-2
lines changed

tests/test_abaco_core.py

Lines changed: 214 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
import json
4444
import pytest
4545

46-
from actors import health, models, codes, stores, spawner
46+
from actors import controllers, health, models, codes, stores, spawner
4747
from channels import ActorMsgChannel, CommandChannel
4848
from util import headers, base_url, case, \
4949
response_format, basic_response_checks, get_actor_id, check_execution_details, \
@@ -622,14 +622,32 @@ def test_execute_and_delete_sleep_loop_actor(headers):
622622
else:
623623
assert result.get('executionId')
624624
exc_id = result.get('executionId')
625+
# wait for a worker to take the execution -
626+
url = '{}/actors/{}/executions/{}'.format(base_url, actor_id, exc_id)
627+
worker_id = None
628+
idx = 0
629+
while not worker_id:
630+
rsp = requests.get(url, headers=headers).json().get('result')
631+
if case == 'snake':
632+
worker_id = rsp.get('worker_id')
633+
else:
634+
worker_id = rsp.get('workerId')
635+
idx += 1
636+
time.sleep(1)
637+
if idx > 10:
638+
print("worker never got sleep_loop execution. "
639+
"actor: {}; execution: {}; idx:{}".format(actor_id, exc_id, idx))
640+
assert False
625641
# now let's kill the execution -
626642
time.sleep(1)
627643
url = '{}/actors/{}/executions/{}'.format(base_url, actor_id, exc_id)
628644
rsp = requests.delete(url, headers=headers)
629645
assert rsp.status_code in [200, 201, 202, 203, 204]
646+
assert 'Issued force quit command for execution' in rsp.json().get('message')
630647
# make sure execution is stopped in a timely manner
631648
i = 0
632649
stopped = False
650+
status = None
633651
while i < 20:
634652
rsp = requests.get(url, headers=headers)
635653
rsp_data = json.loads(rsp.content.decode('utf-8'))
@@ -639,6 +657,8 @@ def test_execute_and_delete_sleep_loop_actor(headers):
639657
break
640658
time.sleep(1)
641659
i += 1
660+
print("Execution never stopped. Last status of execution: {}; "
661+
"actor_id: {}; execution_id: {}".format(status, actor_id, exc_id))
642662
assert stopped
643663

644664
def test_list_execution_details(headers):
@@ -786,7 +806,7 @@ def test_create_actor_with_custom_queue_name(headers):
786806
@pytest.mark.queuetest
787807
def test_actor_uses_custom_queue(headers):
788808
url = '{}/actors'.format(base_url)
789-
# get the actor id of an actor registered on the defaul queue:
809+
# get the actor id of an actor registered on the default queue:
790810
default_queue_actor_id = get_actor_id(headers, name='abaco_test_suite_statelesss')
791811
# and the actor id for the actor on the special queue:
792812
special_queue_actor_id = get_actor_id(headers, name='abaco_test_suite_queue1_actor1')
@@ -1020,6 +1040,16 @@ def test_other_user_still_cant_list_actor(headers):
10201040
data = response_format(rsp)
10211041
assert 'you do not have access to this actor' in data['message']
10221042

1043+
@pytest.mark.aliastest
1044+
def test_other_user_still_cant_create_alias_nonce(headers):
1045+
# alias permissions do not confer access to the actor itself, and alias nonces require BOTH
1046+
# permissions on the alias AND on the actor
1047+
url = '{}/actors/aliases/{}/nonces'.format(base_url, ALIAS_1)
1048+
rsp = requests.get(url, headers=priv_headers())
1049+
assert rsp.status_code == 400
1050+
data = response_format(rsp)
1051+
assert 'you do not have access to this alias and actor' in data['message']
1052+
10231053

10241054
@pytest.mark.aliastest
10251055
def test_get_actor_with_alias(headers):
@@ -1620,6 +1650,188 @@ def test_tenant_list_workers(headers):
16201650
check_worker_fields(worker)
16211651

16221652

1653+
##############
1654+
# events tests
1655+
##############
1656+
1657+
REQUEST_BIN_URL = 'https://enqjwyug892gl.x.pipedream.net'
1658+
1659+
1660+
def check_event_logs(logs):
1661+
assert 'event_time_utc' in logs
1662+
assert 'event_time_display' in logs
1663+
assert 'actor_id' in logs
1664+
1665+
def test_has_cycles_1():
1666+
links = {'A': 'B',
1667+
'B': 'C',
1668+
'C': 'D'}
1669+
assert not controllers.has_cycles(links)
1670+
1671+
def test_has_cycles_2():
1672+
links = {'A': 'B',
1673+
'B': 'A',
1674+
'C': 'D'}
1675+
assert controllers.has_cycles(links)
1676+
1677+
def test_has_cycles_3():
1678+
links = {'A': 'B',
1679+
'B': 'C',
1680+
'C': 'D',
1681+
'D': 'E',
1682+
'E': 'H',
1683+
'H': 'B'}
1684+
assert controllers.has_cycles(links)
1685+
1686+
def test_has_cycles_4():
1687+
links = {'A': 'B',
1688+
'B': 'C',
1689+
'D': 'E',
1690+
'E': 'H',
1691+
'H': 'J',
1692+
'I': 'J',
1693+
'K': 'J',
1694+
'L': 'M',
1695+
'M': 'J'}
1696+
assert not controllers.has_cycles(links)
1697+
1698+
def test_has_cycles_5():
1699+
links = {'A': 'B',
1700+
'B': 'C',
1701+
'C': 'C'}
1702+
assert controllers.has_cycles(links)
1703+
1704+
def test_create_event_link_actor(headers):
1705+
url = '{}/{}'.format(base_url, '/actors')
1706+
data = {'image': 'jstubbs/abaco_test', 'name': 'abaco_test_suite_event-link', 'stateless': False}
1707+
rsp = requests.post(url, data=data, headers=headers)
1708+
result = basic_response_checks(rsp)
1709+
1710+
def test_create_actor_with_link(headers):
1711+
# first, get the actor id of the event_link actor:
1712+
link_actor_id = get_actor_id(headers, name='abaco_test_suite_event-link')
1713+
# register a new actor with link to event_link actor
1714+
url = '{}/{}'.format(base_url, '/actors')
1715+
data = {'image': 'jstubbs/abaco_test',
1716+
'name': 'abaco_test_suite_event',
1717+
'link': link_actor_id}
1718+
rsp = requests.post(url, data=data, headers=headers)
1719+
result = basic_response_checks(rsp)
1720+
1721+
def test_execute_event_actor(headers):
1722+
actor_id = get_actor_id(headers, name='abaco_test_suite_event')
1723+
data = {'message': 'testing events execution'}
1724+
result = execute_actor(headers, actor_id, data=data)
1725+
exec_id = result['id']
1726+
# now that this execution has completed, check that the linked actor also executed:
1727+
idx = 0
1728+
link_execution_ex_id = None
1729+
link_actor_id = get_actor_id(headers, name='abaco_test_suite_event-link')
1730+
url = '{}/actors/{}/executions'.format(base_url, link_actor_id)
1731+
# the linked actor should get 2 messages - one for the original actor initially being set to READY
1732+
# and a second when the execution sent above completes.
1733+
while not link_execution_ex_id and idx < 15:
1734+
rsp = requests.get(url, headers=headers)
1735+
ex_data = rsp.json().get('result').get('executions')
1736+
if ex_data and len(ex_data) > 1:
1737+
link_ready_ex_id = ex_data[0]['id']
1738+
link_execution_ex_id = ex_data[1]['id']
1739+
break
1740+
else:
1741+
idx = idx + 1
1742+
time.sleep(1)
1743+
if not link_execution_ex_id:
1744+
print("linked actor never executed. actor_id: {}; link_actor_id: {}".format(actor_id, link_actor_id))
1745+
assert False
1746+
# wait for linked execution to complete and get logs
1747+
idx = 0
1748+
done = False
1749+
while not done and idx < 20:
1750+
# get executions for linked actor and check status of each
1751+
rsp = requests.get(url, headers=headers)
1752+
ex_data = rsp.json().get('result').get('executions')
1753+
if ex_data[0].get('status') == 'COMPLETE' and ex_data[1].get('status') == 'COMPLETE':
1754+
done = True
1755+
break
1756+
else:
1757+
time.sleep(1)
1758+
idx = idx + 1
1759+
if not done:
1760+
print("linked actor executions never completed. actor: {}; "
1761+
"linked_actor: {}; Final execution data: {}".format(actor_id, link_actor_id, ex_data))
1762+
assert False
1763+
# now check the logs from the two executions --
1764+
# first one should be the actor READY message:
1765+
url = '{}/actors/{}/executions/{}/logs'.format(base_url, link_actor_id, link_ready_ex_id)
1766+
rsp = requests.get(url, headers=headers)
1767+
result = basic_response_checks(rsp)
1768+
logs = result.get('logs')
1769+
assert "'event_type': 'ACTOR_READY'" in logs
1770+
check_event_logs(logs)
1771+
1772+
# second one should be the actor execution COMPLETE message:
1773+
url = '{}/actors/{}/executions/{}/logs'.format(base_url, link_actor_id, link_execution_ex_id)
1774+
rsp = requests.get(url, headers=headers)
1775+
result = basic_response_checks(rsp)
1776+
logs = result.get('logs')
1777+
assert "'event_type': 'EXECUTION_COMPLETE'" in logs
1778+
assert 'execution_id' in logs
1779+
check_event_logs(logs)
1780+
1781+
def test_cant_create_link_with_cycle(headers):
1782+
# this test checks that adding a link to an actor that did not have one that creates a cycle
1783+
# is not allowed.
1784+
# register a new actor with no link
1785+
url = '{}/{}'.format(base_url, '/actors')
1786+
data = {'image': 'jstubbs/abaco_test',
1787+
'name': 'abaco_test_suite_create_link',}
1788+
rsp = requests.post(url, data=data, headers=headers)
1789+
result = basic_response_checks(rsp)
1790+
new_actor_id = result['id']
1791+
# create 5 new actors, each with a link to the one created previously:
1792+
new_actor_ids = []
1793+
for i in range(5):
1794+
data['link'] = new_actor_id
1795+
rsp = requests.post(url, data=data, headers=headers)
1796+
result = basic_response_checks(rsp)
1797+
new_actor_id = result['id']
1798+
new_actor_ids.append(new_actor_id)
1799+
# now, update the first created actor with a link that would create a cycle
1800+
first_aid = new_actor_ids[0]
1801+
data['link'] = new_actor_ids[4]
1802+
url = '{}/actors/{}'.format(base_url, first_aid)
1803+
print("url: {}; data: {}".format(url, data))
1804+
rsp = requests.put(url, data=data, headers=headers)
1805+
assert rsp.status_code == 400
1806+
assert 'this update would result in a cycle of linked actors' in rsp.json().get('message')
1807+
1808+
def test_cant_update_link_with_cycle(headers):
1809+
# this test checks that an update to a link that would create a cycle is not allowed
1810+
link_actor_id = get_actor_id(headers, name='abaco_test_suite_event-link')
1811+
# register a new actor with link to event_link actor
1812+
url = '{}/{}'.format(base_url, '/actors')
1813+
data = {'image': 'jstubbs/abaco_test',
1814+
'name': 'abaco_test_suite_event',
1815+
'link': link_actor_id}
1816+
# create 5 new actors, each with a link to the one created previously:
1817+
new_actor_ids = []
1818+
for i in range(5):
1819+
rsp = requests.post(url, data=data, headers=headers)
1820+
result = basic_response_checks(rsp)
1821+
new_actor_id = result['id']
1822+
data['link'] = new_actor_id
1823+
new_actor_ids.append(new_actor_id)
1824+
# now, update the first created actor with a link that would great a cycle
1825+
first_aid = new_actor_ids[0]
1826+
data['link'] = new_actor_ids[4]
1827+
url = '{}/actors/{}'.format(base_url, first_aid)
1828+
print("url: {}; data: {}".format(url, data))
1829+
1830+
rsp = requests.put(url, data=data, headers=headers)
1831+
assert rsp.status_code == 400
1832+
assert 'this update would result in a cycle of linked actors' in rsp.json().get('message')
1833+
1834+
16231835
##############
16241836
# Clean up
16251837
##############

0 commit comments

Comments
 (0)