rspec-bash 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +8 -0
  3. data/Gemfile +1 -0
  4. data/README.md +23 -0
  5. data/Rakefile +15 -4
  6. data/bin/bash_stub.sh +92 -0
  7. data/bin/bash_wrapper.sh.erb +12 -0
  8. data/bin/ruby_stub.rb +33 -0
  9. data/lib/rspec/bash.rb +5 -4
  10. data/lib/rspec/bash/command.rb +5 -0
  11. data/lib/rspec/bash/command/call_configuration.rb +76 -0
  12. data/lib/rspec/bash/command/call_configuration_manager.rb +24 -0
  13. data/lib/rspec/bash/command/call_log.rb +48 -0
  14. data/lib/rspec/bash/command/call_log_manager.rb +38 -0
  15. data/lib/rspec/bash/command/stubbed_command.rb +64 -0
  16. data/lib/rspec/bash/server.rb +3 -0
  17. data/lib/rspec/bash/server/bash_stub_marshaller.rb +19 -0
  18. data/lib/rspec/bash/server/ruby_stub_marshaller.rb +13 -0
  19. data/lib/rspec/bash/server/stub_server.rb +47 -0
  20. data/lib/rspec/bash/stubbed_env.rb +75 -54
  21. data/lib/rspec/bash/util/call_conf_argument_list_matcher.rb +5 -5
  22. data/lib/rspec/bash/util/call_log_argument_list_matcher.rb +1 -1
  23. data/lib/rspec/bash/wrapper.rb +4 -0
  24. data/lib/rspec/bash/wrapper/bash_stub_script.rb +15 -0
  25. data/lib/rspec/bash/wrapper/bash_wrapper.rb +54 -0
  26. data/lib/rspec/bash/wrapper/ruby_stub_script.rb +15 -0
  27. data/lib/rspec/bash/wrapper/stub_function.rb +36 -0
  28. data/rspec-bash.gemspec +2 -1
  29. data/spec/classes/command/call_configuration_manager_spec.rb +68 -0
  30. data/spec/classes/{call_configuration_spec.rb → command/call_configuration_spec.rb} +51 -114
  31. data/spec/classes/command/call_log_manager_spec.rb +83 -0
  32. data/spec/classes/{call_log_spec.rb → command/call_log_spec.rb} +23 -82
  33. data/spec/classes/command/stubbed_command_spec.rb +118 -0
  34. data/spec/classes/server/bash_stub_marshaller_spec.rb +38 -0
  35. data/spec/classes/server/ruby_stub_marshaller_spec.rb +31 -0
  36. data/spec/classes/server/stub_server_spec.rb +121 -0
  37. data/spec/classes/stubbed_env_spec.rb +141 -280
  38. data/spec/classes/util/call_conf_argument_list_matcher_spec.rb +17 -17
  39. data/spec/classes/util/call_log_argument_list_matcher_spec.rb +24 -18
  40. data/spec/classes/wrapper/bash_wrapper_spec.rb +37 -0
  41. data/spec/classes/wrapper/ruby_stub_script_spec.rb +204 -0
  42. data/spec/helper/string_file_io.rb +1 -1
  43. data/spec/integration/call_log/called_with_args_spec.rb +8 -4
  44. data/spec/integration/call_log/called_with_no_args_spec.rb +1 -1
  45. data/spec/integration/call_log/stdin_spec.rb +10 -4
  46. data/spec/integration/edge_cases_spec.rb +34 -0
  47. data/spec/integration/matchers/be_called_with_arguments_spec.rb +12 -13
  48. data/spec/integration/matchers/be_called_with_no_arguments_spec.rb +6 -7
  49. data/spec/integration/stubbed_command/outputs_spec.rb +111 -91
  50. data/spec/integration/stubbed_command/returns_exitstatus_spec.rb +46 -37
  51. data/spec/integration/stubbed_env/execute_with_env_vars_spec.rb +3 -4
  52. data/spec/integration/stubbed_env/execute_with_path_spec.rb +6 -7
  53. data/spec/integration/stubbed_env/execute_with_stub_wrapper_spec.rb +4 -12
  54. data/spec/integration/stubbed_env/override_spec.rb +354 -0
  55. data/spec/integration/wrapper/bash_stub_script_spec.rb +383 -0
  56. data/spec/integration/wrapper/bash_wrapper_spec.rb +48 -0
  57. data/spec/scripts/function_library.sh +9 -1
  58. data/spec/spec_helper.rb +2 -0
  59. metadata +65 -21
  60. data/bin/function_override.sh.erb +0 -7
  61. data/bin/function_override_wrapper.sh.erb +0 -19
  62. data/bin/stub.rb.erb +0 -56
  63. data/lib/rspec/bash/call_configuration.rb +0 -62
  64. data/lib/rspec/bash/call_log.rb +0 -71
  65. data/lib/rspec/bash/stubbed_command.rb +0 -88
  66. data/spec/classes/stub_spec.rb +0 -510
  67. data/spec/classes/stubbed_command_spec.rb +0 -134
  68. 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
+ }
data/spec/spec_helper.rb CHANGED
@@ -3,6 +3,8 @@ SimpleCov.start
3
3
 
4
4
  require 'English'
5
5
  require 'rspec/bash'
6
+ require 'socket'
7
+ require 'sparsify'
6
8
  require 'tempfile'
7
9
  require 'yaml'
8
10