rspec-bash 0.1.1 → 0.2.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.
- checksums.yaml +4 -4
- data/.rubocop.yml +8 -0
- data/Gemfile +1 -0
- data/README.md +23 -0
- data/Rakefile +15 -4
- data/bin/bash_stub.sh +92 -0
- data/bin/bash_wrapper.sh.erb +12 -0
- data/bin/ruby_stub.rb +33 -0
- data/lib/rspec/bash.rb +5 -4
- data/lib/rspec/bash/command.rb +5 -0
- data/lib/rspec/bash/command/call_configuration.rb +76 -0
- data/lib/rspec/bash/command/call_configuration_manager.rb +24 -0
- data/lib/rspec/bash/command/call_log.rb +48 -0
- data/lib/rspec/bash/command/call_log_manager.rb +38 -0
- data/lib/rspec/bash/command/stubbed_command.rb +64 -0
- data/lib/rspec/bash/server.rb +3 -0
- data/lib/rspec/bash/server/bash_stub_marshaller.rb +19 -0
- data/lib/rspec/bash/server/ruby_stub_marshaller.rb +13 -0
- data/lib/rspec/bash/server/stub_server.rb +47 -0
- data/lib/rspec/bash/stubbed_env.rb +75 -54
- data/lib/rspec/bash/util/call_conf_argument_list_matcher.rb +5 -5
- data/lib/rspec/bash/util/call_log_argument_list_matcher.rb +1 -1
- data/lib/rspec/bash/wrapper.rb +4 -0
- data/lib/rspec/bash/wrapper/bash_stub_script.rb +15 -0
- data/lib/rspec/bash/wrapper/bash_wrapper.rb +54 -0
- data/lib/rspec/bash/wrapper/ruby_stub_script.rb +15 -0
- data/lib/rspec/bash/wrapper/stub_function.rb +36 -0
- data/rspec-bash.gemspec +2 -1
- data/spec/classes/command/call_configuration_manager_spec.rb +68 -0
- data/spec/classes/{call_configuration_spec.rb → command/call_configuration_spec.rb} +51 -114
- data/spec/classes/command/call_log_manager_spec.rb +83 -0
- data/spec/classes/{call_log_spec.rb → command/call_log_spec.rb} +23 -82
- data/spec/classes/command/stubbed_command_spec.rb +118 -0
- data/spec/classes/server/bash_stub_marshaller_spec.rb +38 -0
- data/spec/classes/server/ruby_stub_marshaller_spec.rb +31 -0
- data/spec/classes/server/stub_server_spec.rb +121 -0
- data/spec/classes/stubbed_env_spec.rb +141 -280
- data/spec/classes/util/call_conf_argument_list_matcher_spec.rb +17 -17
- data/spec/classes/util/call_log_argument_list_matcher_spec.rb +24 -18
- data/spec/classes/wrapper/bash_wrapper_spec.rb +37 -0
- data/spec/classes/wrapper/ruby_stub_script_spec.rb +204 -0
- data/spec/helper/string_file_io.rb +1 -1
- data/spec/integration/call_log/called_with_args_spec.rb +8 -4
- data/spec/integration/call_log/called_with_no_args_spec.rb +1 -1
- data/spec/integration/call_log/stdin_spec.rb +10 -4
- data/spec/integration/edge_cases_spec.rb +34 -0
- data/spec/integration/matchers/be_called_with_arguments_spec.rb +12 -13
- data/spec/integration/matchers/be_called_with_no_arguments_spec.rb +6 -7
- data/spec/integration/stubbed_command/outputs_spec.rb +111 -91
- data/spec/integration/stubbed_command/returns_exitstatus_spec.rb +46 -37
- data/spec/integration/stubbed_env/execute_with_env_vars_spec.rb +3 -4
- data/spec/integration/stubbed_env/execute_with_path_spec.rb +6 -7
- data/spec/integration/stubbed_env/execute_with_stub_wrapper_spec.rb +4 -12
- data/spec/integration/stubbed_env/override_spec.rb +354 -0
- data/spec/integration/wrapper/bash_stub_script_spec.rb +383 -0
- data/spec/integration/wrapper/bash_wrapper_spec.rb +48 -0
- data/spec/scripts/function_library.sh +9 -1
- data/spec/spec_helper.rb +2 -0
- metadata +65 -21
- data/bin/function_override.sh.erb +0 -7
- data/bin/function_override_wrapper.sh.erb +0 -19
- data/bin/stub.rb.erb +0 -56
- data/lib/rspec/bash/call_configuration.rb +0 -62
- data/lib/rspec/bash/call_log.rb +0 -71
- data/lib/rspec/bash/stubbed_command.rb +0 -88
- data/spec/classes/stub_spec.rb +0 -510
- data/spec/classes/stubbed_command_spec.rb +0 -134
- data/spec/integration/assert_called_spec.rb +0 -0
@@ -0,0 +1,383 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
include Rspec::Bash
|
3
|
+
|
4
|
+
def execute_script(script)
|
5
|
+
let(:temp_file) { Tempfile.new('for-testing') }
|
6
|
+
|
7
|
+
capture_standard_streams script
|
8
|
+
|
9
|
+
after do
|
10
|
+
FileUtils.remove_entry_secure temp_file if script.include? '<temp file>'
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def capture_standard_streams(script)
|
15
|
+
let!(:execute_results) do
|
16
|
+
script.gsub!(/<temp file>/, temp_file.path) if script.include? '<temp file>'
|
17
|
+
stubbed_env.execute_function(BashStubScript.path, script)
|
18
|
+
end
|
19
|
+
|
20
|
+
let(:stdout) { execute_results[0] }
|
21
|
+
let(:stderr) { execute_results[1] }
|
22
|
+
end
|
23
|
+
|
24
|
+
describe 'BashStub' do
|
25
|
+
let(:stubbed_env) { create_stubbed_env(StubbedEnv::RUBY_STUB) }
|
26
|
+
|
27
|
+
context '.create-call-log' do
|
28
|
+
context 'with no stdin or arguments' do
|
29
|
+
execute_script(
|
30
|
+
'create-call-log first_command 55555'
|
31
|
+
)
|
32
|
+
it 'makes a call log with just the name and stdin set to blank' do
|
33
|
+
expect(stdout.chomp).to eql JSON.pretty_generate(
|
34
|
+
Sparsify.sparse(
|
35
|
+
{
|
36
|
+
command: 'first_command',
|
37
|
+
stdin: ''
|
38
|
+
}, sparse_array: true
|
39
|
+
), indent: '', space: ''
|
40
|
+
)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
context 'with stdin and no arguments' do
|
44
|
+
execute_script(
|
45
|
+
"echo -e '\\nst d\nin' | create-call-log first_command 55555"
|
46
|
+
)
|
47
|
+
|
48
|
+
it 'makes a call log with just the name and stdin set to supplied stdin' do
|
49
|
+
expect(stdout.chomp).to eql JSON.pretty_generate(
|
50
|
+
Sparsify.sparse(
|
51
|
+
{
|
52
|
+
command: 'first_command',
|
53
|
+
stdin: "\nst d\nin\n"
|
54
|
+
}, sparse_array: true
|
55
|
+
), indent: '', space: ''
|
56
|
+
)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
context 'with arguments and no stdin' do
|
60
|
+
execute_script(
|
61
|
+
"create-call-log first_command 55555 first_argument 'second argument' '\nthird\nargument\n'"
|
62
|
+
)
|
63
|
+
|
64
|
+
it 'makes a call log with the name, stdin set to blank, and the supplied arguments' do
|
65
|
+
expect(stdout.chomp).to eql JSON.pretty_generate(
|
66
|
+
Sparsify.sparse(
|
67
|
+
{
|
68
|
+
command: 'first_command',
|
69
|
+
stdin: '',
|
70
|
+
args: [
|
71
|
+
'first_argument',
|
72
|
+
'second argument',
|
73
|
+
"\nthird\nargument\n"
|
74
|
+
]
|
75
|
+
}, sparse_array: true
|
76
|
+
), indent: '', space: ''
|
77
|
+
)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
context 'with arguments and stdin' do
|
81
|
+
execute_script(
|
82
|
+
<<-multiline_script
|
83
|
+
echo 'st d\nin' | \
|
84
|
+
create-call-log first_command 55555 first_argument 'second argument' '\nthird\nargument\n'
|
85
|
+
multiline_script
|
86
|
+
)
|
87
|
+
|
88
|
+
it 'makes a call log with the name, stdin set to supplied stdn, and the supplied arguments' do
|
89
|
+
expect(stdout.chomp).to eql JSON.pretty_generate(
|
90
|
+
Sparsify.sparse(
|
91
|
+
{
|
92
|
+
command: 'first_command',
|
93
|
+
stdin: "st d\nin\n",
|
94
|
+
args: [
|
95
|
+
'first_argument',
|
96
|
+
'second argument',
|
97
|
+
"\nthird\nargument\n"
|
98
|
+
]
|
99
|
+
}, sparse_array: true
|
100
|
+
), indent: '', space: ''
|
101
|
+
)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
context 'with verifyable json-encode stub' do
|
106
|
+
before(:all) do
|
107
|
+
stubbed_env = create_stubbed_env
|
108
|
+
json_encode = stubbed_env.stub_command('json-encode')
|
109
|
+
json_encode.outputs('json encoded', to: :stdout)
|
110
|
+
command = 'first_command 55555 first_argument second_argument third_argument'
|
111
|
+
|
112
|
+
@stdout, = stubbed_env.execute_function(
|
113
|
+
BashStubScript.path,
|
114
|
+
"echo stdin | create-call-log #{command}"
|
115
|
+
)
|
116
|
+
end
|
117
|
+
|
118
|
+
it 'passes the stdin and args through the json-decode function' do
|
119
|
+
expect(@stdout.chomp).to eql JSON.pretty_generate(
|
120
|
+
Sparsify.sparse(
|
121
|
+
{
|
122
|
+
command: 'first_command',
|
123
|
+
stdin: 'json encoded',
|
124
|
+
args: [
|
125
|
+
'json encoded',
|
126
|
+
'json encoded',
|
127
|
+
'json encoded'
|
128
|
+
]
|
129
|
+
}, sparse_array: true
|
130
|
+
), indent: '', space: ''
|
131
|
+
)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
context '.send-to-server' do
|
137
|
+
context 'with a server port and call log message' do
|
138
|
+
before(:all) do
|
139
|
+
stubbed_env = create_stubbed_env
|
140
|
+
@netcat = stubbed_env.stub_command('nc').outputs('call conf message')
|
141
|
+
|
142
|
+
@stdout, = stubbed_env.execute_function(
|
143
|
+
BashStubScript.path,
|
144
|
+
'send-to-server 55555 "call log message"'
|
145
|
+
)
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'calls netcat to send the message to the server port and returns its response' do
|
149
|
+
expect(@netcat).to be_called_with_arguments('localhost', '55555')
|
150
|
+
end
|
151
|
+
|
152
|
+
it 'calls netcat to send the message to the server port and returns its response' do
|
153
|
+
expect(@netcat.with_args('localhost', '55555').stdin).to eql 'call log message'
|
154
|
+
end
|
155
|
+
|
156
|
+
it 'calls netcat to send the message to the server port and returns its response' do
|
157
|
+
expect(@stdout.chomp).to eql 'call conf message'
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
context '.extract-properties' do
|
163
|
+
context 'given a standard call conf message' do
|
164
|
+
let(:call_conf) do
|
165
|
+
JSON.pretty_generate(
|
166
|
+
Sparsify.sparse(
|
167
|
+
{
|
168
|
+
exitcode: 10,
|
169
|
+
outputs: [
|
170
|
+
{
|
171
|
+
target: 'stdout',
|
172
|
+
content: "stdout\nstdout stdout"
|
173
|
+
},
|
174
|
+
{
|
175
|
+
target: 'stderr',
|
176
|
+
content: "stderr stderr\nstderr"
|
177
|
+
},
|
178
|
+
{
|
179
|
+
target: 'tofile',
|
180
|
+
content: "tofile\ntofile tofile"
|
181
|
+
}
|
182
|
+
]
|
183
|
+
}, sparse_array: true
|
184
|
+
), indent: '', space: ''
|
185
|
+
)
|
186
|
+
end
|
187
|
+
|
188
|
+
it 'extracts a single value field' do
|
189
|
+
stdout, = stubbed_env.execute_function(
|
190
|
+
BashStubScript.path,
|
191
|
+
"extract-properties '#{call_conf}' 'exitcode'"
|
192
|
+
)
|
193
|
+
expect(stdout.chomp).to eql '10'
|
194
|
+
end
|
195
|
+
|
196
|
+
it 'extracts a multiple value field' do
|
197
|
+
stdout, _stderr = stubbed_env.execute_function(
|
198
|
+
BashStubScript.path,
|
199
|
+
"extract-properties '#{call_conf}' 'outputs\\..*\\.content'"
|
200
|
+
)
|
201
|
+
expect(stdout.chomp).to eql "stdout\\nstdout stdout\nstderr stderr\\nstderr" \
|
202
|
+
"\ntofile\\ntofile tofile"
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
context '.print-output' do
|
208
|
+
context 'given a stdout target and its associated content' do
|
209
|
+
execute_script("print-output 'stdout' '\\nstdout \\\\nstdout\nstdout\\n'")
|
210
|
+
|
211
|
+
it 'prints the output to stdout' do
|
212
|
+
expect(stdout).to eql "\nstdout \\nstdout\nstdout\n"
|
213
|
+
end
|
214
|
+
|
215
|
+
it 'does not print the output to stderr' do
|
216
|
+
expect(stderr).to eql ''
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
context 'given a stderr target and its associated content' do
|
221
|
+
execute_script("print-output 'stderr' '\\nstderr \\\\nstderr\nstderr\\n'")
|
222
|
+
|
223
|
+
it 'prints the output to stderr' do
|
224
|
+
expect(stderr).to eql "\nstderr \\nstderr\nstderr\n"
|
225
|
+
end
|
226
|
+
|
227
|
+
it 'does not print the output to stdout' do
|
228
|
+
expect(stdout).to eql ''
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
context 'given a file target (anything but stderr or stdout)' do
|
233
|
+
execute_script("print-output '<temp file>' '\\ntofile \\\\ntofile\ntofile\\n'")
|
234
|
+
|
235
|
+
it 'prints the output to the file' do
|
236
|
+
expect(temp_file.read).to eql "\ntofile \\ntofile\ntofile\n"
|
237
|
+
end
|
238
|
+
|
239
|
+
it 'does not print the output to stderr' do
|
240
|
+
expect(stderr.chomp).to eql ''
|
241
|
+
end
|
242
|
+
|
243
|
+
it 'does not print the output to stdout' do
|
244
|
+
expect(stdout.chomp).to eql ''
|
245
|
+
end
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
context '.json-decode' do
|
250
|
+
context 'with an encoded quotation mark' do
|
251
|
+
execute_script('json-decode "\\\\\\""')
|
252
|
+
|
253
|
+
it 'converts \" to "' do
|
254
|
+
expect(stdout.chomp).to eql '"'
|
255
|
+
end
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
context '.json-encode' do
|
260
|
+
context 'with a quotation mark' do
|
261
|
+
execute_script('json-encode "\""')
|
262
|
+
|
263
|
+
it 'converts " to \"' do
|
264
|
+
expect(stdout.chomp).to eql '\"'
|
265
|
+
end
|
266
|
+
end
|
267
|
+
context 'with a new line character' do
|
268
|
+
execute_script("json-encode '\ncat\ndog\n'")
|
269
|
+
|
270
|
+
it 'converts \n to escaped \n' do
|
271
|
+
expect(stdout.chomp).to eql '\ncat\ndog\n'
|
272
|
+
end
|
273
|
+
end
|
274
|
+
context 'with a tab character' do
|
275
|
+
execute_script("json-encode '\t'")
|
276
|
+
|
277
|
+
it 'converts \t to escaped \t' do
|
278
|
+
expect(stdout.chomp).to eql '\t'
|
279
|
+
end
|
280
|
+
end
|
281
|
+
context 'with a carriage return character' do
|
282
|
+
execute_script("json-encode '\r'")
|
283
|
+
|
284
|
+
it 'converts \r to escaped \r' do
|
285
|
+
expect(stdout.chomp).to eql '\r'
|
286
|
+
end
|
287
|
+
end
|
288
|
+
context 'with a backspace character' do
|
289
|
+
execute_script("json-encode '\b'")
|
290
|
+
|
291
|
+
it 'converts \r to escaped \r' do
|
292
|
+
expect(stdout.chomp).to eql '\b'
|
293
|
+
end
|
294
|
+
end
|
295
|
+
context 'with a unicode character' do
|
296
|
+
execute_script('json-encode "@"')
|
297
|
+
|
298
|
+
it 'does not convert the character' do
|
299
|
+
expect(stdout.chomp).to eql '@'
|
300
|
+
end
|
301
|
+
end
|
302
|
+
context 'with a forward slash character' do
|
303
|
+
execute_script('json-encode "/"')
|
304
|
+
|
305
|
+
it 'does not convert the character' do
|
306
|
+
expect(stdout.chomp).to eql '/'
|
307
|
+
end
|
308
|
+
end
|
309
|
+
context 'with an escaped character' do
|
310
|
+
execute_script('json-encode "\u"')
|
311
|
+
|
312
|
+
it 'converts \u to \\u' do
|
313
|
+
expect(stdout.chomp).to eql '\\\\u'
|
314
|
+
end
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
318
|
+
context '.main' do
|
319
|
+
context 'with stdin, command, port and arguments' do
|
320
|
+
before(:all) do
|
321
|
+
stubbed_env = create_stubbed_env
|
322
|
+
@create_call_log = stubbed_env.stub_command('create-call-log').outputs('call log')
|
323
|
+
@send_to_server = stubbed_env.stub_command('send-to-server').outputs('call conf')
|
324
|
+
@extract_properties = stubbed_env.stub_command('extract-properties')
|
325
|
+
@print_output = stubbed_env.stub_command('print-output')
|
326
|
+
|
327
|
+
@extract_properties
|
328
|
+
.with_args('call conf', 'outputs\..*\.target')
|
329
|
+
.outputs("stdout\nstderr\ntofile\n")
|
330
|
+
@extract_properties
|
331
|
+
.with_args('call conf', 'outputs\..*\.content')
|
332
|
+
.outputs("\\nstd out\\n\n\\nstd err\\n\n\\nto file\\n\n")
|
333
|
+
@extract_properties.with_args('call conf', 'exitcode').outputs("3\n")
|
334
|
+
|
335
|
+
_, _, @status = stubbed_env.execute_function(
|
336
|
+
BashStubScript.path,
|
337
|
+
'echo "stdin" | main first_command 55555 first_argument second_argument'
|
338
|
+
)
|
339
|
+
end
|
340
|
+
|
341
|
+
it 'creates a call log from the stdin and args' do
|
342
|
+
expect(@create_call_log).to be_called_with_arguments(
|
343
|
+
'first_command', '55555', 'first_argument', 'second_argument'
|
344
|
+
)
|
345
|
+
expect(@create_call_log.stdin.chomp).to eql 'stdin'
|
346
|
+
end
|
347
|
+
it 'sends that call log to the server' do
|
348
|
+
expect(@send_to_server).to be_called_with_arguments(
|
349
|
+
'55555', 'call log'
|
350
|
+
)
|
351
|
+
end
|
352
|
+
it 'extracts the target list from the call conf returned by the server' do
|
353
|
+
expect(@extract_properties).to be_called_with_arguments(
|
354
|
+
'call conf', 'outputs\..*\.target'
|
355
|
+
)
|
356
|
+
end
|
357
|
+
it 'extracts the content list from the call conf returned by the server' do
|
358
|
+
expect(@extract_properties).to be_called_with_arguments(
|
359
|
+
'call conf', 'outputs\..*\.content'
|
360
|
+
)
|
361
|
+
end
|
362
|
+
it 'extracts the exit code from the call conf returned by the server' do
|
363
|
+
expect(@extract_properties).to be_called_with_arguments(
|
364
|
+
'call conf', 'exitcode'
|
365
|
+
)
|
366
|
+
end
|
367
|
+
it 'prints the extracted outputs (with newlines still escaped)' do
|
368
|
+
expect(@print_output).to be_called_with_arguments(
|
369
|
+
'stdout', '\nstd out\n'
|
370
|
+
)
|
371
|
+
expect(@print_output).to be_called_with_arguments(
|
372
|
+
'stderr', '\nstd err\n'
|
373
|
+
)
|
374
|
+
expect(@print_output).to be_called_with_arguments(
|
375
|
+
'tofile', '\nto file\n'
|
376
|
+
)
|
377
|
+
end
|
378
|
+
it 'exits with the extracted exit code' do
|
379
|
+
expect(@status.exitstatus).to eql 3
|
380
|
+
end
|
381
|
+
end
|
382
|
+
end
|
383
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
include Rspec::Bash
|
3
|
+
|
4
|
+
describe 'BashWrapper' do
|
5
|
+
context '.main' do
|
6
|
+
before(:all) do
|
7
|
+
stubbed_env = create_stubbed_env
|
8
|
+
|
9
|
+
first_command = <<-multiline_script
|
10
|
+
function first_command {
|
11
|
+
echo 'first_command called'
|
12
|
+
}
|
13
|
+
readonly -f first_command
|
14
|
+
multiline_script
|
15
|
+
second_command = <<-multiline_script
|
16
|
+
function second_command {
|
17
|
+
echo 'second_command called' >&2
|
18
|
+
}
|
19
|
+
multiline_script
|
20
|
+
|
21
|
+
subject = BashWrapper.new(4000)
|
22
|
+
subject.add_override(first_command)
|
23
|
+
subject.add_override(second_command)
|
24
|
+
script_path = subject.wrap_script(
|
25
|
+
<<-multiline_script
|
26
|
+
function first_command {
|
27
|
+
echo 'overridden'
|
28
|
+
}
|
29
|
+
first_command
|
30
|
+
second_command
|
31
|
+
multiline_script
|
32
|
+
)
|
33
|
+
@stdout, @stderr, @status = stubbed_env.execute(script_path)
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'exits with a 0 exit code by default' do
|
37
|
+
expect(@status.exitstatus).to eql 0
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'injects the first_command override' do
|
41
|
+
expect(@stdout.chomp).to eql 'first_command called'
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'injects the second_command override (and omits a readonly error for first_command)' do
|
45
|
+
expect(@stderr.chomp).to eql 'second_command called'
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -3,7 +3,15 @@ function overridden_function {
|
|
3
3
|
echo 'i was not overridden'
|
4
4
|
}
|
5
5
|
|
6
|
+
function /absolute/path/to/overridden_path_functions {
|
7
|
+
echo 'i was not overridden'
|
8
|
+
}
|
9
|
+
|
10
|
+
function relative/path/to/overridden_path_functions {
|
11
|
+
echo 'i was not overridden'
|
12
|
+
}
|
13
|
+
|
6
14
|
function overridden_command_function {
|
7
15
|
overridden_command "${1}" "${2}"
|
8
16
|
echo 'standard error output' >&2
|
9
|
-
}
|
17
|
+
}
|