winrm 2.0.3 → 2.1.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 (127) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +10 -10
  3. data/.rubocop.yml +26 -26
  4. data/.travis.yml +11 -11
  5. data/Gemfile +3 -3
  6. data/README.md +260 -233
  7. data/Rakefile +34 -34
  8. data/Vagrantfile +6 -6
  9. data/WinrmAppveyor.psm1 +31 -31
  10. data/appveyor.yml +51 -51
  11. data/changelog.md +104 -101
  12. data/lib/winrm.rb +39 -39
  13. data/lib/winrm/connection.rb +83 -82
  14. data/lib/winrm/connection_opts.rb +91 -91
  15. data/lib/winrm/exceptions.rb +76 -76
  16. data/lib/winrm/http/response_handler.rb +96 -96
  17. data/lib/winrm/http/transport.rb +424 -424
  18. data/lib/winrm/http/transport_factory.rb +68 -68
  19. data/lib/winrm/output.rb +59 -59
  20. data/lib/winrm/psrp/create_pipeline.xml.erb +167 -167
  21. data/lib/winrm/psrp/fragment.rb +70 -70
  22. data/lib/winrm/psrp/init_runspace_pool.xml.erb +224 -224
  23. data/lib/winrm/psrp/message.rb +130 -130
  24. data/lib/winrm/psrp/message_data.rb +42 -42
  25. data/lib/winrm/psrp/message_data/base.rb +49 -49
  26. data/lib/winrm/psrp/message_data/error_record.rb +68 -68
  27. data/lib/winrm/psrp/message_data/pipeline_host_call.rb +32 -32
  28. data/lib/winrm/psrp/message_data/pipeline_output.rb +49 -49
  29. data/lib/winrm/psrp/message_data/pipeline_state.rb +40 -40
  30. data/lib/winrm/psrp/message_data/runspacepool_host_call.rb +32 -32
  31. data/lib/winrm/psrp/message_data/runspacepool_state.rb +39 -39
  32. data/lib/winrm/psrp/message_data/session_capability.rb +36 -36
  33. data/lib/winrm/psrp/message_defragmenter.rb +62 -62
  34. data/lib/winrm/psrp/message_factory.rb +75 -75
  35. data/lib/winrm/psrp/message_fragmenter.rb +60 -60
  36. data/lib/winrm/psrp/powershell_output_decoder.rb +139 -139
  37. data/lib/winrm/psrp/receive_response_reader.rb +97 -97
  38. data/lib/winrm/psrp/session_capability.xml.erb +7 -7
  39. data/lib/winrm/psrp/uuid.rb +40 -40
  40. data/lib/winrm/shells/base.rb +180 -175
  41. data/lib/winrm/shells/cmd.rb +65 -65
  42. data/lib/winrm/shells/power_shell.rb +202 -202
  43. data/lib/winrm/shells/retryable.rb +45 -45
  44. data/lib/winrm/shells/shell_factory.rb +58 -50
  45. data/lib/winrm/version.rb +7 -7
  46. data/lib/winrm/wsmv/base.rb +59 -59
  47. data/lib/winrm/wsmv/cleanup_command.rb +61 -61
  48. data/lib/winrm/wsmv/close_shell.rb +50 -50
  49. data/lib/winrm/wsmv/command.rb +101 -101
  50. data/lib/winrm/wsmv/command_output.rb +76 -76
  51. data/lib/winrm/wsmv/command_output_decoder.rb +55 -55
  52. data/lib/winrm/wsmv/configuration.rb +46 -46
  53. data/lib/winrm/wsmv/create_pipeline.rb +66 -66
  54. data/lib/winrm/wsmv/create_shell.rb +119 -119
  55. data/lib/winrm/wsmv/header.rb +203 -203
  56. data/lib/winrm/wsmv/init_runspace_pool.rb +95 -95
  57. data/lib/winrm/wsmv/iso8601_duration.rb +60 -60
  58. data/lib/winrm/wsmv/keep_alive.rb +68 -68
  59. data/lib/winrm/wsmv/receive_response_reader.rb +126 -126
  60. data/lib/winrm/wsmv/send_data.rb +68 -68
  61. data/lib/winrm/wsmv/soap.rb +51 -51
  62. data/lib/winrm/wsmv/wql_query.rb +79 -79
  63. data/lib/winrm/wsmv/write_stdin.rb +88 -88
  64. data/tests/integration/auth_timeout_spec.rb +18 -18
  65. data/tests/integration/cmd_spec.rb +131 -110
  66. data/tests/integration/config-example.yml +16 -16
  67. data/tests/integration/issue_59_spec.rb +26 -26
  68. data/tests/integration/powershell_spec.rb +165 -165
  69. data/tests/integration/spec_helper.rb +65 -65
  70. data/tests/integration/transport_spec.rb +99 -99
  71. data/tests/integration/wql_spec.rb +16 -16
  72. data/tests/matchers.rb +60 -60
  73. data/tests/spec/configuration_spec.rb +184 -184
  74. data/tests/spec/connection_spec.rb +39 -39
  75. data/tests/spec/exception_spec.rb +50 -50
  76. data/tests/spec/http/transport_factory_spec.rb +68 -68
  77. data/tests/spec/http/transport_spec.rb +44 -44
  78. data/tests/spec/output_spec.rb +127 -127
  79. data/tests/spec/psrp/fragment_spec.rb +62 -62
  80. data/tests/spec/psrp/message_data/base_spec.rb +13 -13
  81. data/tests/spec/psrp/message_data/error_record_spec.rb +41 -41
  82. data/tests/spec/psrp/message_data/pipeline_host_call_spec.rb +25 -25
  83. data/tests/spec/psrp/message_data/pipeline_output_spec.rb +32 -32
  84. data/tests/spec/psrp/message_data/pipeline_state_spec.rb +40 -40
  85. data/tests/spec/psrp/message_data/runspace_pool_host_call_spec.rb +25 -25
  86. data/tests/spec/psrp/message_data/runspacepool_state_spec.rb +16 -16
  87. data/tests/spec/psrp/message_data/session_capability_spec.rb +30 -30
  88. data/tests/spec/psrp/message_data_spec.rb +35 -35
  89. data/tests/spec/psrp/message_defragmenter_spec.rb +47 -47
  90. data/tests/spec/psrp/message_fragmenter_spec.rb +105 -105
  91. data/tests/spec/psrp/powershell_output_decoder_spec.rb +100 -100
  92. data/tests/spec/psrp/psrp_message_spec.rb +70 -70
  93. data/tests/spec/psrp/recieve_response_reader_spec.rb +172 -172
  94. data/tests/spec/psrp/uuid_spec.rb +28 -28
  95. data/tests/spec/response_handler_spec.rb +61 -61
  96. data/tests/spec/shells/base_spec.rb +202 -202
  97. data/tests/spec/shells/cmd_spec.rb +75 -75
  98. data/tests/spec/shells/powershell_spec.rb +175 -175
  99. data/tests/spec/spec_helper.rb +47 -47
  100. data/tests/spec/stubs/clixml/error_record.xml.erb +84 -84
  101. data/tests/spec/stubs/clixml/pipeline_state.xml.erb +88 -88
  102. data/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 -10
  104. data/tests/spec/stubs/responses/get_powershell_keepalive_response.xml.erb +10 -10
  105. data/tests/spec/stubs/responses/get_powershell_output_response.xml.erb +12 -12
  106. data/tests/spec/stubs/responses/get_powershell_output_response_not_done.xml.erb +9 -9
  107. data/tests/spec/stubs/responses/open_shell_v1.xml +19 -19
  108. data/tests/spec/stubs/responses/open_shell_v2.xml +20 -20
  109. data/tests/spec/stubs/responses/soap_fault_v1.xml +36 -36
  110. data/tests/spec/stubs/responses/soap_fault_v2.xml +42 -42
  111. data/tests/spec/stubs/responses/wmi_error_v2.xml +41 -41
  112. data/tests/spec/wsmv/cleanup_command_spec.rb +22 -22
  113. data/tests/spec/wsmv/close_shell_spec.rb +17 -17
  114. data/tests/spec/wsmv/command_output_decoder_spec.rb +37 -37
  115. data/tests/spec/wsmv/command_output_spec.rb +45 -45
  116. data/tests/spec/wsmv/command_spec.rb +19 -19
  117. data/tests/spec/wsmv/configuration_spec.rb +17 -17
  118. data/tests/spec/wsmv/create_pipeline_spec.rb +31 -31
  119. data/tests/spec/wsmv/create_shell_spec.rb +38 -38
  120. data/tests/spec/wsmv/init_runspace_pool_spec.rb +36 -36
  121. data/tests/spec/wsmv/keep_alive_spec.rb +21 -21
  122. data/tests/spec/wsmv/receive_response_reader_spec.rb +123 -123
  123. data/tests/spec/wsmv/send_data_spec.rb +30 -30
  124. data/tests/spec/wsmv/wql_query_spec.rb +13 -13
  125. data/tests/spec/wsmv/write_stdin_spec.rb +22 -22
  126. data/winrm.gemspec +42 -42
  127. metadata +2 -2
@@ -1,68 +1,68 @@
1
- # encoding: UTF-8
2
- require 'winrm/exceptions'
3
- require 'winrm/http/transport_factory'
4
-
5
- module WinRM
6
- module HTTP
7
- # Remove the gssapi stuff in kerberos init for tests
8
- class HttpGSSAPI < HttpTransport
9
- def initialize(endpoint, realm, opts, service = nil)
10
- end
11
- end
12
- end
13
- end
14
-
15
- describe WinRM::HTTP::TransportFactory do
16
- describe '#create_transport' do
17
- let(:transport) { :negotiate }
18
- let(:options) do
19
- {
20
- transport: transport,
21
- endpoint: 'endpoint',
22
- user: 'user'
23
- }
24
- end
25
-
26
- it 'creates a negotiate transport' do
27
- options[:transport] = :negotiate
28
- expect(subject.create_transport(options)).to be_a(WinRM::HTTP::HttpNegotiate)
29
- end
30
-
31
- it 'creates a plaintext transport' do
32
- options[:transport] = :plaintext
33
- expect(subject.create_transport(options)).to be_a(WinRM::HTTP::HttpPlaintext)
34
- end
35
-
36
- it 'creates a basic auth ssl transport' do
37
- options[:transport] = :ssl
38
- options[:basic_auth_only] = true
39
- expect(subject.create_transport(options)).to be_a(WinRM::HTTP::BasicAuthSSL)
40
- end
41
-
42
- it 'creates a client cert ssl transport' do
43
- options[:transport] = :ssl
44
- options[:client_cert] = 'cert'
45
- expect(subject.create_transport(options)).to be_a(WinRM::HTTP::ClientCertAuthSSL)
46
- end
47
-
48
- it 'creates a negotiate over ssl transport' do
49
- options[:transport] = :ssl
50
- expect(subject.create_transport(options)).to be_a(WinRM::HTTP::HttpNegotiate)
51
- end
52
-
53
- it 'creates a kerberos transport' do
54
- options[:transport] = :kerberos
55
- expect(subject.create_transport(options)).to be_a(WinRM::HTTP::HttpGSSAPI)
56
- end
57
-
58
- it 'creates a transport from a stringified transport' do
59
- options[:transport] = 'negotiate'
60
- expect(subject.create_transport(options)).to be_a(WinRM::HTTP::HttpNegotiate)
61
- end
62
-
63
- it 'raises when transport type does not exist' do
64
- options[:transport] = :fancy
65
- expect { subject.create_transport(options) }.to raise_error(WinRM::InvalidTransportError)
66
- end
67
- end
68
- end
1
+ # encoding: UTF-8
2
+ require 'winrm/exceptions'
3
+ require 'winrm/http/transport_factory'
4
+
5
+ module WinRM
6
+ module HTTP
7
+ # Remove the gssapi stuff in kerberos init for tests
8
+ class HttpGSSAPI < HttpTransport
9
+ def initialize(endpoint, realm, opts, service = nil)
10
+ end
11
+ end
12
+ end
13
+ end
14
+
15
+ describe WinRM::HTTP::TransportFactory do
16
+ describe '#create_transport' do
17
+ let(:transport) { :negotiate }
18
+ let(:options) do
19
+ {
20
+ transport: transport,
21
+ endpoint: 'endpoint',
22
+ user: 'user'
23
+ }
24
+ end
25
+
26
+ it 'creates a negotiate transport' do
27
+ options[:transport] = :negotiate
28
+ expect(subject.create_transport(options)).to be_a(WinRM::HTTP::HttpNegotiate)
29
+ end
30
+
31
+ it 'creates a plaintext transport' do
32
+ options[:transport] = :plaintext
33
+ expect(subject.create_transport(options)).to be_a(WinRM::HTTP::HttpPlaintext)
34
+ end
35
+
36
+ it 'creates a basic auth ssl transport' do
37
+ options[:transport] = :ssl
38
+ options[:basic_auth_only] = true
39
+ expect(subject.create_transport(options)).to be_a(WinRM::HTTP::BasicAuthSSL)
40
+ end
41
+
42
+ it 'creates a client cert ssl transport' do
43
+ options[:transport] = :ssl
44
+ options[:client_cert] = 'cert'
45
+ expect(subject.create_transport(options)).to be_a(WinRM::HTTP::ClientCertAuthSSL)
46
+ end
47
+
48
+ it 'creates a negotiate over ssl transport' do
49
+ options[:transport] = :ssl
50
+ expect(subject.create_transport(options)).to be_a(WinRM::HTTP::HttpNegotiate)
51
+ end
52
+
53
+ it 'creates a kerberos transport' do
54
+ options[:transport] = :kerberos
55
+ expect(subject.create_transport(options)).to be_a(WinRM::HTTP::HttpGSSAPI)
56
+ end
57
+
58
+ it 'creates a transport from a stringified transport' do
59
+ options[:transport] = 'negotiate'
60
+ expect(subject.create_transport(options)).to be_a(WinRM::HTTP::HttpNegotiate)
61
+ end
62
+
63
+ it 'raises when transport type does not exist' do
64
+ options[:transport] = :fancy
65
+ expect { subject.create_transport(options) }.to raise_error(WinRM::InvalidTransportError)
66
+ end
67
+ end
68
+ end
@@ -1,44 +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
+ # 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,127 +1,127 @@
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
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