winrm 1.8.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (139) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +10 -11
  3. data/.rubocop.yml +26 -22
  4. data/.travis.yml +11 -12
  5. data/Gemfile +3 -9
  6. data/LICENSE +202 -202
  7. data/README.md +232 -215
  8. data/Rakefile +34 -36
  9. data/Vagrantfile +6 -9
  10. data/WinrmAppveyor.psm1 +31 -31
  11. data/appveyor.yml +51 -51
  12. data/bin/rwinrm +97 -97
  13. data/changelog.md +86 -86
  14. data/lib/winrm.rb +39 -42
  15. data/lib/winrm/connection.rb +82 -0
  16. data/lib/winrm/connection_opts.rb +87 -0
  17. data/lib/winrm/{exceptions/exceptions.rb → exceptions.rb} +76 -57
  18. data/lib/winrm/http/response_handler.rb +96 -82
  19. data/lib/winrm/http/transport.rb +424 -435
  20. data/lib/winrm/http/transport_factory.rb +68 -0
  21. data/lib/winrm/output.rb +59 -43
  22. data/lib/winrm/psrp/create_pipeline.xml.erb +167 -0
  23. data/lib/winrm/psrp/fragment.rb +70 -0
  24. data/lib/winrm/psrp/init_runspace_pool.xml.erb +224 -0
  25. data/lib/winrm/psrp/message.rb +130 -0
  26. data/lib/winrm/psrp/message_data.rb +41 -0
  27. data/lib/winrm/psrp/message_data/base.rb +49 -0
  28. data/lib/winrm/psrp/message_data/error_record.rb +68 -0
  29. data/lib/winrm/psrp/message_data/pipeline_host_call.rb +32 -0
  30. data/lib/winrm/psrp/message_data/pipeline_output.rb +49 -0
  31. data/lib/winrm/psrp/message_data/runspacepool_host_call.rb +32 -0
  32. data/lib/winrm/psrp/message_data/runspacepool_state.rb +39 -0
  33. data/lib/winrm/psrp/message_data/session_capability.rb +36 -0
  34. data/lib/winrm/psrp/message_defragmenter.rb +62 -0
  35. data/lib/winrm/psrp/message_factory.rb +75 -0
  36. data/lib/winrm/psrp/message_fragmenter.rb +60 -0
  37. data/lib/winrm/psrp/powershell_output_decoder.rb +120 -0
  38. data/lib/winrm/psrp/receive_response_reader.rb +93 -0
  39. data/lib/winrm/psrp/session_capability.xml.erb +7 -0
  40. data/lib/winrm/psrp/uuid.rb +40 -0
  41. data/lib/winrm/shells/base.rb +175 -0
  42. data/lib/winrm/shells/cmd.rb +65 -0
  43. data/lib/winrm/shells/power_shell.rb +201 -0
  44. data/lib/winrm/shells/retryable.rb +45 -0
  45. data/lib/winrm/shells/shell_factory.rb +50 -0
  46. data/lib/winrm/version.rb +7 -7
  47. data/lib/winrm/wsmv/base.rb +59 -0
  48. data/lib/winrm/wsmv/cleanup_command.rb +61 -0
  49. data/lib/winrm/wsmv/close_shell.rb +50 -0
  50. data/lib/winrm/wsmv/command.rb +101 -0
  51. data/lib/winrm/wsmv/command_output.rb +76 -0
  52. data/lib/winrm/wsmv/command_output_decoder.rb +55 -0
  53. data/lib/winrm/wsmv/configuration.rb +46 -0
  54. data/lib/winrm/wsmv/create_pipeline.rb +66 -0
  55. data/lib/winrm/wsmv/create_shell.rb +119 -0
  56. data/lib/winrm/wsmv/header.rb +203 -0
  57. data/lib/winrm/wsmv/init_runspace_pool.rb +95 -0
  58. data/lib/winrm/wsmv/iso8601_duration.rb +60 -0
  59. data/lib/winrm/wsmv/keep_alive.rb +68 -0
  60. data/lib/winrm/wsmv/receive_response_reader.rb +128 -0
  61. data/lib/winrm/wsmv/send_data.rb +68 -0
  62. data/lib/winrm/wsmv/soap.rb +51 -0
  63. data/lib/winrm/wsmv/wql_query.rb +79 -0
  64. data/lib/winrm/wsmv/write_stdin.rb +88 -0
  65. data/preamble +17 -17
  66. data/{spec → tests/integration}/auth_timeout_spec.rb +18 -16
  67. data/{spec → tests/integration}/cmd_spec.rb +104 -102
  68. data/{spec → tests/integration}/config-example.yml +16 -19
  69. data/{spec → tests/integration}/issue_59_spec.rb +26 -23
  70. data/tests/integration/powershell_spec.rb +154 -0
  71. data/{spec → tests/integration}/spec_helper.rb +65 -73
  72. data/{spec → tests/integration}/transport_spec.rb +99 -139
  73. data/{spec → tests/integration}/wql_spec.rb +16 -14
  74. data/{spec → tests}/matchers.rb +60 -74
  75. data/tests/spec/configuration_spec.rb +93 -0
  76. data/tests/spec/connection_spec.rb +39 -0
  77. data/{spec → tests/spec}/exception_spec.rb +50 -50
  78. data/tests/spec/http/transport_factory_spec.rb +68 -0
  79. data/tests/spec/http/transport_spec.rb +44 -0
  80. data/{spec → tests/spec}/output_spec.rb +127 -110
  81. data/tests/spec/psrp/fragment_spec.rb +62 -0
  82. data/tests/spec/psrp/message_data/base_spec.rb +13 -0
  83. data/tests/spec/psrp/message_data/error_record_spec.rb +41 -0
  84. data/tests/spec/psrp/message_data/pipeline_host_call_spec.rb +25 -0
  85. data/tests/spec/psrp/message_data/pipeline_output_spec.rb +32 -0
  86. data/tests/spec/psrp/message_data/runspace_pool_host_call_spec.rb +25 -0
  87. data/tests/spec/psrp/message_data/runspacepool_state_spec.rb +16 -0
  88. data/tests/spec/psrp/message_data/session_capability_spec.rb +30 -0
  89. data/tests/spec/psrp/message_data_spec.rb +35 -0
  90. data/tests/spec/psrp/message_defragmenter_spec.rb +47 -0
  91. data/tests/spec/psrp/message_fragmenter_spec.rb +105 -0
  92. data/tests/spec/psrp/powershell_output_decoder_spec.rb +84 -0
  93. data/tests/spec/psrp/psrp_message_spec.rb +70 -0
  94. data/tests/spec/psrp/recieve_response_reader_spec.rb +154 -0
  95. data/tests/spec/psrp/uuid_spec.rb +28 -0
  96. data/{spec → tests/spec}/response_handler_spec.rb +61 -61
  97. data/tests/spec/shells/base_spec.rb +202 -0
  98. data/tests/spec/shells/cmd_spec.rb +75 -0
  99. data/tests/spec/shells/powershell_spec.rb +175 -0
  100. data/tests/spec/spec_helper.rb +47 -0
  101. data/tests/spec/stubs/clixml/error_record.xml.erb +84 -0
  102. data/{spec → tests/spec}/stubs/responses/get_command_output_response.xml.erb +13 -13
  103. data/tests/spec/stubs/responses/get_command_output_response_not_done.xml.erb +10 -0
  104. data/tests/spec/stubs/responses/get_powershell_keepalive_response.xml.erb +10 -0
  105. data/tests/spec/stubs/responses/get_powershell_output_response.xml.erb +12 -0
  106. data/tests/spec/stubs/responses/get_powershell_output_response_not_done.xml.erb +9 -0
  107. data/{spec → tests/spec}/stubs/responses/open_shell_v1.xml +19 -19
  108. data/{spec → tests/spec}/stubs/responses/open_shell_v2.xml +20 -20
  109. data/{spec → tests/spec}/stubs/responses/soap_fault_v1.xml +36 -36
  110. data/{spec → tests/spec}/stubs/responses/soap_fault_v2.xml +42 -42
  111. data/{spec → tests/spec}/stubs/responses/wmi_error_v2.xml +41 -41
  112. data/tests/spec/wsmv/cleanup_command_spec.rb +22 -0
  113. data/tests/spec/wsmv/close_shell_spec.rb +17 -0
  114. data/{spec → tests/spec/wsmv}/command_output_decoder_spec.rb +37 -37
  115. data/tests/spec/wsmv/command_output_spec.rb +45 -0
  116. data/tests/spec/wsmv/command_spec.rb +19 -0
  117. data/tests/spec/wsmv/configuration_spec.rb +17 -0
  118. data/tests/spec/wsmv/create_pipeline_spec.rb +31 -0
  119. data/tests/spec/wsmv/create_shell_spec.rb +38 -0
  120. data/tests/spec/wsmv/init_runspace_pool_spec.rb +36 -0
  121. data/tests/spec/wsmv/keep_alive_spec.rb +21 -0
  122. data/tests/spec/wsmv/receive_response_reader_spec.rb +123 -0
  123. data/tests/spec/wsmv/send_data_spec.rb +30 -0
  124. data/tests/spec/wsmv/wql_query_spec.rb +13 -0
  125. data/tests/spec/wsmv/write_stdin_spec.rb +22 -0
  126. data/winrm.gemspec +42 -40
  127. metadata +140 -38
  128. data/.rspec +0 -3
  129. data/lib/winrm/command_executor.rb +0 -243
  130. data/lib/winrm/command_output_decoder.rb +0 -53
  131. data/lib/winrm/helpers/iso8601_duration.rb +0 -58
  132. data/lib/winrm/helpers/powershell_script.rb +0 -42
  133. data/lib/winrm/soap_provider.rb +0 -39
  134. data/lib/winrm/winrm_service.rb +0 -550
  135. data/spec/command_executor_spec.rb +0 -475
  136. data/spec/issue_184_spec.rb +0 -67
  137. data/spec/powershell_spec.rb +0 -97
  138. data/spec/winrm_options_spec.rb +0 -76
  139. data/spec/winrm_primitives_spec.rb +0 -51
@@ -0,0 +1,44 @@
1
+ # encoding: UTF-8
2
+ require 'rubyntlm'
3
+ require 'winrm/http/transport'
4
+
5
+ describe WinRM::HTTP::HttpNegotiate do
6
+ describe '#init' do
7
+ let(:endpoint) { 'some_endpoint' }
8
+ let(:domain) { 'some_domain' }
9
+ let(:user) { 'some_user' }
10
+ let(:password) { 'some_password' }
11
+ let(:options) { {} }
12
+
13
+ context 'user is not domain prefixed' do
14
+ it 'does not pass a domain to the NTLM client' do
15
+ expect(Net::NTLM::Client).to receive(:new).with(user, password, options)
16
+ WinRM::HTTP::HttpNegotiate.new(endpoint, user, password, options)
17
+ end
18
+ end
19
+
20
+ context 'user is domain prefixed' do
21
+ it 'passes prefixed domain to the NTLM client' do
22
+ expect(Net::NTLM::Client).to receive(:new) do |passed_user, passed_password, passed_options|
23
+ expect(passed_user).to eq user
24
+ expect(passed_password).to eq password
25
+ expect(passed_options[:domain]).to eq domain
26
+ end
27
+ WinRM::HTTP::HttpNegotiate.new(endpoint, "#{domain}\\#{user}", password, options)
28
+ end
29
+ end
30
+
31
+ context 'option is passed with a domain' do
32
+ let(:options) { { domain: domain } }
33
+
34
+ it 'passes domain option to the NTLM client' do
35
+ expect(Net::NTLM::Client).to receive(:new) do |passed_user, passed_password, passed_options|
36
+ expect(passed_user).to eq user
37
+ expect(passed_password).to eq password
38
+ expect(passed_options[:domain]).to eq domain
39
+ end
40
+ WinRM::HTTP::HttpNegotiate.new(endpoint, user, password, options)
41
+ end
42
+ end
43
+ end
44
+ end
@@ -1,110 +1,127 @@
1
- # encoding: UTF-8
2
- describe WinRM::Output, unit: true do
3
- subject { WinRM::Output.new }
4
-
5
- context 'when there is no output' do
6
- describe '#stdout' do
7
- it 'is empty' do
8
- expect(subject.stdout).to be_empty
9
- end
10
- end
11
-
12
- describe '#stderr' do
13
- it 'is empty' do
14
- expect(subject.stderr).to be_empty
15
- end
16
- end
17
-
18
- describe '#output' do
19
- it 'is empty' do
20
- expect(subject.output).to be_empty
21
- end
22
- end
23
- end
24
-
25
- context 'when there is only one line' do
26
- describe '#stdout' do
27
- it 'is equal to that line' do
28
- subject[:data] << { stdout: 'foo' }
29
- expect(subject.stdout).to eq('foo')
30
- end
31
- end
32
-
33
- describe '#stderr' do
34
- it 'is equal to that line' do
35
- subject[:data] << { stderr: 'foo' }
36
- expect(subject.stderr).to eq('foo')
37
- end
38
- end
39
-
40
- describe '#output' do
41
- it 'is equal to stdout' do
42
- subject[:data] << { stdout: 'foo' }
43
- expect(subject.output).to eq('foo')
44
- end
45
-
46
- it 'is equal to stderr' do
47
- subject[:data] << { stderr: 'foo' }
48
- expect(subject.output).to eq('foo')
49
- end
50
- end
51
- end
52
-
53
- context 'when there is one line of each type' do
54
- before(:each) do
55
- subject[:data] << { stdout: 'foo' }
56
- subject[:data] << { stderr: 'bar' }
57
- end
58
-
59
- describe '#stdout' do
60
- it 'is equal to that line' do
61
- expect(subject.stdout).to eq('foo')
62
- end
63
- end
64
-
65
- describe '#stderr' do
66
- it 'is equal to that line' do
67
- expect(subject.stderr).to eq('bar')
68
- end
69
- end
70
-
71
- describe '#output' do
72
- it 'is equal to stdout + stderr' do
73
- expect(subject.output).to eq('foobar')
74
- end
75
- end
76
- end
77
-
78
- context 'when there are multiple lines' do
79
- before(:each) do
80
- subject[:data] << { stdout: 'I can have a newline\nanywhere, ' }
81
- subject[:data] << { stderr: 'I can also have stderr' }
82
- subject[:data] << { stdout: 'or stdout', stderr: ' and stderr' }
83
- subject[:data] << {}
84
- subject[:data] << { stdout: ' or nothing! (above)' }
85
- end
86
-
87
- describe '#stdout' do
88
- it 'is equal to that line' do
89
- expect(subject.stdout).to eq(
90
- 'I can have a newline\nanywhere, or stdout or nothing! (above)')
91
- end
92
- end
93
-
94
- describe '#stderr' do
95
- it 'is equal to that line' do
96
- expect(subject.stderr).to eq('I can also have stderr and stderr')
97
- end
98
- end
99
-
100
- describe '#output' do
101
- it 'is equal to stdout + stderr' do
102
- expect(subject.output).to eq(
103
- 'I can have a newline\nanywhere, I can also have stderror stdout ' \
104
- 'and stderr or nothing! (above)')
105
- end
106
- end
107
- end
108
-
109
- pending 'parse CLIXML errors and convert to Strings and/or Exceptions'
110
- end
1
+ # encoding: UTF-8
2
+ describe WinRM::Output do
3
+ subject { WinRM::Output.new }
4
+
5
+ context 'when there is no output' do
6
+ describe '#stdout' do
7
+ it 'is empty' do
8
+ expect(subject.stdout).to be_empty
9
+ end
10
+ end
11
+
12
+ describe '#stderr' do
13
+ it 'is empty' do
14
+ expect(subject.stderr).to be_empty
15
+ end
16
+ end
17
+
18
+ describe '#output' do
19
+ it 'is empty' do
20
+ expect(subject.output).to be_empty
21
+ end
22
+ end
23
+ end
24
+
25
+ context 'when there is only one line' do
26
+ describe '#stdout' do
27
+ it 'is equal to that line' do
28
+ subject << { stdout: 'foo' }
29
+ expect(subject.stdout).to eq('foo')
30
+ end
31
+ end
32
+
33
+ describe '#stderr' do
34
+ it 'is equal to that line' do
35
+ subject << { stderr: 'foo' }
36
+ expect(subject.stderr).to eq('foo')
37
+ end
38
+ end
39
+
40
+ describe '#output' do
41
+ it 'is equal to stdout' do
42
+ subject << { stdout: 'foo' }
43
+ expect(subject.output).to eq('foo')
44
+ end
45
+
46
+ it 'is equal to stderr' do
47
+ subject << { stderr: 'foo' }
48
+ expect(subject.output).to eq('foo')
49
+ end
50
+ end
51
+ end
52
+
53
+ context 'when there is one line of each type' do
54
+ before(:each) do
55
+ subject << { stdout: 'foo' }
56
+ subject << { stderr: 'bar' }
57
+ end
58
+
59
+ describe '#stdout' do
60
+ it 'is equal to that line' do
61
+ expect(subject.stdout).to eq('foo')
62
+ end
63
+ end
64
+
65
+ describe '#stderr' do
66
+ it 'is equal to that line' do
67
+ expect(subject.stderr).to eq('bar')
68
+ end
69
+ end
70
+
71
+ describe '#output' do
72
+ it 'is equal to stdout + stderr' do
73
+ expect(subject.output).to eq('foobar')
74
+ end
75
+ end
76
+ end
77
+
78
+ context 'when there are multiple lines' do
79
+ before(:each) do
80
+ subject << { stdout: 'I can have a newline\nanywhere, ' }
81
+ subject << { stderr: 'I can also have stderr' }
82
+ subject << { stdout: 'or stdout', stderr: ' and stderr' }
83
+ subject << {}
84
+ subject << { stdout: ' or nothing! (above)' }
85
+ end
86
+
87
+ describe '#stdout' do
88
+ it 'is equal to that line' do
89
+ expect(subject.stdout).to eq(
90
+ 'I can have a newline\nanywhere, or stdout or nothing! (above)')
91
+ end
92
+ end
93
+
94
+ describe '#stderr' do
95
+ it 'is equal to that line' do
96
+ expect(subject.stderr).to eq('I can also have stderr and stderr')
97
+ end
98
+ end
99
+
100
+ describe '#output' do
101
+ it 'is equal to stdout + stderr' do
102
+ expect(subject.output).to eq(
103
+ 'I can have a newline\nanywhere, I can also have stderror stdout ' \
104
+ 'and stderr or nothing! (above)')
105
+ end
106
+ end
107
+ end
108
+
109
+ describe '#exitcode' do
110
+ let(:exitcode) { 0 }
111
+
112
+ context 'when a valid exit code is set' do
113
+ it 'sets the exit code' do
114
+ subject.exitcode = exitcode
115
+ expect(subject.exitcode).to eq exitcode
116
+ end
117
+ end
118
+
119
+ context 'when an invalid exit code is set' do
120
+ let(:exitcode) { 'bad' }
121
+
122
+ it 'sets the exit code' do
123
+ expect { subject.exitcode = exitcode }.to raise_error WinRM::InvalidExitCode
124
+ end
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,62 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'winrm/psrp/fragment'
4
+
5
+ describe WinRM::PSRP::Fragment do
6
+ let(:id) { 1 }
7
+ let(:message) { 'blah blah blah' }
8
+
9
+ context 'called with just id and blob' do
10
+ subject { described_class.new(id, message.bytes) }
11
+
12
+ it 'sets the message id to 1' do
13
+ expect(subject.bytes[0..7]).to eq([0, 0, 0, 0, 0, 0, 0, id])
14
+ end
15
+ it 'sets the fragment id to 0' do
16
+ expect(subject.bytes[8..15]).to eq([0, 0, 0, 0, 0, 0, 0, 0])
17
+ end
18
+ it 'sets the last 2 bits of the end/start fragment' do
19
+ expect(subject.bytes[16]).to eq(3)
20
+ end
21
+ it 'sets message blob length to 3640' do
22
+ expect(subject.bytes[17..20]).to eq([0, 0, 0, message.bytes.length])
23
+ end
24
+ it 'sets message blob' do
25
+ expect(subject.bytes[21..-1]).to eq(message.bytes)
26
+ end
27
+ end
28
+
29
+ context 'specifying a fragment id' do
30
+ let(:fragment_id) { 1 }
31
+
32
+ subject { described_class.new(id, message.bytes, fragment_id) }
33
+
34
+ it 'sets the fragment id' do
35
+ expect(subject.bytes[8..15]).to eq([0, 0, 0, 0, 0, 0, 0, fragment_id])
36
+ end
37
+ end
38
+
39
+ context 'middle fragment' do
40
+ subject { described_class.new(id, message.bytes, 1, false, false) }
41
+
42
+ it 'sets the last 2 bits of the end/start fragment to 0' do
43
+ expect(subject.bytes[16]).to eq(0)
44
+ end
45
+ end
46
+
47
+ context 'end fragment' do
48
+ subject { described_class.new(id, message.bytes, 1, true, false) }
49
+
50
+ it 'sets the end fragment bit' do
51
+ expect(subject.bytes[16]).to eq(1)
52
+ end
53
+ end
54
+
55
+ context 'start fragment' do
56
+ subject { described_class.new(id, message.bytes, 1, false, true) }
57
+
58
+ it 'sets the start fragment bit' do
59
+ expect(subject.bytes[16]).to eq(2)
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,13 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'winrm/psrp/message_data/base'
4
+
5
+ describe WinRM::PSRP::MessageData::Base do
6
+ let(:raw_data) { 'raw_data' }
7
+
8
+ subject { WinRM::PSRP::MessageData::Base.new(raw_data) }
9
+
10
+ it 'holds raw message data' do
11
+ expect(subject.raw).to eq(raw_data)
12
+ end
13
+ end
@@ -0,0 +1,41 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'winrm/psrp/message_data/base'
4
+ require 'winrm/psrp/message_data/error_record'
5
+
6
+ describe WinRM::PSRP::MessageData::ErrorRecord do
7
+ let(:test_data_xml_template) do
8
+ ERB.new(stubbed_clixml('error_record.xml.erb'))
9
+ end
10
+ let(:error_message) { 'an error' }
11
+ let(:script_root) { 'script_root' }
12
+ let(:category_message) { 'category message' }
13
+ let(:stack_trace) { 'stack trace' }
14
+ let(:error_id) { 'Microsoft.PowerShell.Commands.WriteErrorException' }
15
+ let(:raw_data) { test_data_xml_template.result(binding) }
16
+ subject { described_class.new(raw_data) }
17
+
18
+ it 'returns the exception' do
19
+ expect(subject.exception[:message]).to eq(error_message)
20
+ end
21
+
22
+ it 'returns the FullyQualifiedErrorId' do
23
+ expect(subject.fully_qualified_error_id).to eq(error_id)
24
+ end
25
+
26
+ it 'returns the invocation info' do
27
+ expect(subject.invocation_info[:line]).to eq("write-error '#{error_message}'")
28
+ end
29
+
30
+ it 'converts camel case properties to underscore' do
31
+ expect(subject.invocation_info[:ps_script_root]).to eq(script_root)
32
+ end
33
+
34
+ it 'returns the error category message' do
35
+ expect(subject.error_category_message).to eq(category_message)
36
+ end
37
+
38
+ it 'returns the script stack trace' do
39
+ expect(subject.error_details_script_stack_trace).to eq(stack_trace)
40
+ end
41
+ end
@@ -0,0 +1,25 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'winrm/psrp/message_data/base'
4
+ require 'winrm/psrp/message_data/pipeline_host_call'
5
+
6
+ describe WinRM::PSRP::MessageData::PipelineHostCall do
7
+ let(:raw_data) do
8
+ "\xEF\xBB\xBF<Obj RefId=\"0\"><MS><I64 N=\"ci\">-100</I64><Obj N=\"mi\" RefId=\"1\">"\
9
+ '<TN RefId="0"><T>System.Management.Automation.Remoting.RemoteHostMethodId</T>'\
10
+ '<T>System.Enum</T><T>System.ValueType</T><T>System.Object</T></TN>'\
11
+ '<ToString>WriteLine3</ToString><I32>17</I32></Obj><Obj N="mp" RefId="2">'\
12
+ '<TN RefId="1"><T>System.Collections.ArrayList</T><T>System.Object</T></TN><LST>'\
13
+ '<I32>7</I32><I32>0</I32><S>hello</S></LST></Obj></MS></Obj>'
14
+ end
15
+
16
+ subject { described_class.new(raw_data) }
17
+
18
+ it 'parses method identifier' do
19
+ expect(subject.method_identifier).to eq('WriteLine3')
20
+ end
21
+
22
+ it 'parses method parameters' do
23
+ expect(subject.method_parameters[:s]).to eq('hello')
24
+ end
25
+ end
@@ -0,0 +1,32 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'winrm/psrp/message_data/base'
4
+ require 'winrm/psrp/message_data/pipeline_output'
5
+
6
+ describe WinRM::PSRP::MessageData::PipelineOutput do
7
+ subject { described_class.new(raw_data) }
8
+
9
+ context 'receiving output with BOM and no new line' do
10
+ let(:raw_data) { "\xEF\xBB\xBF<obj><S>some data</S></obj>" }
11
+
12
+ it 'output removes BOM and adds newline' do
13
+ expect(subject.output).to eq("some data\r\n")
14
+ end
15
+ end
16
+
17
+ context 'receiving output with encoded new line' do
18
+ let(:raw_data) { '<obj><S>some data_x000D__x000A_</S></obj>' }
19
+
20
+ it 'decodes without double newline' do
21
+ expect(subject.output).to eq("some data\r\n")
22
+ end
23
+ end
24
+
25
+ context 'receiving output with new line in middle' do
26
+ let(:raw_data) { '<obj><S>some_x000D__x000A_data</S></obj>' }
27
+
28
+ it 'decodes and replaces newline' do
29
+ expect(subject.output).to eq("some\r\ndata\r\n")
30
+ end
31
+ end
32
+ end