ztk 0.2.4 → 0.2.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -19,5 +19,5 @@
19
19
  ################################################################################
20
20
 
21
21
  module ZTK
22
- VERSION = "0.2.4" unless const_defined?(:VERSION)
22
+ VERSION = "0.2.5" unless const_defined?(:VERSION)
23
23
  end
@@ -28,6 +28,14 @@ SimpleCov.start do
28
28
  add_filter '/spec/'
29
29
  end if ENV["COVERAGE"]
30
30
 
31
+ ENV['LOG_LEVEL'] = "DEBUG"
32
+
33
+ WAIT_SMALL = 3
34
+
31
35
  $logger = ZTK::Logger.new(File.join("/tmp", "test.log"))
32
36
 
37
+ $logger.info { "=" * 80 }
38
+ $logger.info { "STARTING ZTK v#{ZTK::VERSION} TEST RUN @ #{Time.now.utc}" }
39
+ $logger.info { "=" * 80 }
40
+
33
41
  ################################################################################
@@ -0,0 +1,41 @@
1
+ ################################################################################
2
+ #
3
+ # Author: Zachary Patten <zachary@jovelabs.net>
4
+ # Copyright: Copyright (c) Jove Labs
5
+ # License: Apache License, Version 2.0
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+ ################################################################################
20
+
21
+ require "spec_helper"
22
+
23
+ describe ZTK::Base do
24
+
25
+ subject { ZTK::Base }
26
+
27
+ before(:all) do
28
+ $stdout = File.open("/dev/null", "w")
29
+ $stderr = File.open("/dev/null", "w")
30
+ $stdin = File.open("/dev/null", "r")
31
+ end
32
+
33
+ describe "class" do
34
+
35
+ it "should be ZTK::Base" do
36
+ subject.should be ZTK::Base
37
+ end
38
+
39
+ end
40
+
41
+ end
@@ -53,25 +53,23 @@ describe ZTK::Benchmark do
53
53
  mark.should be_an_instance_of Float
54
54
  end
55
55
 
56
- it "should not write to STDOUT if not given a message or mark" do
56
+ it "should throw an exception if executed with a message but without a mark" do
57
57
  stdout = StringIO.new
58
- ZTK::Benchmark.bench(:stdout => stdout) do
59
- sleep(0.1)
60
- end
61
- stdout.size.should == 0
58
+ lambda {
59
+ ZTK::Benchmark.bench(:stdout => stdout, :message => "Hello World")
60
+ }.should raise_error ZTK::BenchmarkError
62
61
  end
63
62
 
64
- it "should not write to STDOUT if not given a message" do
63
+ it "should throw an exception if executed without a message but with a mark" do
65
64
  stdout = StringIO.new
66
- ZTK::Benchmark.bench(:stdout => stdout, :mark => "%0.4f") do
67
- sleep(0.1)
68
- end
69
- stdout.size.should == 0
65
+ lambda {
66
+ ZTK::Benchmark.bench(:stdout => stdout, :mark => "%0.4f")
67
+ }.should raise_error ZTK::BenchmarkError
70
68
  end
71
69
 
72
- it "should not write to STDOUT if not given a mark" do
70
+ it "should not write to STDOUT if not given a message or mark" do
73
71
  stdout = StringIO.new
74
- ZTK::Benchmark.bench(:stdout => stdout, :message => "Hello World") do
72
+ ZTK::Benchmark.bench(:stdout => stdout) do
75
73
  sleep(0.1)
76
74
  end
77
75
  stdout.size.should == 0
@@ -62,16 +62,149 @@ describe ZTK::Command do
62
62
 
63
63
  end
64
64
 
65
- it "should be able to execute the command \"hostname -f\"" do
66
- stdout = StringIO.new
67
- subject.config do |config|
68
- config.stdout = stdout
65
+ describe "behaviour" do
66
+
67
+ describe "execute" do
68
+
69
+ it "should be able to execute the command \"hostname -f\"" do
70
+ stdout = StringIO.new
71
+ subject.config do |config|
72
+ config.stdout = stdout
73
+ end
74
+ hostname = %x(hostname -f).chomp
75
+ status = subject.exec("hostname -f")
76
+ status.exit_code.should == 0
77
+ stdout.rewind
78
+ stdout.read.chomp.should == hostname
79
+ end
80
+
81
+ it "should timeout after the period specified" do
82
+ stdout = StringIO.new
83
+ subject.config do |config|
84
+ config.stdout = stdout
85
+ config.timeout = WAIT_SMALL
86
+ end
87
+ hostname = %x(hostname -f).chomp
88
+ lambda { subject.exec("hostname -f ; sleep 10") }.should raise_error ZTK::CommandError
89
+ end
90
+
91
+ it "should throw an exception if the exit status is not as expected" do
92
+ stdout = StringIO.new
93
+ subject.config do |config|
94
+ config.stdout = stdout
95
+ end
96
+ lambda { subject.exec("/bin/bash -c 'exit 64'") }.should raise_error ZTK::CommandError
97
+ end
98
+
99
+ it "should return a instance of an OpenStruct object" do
100
+ stdout = StringIO.new
101
+ subject.config do |config|
102
+ config.stdout = stdout
103
+ end
104
+ result = subject.exec(%q{echo "Hello World"})
105
+ result.should be_an_instance_of OpenStruct
106
+ end
107
+
108
+ it "should return the exit code" do
109
+ stdout = StringIO.new
110
+ subject.config do |config|
111
+ config.stdout = stdout
112
+ end
113
+ data = 64
114
+
115
+ result = subject.exec(%Q{/bin/bash -c 'exit #{data}'}, :exit_code => data)
116
+ result.exit_code.should == data
117
+ end
118
+
119
+ it "should return the output" do
120
+ stdout = StringIO.new
121
+ subject.config do |config|
122
+ config.stdout = stdout
123
+ end
124
+ data = "Hello World @ #{Time.now.utc}"
125
+
126
+ result = subject.exec(%Q{echo "#{data}"})
127
+ result.output.match(data).should_not be nil
128
+ end
129
+
130
+ it "should allow us to change the expected exit code" do
131
+ stdout = StringIO.new
132
+ subject.config do |config|
133
+ config.stdout = stdout
134
+ end
135
+ data = 32
136
+ result = subject.exec(%Q{/bin/bash -c 'exit #{data}'}, :exit_code => data)
137
+ end
138
+
139
+ describe "stdout" do
140
+
141
+ it "should capture STDOUT and send it to the appropriate pipe" do
142
+ stdout, stderr, stdin = StringIO.new, StringIO.new, StringIO.new
143
+
144
+ subject.config do |config|
145
+ config.stdout = stdout
146
+ config.stderr = stderr
147
+ config.stdin = stdin
148
+ end
149
+ data = "Hello World @ #{Time.now.utc}"
150
+
151
+ subject.exec(%Q{echo "#{data}" -f >&1})
152
+
153
+ stdout.rewind
154
+ stdout.read.match(data).should_not be nil
155
+
156
+ stderr.rewind
157
+ stderr.read.match(data).should be nil
158
+
159
+ stdin.rewind
160
+ stdin.read.match(data).should be nil
161
+ end
162
+
163
+ end
164
+
165
+ describe "stderr" do
166
+
167
+ it "should capture STDERR and send it to the appropriate pipe" do
168
+ stdout, stderr, stdin = StringIO.new, StringIO.new, StringIO.new
169
+
170
+ subject.config do |config|
171
+ config.stdout = stdout
172
+ config.stderr = stderr
173
+ config.stdin = stdin
174
+ end
175
+ data = "Hello World @ #{Time.now.utc}"
176
+
177
+ subject.exec(%Q{echo "#{data}" -f >&2})
178
+
179
+ stdout.rewind
180
+ stdout.read.match(data).should be nil
181
+
182
+ stderr.rewind
183
+ stderr.read.match(data).should_not be nil
184
+
185
+ stdin.rewind
186
+ stdin.read.match(data).should be nil
187
+ end
188
+ end
189
+
69
190
  end
70
- hostname = %x( hostname -f ).chomp
71
- status = subject.exec("hostname -f")
72
- status.exit.exitstatus.should == 0
73
- stdout.rewind
74
- stdout.read.chomp.should == hostname
191
+
192
+ describe "upload" do
193
+
194
+ it "should raise a 'Not Supported' exception when attempting to upload" do
195
+ lambda { subject.upload("abc", "123") }.should raise_error
196
+ end
197
+
198
+ end
199
+
200
+ describe "download" do
201
+
202
+ it "should raise a 'Not Supported' exception when attempting to download" do
203
+ lambda { subject.download("abc", "123") }.should raise_error
204
+ end
205
+
206
+ end
207
+
75
208
  end
76
209
 
77
210
  end
@@ -45,26 +45,26 @@ describe ZTK::Config do
45
45
 
46
46
  end
47
47
 
48
- describe "behaviour" do
48
+ end
49
49
 
50
- it "should allow setting of arbratary configuration keys" do
51
- subject.thing = "something"
52
- subject.thing.should == "something"
53
- subject[:thing].should == "something"
54
- end
50
+ describe "behaviour" do
55
51
 
56
- it "should allow hash bracket style access to configuration keys" do
57
- subject[:thing] = "nothing"
58
- subject[:thing].should == "nothing"
59
- end
52
+ it "should allow setting of arbratary configuration keys" do
53
+ subject.thing = "something"
54
+ subject.thing.should == "something"
55
+ subject[:thing].should == "something"
56
+ end
60
57
 
61
- it "should allow loading of configurations from disk" do
62
- config_file = File.expand_path(File.join(File.dirname(__FILE__), "..", "support", "test-config.rb"))
63
- subject.from_file(config_file)
64
- subject.message.should == "Hello World"
65
- subject.thing.should == 2
66
- end
58
+ it "should allow hash bracket style access to configuration keys" do
59
+ subject[:thing] = "nothing"
60
+ subject[:thing].should == "nothing"
61
+ end
67
62
 
63
+ it "should allow loading of configurations from disk" do
64
+ config_file = File.expand_path(File.join(File.dirname(__FILE__), "..", "support", "test-config.rb"))
65
+ subject.from_file(config_file)
66
+ subject.message.should == "Hello World"
67
+ subject.thing.should == 2
68
68
  end
69
69
 
70
70
  end
@@ -85,7 +85,7 @@ describe ZTK::Logger do
85
85
 
86
86
  it "should allow writing directly to the log device" do
87
87
  data = "Hello World"
88
- IO.write(subject.logdev, data)
88
+ subject.logdev.write(data)
89
89
  IO.read(@logfile).match(data).should_not be nil
90
90
  end
91
91
 
@@ -46,7 +46,7 @@ describe ZTK::RescueRetry do
46
46
  }.should raise_error ZTK::RescueRetryError, "You must supply a block!"
47
47
  end
48
48
 
49
- it "should retry on all exceptions" do
49
+ it "should retry on all exceptions by default if one is not supplied" do
50
50
  $counter = 0
51
51
  lambda {
52
52
  ZTK::RescueRetry.try(:tries => 3) do
@@ -57,7 +57,7 @@ describe ZTK::RescueRetry do
57
57
  $counter.should == 3
58
58
  end
59
59
 
60
- it "should retry on specific exceptions" do
60
+ it "should retry on supplied exception" do
61
61
  $counter = 0
62
62
  lambda {
63
63
  ZTK::RescueRetry.try(:tries => 3, :on => EOFError) do
@@ -68,7 +68,7 @@ describe ZTK::RescueRetry do
68
68
  $counter.should == 3
69
69
  end
70
70
 
71
- it "should not retry on specific exceptions if exceptions do not match" do
71
+ it "should not retry on exception if it does not match the supplied exception" do
72
72
  $counter = 0
73
73
  lambda {
74
74
  ZTK::RescueRetry.try(:tries => 3, :on => EOFError) do
@@ -0,0 +1,51 @@
1
+ ################################################################################
2
+ #
3
+ # Author: Zachary Patten <zachary@jovelabs.net>
4
+ # Copyright: Copyright (c) Jove Labs
5
+ # License: Apache License, Version 2.0
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+ ################################################################################
20
+
21
+ require "spec_helper"
22
+
23
+ describe ZTK::Spinner do
24
+
25
+ subject { ZTK::Spinner }
26
+
27
+ before(:all) do
28
+ $stdout = File.open("/dev/null", "w")
29
+ $stderr = File.open("/dev/null", "w")
30
+ $stdin = File.open("/dev/null", "r")
31
+ end
32
+
33
+ describe "class" do
34
+
35
+ it "should be ZTK::Spinner" do
36
+ subject.should be ZTK::Spinner
37
+ end
38
+
39
+ end
40
+
41
+ describe "behaviour" do
42
+
43
+ it "should throw an exception if executed without a block" do
44
+ lambda {
45
+ ZTK::Spinner.spin
46
+ }.should raise_error ZTK::SpinnerError, "You must supply a block!"
47
+ end
48
+
49
+ end
50
+
51
+ end
@@ -60,183 +60,449 @@ describe ZTK::SSH do
60
60
 
61
61
  end
62
62
 
63
- # this stuff doesn't work as is under travis-ci
64
- if !ENV['CI'] && !ENV['TRAVIS']
63
+ end
65
64
 
66
- describe "direct behaviour" do
65
+ # this stuff doesn't work as is under travis-ci right now
66
+ describe "direct SSH behaviour" do
67
67
 
68
- describe "execute" do
68
+ describe "execute" do
69
69
 
70
- it "should be able to connect to 127.0.0.1 as the current user and execute a command (your key must be in ssh-agent)" do
71
- stdout, stderr = StringIO.new, StringIO.new
72
- subject.config do |config|
73
- config.stdout = stdout
74
- config.stderr = stderr
75
- config.user = ENV["USER"]
76
- config.host_name = "127.0.0.1"
77
- end
70
+ it "should be able to connect to 127.0.0.1 as the current user and execute a command (your key must be in ssh-agent)" do
71
+ stdout, stderr, stdin = StringIO.new, StringIO.new, StringIO.new
72
+ subject.config do |config|
73
+ config.stdout, config.stderr, config.stdin = stdout, stderr, stdin
78
74
 
79
- data = %x(hostname -f).chomp
75
+ config.user = ENV["USER"]
76
+ config.host_name = "127.0.0.1"
77
+ end
80
78
 
81
- status = subject.exec("hostname -f")
82
- status.exit.exitstatus.should == 0
83
- stdout.rewind
84
- stdout.read.chomp.should == data
85
- end
79
+ data = %x(hostname -f).chomp
86
80
 
81
+ status = subject.exec("hostname -f")
82
+ status.exit_code.should == 0
83
+ stdout.rewind
84
+ stdout.read.chomp.should == data
85
+ end
86
+
87
+ it "should timeout after the period specified" do
88
+ stdout, stderr, stdin = StringIO.new, StringIO.new, StringIO.new
89
+ subject.config do |config|
90
+ config.stdout, config.stderr, config.stdin = stdout, stderr, stdin
91
+
92
+ config.user = ENV["USER"]
93
+ config.host_name = "127.0.0.1"
94
+ config.timeout = WAIT_SMALL
87
95
  end
96
+ hostname = %x(hostname -f).chomp
97
+ lambda { subject.exec("hostname -f ; sleep 10") }.should raise_error ZTK::SSHError
98
+ end
88
99
 
89
- describe "upload" do
100
+ it "should throw an exception if the exit status is not as expected" do
101
+ stdout, stderr, stdin = StringIO.new, StringIO.new, StringIO.new
102
+ subject.config do |config|
103
+ config.stdout, config.stderr, config.stdin = stdout, stderr, stdin
90
104
 
91
- it "should be able to upload a file to 127.0.0.1 as the current user and execute a command (your key must be in ssh-agent)" do
92
- stdout, stderr = StringIO.new, StringIO.new
93
- subject.config do |config|
94
- config.stdout = stdout
95
- config.stderr = stderr
96
- config.user = ENV["USER"]
97
- config.host_name = "127.0.0.1"
98
- end
105
+ config.user = ENV["USER"]
106
+ config.host_name = "127.0.0.1"
107
+ end
108
+ lambda { subject.exec("/bin/bash -c 'exit 64'") }.should raise_error ZTK::SSHError
109
+ end
99
110
 
100
- data = "Hello World"
111
+ it "should return a instance of an OpenStruct object" do
112
+ stdout, stderr, stdin = StringIO.new, StringIO.new, StringIO.new
113
+ subject.config do |config|
114
+ config.stdout, config.stderr, config.stdin = stdout, stderr, stdin
101
115
 
102
- remote_file = File.join("/tmp", "ssh-upload-remote")
103
- File.exists?(remote_file) && File.delete(remote_file)
116
+ config.user = ENV["USER"]
117
+ config.host_name = "127.0.0.1"
118
+ end
119
+ result = subject.exec(%q{echo "Hello World"})
120
+ result.should be_an_instance_of OpenStruct
121
+ end
104
122
 
105
- local_file = File.join("/tmp", "ssh-upload-local")
106
- IO.write(local_file, data)
123
+ it "should return the exit code" do
124
+ stdout, stderr, stdin = StringIO.new, StringIO.new, StringIO.new
125
+ subject.config do |config|
126
+ config.stdout, config.stderr, config.stdin = stdout, stderr, stdin
107
127
 
108
- File.exists?(remote_file).should == false
109
- subject.upload(local_file, remote_file)
110
- File.exists?(remote_file).should == true
128
+ config.user = ENV["USER"]
129
+ config.host_name = "127.0.0.1"
130
+ end
131
+ data = 64
111
132
 
112
- File.exists?(remote_file) && File.delete(remote_file)
113
- File.exists?(local_file) && File.delete(local_file)
114
- end
133
+ result = subject.exec(%Q{/bin/bash -c 'exit #{data}'}, :exit_code => data)
134
+ result.exit_code.should == data
135
+ end
115
136
 
137
+ it "should return the output" do
138
+ stdout, stderr, stdin = StringIO.new, StringIO.new, StringIO.new
139
+ subject.config do |config|
140
+ config.stdout, config.stderr, config.stdin = stdout, stderr, stdin
141
+
142
+ config.user = ENV["USER"]
143
+ config.host_name = "127.0.0.1"
116
144
  end
145
+ data = "Hello World @ #{Time.now.utc}"
146
+
147
+ result = subject.exec(%Q{echo "#{data}"})
148
+ result.output.match(data).should_not be nil
149
+ end
150
+
151
+ it "should allow us to change the expected exit code" do
152
+ stdout, stderr, stdin = StringIO.new, StringIO.new, StringIO.new
153
+ subject.config do |config|
154
+ config.stdout, config.stderr, config.stdin = stdout, stderr, stdin
155
+
156
+ config.user = ENV["USER"]
157
+ config.host_name = "127.0.0.1"
158
+ end
159
+ data = 32
160
+ result = subject.exec(%Q{/bin/bash -c 'exit #{data}'}, :exit_code => data)
161
+ end
117
162
 
118
- describe "download" do
163
+ describe "stdout" do
119
164
 
120
- it "should be able to download a file from 127.0.0.1 as the current user and execute a command (your key must be in ssh-agent)" do
121
- stdout, stderr = StringIO.new, StringIO.new
122
- subject.config do |config|
123
- config.stdout = stdout
124
- config.stderr = stderr
125
- config.user = ENV["USER"]
126
- config.host_name = "127.0.0.1"
127
- end
165
+ it "should capture STDOUT and send it to the appropriate pipe" do
166
+ stdout, stderr, stdin = StringIO.new, StringIO.new, StringIO.new
167
+ subject.config do |config|
168
+ config.stdout, config.stderr, config.stdin = stdout, stderr, stdin
128
169
 
129
- data = "Hello World"
170
+ config.user = ENV["USER"]
171
+ config.host_name = "127.0.0.1"
172
+ end
173
+ data = "Hello World @ #{Time.now.utc}"
174
+
175
+ subject.exec(%Q{echo "#{data}" -f >&1})
176
+
177
+ stdout.rewind
178
+ stdout.read.match(data).should_not be nil
179
+
180
+ stderr.rewind
181
+ stderr.read.match(data).should be nil
130
182
 
131
- local_file = File.join("/tmp", "ssh-download-local")
132
- File.exists?(local_file) && File.delete(local_file)
183
+ stdin.rewind
184
+ stdin.read.match(data).should be nil
185
+ end
186
+
187
+ end
133
188
 
134
- remote_file = File.join("/tmp", "ssh-download-remote")
135
- IO.write(remote_file, data)
189
+ describe "stderr" do
136
190
 
137
- File.exists?(local_file).should == false
138
- subject.download(remote_file, local_file)
139
- File.exists?(local_file).should == true
191
+ it "should capture STDERR and send it to the appropriate pipe" do
192
+ stdout, stderr, stdin = StringIO.new, StringIO.new, StringIO.new
193
+ subject.config do |config|
194
+ config.stdout, config.stderr, config.stdin = stdout, stderr, stdin
140
195
 
141
- File.exists?(local_file) && File.delete(local_file)
142
- File.exists?(remote_file) && File.delete(remote_file)
196
+ config.user = ENV["USER"]
197
+ config.host_name = "127.0.0.1"
143
198
  end
199
+ data = "Hello World @ #{Time.now.utc}"
144
200
 
201
+ subject.exec(%Q{echo "#{data}" -f >&2})
202
+
203
+ stdout.rewind
204
+ stdout.read.match(data).should be nil
205
+
206
+ stderr.rewind
207
+ stderr.read.match(data).should_not be nil
208
+
209
+ stdin.rewind
210
+ stdin.read.match(data).should be nil
211
+ end
212
+ end
213
+
214
+ end
215
+
216
+ describe "upload" do
217
+
218
+ it "should be able to upload a file to 127.0.0.1 as the current user and execute a command (your key must be in ssh-agent)" do
219
+ stdout, stderr, stdin = StringIO.new, StringIO.new, StringIO.new
220
+ subject.config do |config|
221
+ config.stdout, config.stderr, config.stdin = stdout, stderr, stdin
222
+
223
+ config.user = ENV["USER"]
224
+ config.host_name = "127.0.0.1"
225
+ end
226
+
227
+ data = "Hello World @ #{Time.now.utc}"
228
+
229
+ remote_file = File.join("/tmp", "ssh-upload-remote")
230
+ File.exists?(remote_file) && File.delete(remote_file)
231
+
232
+ local_file = File.join("/tmp", "ssh-upload-local")
233
+ IO.write(local_file, data)
234
+
235
+ File.exists?(remote_file).should == false
236
+ subject.upload(local_file, remote_file)
237
+ File.exists?(remote_file).should == true
238
+
239
+ File.exists?(remote_file) && File.delete(remote_file)
240
+ File.exists?(local_file) && File.delete(local_file)
241
+ end
242
+
243
+ end
244
+
245
+ describe "download" do
246
+
247
+ it "should be able to download a file from 127.0.0.1 as the current user and execute a command (your key must be in ssh-agent)" do
248
+ stdout, stderr, stdin = StringIO.new, StringIO.new, StringIO.new
249
+ subject.config do |config|
250
+ config.stdout, config.stderr, config.stdin = stdout, stderr, stdin
251
+
252
+ config.user = ENV["USER"]
253
+ config.host_name = "127.0.0.1"
145
254
  end
146
255
 
256
+ data = "Hello World @ #{Time.now.utc}"
257
+
258
+ local_file = File.join("/tmp", "ssh-download-local")
259
+ File.exists?(local_file) && File.delete(local_file)
260
+
261
+ remote_file = File.join("/tmp", "ssh-download-remote")
262
+ IO.write(remote_file, data)
263
+
264
+ File.exists?(local_file).should == false
265
+ subject.download(remote_file, local_file)
266
+ File.exists?(local_file).should == true
267
+
268
+ File.exists?(local_file) && File.delete(local_file)
269
+ File.exists?(remote_file) && File.delete(remote_file)
147
270
  end
148
271
 
149
- describe "proxy behaviour" do
272
+ end
150
273
 
151
- describe "execute" do
274
+ end if !ENV['CI'] && !ENV['TRAVIS']
152
275
 
153
- it "should be able to proxy through 127.0.0.1, connecting to 127.0.0.1 as the current user and execute a command (your key must be in ssh-agent)" do
154
- stdout, stderr = StringIO.new, StringIO.new
155
- subject.config do |config|
156
- config.stdout = stdout
157
- config.stderr = stderr
158
- config.user = ENV["USER"]
159
- config.host_name = "127.0.0.1"
160
- config.proxy_user = ENV["USER"]
161
- config.proxy_host_name = "127.0.0.1"
162
- end
276
+ describe "proxy SSH behaviour" do
163
277
 
164
- data = %x( hostname -f ).chomp
278
+ describe "execute" do
165
279
 
166
- status = subject.exec("hostname -f")
167
- status.exit.exitstatus.should == 0
168
- stdout.rewind
169
- stdout.read.chomp.should == data
170
- end
280
+ it "should be able to proxy through 127.0.0.1, connecting to 127.0.0.1 as the current user and execute a command (your key must be in ssh-agent)" do
281
+ stdout, stderr, stdin = StringIO.new, StringIO.new, StringIO.new
282
+ subject.config do |config|
283
+ config.stdout, config.stderr, config.stdin = stdout, stderr, stdin
171
284
 
285
+ config.user = ENV["USER"]
286
+ config.host_name = "127.0.0.1"
287
+ config.proxy_user = ENV["USER"]
288
+ config.proxy_host_name = "127.0.0.1"
172
289
  end
173
290
 
174
- describe "upload" do
291
+ data = %x( hostname -f ).chomp
175
292
 
176
- it "should be able to upload a file to 127.0.0.1 as the current user and execute a command (your key must be in ssh-agent)" do
177
- stdout, stderr = StringIO.new, StringIO.new
178
- subject.config do |config|
179
- config.stdout = stdout
180
- config.stderr = stderr
181
- config.user = ENV["USER"]
182
- config.host_name = "127.0.0.1"
183
- config.proxy_user = ENV["USER"]
184
- config.proxy_host_name = "127.0.0.1"
185
- end
293
+ status = subject.exec("hostname -f")
294
+ status.exit_code.should == 0
295
+ stdout.rewind
296
+ stdout.read.chomp.should == data
297
+ end
186
298
 
187
- data = "Hello World"
299
+ it "should timeout after the period specified" do
300
+ stdout, stderr, stdin = StringIO.new, StringIO.new, StringIO.new
301
+ subject.config do |config|
302
+ config.stdout, config.stderr, config.stdin = stdout, stderr, stdin
188
303
 
189
- remote_file = File.join("/tmp", "ssh-upload-remote")
190
- File.exists?(remote_file) && File.delete(remote_file)
304
+ config.user = ENV["USER"]
305
+ config.host_name = "127.0.0.1"
306
+ config.proxy_user = ENV["USER"]
307
+ config.proxy_host_name = "127.0.0.1"
308
+ config.timeout = WAIT_SMALL
309
+ end
310
+ hostname = %x(hostname -f).chomp
311
+ lambda { subject.exec("hostname -f ; sleep 10") }.should raise_error ZTK::SSHError
312
+ end
191
313
 
192
- local_file = File.join("/tmp", "ssh-upload-local")
193
- IO.write(local_file, data)
314
+ it "should throw an exception if the exit status is not as expected" do
315
+ stdout, stderr, stdin = StringIO.new, StringIO.new, StringIO.new
316
+ subject.config do |config|
317
+ config.stdout, config.stderr, config.stdin = stdout, stderr, stdin
194
318
 
195
- File.exists?(remote_file).should == false
196
- subject.upload(local_file, remote_file)
197
- File.exists?(remote_file).should == true
319
+ config.user = ENV["USER"]
320
+ config.host_name = "127.0.0.1"
321
+ config.proxy_user = ENV["USER"]
322
+ config.proxy_host_name = "127.0.0.1"
323
+ end
324
+ lambda { subject.exec("/bin/bash -c 'exit 64'") }.should raise_error ZTK::SSHError
325
+ end
198
326
 
199
- File.exists?(remote_file) && File.delete(remote_file)
200
- File.exists?(local_file) && File.delete(local_file)
201
- end
327
+ it "should return a instance of an OpenStruct object" do
328
+ stdout, stderr, stdin = StringIO.new, StringIO.new, StringIO.new
329
+ subject.config do |config|
330
+ config.stdout, config.stderr, config.stdin = stdout, stderr, stdin
331
+
332
+ config.user = ENV["USER"]
333
+ config.host_name = "127.0.0.1"
334
+ config.proxy_user = ENV["USER"]
335
+ config.proxy_host_name = "127.0.0.1"
336
+ end
337
+ result = subject.exec(%q{echo "Hello World"})
338
+ result.should be_an_instance_of OpenStruct
339
+ end
202
340
 
341
+ it "should return the exit code" do
342
+ stdout, stderr, stdin = StringIO.new, StringIO.new, StringIO.new
343
+ subject.config do |config|
344
+ config.stdout, config.stderr, config.stdin = stdout, stderr, stdin
345
+
346
+ config.user = ENV["USER"]
347
+ config.host_name = "127.0.0.1"
348
+ config.proxy_user = ENV["USER"]
349
+ config.proxy_host_name = "127.0.0.1"
203
350
  end
351
+ data = 64
204
352
 
205
- describe "download" do
353
+ result = subject.exec(%Q{/bin/bash -c 'exit #{data}'}, :exit_code => data)
354
+ result.exit_code.should == data
355
+ end
356
+
357
+ it "should return the output" do
358
+ stdout, stderr, stdin = StringIO.new, StringIO.new, StringIO.new
359
+ subject.config do |config|
360
+ config.stdout, config.stderr, config.stdin = stdout, stderr, stdin
361
+
362
+ config.user = ENV["USER"]
363
+ config.host_name = "127.0.0.1"
364
+ config.proxy_user = ENV["USER"]
365
+ config.proxy_host_name = "127.0.0.1"
366
+ end
367
+ data = "Hello World @ #{Time.now.utc}"
206
368
 
207
- it "should be able to download a file from 127.0.0.1 as the current user and execute a command (your key must be in ssh-agent)" do
208
- stdout, stderr = StringIO.new, StringIO.new
209
- subject.config do |config|
210
- config.stdout = stdout
211
- config.stderr = stderr
212
- config.user = ENV["USER"]
213
- config.host_name = "127.0.0.1"
214
- config.proxy_user = ENV["USER"]
215
- config.proxy_host_name = "127.0.0.1"
216
- end
369
+ result = subject.exec(%Q{echo "#{data}"})
370
+ result.output.match(data).should_not be nil
371
+ end
217
372
 
218
- data = "Hello World"
373
+ it "should allow us to change the expected exit code" do
374
+ stdout, stderr, stdin = StringIO.new, StringIO.new, StringIO.new
375
+ subject.config do |config|
376
+ config.stdout, config.stderr, config.stdin = stdout, stderr, stdin
219
377
 
220
- local_file = File.join("/tmp", "ssh-download-local")
221
- File.exists?(local_file) && File.delete(local_file)
378
+ config.user = ENV["USER"]
379
+ config.host_name = "127.0.0.1"
380
+ config.proxy_user = ENV["USER"]
381
+ config.proxy_host_name = "127.0.0.1"
382
+ end
383
+ data = 32
384
+ result = subject.exec(%Q{/bin/bash -c 'exit #{data}'}, :exit_code => data)
385
+ end
222
386
 
223
- remote_file = File.join("/tmp", "ssh-download-remote")
224
- IO.write(remote_file, data)
387
+ describe "stdout" do
225
388
 
226
- File.exists?(local_file).should == false
227
- subject.download(remote_file, local_file)
228
- File.exists?(local_file).should == true
389
+ it "should capture STDOUT and send it to the appropriate pipe" do
390
+ stdout, stderr, stdin = StringIO.new, StringIO.new, StringIO.new
391
+ subject.config do |config|
392
+ config.stdout, config.stderr, config.stdin = stdout, stderr, stdin
229
393
 
230
- File.exists?(local_file) && File.delete(local_file)
231
- File.exists?(remote_file) && File.delete(remote_file)
394
+ config.user = ENV["USER"]
395
+ config.host_name = "127.0.0.1"
396
+ config.proxy_user = ENV["USER"]
397
+ config.proxy_host_name = "127.0.0.1"
232
398
  end
399
+ data = "Hello World @ #{Time.now.utc}"
400
+
401
+ subject.exec(%Q{echo "#{data}" -f >&1})
233
402
 
403
+ stdout.rewind
404
+ stdout.read.match(data).should_not be nil
405
+
406
+ stderr.rewind
407
+ stderr.read.match(data).should be nil
408
+
409
+ stdin.rewind
410
+ stdin.read.match(data).should be nil
234
411
  end
235
412
 
236
413
  end
237
414
 
415
+ describe "stderr" do
416
+
417
+ it "should capture STDERR and send it to the appropriate pipe" do
418
+ stdout, stderr, stdin = StringIO.new, StringIO.new, StringIO.new
419
+ subject.config do |config|
420
+ config.stdout, config.stderr, config.stdin = stdout, stderr, stdin
421
+
422
+ config.user = ENV["USER"]
423
+ config.host_name = "127.0.0.1"
424
+ config.proxy_user = ENV["USER"]
425
+ config.proxy_host_name = "127.0.0.1"
426
+ end
427
+ data = "Hello World @ #{Time.now.utc}"
428
+
429
+ subject.exec(%Q{echo "#{data}" -f >&2})
430
+
431
+ stdout.rewind
432
+ stdout.read.match(data).should be nil
433
+
434
+ stderr.rewind
435
+ stderr.read.match(data).should_not be nil
436
+
437
+ stdin.rewind
438
+ stdin.read.match(data).should be nil
439
+ end
440
+ end
441
+
238
442
  end
239
443
 
240
- end
444
+ describe "upload" do
445
+
446
+ it "should be able to upload a file to 127.0.0.1 as the current user and execute a command (your key must be in ssh-agent)" do
447
+ stdout, stderr, stdin = StringIO.new, StringIO.new, StringIO.new
448
+ subject.config do |config|
449
+ config.stdout, config.stderr, config.stdin = stdout, stderr, stdin
450
+
451
+ config.user = ENV["USER"]
452
+ config.host_name = "127.0.0.1"
453
+ config.proxy_user = ENV["USER"]
454
+ config.proxy_host_name = "127.0.0.1"
455
+ end
456
+
457
+ data = "Hello World @ #{Time.now.utc}"
458
+
459
+ remote_file = File.join("/tmp", "ssh-upload-remote")
460
+ File.exists?(remote_file) && File.delete(remote_file)
461
+
462
+ local_file = File.join("/tmp", "ssh-upload-local")
463
+ IO.write(local_file, data)
464
+
465
+ File.exists?(remote_file).should == false
466
+ subject.upload(local_file, remote_file)
467
+ File.exists?(remote_file).should == true
468
+
469
+ File.exists?(remote_file) && File.delete(remote_file)
470
+ File.exists?(local_file) && File.delete(local_file)
471
+ end
472
+
473
+ end
474
+
475
+ describe "download" do
476
+
477
+ it "should be able to download a file from 127.0.0.1 as the current user and execute a command (your key must be in ssh-agent)" do
478
+ stdout, stderr, stdin = StringIO.new, StringIO.new, StringIO.new
479
+ subject.config do |config|
480
+ config.stdout, config.stderr, config.stdin = stdout, stderr, stdin
481
+
482
+ config.user = ENV["USER"]
483
+ config.host_name = "127.0.0.1"
484
+ config.proxy_user = ENV["USER"]
485
+ config.proxy_host_name = "127.0.0.1"
486
+ end
487
+
488
+ data = "Hello World @ #{Time.now.utc}"
489
+
490
+ local_file = File.join("/tmp", "ssh-download-local")
491
+ File.exists?(local_file) && File.delete(local_file)
492
+
493
+ remote_file = File.join("/tmp", "ssh-download-remote")
494
+ IO.write(remote_file, data)
495
+
496
+ File.exists?(local_file).should == false
497
+ subject.download(remote_file, local_file)
498
+ File.exists?(local_file).should == true
499
+
500
+ File.exists?(local_file) && File.delete(local_file)
501
+ File.exists?(remote_file) && File.delete(remote_file)
502
+ end
503
+
504
+ end
505
+
506
+ end if !ENV['CI'] && !ENV['TRAVIS']
241
507
 
242
508
  end