- hosts: all
  gather_facts: no
  tasks:
    - name: intentionally fail module execution with a handled exception
      ansibull:
        errors:
          - one
          - two
      ignore_errors: yes
      register: handled_error
    - name: intentionally fail module execution with an unhandled handled exception
      ansibull:
        trigger_unhandled_exception: boom
      ignore_errors: yes
      register: unhandled_error
    - name: intentionally return from module main instead of exiting
      ansibull:
        return_from_main: true
      ignore_errors: yes
      register: return_from_main

    - name: check if error tracebacks are enabled
      set_fact:
        error_tracebacks: "{{ lookup('env', 'ANSIBLE_DISPLAY_TRACEBACK') == 'error' }}"

    - name: verify exceptions were properly handled
      assert:
        that:
          # NB: these are regexes- using . to avoid YAML colon escaping
          - handled_error is failed
          - handled_error.msg is match 'Task failed. Module failed. one. two'

          - unhandled_error is failed
          - (unhandled_error.module_stderr ~ unhandled_error.module_stdout) is search 'Die.*boom'

          - return_from_main is failed
          - return_from_main.msg is match 'Task failed. Module failed. New-style module did not handle its own exit.'

    - name: verify tracebacks were captured
      assert:
        that:
          - handled_error.exception is contains 'Traceback'
          - unhandled_error.exception is contains 'Traceback'
      when: error_tracebacks

    - name: verify tracebacks were not captured
      assert:
        that:
          - handled_error.exception == '(traceback unavailable)'
          - unhandled_error.exception == '(traceback unavailable)'
      when: not error_tracebacks
