+
+def _verify_instance_and_status(client, expected_instance, expected_status, expected_deleted, seconds_to_try=5):
+ # get the instance
+ res = client.get(ADM_CTRL_INSTANCE)
+ assert res.status_code == 200
+ assert res.json == expected_instance
+
+ for _ in range(seconds_to_try):
+ # idea here is that we have to wait for the seperate thread to process the event
+ res = client.get(ADM_CTRL_INSTANCE_STATUS)
+ assert res.status_code == 200
+ assert res.json["has_been_deleted"] == expected_deleted
+ try:
+ assert res.json["instance_status"] == expected_status
+ return
+ except AssertionError:
+ time.sleep(1)
+ assert res.json["instance_status"] == expected_status
+
+
+# Module level Hack
+
+
+def setup_module():
+ """module level setup"""
+
+ # swap sdl for the fake backend
+ data.SDL = SDLWrapper(use_fake_sdl=True)
+
+ def noop():
+ pass
+
+ # launch the thread with a fake init func and a patched rcv func; we will "repatch" later
+ a1rmr.start_rmr_thread(init_func_override=noop, rcv_func_override=_fake_dequeue_none)
+
+
+# Actual Tests
+
+
+def test_workflow(client, monkeypatch, adm_type_good, adm_instance_good):
+ """
+ test a full A1 workflow
+ """
+
+ # put type and instance
+ _put_ac_type(client, adm_type_good)
+ _put_ac_instance(client, monkeypatch, adm_instance_good)
+
+ """
+ we test the state transition diagram of all 5 states here;
+ 1. not in effect, not deleted
+ 2. in effect, not deleted
+ 3. in effect, deleted
+ 4. not in effect, deleted
+ 5. gone (timeout expires)
+ """
+
+ # try a status get but we didn't get any ACKs yet to test NOT IN EFFECT
+ _verify_instance_and_status(client, adm_instance_good, "NOT IN EFFECT", False)
+
+ # now pretend we did get a good ACK
+ a1rmr.replace_rcv_func(_fake_dequeue)
+ _verify_instance_and_status(client, adm_instance_good, "IN EFFECT", False)
+
+ # delete the instance
+ _delete_instance(client)
+
+ # status after a delete, but there are no messages yet, should still return
+ _verify_instance_and_status(client, adm_instance_good, "IN EFFECT", True)
+
+ # now pretend we deleted successfully
+ a1rmr.replace_rcv_func(_fake_dequeue_deleted)
+
+ # status should be reflected first (before delete triggers)
+ _verify_instance_and_status(client, adm_instance_good, "NOT IN EFFECT", True)
+
+ # instance should be totally gone after a few seconds
+ _instance_is_gone(client)
+
+ # delete the type
+ _delete_ac_type(client)
+
+
+def test_cleanup_via_t1(client, monkeypatch, adm_type_good, adm_instance_good):
+ """
+ create a type, create an instance, but no acks ever come in, delete instance
+ """
+ _put_ac_type(client, adm_type_good)
+
+ a1rmr.replace_rcv_func(_fake_dequeue_none)
+
+ _put_ac_instance(client, monkeypatch, adm_instance_good)
+
+ """
+ here we test the state transition diagram when it never goes into effect:
+ 1. not in effect, not deleted
+ 2. not in effect, deleted
+ 3. gone (timeout expires)
+ """
+
+ _verify_instance_and_status(client, adm_instance_good, "NOT IN EFFECT", False)
+
+ # delete the instance
+ _delete_instance(client)
+
+ _verify_instance_and_status(client, adm_instance_good, "NOT IN EFFECT", True)
+
+ # instance should be totally gone after a few seconds
+ _instance_is_gone(client)
+
+ # delete the type
+ _delete_ac_type(client)
+
+
+def test_bad_instances(client, monkeypatch, adm_type_good):
+ """
+ test various failure modes
+ """
+ # put the type (needed for some of the tests below)
+ rmr_mocks.patch_rmr(monkeypatch)
+ res = client.put(ADM_CTRL_TYPE, json=adm_type_good)
+ assert res.status_code == 201
+
+ # bad body
+ res = client.put(ADM_CTRL_INSTANCE, json={"not": "expected"})
+ assert res.status_code == 400
+