From 89852db163a922f4b4c2cf9bf3519ea19eeee113 Mon Sep 17 00:00:00 2001
From: David Wilson <dw@botanicus.net>
Date: Mon, 29 Oct 2018 16:32:34 +0000
Subject: [PATCH] issue #370: add 'disconnect resets connection' test

---
 tests/ansible/integration/connection/all.yml  |  1 +
 .../disconnect_resets_connection.yml          | 44 +++++++++++++++++++
 .../lib/action/mitogen_action_script.py       | 28 ++++++++++++
 3 files changed, 73 insertions(+)
 create mode 100644 tests/ansible/integration/connection/disconnect_resets_connection.yml
 create mode 100644 tests/ansible/lib/action/mitogen_action_script.py

diff --git a/tests/ansible/integration/connection/all.yml b/tests/ansible/integration/connection/all.yml
index d0ad4c1b..34e21f61 100644
--- a/tests/ansible/integration/connection/all.yml
+++ b/tests/ansible/integration/connection/all.yml
@@ -1,6 +1,7 @@
 ---
 
 - import_playbook: disconnect_during_module.yml
+- import_playbook: disconnect_resets_connection.yml
 - import_playbook: exec_command.yml
 - import_playbook: put_large_file.yml
 - import_playbook: put_small_file.yml
diff --git a/tests/ansible/integration/connection/disconnect_resets_connection.yml b/tests/ansible/integration/connection/disconnect_resets_connection.yml
new file mode 100644
index 00000000..9e186182
--- /dev/null
+++ b/tests/ansible/integration/connection/disconnect_resets_connection.yml
@@ -0,0 +1,44 @@
+# issue 370: Connection should reset to 'disconnected' state when disconnect
+# detected
+#
+# Previously the 'Mitogen was disconnected' error would fail the first task,
+# but the Connection instance would still think it still had a valid
+# connection.
+#
+# See also disconnect_during_module.yml
+
+---
+
+- name: integration/connection/disconnect_resets_connection.yml
+  hosts: test-targets
+  gather_facts: no
+  any_errors_fatal: true
+  tasks:
+  - mitogen_action_script:
+      script: |
+        import sys
+        from ansible.errors import AnsibleConnectionFailure
+
+        assert not self._connection.connected, \
+          "Connection was not initially disconnected."
+
+        self._low_level_execute_command('echo')
+        assert self._connection.connected, \
+          "Connection was not connected after good command."
+
+        try:
+          self._low_level_execute_command('kill -9 $PPID')
+          assert 0, 'AnsibleConnectionFailure was not raised'
+        except AnsibleConnectionFailure:
+          e = sys.exc_info()[1]
+          assert str(e).startswith('Mitogen was disconnected')
+
+        assert not self._connection.connected, \
+          "Connection did not reset."
+
+        try:
+          self._low_level_execute_command('kill -9 $PPID')
+          assert 0, 'AnsibleConnectionFailure was not raised'
+        except AnsibleConnectionFailure:
+          e = sys.exc_info()[1]
+          assert str(e).startswith('Mitogen was disconnected')
diff --git a/tests/ansible/lib/action/mitogen_action_script.py b/tests/ansible/lib/action/mitogen_action_script.py
new file mode 100644
index 00000000..e034345c
--- /dev/null
+++ b/tests/ansible/lib/action/mitogen_action_script.py
@@ -0,0 +1,28 @@
+# I am an Ansible action plug-in. I run the script provided in the parameter in
+# the context of the action.
+
+import sys
+
+from ansible.plugins.action import ActionBase
+
+
+def execute(s, gbls, lcls):
+    if sys.version_info > (3,):
+        exec(s, gbls, lcls)
+    else:
+        exec('exec s in gbls, lcls')
+
+
+class ActionModule(ActionBase):
+    def run(self, tmp=None, task_vars=None):
+        super(ActionModule, self).run(tmp=tmp, task_vars=task_vars)
+        lcls = {
+            'self': self,
+            'result': {}
+        }
+        execute(self._task.args['script'], globals(), lcls)
+        return lcls['result']
+
+
+if __name__ == '__main__':
+    main()