- name: execute a powershell cmdlet
  win_shell: Write-Output "hello from Ansible"
  register: shellout

- name: validate result
  assert:
    that:
    - shellout|success
    - shellout|changed
    - shellout.cmd == 'Write-Output "hello from Ansible"'
    - shellout.delta is match('^\d:(\d){2}:(\d){2}.(\d){6}$')
    - shellout.end is match('^(\d){4}\-(\d){2}\-(\d){2} (\d){2}:(\d){2}:(\d){2}.(\d){6}$')
    - shellout.rc == 0
    - shellout.start is match('^(\d){4}\-(\d){2}\-(\d){2} (\d){2}:(\d){2}:(\d){2}.(\d){6}$')
    # assertion disabled since it does not pass on Windows Server 2016
    # - shellout.stderr == ""
    - shellout.stdout == "hello from Ansible\r\n"
    - shellout.stdout_lines == ["hello from Ansible"]

- name: execute a powershell cmdlet with multi-line output that uses environment with embedded quotes
  win_shell: Write-Output "hello from Ansible"; Write-Output "another line"; Write-Output "yet another line"; Write-Output "envvar was $env:taskvar"
  environment:
    taskvar: "o'doyle rules"
  register: shellout

- name: validate result
  assert:
    that:
    - shellout|success
    - shellout|changed
    - shellout.cmd == 'Write-Output "hello from Ansible"; Write-Output "another line"; Write-Output "yet another line"; Write-Output "envvar was $env:taskvar"'
    - shellout.delta is match('^\d:(\d){2}:(\d){2}.(\d){6}$')
    - shellout.end is match('^(\d){4}\-(\d){2}\-(\d){2} (\d){2}:(\d){2}:(\d){2}.(\d){6}$')
    - shellout.rc == 0
    - shellout.start is match('^(\d){4}\-(\d){2}\-(\d){2} (\d){2}:(\d){2}:(\d){2}.(\d){6}$')
    # assertion disabled since it does not pass on Windows Server 2016
    # - shellout.stderr == ""
    - shellout.stdout == "hello from Ansible\r\nanother line\r\nyet another line\r\nenvvar was o'doyle rules\r\n"
    - shellout.stdout_lines == ["hello from Ansible","another line", "yet another line", "envvar was o'doyle rules"]

- name: execute something nonexistent
  win_shell: bogus_command1234
  register: shellout
  ignore_errors: true

- name: validate result
  assert:
    that:
    - shellout|failed
    - shellout.failed == true # check the failure key explicitly, since failed does magic with RC
    - shellout|changed
    - shellout.cmd == 'bogus_command1234'
    - shellout.delta is match('^\d:(\d){2}:(\d){2}.(\d){6}$')
    - shellout.end is match('^(\d){4}\-(\d){2}\-(\d){2} (\d){2}:(\d){2}:(\d){2}.(\d){6}$')
    - shellout.rc == 1
    - shellout.start is match('^(\d){4}\-(\d){2}\-(\d){2} (\d){2}:(\d){2}:(\d){2}.(\d){6}$')
    - shellout.stderr is search('not recognized')
    - shellout.stdout == ""
    - shellout.stdout_lines == []

- name: execute something with error output
  win_shell: Write-Error "it broke"; Write-Output "some output"
  register: shellout

- name: validate result
  assert:
    that:
    - shellout|success
    - shellout|changed
    - shellout.cmd == 'Write-Error "it broke"; Write-Output "some output"'
    - shellout.delta is match('^\d:(\d){2}:(\d){2}.(\d){6}$')
    - shellout.end is match('^(\d){4}\-(\d){2}\-(\d){2} (\d){2}:(\d){2}:(\d){2}.(\d){6}$')
    - shellout.rc == 0
    - shellout.start is match('^(\d){4}\-(\d){2}\-(\d){2} (\d){2}:(\d){2}:(\d){2}.(\d){6}$')
    - shellout.stderr is search('it broke')
    - shellout.stdout == "some output\r\n"
    - shellout.stdout_lines == ["some output"]

- name: ensure test file is absent
  win_file:
    path: c:\testfile.txt
    state: absent

- name: run with creates, should create
  win_shell: echo $null >> c:\testfile.txt
  args:
    creates: c:\testfile.txt
  register: shellout

- name: validate result
  assert:
    that:
    - shellout|success
    - shellout|changed

- name: run again with creates, should skip
  win_shell: echo $null >> c:\testfile.txt
  args:
    creates: c:\testfile.txt
  register: shellout

- name: validate result
  assert:
    that:
    - shellout|skipped
    - shellout.msg is search('exists')

- name: ensure testfile is still present
  win_stat:
    path: c:\testfile.txt
  register: statout

- name: validate result
  assert:
    that:
    - statout.stat.exists == true

- name: run with removes, should remove
  win_shell: Remove-Item c:\testfile.txt
  args:
    removes: c:\testfile.txt
  register: shellout

- name: validate result
  assert:
    that:
    - shellout|success
    - shellout|changed

- name: run again with removes, should skip
  win_shell: echo $null >> c:\testfile.txt
  args:
    removes: c:\testfile.txt
  register: shellout

- name: validate result
  assert:
    that:
    - shellout|skipped
    - shellout.msg is search('does not exist')

- name: run something with known nonzero exit code
  win_shell: exit 254
  register: shellout
  ignore_errors: true

- name: validate result
  assert:
    that:
    - shellout|failed
    - shellout.failed == True # check the failure key explicitly, since failed does magic with RC
    - shellout.rc == 254

- name: run something via cmd that will fail in powershell
  win_shell: echo line1 & echo.line2
  args:
    executable: cmd
  register: shellout

- name: validate result
  assert:
    that:
    - shellout|success
    - shellout|changed
    - shellout.rc == 0
    - shellout.stdout == "line1 \r\nline2\r\n"
    - shellout.stdout_lines == ["line1 ", "line2"]
    - shellout.stderr == ""

- name: test with job to ensure that preamble-free InputEncoding is working
  win_shell: Start-Job { echo yo } | Receive-Job -Wait
  register: shellout

- name: check job result
  assert:
    that:
    - shellout | succeeded
    - shellout.stdout_lines[0] == 'yo'

- name: interleave large writes between stdout/stderr (check for buffer consumption deadlock)
  win_shell: $ba = New-Object byte[] 4096; (New-Object System.Random 32).NextBytes($ba); $text = [Convert]::ToBase64String($ba); Write-Output startout; Write-Error starterror; Write-Error $text; Write-Output $text; Write-Error $text; Write-Output $text; Write-Error $text; Write-Output $text; Write-Output doneout Write-Error doneerror
  register: shellout

- name: ensure that the entirety of both streams were read
  assert:
    that:
    - shellout.stdout is search("startout")
    - shellout.stdout is search("doneout")
    - shellout.stderr is search("starterror")
    - shellout.stderr is search("doneerror")