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.
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