from __future__ import annotations import pytest from ansible.plugins.shell.powershell import _parse_clixml, ShellModule def test_parse_clixml_empty(): empty = b'#< CLIXML\r\n' expected = b'' actual = _parse_clixml(empty) assert actual == expected def test_parse_clixml_with_progress(): progress = b'#< CLIXML\r\n' \ b'System.Management.Automation.PSCustomObjectSystem.Object' \ b'1Preparing modules for first use.0' \ b'-1-1Completed-1 ' expected = b'' actual = _parse_clixml(progress) assert actual == expected def test_parse_clixml_single_stream(): single_stream = b'#< CLIXML\r\n' \ b'fake : The term \'fake\' is not recognized as the name of a cmdlet. Check _x000D__x000A_' \ b'the spelling of the name, or if a path was included._x000D__x000A_' \ b'At line:1 char:1_x000D__x000A_' \ b'+ fake cmdlet_x000D__x000A_+ ~~~~_x000D__x000A_' \ b' + CategoryInfo : ObjectNotFound: (fake:String) [], CommandNotFoundException_x000D__x000A_' \ b' + FullyQualifiedErrorId : CommandNotFoundException_x000D__x000A_' \ b' _x000D__x000A_' \ b'' expected = b"fake : The term 'fake' is not recognized as the name of a cmdlet. Check \r\n" \ b"the spelling of the name, or if a path was included.\r\n" \ b"At line:1 char:1\r\n" \ b"+ fake cmdlet\r\n" \ b"+ ~~~~\r\n" \ b" + CategoryInfo : ObjectNotFound: (fake:String) [], CommandNotFoundException\r\n" \ b" + FullyQualifiedErrorId : CommandNotFoundException\r\n" \ b" \r\n" actual = _parse_clixml(single_stream) assert actual == expected def test_parse_clixml_multiple_streams(): multiple_stream = b'#< CLIXML\r\n' \ b'fake : The term \'fake\' is not recognized as the name of a cmdlet. Check _x000D__x000A_' \ b'the spelling of the name, or if a path was included._x000D__x000A_' \ b'At line:1 char:1_x000D__x000A_' \ b'+ fake cmdlet_x000D__x000A_+ ~~~~_x000D__x000A_' \ b' + CategoryInfo : ObjectNotFound: (fake:String) [], CommandNotFoundException_x000D__x000A_' \ b' + FullyQualifiedErrorId : CommandNotFoundException_x000D__x000A_ _x000D__x000A_' \ b'hi info' \ b'other' \ b'' expected = b"hi infoother" actual = _parse_clixml(multiple_stream, stream="Info") assert actual == expected def test_parse_clixml_multiple_elements(): multiple_elements = b'#< CLIXML\r\n#< CLIXML\r\n' \ b'System.Management.Automation.PSCustomObjectSystem.Object' \ b'1Preparing modules for first use.0' \ b'-1-1Completed-1 ' \ b'Error 1' \ b'' \ b'System.Management.Automation.PSCustomObjectSystem.Object' \ b'1Preparing modules for first use.0' \ b'-1-1Completed-1 ' \ b'2' \ b'Preparing modules for first use.0' \ b'-1-1Completed-1 ' \ b'Error 2' expected = b"Error 1\r\nError 2" actual = _parse_clixml(multiple_elements) assert actual == expected @pytest.mark.parametrize('clixml, expected', [ ('', ''), ('just newline _x000A_', 'just newline \n'), ('surrogate pair _xD83C__xDFB5_', 'surrogate pair 🎵'), ('null char _x0000_', 'null char \0'), ('normal char _x0061_', 'normal char a'), ('escaped literal _x005F_x005F_', 'escaped literal _x005F_'), ('underscope before escape _x005F__x000A_', 'underscope before escape _\n'), ('surrogate high _xD83C_', 'surrogate high \uD83C'), ('surrogate low _xDFB5_', 'surrogate low \uDFB5'), ('lower case hex _x005f_', 'lower case hex _'), ('invalid hex _x005G_', 'invalid hex _x005G_'), ]) def test_parse_clixml_with_comlex_escaped_chars(clixml, expected): clixml_data = ( '<# CLIXML\r\n' '' f'{clixml}' '' ).encode() b_expected = expected.encode(errors="surrogatepass") actual = _parse_clixml(clixml_data) assert actual == b_expected def test_join_path_unc(): pwsh = ShellModule() unc_path_parts = ['\\\\host\\share\\dir1\\\\dir2\\', '\\dir3/dir4', 'dir5', 'dir6\\'] expected = '\\\\host\\share\\dir1\\dir2\\dir3\\dir4\\dir5\\dir6' actual = pwsh.join_path(*unc_path_parts) assert actual == expected