ronin-core 0.1.0.beta1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (99) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +1 -0
  3. data/.yardopts +1 -1
  4. data/README.md +2 -1
  5. data/gemspec.yml +1 -1
  6. data/lib/ronin/core/class_registry.rb +3 -3
  7. data/lib/ronin/core/cli/command.rb +1 -1
  8. data/lib/ronin/core/cli/command_shell/command.rb +1 -1
  9. data/lib/ronin/core/cli/command_shell.rb +2 -2
  10. data/lib/ronin/core/cli/generator/options/author.rb +1 -1
  11. data/lib/ronin/core/cli/generator/options/description.rb +1 -1
  12. data/lib/ronin/core/cli/generator/options/reference.rb +1 -1
  13. data/lib/ronin/core/cli/generator/options/summary.rb +1 -1
  14. data/lib/ronin/core/cli/generator.rb +1 -1
  15. data/lib/ronin/core/cli/logging.rb +1 -1
  16. data/lib/ronin/core/cli/options/param.rb +1 -1
  17. data/lib/ronin/core/cli/options/values/arches.rb +1 -1
  18. data/lib/ronin/core/cli/options/values/oses.rb +1 -1
  19. data/lib/ronin/core/cli/printing/arch.rb +1 -1
  20. data/lib/ronin/core/cli/printing/metadata.rb +2 -2
  21. data/lib/ronin/core/cli/printing/os.rb +1 -1
  22. data/lib/ronin/core/cli/printing/params.rb +1 -1
  23. data/lib/ronin/core/cli/ruby_shell.rb +1 -1
  24. data/lib/ronin/core/cli/shell.rb +2 -2
  25. data/lib/ronin/core/git.rb +1 -1
  26. data/lib/ronin/core/home.rb +1 -1
  27. data/lib/ronin/core/metadata/authors/author.rb +1 -1
  28. data/lib/ronin/core/metadata/authors.rb +1 -1
  29. data/lib/ronin/core/metadata/description.rb +1 -1
  30. data/lib/ronin/core/metadata/id.rb +1 -1
  31. data/lib/ronin/core/metadata/references.rb +1 -1
  32. data/lib/ronin/core/metadata/summary.rb +1 -1
  33. data/lib/ronin/core/metadata/version.rb +1 -1
  34. data/lib/ronin/core/params/exceptions.rb +1 -1
  35. data/lib/ronin/core/params/mixin.rb +2 -2
  36. data/lib/ronin/core/params/param.rb +2 -2
  37. data/lib/ronin/core/params/types/boolean.rb +1 -1
  38. data/lib/ronin/core/params/types/enum.rb +1 -1
  39. data/lib/ronin/core/params/types/float.rb +1 -1
  40. data/lib/ronin/core/params/types/integer.rb +1 -1
  41. data/lib/ronin/core/params/types/numeric.rb +1 -1
  42. data/lib/ronin/core/params/types/regexp.rb +1 -1
  43. data/lib/ronin/core/params/types/string.rb +1 -1
  44. data/lib/ronin/core/params/types/type.rb +1 -1
  45. data/lib/ronin/core/params/types/uri.rb +1 -1
  46. data/lib/ronin/core/params/types.rb +1 -1
  47. data/lib/ronin/core/params.rb +1 -1
  48. data/lib/ronin/core/version.rb +2 -2
  49. data/ronin-core.gemspec +2 -1
  50. metadata +4 -90
  51. data/spec/class_registry_spec.rb +0 -224
  52. data/spec/cli/command_shell/command_spec.rb +0 -113
  53. data/spec/cli/command_shell_spec.rb +0 -1114
  54. data/spec/cli/command_spec.rb +0 -16
  55. data/spec/cli/fixtures/irb_command +0 -8
  56. data/spec/cli/fixtures/template/dir/file1.txt +0 -1
  57. data/spec/cli/fixtures/template/dir/file2.txt +0 -1
  58. data/spec/cli/fixtures/template/file.erb +0 -1
  59. data/spec/cli/fixtures/template/file.txt +0 -1
  60. data/spec/cli/generator/options/author_spec.rb +0 -121
  61. data/spec/cli/generator/options/description_spec.rb +0 -45
  62. data/spec/cli/generator/options/reference_spec.rb +0 -53
  63. data/spec/cli/generator/options/summary_spec.rb +0 -45
  64. data/spec/cli/generator_spec.rb +0 -244
  65. data/spec/cli/logging_spec.rb +0 -95
  66. data/spec/cli/options/param_spec.rb +0 -67
  67. data/spec/cli/options/values/arches_spec.rb +0 -62
  68. data/spec/cli/printing/arch_spec.rb +0 -130
  69. data/spec/cli/printing/metadata_spec.rb +0 -211
  70. data/spec/cli/printing/os_spec.rb +0 -64
  71. data/spec/cli/printing/params_spec.rb +0 -63
  72. data/spec/cli/ruby_shell.rb +0 -99
  73. data/spec/cli/shell_spec.rb +0 -211
  74. data/spec/fixtures/example_class_registry/base_class.rb +0 -9
  75. data/spec/fixtures/example_class_registry/classes/loaded_class.rb +0 -9
  76. data/spec/fixtures/example_class_registry/classes/name_mismatch.rb +0 -9
  77. data/spec/fixtures/example_class_registry/classes/no_module.rb +0 -4
  78. data/spec/fixtures/example_class_registry.rb +0 -8
  79. data/spec/git_spec.rb +0 -58
  80. data/spec/home_spec.rb +0 -64
  81. data/spec/metadata/authors/author_spec.rb +0 -335
  82. data/spec/metadata/authors_spec.rb +0 -126
  83. data/spec/metadata/description_spec.rb +0 -74
  84. data/spec/metadata/id_spec.rb +0 -92
  85. data/spec/metadata/references_spec.rb +0 -100
  86. data/spec/metadata/summary_spec.rb +0 -74
  87. data/spec/metadata/version_spec.rb +0 -72
  88. data/spec/params/mixin_spec.rb +0 -484
  89. data/spec/params/param_spec.rb +0 -164
  90. data/spec/params/types/boolean_spec.rb +0 -56
  91. data/spec/params/types/enum_spec.rb +0 -94
  92. data/spec/params/types/float_spec.rb +0 -107
  93. data/spec/params/types/integer_spec.rb +0 -155
  94. data/spec/params/types/numeric_spec.rb +0 -138
  95. data/spec/params/types/regexp_spec.rb +0 -64
  96. data/spec/params/types/string_spec.rb +0 -174
  97. data/spec/params/types/type_spec.rb +0 -14
  98. data/spec/params/types/uri_spec.rb +0 -62
  99. data/spec/spec_helper.rb +0 -11
@@ -1,1114 +0,0 @@
1
- require 'spec_helper'
2
- require 'ronin/core/cli/command_shell'
3
-
4
- describe Ronin::Core::CLI::CommandShell do
5
- describe ".commands" do
6
- subject { shell_class }
7
-
8
- context "when no commands have been defined in the shell class" do
9
- module TestCommandShell
10
- class ShellWithNoCommands < Ronin::Core::CLI::CommandShell
11
- shell_name 'test'
12
- end
13
- end
14
-
15
- let(:shell_class) { TestCommandShell::ShellWithNoCommands }
16
-
17
- it "must return a Hash only containing the help command" do
18
- expect(subject.commands.keys).to eq(%w[help])
19
- expect(subject.commands['help']).to be_kind_of(described_class::Command)
20
- end
21
- end
22
-
23
- context "when commands have been defined in the shell class" do
24
- module TestCommandShell
25
- class ShellWithCommands < Ronin::Core::CLI::CommandShell
26
- shell_name 'test'
27
-
28
- command :foo, summary: 'Foo command'
29
- def foo
30
- end
31
- end
32
- end
33
-
34
- let(:shell_class) { TestCommandShell::ShellWithCommands }
35
-
36
- it "must return the Hash of command names and Command classes" do
37
- expect(subject.commands['foo']).to be_kind_of(described_class::Command)
38
- expect(subject.commands['foo'].name).to eq(:foo)
39
- expect(subject.commands['foo'].summary).to eq('Foo command')
40
- end
41
- end
42
-
43
- context "but when the commands are defined in the superclass" do
44
- module TestCommandShell
45
- class ShellWithInheritedCommands < ShellWithCommands
46
- shell_name 'test'
47
- end
48
- end
49
-
50
- let(:shell_superclass) do
51
- TestCommandShell::ShellWithCommands
52
- end
53
-
54
- let(:shell_class) do
55
- TestCommandShell::ShellWithInheritedCommands
56
- end
57
-
58
- it "must return the commands defined in the superclass" do
59
- expect(subject.commands['foo']).to be(shell_superclass.commands['foo'])
60
- end
61
-
62
- context "but additional commands are defined in the sub-class" do
63
- module TestCommandShell
64
- class ShellWithInheritedCommandsAndItsOwnCommands < ShellWithCommands
65
- shell_name 'test'
66
- command :bar, summary: 'Bar command'
67
- def bar
68
- end
69
- end
70
- end
71
-
72
- let(:shell_class) do
73
- TestCommandShell::ShellWithInheritedCommandsAndItsOwnCommands
74
- end
75
-
76
- it "must contain the commands defined in the subclass" do
77
- expect(subject.commands['bar']).to be_kind_of(described_class::Command)
78
- expect(subject.commands['bar'].name).to eq(:bar)
79
- expect(subject.commands['bar'].summary).to eq('Bar command')
80
- end
81
-
82
- it "must also contain the commands defined in the superclass" do
83
- expect(subject.commands['foo']).to be(shell_superclass.commands['foo'])
84
- end
85
-
86
- it "must not modify the superclass'es .commands" do
87
- expect(shell_superclass.commands['foo']).to be_kind_of(described_class::Command)
88
- expect(shell_superclass.commands['foo'].name).to eq(:foo)
89
- expect(shell_superclass.commands['foo'].summary).to eq('Foo command')
90
-
91
- expect(shell_superclass.commands['bar']).to be(nil)
92
- end
93
- end
94
-
95
- context "but the commands defined in the sub-class override those in the superclass" do
96
- module TestCommandShell
97
- class ShellThatOverridesInheritedCommands < ShellWithCommands
98
- shell_name 'test'
99
- command :foo, summary: 'Overrided foo command'
100
- def foo
101
- end
102
- end
103
- end
104
-
105
- let(:shell_class) { TestCommandShell::ShellThatOverridesInheritedCommands }
106
-
107
- it "must contain the commands overridden in the sub-class" do
108
- expect(subject.commands['foo']).to_not be(shell_superclass.commands['foo'])
109
- expect(subject.commands['foo'].summary).to eq('Overrided foo command')
110
- end
111
-
112
- it "must not modify the superclass'es .commands" do
113
- expect(shell_superclass.commands['foo']).to be_kind_of(described_class::Command)
114
- expect(shell_superclass.commands['foo'].name).to eq(:foo)
115
- expect(shell_superclass.commands['foo'].summary).to eq('Foo command')
116
- end
117
- end
118
- end
119
- end
120
-
121
- describe ".parse_command" do
122
- subject { described_class }
123
-
124
- let(:command_name) { 'foo' }
125
-
126
- context "when given a single command name" do
127
- let(:line) { command_name.to_s }
128
-
129
- it "must return the command name" do
130
- expect(subject.parse_command(line)).to eq(
131
- [command_name]
132
- )
133
- end
134
- end
135
-
136
- context "when given a command name and additional arguments" do
137
- let(:arg1) { "bar" }
138
- let(:arg2) { "baz" }
139
- let(:line) { "#{command_name} #{arg1} #{arg2}" }
140
-
141
- it "must return the command name and an Array of arguments" do
142
- expect(subject.parse_command(line)).to eq(
143
- [command_name, arg1, arg2]
144
- )
145
- end
146
-
147
- context "but the arguments are in quotes" do
148
- let(:line) { "#{command_name} \"#{arg1} #{arg2}\"" }
149
-
150
- it "must keep quoted arguments together" do
151
- expect(subject.parse_command(line)).to eq(
152
- [command_name, "#{arg1} #{arg2}"]
153
- )
154
- end
155
- end
156
- end
157
- end
158
-
159
- describe "#complete" do
160
- module TestCommandShell
161
- class ShellWithCompletions < Ronin::Core::CLI::CommandShell
162
- shell_name 'test'
163
-
164
- command :foo, summary: 'Foo command'
165
- def foo
166
- end
167
-
168
- command :bar, completions: %w[arg1 arg2 foo], summary: 'Bar command'
169
- def bar
170
- end
171
-
172
- command :baz, summary: 'Baz command'
173
- def baz
174
- end
175
- end
176
- end
177
-
178
- let(:shell_class) { TestCommandShell::ShellWithCompletions }
179
- subject { shell_class.new }
180
-
181
- context "when the input is empty" do
182
- let(:preposing) { '' }
183
- let(:word) { '' }
184
-
185
- it "must return all available command names" do
186
- expect(subject.complete(word,preposing)).to eq(subject.class.commands.keys)
187
- end
188
- end
189
-
190
- context "when the input does not contain a space" do
191
- let(:preposing) { '' }
192
- let(:word) { 'ba' }
193
-
194
- it "must return the matching command names" do
195
- expect(subject.complete(word,preposing)).to eq(%w[bar baz])
196
- end
197
- end
198
-
199
- context "when the input does contain a space" do
200
- context "and the input starts with a known command" do
201
- let(:command) { 'bar' }
202
- let(:arg) { "arg" }
203
- let(:preposing) { "#{command} " }
204
- let(:word) { arg }
205
-
206
- context "and the command defines an Array of completion values" do
207
- it "must return the command's argument values that match the end of the input" do
208
- expect(subject.complete(word,preposing)).to eq(
209
- subject.class.commands[command].completions.select { |value|
210
- value.start_with?(word)
211
- }
212
- )
213
- end
214
-
215
- context "but the input contains multiple spaces" do
216
- let(:preposing) { "#{command} bla bla " }
217
-
218
- it "must still return the command's argument values that match the end of the input" do
219
- expect(subject.complete(word,preposing)).to eq(
220
- subject.class.commands[command].completions.select { |value|
221
- value.start_with?(word)
222
- }
223
- )
224
- end
225
- end
226
- end
227
-
228
- context "and the command defines a completion method name" do
229
- module TestCommandShell
230
- class ShellWithCompletionMethod < Ronin::Core::CLI::CommandShell
231
- shell_name 'test'
232
-
233
- command :foo, summary: 'Foo command'
234
- def foo
235
- end
236
-
237
- command :bar, summary: 'Bar command',
238
- completions: :bar_completion
239
- def bar
240
- end
241
-
242
- def bar_completion(arg,preposing)
243
- %w[
244
- foo
245
- arg-A
246
- arg-B
247
- bar
248
- ]
249
- end
250
-
251
- command :baz, summary: 'Baz command'
252
- def baz
253
- end
254
- end
255
- end
256
-
257
- let(:shell_class) { TestCommandShell::ShellWithCompletionMethod }
258
-
259
- it "must call the completion method with the argument and filter the results" do
260
- completion_method = subject.class.commands[command].completions
261
-
262
- expect(subject.complete(word,preposing)).to eq(
263
- subject.send(completion_method,word,preposing).select { |value|
264
- value.start_with?(word)
265
- }
266
- )
267
- end
268
-
269
- context "but the completion method was not defined" do
270
- module TestCommandShell
271
- class ShellWithMissingCompletionMethod < Ronin::Core::CLI::CommandShell
272
- shell_name 'test'
273
-
274
- command :foo, summary: 'Foo command'
275
- def foo
276
- end
277
-
278
- command :bar, summary: 'Bar command',
279
- completions: :bar_completion
280
- def bar
281
- end
282
-
283
- command :baz, summary: 'Baz command'
284
- def baz
285
- end
286
- end
287
- end
288
-
289
- let(:shell_class) do
290
- TestCommandShell::ShellWithMissingCompletionMethod
291
- end
292
-
293
- it "must call the completion method with the argument" do
294
- expect {
295
- subject.complete(word,preposing)
296
- }.to raise_error(NotImplementedError,"#{subject.class}#bar_completion was not defined")
297
- end
298
- end
299
- end
300
- end
301
-
302
- context "but the input does not start with a known command" do
303
- let(:command) { 'does_not_exist' }
304
- let(:arg) { "arg" }
305
- let(:preposing) { "#{command} " }
306
- let(:word) { arg }
307
-
308
- it "must return nil" do
309
- expect(subject.complete(word,preposing)).to be(nil)
310
- end
311
- end
312
- end
313
-
314
- context "when the input ends with a space" do
315
- context "and the input starts with a known command" do
316
- let(:command) { 'bar' }
317
-
318
- let(:preposing) { "#{command} " }
319
- let(:word) { '' }
320
-
321
- it "must return all possible completion values for the command" do
322
- expect(subject.complete(word,preposing)).to eq(
323
- subject.class.commands[command].completions
324
- )
325
- end
326
- end
327
-
328
- context "but the input does not start with a known command" do
329
- let(:command) { 'does_not_exist' }
330
-
331
- let(:preposing) { '' }
332
- let(:word) { command }
333
-
334
- it "must return nil" do
335
- expect(subject.complete(word,preposing)).to eq([])
336
- end
337
- end
338
- end
339
- end
340
-
341
- module TestCommandShell
342
- class TestCommandShell < Ronin::Core::CLI::CommandShell
343
- shell_name 'test'
344
-
345
- command :foo, summary: 'Foo command'
346
- def foo
347
- end
348
-
349
- command :bar, summary: 'Bar command'
350
- def bar
351
- end
352
- end
353
- end
354
-
355
- let(:shell_class) { TestCommandShell::TestCommandShell }
356
- subject { shell_class.new }
357
-
358
- describe "#exec" do
359
- it "must call the underlying command method" do
360
- expect(subject).to receive(:foo)
361
-
362
- subject.exec('foo')
363
- end
364
- end
365
-
366
- describe "#call" do
367
- context "when the command exists" do
368
- context "but the command does not accept any arguments" do
369
- module TestCommandShell
370
- class ShellWithCommandWithNoArgs < Ronin::Core::CLI::CommandShell
371
- shell_name 'test'
372
-
373
- command :cmd, summary: 'Example command'
374
- def cmd
375
- puts "#{__method__} called"
376
- end
377
- end
378
- end
379
-
380
- let(:shell_class) do
381
- TestCommandShell::ShellWithCommandWithNoArgs
382
- end
383
- let(:name) { 'cmd' }
384
-
385
- context "and no arguments are given" do
386
- let(:args) { [] }
387
-
388
- it "must call the command method and return true" do
389
- expect {
390
- expect(subject.call(name,*args)).to be(true)
391
- }.to output("#{name} called#{$/}").to_stdout
392
- end
393
- end
394
-
395
- context "and one argument is given" do
396
- let(:arg) { "foo" }
397
- let(:args) { [arg] }
398
-
399
- it "must print an error and return false" do
400
- expect {
401
- expect(subject.call(name,*args)).to be(false)
402
- }.to output("#{name}: too many arguments given#{$/}").to_stderr
403
- end
404
- end
405
- end
406
-
407
- context "and the command accepts an argument" do
408
- module TestCommandShell
409
- class ShellWithCommandWithArg < Ronin::Core::CLI::CommandShell
410
- shell_name 'test'
411
-
412
- command :cmd_with_arg, usage: 'ARG',
413
- summary: 'Example command with arg'
414
- def cmd_with_arg(arg)
415
- puts "#{__method__} called: arg=#{arg}"
416
- end
417
- end
418
- end
419
-
420
- let(:shell_class) do
421
- TestCommandShell::ShellWithCommandWithArg
422
- end
423
- let(:name) { 'cmd_with_arg' }
424
-
425
- context "and no arguments are given" do
426
- let(:args) { [] }
427
-
428
- it "must print an error and return false" do
429
- expect {
430
- expect(subject.call(name,*args)).to be(false)
431
- }.to output("#{name}: too few arguments given#{$/}").to_stderr
432
- end
433
- end
434
-
435
- context "and one argument is given" do
436
- let(:arg) { "foo" }
437
- let(:args) { [arg] }
438
-
439
- it "must call the command mehtod with the argument and return true" do
440
- expect {
441
- expect(subject.call(name,*args)).to be(true)
442
- }.to output("#{name} called: arg=#{arg}#{$/}").to_stdout
443
- end
444
- end
445
-
446
- context "and more than one arguments is given" do
447
- let(:arg1) { "foo" }
448
- let(:arg2) { "bar" }
449
- let(:args) { [arg1, arg2] }
450
-
451
- it "must print an error and return false" do
452
- expect {
453
- expect(subject.call(name,*args)).to be(false)
454
- }.to output("#{name}: too many arguments given#{$/}").to_stderr
455
- end
456
- end
457
- end
458
-
459
- context "and the command accepts multiple arguments" do
460
- module TestCommandShell
461
- class ShellWithCommandWithMultipleArgs < Ronin::Core::CLI::CommandShell
462
- shell_name 'test'
463
-
464
- command :cmd_with_args, usage: 'ARG1 ARG2',
465
- summary: 'Example command with multiple arg'
466
- def cmd_with_args(arg1,arg2)
467
- puts "#{__method__} called: arg1=#{arg1} arg2=#{arg2}"
468
- end
469
- end
470
- end
471
-
472
- let(:shell_class) do
473
- TestCommandShell::ShellWithCommandWithMultipleArgs
474
- end
475
- let(:name) { 'cmd_with_args' }
476
-
477
- context "and no arguments are given" do
478
- let(:args) { [] }
479
-
480
- it "must print an error and return false" do
481
- expect {
482
- expect(subject.call(name,*args)).to be(false)
483
- }.to output("#{name}: too few arguments given#{$/}").to_stderr
484
- end
485
- end
486
-
487
- context "and one argument is given" do
488
- let(:arg) { "foo" }
489
- let(:args) { [arg] }
490
-
491
- it "must print an error and return false" do
492
- expect {
493
- expect(subject.call(name,*args)).to be(false)
494
- }.to output("#{name}: too few arguments given#{$/}").to_stderr
495
- end
496
- end
497
-
498
- context "and two arguments are given" do
499
- let(:arg1) { "foo" }
500
- let(:arg2) { "bar" }
501
- let(:args) { [arg1, arg2] }
502
-
503
- it "must call the command method and return true" do
504
- expect {
505
- expect(subject.call(name,*args)).to be(true)
506
- }.to output("#{name} called: arg1=#{arg1} arg2=#{arg2}#{$/}").to_stdout
507
- end
508
- end
509
-
510
- context "and more than two arguments is given" do
511
- let(:arg1) { "foo" }
512
- let(:arg2) { "bar" }
513
- let(:arg3) { "baz" }
514
- let(:args) { [arg1, arg2, arg3] }
515
-
516
- it "must print an error and return false" do
517
- expect {
518
- expect(subject.call(name,*args)).to be(false)
519
- }.to output("#{name}: too many arguments given#{$/}").to_stderr
520
- end
521
- end
522
- end
523
-
524
- context "and the command accepts an optional argument" do
525
- module TestCommandShell
526
- class ShellWithCommandWithOptionalArg < Ronin::Core::CLI::CommandShell
527
- shell_name 'test'
528
-
529
- command :cmd_with_opt_arg, usage: '[ARG]',
530
- summary: 'Example command with optional arg'
531
- def cmd_with_opt_arg(arg=nil)
532
- puts "#{__method__} called: arg=#{arg}"
533
- end
534
- end
535
- end
536
-
537
- let(:shell_class) do
538
- TestCommandShell::ShellWithCommandWithOptionalArg
539
- end
540
- let(:name) { 'cmd_with_opt_arg' }
541
-
542
- context "and no arguments are given" do
543
- let(:args) { [] }
544
-
545
- it "must call the command mehtod and return true" do
546
- expect {
547
- expect(subject.call(name,*args)).to be(true)
548
- }.to output("#{name} called: arg=#{$/}").to_stdout
549
- end
550
- end
551
-
552
- context "and one argument is given" do
553
- let(:arg) { "foo" }
554
- let(:args) { [arg] }
555
-
556
- it "must call the command mehtod with the argument and return true" do
557
- expect {
558
- expect(subject.call(name,*args)).to be(true)
559
- }.to output("#{name} called: arg=#{arg}#{$/}").to_stdout
560
- end
561
- end
562
-
563
- context "and more than one argument is given" do
564
- let(:arg1) { "foo" }
565
- let(:arg2) { "bar" }
566
- let(:args) { [arg1, arg2] }
567
-
568
- it "must print an error and return false" do
569
- expect {
570
- expect(subject.call(name,*args)).to be(false)
571
- }.to output("#{name}: too many arguments given#{$/}").to_stderr
572
- end
573
- end
574
- end
575
-
576
- context "and the command accepts an argument and an optional argument" do
577
- module TestCommandShell
578
- class ShellWithCommandWithArgAndOptionalArg < Ronin::Core::CLI::CommandShell
579
- shell_name 'test'
580
-
581
- command :cmd_with_arg_and_opt_arg, usage: 'ARG1 [ARG2]',
582
- summary: 'Example command with arg and optional arg'
583
- def cmd_with_arg_and_opt_arg(arg1,arg2=nil)
584
- puts "#{__method__} called: arg1=#{arg1} arg2=#{arg2}"
585
- end
586
- end
587
- end
588
-
589
- let(:shell_class) do
590
- TestCommandShell::ShellWithCommandWithArgAndOptionalArg
591
- end
592
- let(:name) { 'cmd_with_arg_and_opt_arg' }
593
-
594
- context "and no arguments are given" do
595
- let(:args) { [] }
596
-
597
- it "must print an error and return false" do
598
- expect {
599
- expect(subject.call(name,*args)).to be(false)
600
- }.to output("#{name}: too few arguments given#{$/}").to_stderr
601
- end
602
- end
603
-
604
- context "and one argument is given" do
605
- let(:arg) { "foo" }
606
- let(:args) { [arg] }
607
-
608
- it "must call the command mehtod with the argument and return true" do
609
- expect {
610
- expect(subject.call(name,*args)).to be(true)
611
- }.to output("#{name} called: arg1=#{arg} arg2=#{$/}").to_stdout
612
- end
613
- end
614
-
615
- context "and two arguments are given" do
616
- let(:arg1) { "foo" }
617
- let(:arg2) { "bar" }
618
- let(:args) { [arg1, arg2] }
619
-
620
- it "must call the command mehtod with the argument and return true" do
621
- expect {
622
- expect(subject.call(name,*args)).to be(true)
623
- }.to output("#{name} called: arg1=#{arg1} arg2=#{arg2}#{$/}").to_stdout
624
- end
625
- end
626
-
627
- context "and more than two arguments are given" do
628
- let(:arg1) { "foo" }
629
- let(:arg2) { "bar" }
630
- let(:arg3) { "baz" }
631
- let(:args) { [arg1, arg2, arg3] }
632
-
633
- it "must print an error and return false" do
634
- expect {
635
- expect(subject.call(name,*args)).to be(false)
636
- }.to output("#{name}: too many arguments given#{$/}").to_stderr
637
- end
638
- end
639
- end
640
-
641
- context "and the command accepts a splat of arguments" do
642
- module TestCommandShell
643
- class ShellWithCommandWithSplatArgs < Ronin::Core::CLI::CommandShell
644
- shell_name 'test'
645
-
646
- command :cmd_with_splat_args, usage: '[ARGS...]',
647
- summary: 'Example command with splat args'
648
- def cmd_with_splat_args(*args)
649
- puts "#{__method__} called: args=#{args.join(' ')}"
650
- end
651
- end
652
- end
653
-
654
- let(:shell_class) do
655
- TestCommandShell::ShellWithCommandWithSplatArgs
656
- end
657
- let(:name) { 'cmd_with_splat_args' }
658
-
659
- context "and no arguments are given" do
660
- let(:args) { [] }
661
-
662
- it "must call the command mehtod with no arguments and return true" do
663
- expect {
664
- expect(subject.call(name,*args)).to be(true)
665
- }.to output("#{name} called: args=#{$/}").to_stdout
666
- end
667
- end
668
-
669
- context "and one argument is given" do
670
- let(:arg) { "foo" }
671
- let(:args) { [arg] }
672
-
673
- it "must call the command mehtod with the argument and return true" do
674
- expect {
675
- expect(subject.call(name,*args)).to be(true)
676
- }.to output("#{name} called: args=#{arg}#{$/}").to_stdout
677
- end
678
- end
679
-
680
- context "and multiple arguments are given" do
681
- let(:arg1) { "foo" }
682
- let(:arg2) { "bar" }
683
- let(:args) { [arg1, arg2] }
684
-
685
- it "must call the command mehtod with the argument and return true" do
686
- expect {
687
- expect(subject.call(name,*args)).to be(true)
688
- }.to output("#{name} called: args=#{arg1} #{arg2}#{$/}").to_stdout
689
- end
690
- end
691
- end
692
-
693
- context "and the command accepts an argument and splat arguments" do
694
- module TestCommandShell
695
- class ShellWithCommandWithArgAndSplatArgs < Ronin::Core::CLI::CommandShell
696
- shell_name 'test'
697
-
698
- command :cmd_with_arg_and_splat_args, usage: 'ARG [ARGS...]',
699
- summary: 'Example command with arg and splat args'
700
- def cmd_with_arg_and_splat_args(arg,*args)
701
- puts "#{__method__} called: arg=#{arg} args=#{args.join(' ')}"
702
- end
703
- end
704
- end
705
-
706
- let(:shell_class) do
707
- TestCommandShell::ShellWithCommandWithArgAndSplatArgs
708
- end
709
- let(:name) { 'cmd_with_arg_and_splat_args' }
710
-
711
- context "and no arguments are given" do
712
- let(:args) { [] }
713
-
714
- it "must print an error and return false" do
715
- expect {
716
- expect(subject.call(name,*args)).to be(false)
717
- }.to output("#{name}: too few arguments given#{$/}").to_stderr
718
- end
719
- end
720
-
721
- context "and one argument is given" do
722
- let(:arg) { "foo" }
723
- let(:args) { [arg] }
724
-
725
- it "must call the command mehtod with the argument and return true" do
726
- expect {
727
- expect(subject.call(name,*args)).to be(true)
728
- }.to output("#{name} called: arg=#{arg} args=#{$/}").to_stdout
729
- end
730
- end
731
-
732
- context "and two arguments are given" do
733
- let(:arg1) { "foo" }
734
- let(:arg2) { "bar" }
735
- let(:args) { [arg1, arg2] }
736
-
737
- it "must call the command mehtod with the argument and return true" do
738
- expect {
739
- expect(subject.call(name,*args)).to be(true)
740
- }.to output("#{name} called: arg=#{arg1} args=#{arg2}#{$/}").to_stdout
741
- end
742
- end
743
-
744
- context "and more than two arguments are given" do
745
- let(:arg1) { "foo" }
746
- let(:arg2) { "bar" }
747
- let(:arg3) { "baz" }
748
- let(:args) { [arg1, arg2, arg3] }
749
-
750
- it "must call the command mehtod with the argument and return true" do
751
- expect {
752
- expect(subject.call(name,*args)).to be(true)
753
- }.to output("#{name} called: arg=#{arg1} args=#{arg2} #{arg3}#{$/}").to_stdout
754
- end
755
- end
756
- end
757
-
758
- context "and the command accepts an optional argument and splat arguments" do
759
- module TestCommandShell
760
- class ShellWithCommandWithOptionalArgAndSplatArgs < Ronin::Core::CLI::CommandShell
761
- shell_name 'test'
762
-
763
- command :cmd_with_opt_arg_and_splat_args, usage: '[ARG] [ARGS...]',
764
- summary: 'Example command with arg and splat args'
765
- def cmd_with_opt_arg_and_splat_args(arg=nil,*args)
766
- puts "#{__method__} called: arg=#{arg} args=#{args.join(' ')}"
767
- end
768
- end
769
- end
770
-
771
- let(:shell_class) do
772
- TestCommandShell::ShellWithCommandWithOptionalArgAndSplatArgs
773
- end
774
- let(:name) { 'cmd_with_opt_arg_and_splat_args' }
775
-
776
- context "and no arguments are given" do
777
- let(:args) { [] }
778
-
779
- it "must call the command method with no arguments and return true" do
780
- expect {
781
- expect(subject.call(name,*args)).to be(true)
782
- }.to output("#{name} called: arg= args=#{$/}").to_stdout
783
- end
784
- end
785
-
786
- context "and one argument is given" do
787
- let(:arg) { "foo" }
788
- let(:args) { [arg] }
789
-
790
- it "must call the command mehtod with the argument and return true" do
791
- expect {
792
- expect(subject.call(name,*args)).to be(true)
793
- }.to output("#{name} called: arg=#{arg} args=#{$/}").to_stdout
794
- end
795
- end
796
-
797
- context "and two arguments are given" do
798
- let(:arg1) { "foo" }
799
- let(:arg2) { "bar" }
800
- let(:args) { [arg1, arg2] }
801
-
802
- it "must call the command mehtod with the argument and return true" do
803
- expect {
804
- expect(subject.call(name,*args)).to be(true)
805
- }.to output("#{name} called: arg=#{arg1} args=#{arg2}#{$/}").to_stdout
806
- end
807
- end
808
-
809
- context "and more than two arguments are given" do
810
- let(:arg1) { "foo" }
811
- let(:arg2) { "bar" }
812
- let(:arg3) { "baz" }
813
- let(:args) { [arg1, arg2, arg3] }
814
-
815
- it "must call the command mehtod with the argument and return true" do
816
- expect {
817
- expect(subject.call(name,*args)).to be(true)
818
- }.to output("#{name} called: arg=#{arg1} args=#{arg2} #{arg3}#{$/}").to_stdout
819
- end
820
- end
821
- end
822
-
823
- context "but the command method raises an exception" do
824
- module TestCommandShell
825
- class ShellWithCommandThatRaisesAnException < Ronin::Core::CLI::CommandShell
826
-
827
- command 'cmd', summary: 'Test command'
828
- def cmd
829
- raise("error!")
830
- end
831
-
832
- end
833
- end
834
-
835
- let(:shell_class) do
836
- TestCommandShell::ShellWithCommandThatRaisesAnException
837
- end
838
- let(:name) { 'cmd' }
839
-
840
- it "must print an error message and return false" do
841
- expect {
842
- expect(subject.call(name)).to be(false)
843
- }.to output(/an unhandled exception occurred in the #{name} command/).to_stderr
844
- end
845
- end
846
- end
847
-
848
- context "when the command does not exist" do
849
- let(:name) { "does_not_exist" }
850
-
851
- it "must print an error message and return false" do
852
- expect {
853
- expect(subject.call(name)).to be(false)
854
- }.to output("unknown command: #{name}#{$/}").to_stderr
855
- end
856
- end
857
-
858
- context "when the command was defined but no method is defined" do
859
- module TestCommandShell
860
- class ShellWithCommandButNoMethod < Ronin::Core::CLI::CommandShell
861
-
862
- command 'cmd', summary: 'Test command'
863
-
864
- end
865
- end
866
-
867
- let(:shell_class) do
868
- TestCommandShell::ShellWithCommandButNoMethod
869
- end
870
- let(:name) { 'cmd' }
871
-
872
- it "must raise NotImplementedError" do
873
- expect {
874
- subject.call(name)
875
- }.to raise_error(NotImplementedError,"#{shell_class}##{name} was not defined for the #{name.inspect} command")
876
- end
877
- end
878
- end
879
-
880
- describe "#command_missing" do
881
- let(:name) { "foo" }
882
-
883
- it "must print an error message and return false" do
884
- expect {
885
- expect(subject.command_missing(name)).to be(false)
886
- }.to output("unknown command: #{name}#{$/}").to_stderr
887
- end
888
- end
889
-
890
- describe "#command_not_found" do
891
- let(:name) { "foo" }
892
-
893
- it "must print an error message and return false" do
894
- expect {
895
- subject.command_not_found(name)
896
- }.to output("unknown command: #{name}#{$/}").to_stderr
897
- end
898
- end
899
-
900
- describe "#help" do
901
- module TestCommandShell
902
- class ShellWithCommandsWithoutUsages < Ronin::Core::CLI::CommandShell
903
- shell_name 'test'
904
-
905
- command :foo, summary: 'Foo command'
906
- def foo
907
- end
908
-
909
- command :bar, summary: 'Bar command'
910
- def bar
911
- end
912
- end
913
-
914
- class ShellWithCommandsWithCustomUsages < Ronin::Core::CLI::CommandShell
915
- shell_name 'test'
916
-
917
- command :foo, usage: 'ARG',
918
- summary: 'Foo command'
919
- def foo(arg)
920
- end
921
-
922
- command :bar, usage: 'ARG1 [ARG2]',
923
- summary: 'Bar command'
924
- def bar(arg1,arg2=nil)
925
- end
926
- end
927
- end
928
-
929
- context "when called with no arguments" do
930
- context "but the shell has no commands" do
931
- let(:shell_class) do
932
- TestCommandShell::ShellWithNoCommands
933
- end
934
-
935
- it "must list the help command" do
936
- expect {
937
- subject.help
938
- }.to output(
939
- [
940
- " help [COMMAND]\tPrints the list of commands or additional help",
941
- ''
942
- ].join($/)
943
- ).to_stdout
944
- end
945
- end
946
-
947
- context "but the commands do not have usage strings" do
948
- let(:shell_class) do
949
- TestCommandShell::ShellWithCommandsWithoutUsages
950
- end
951
-
952
- it "must print the command names and summaries in two columns" do
953
- expect {
954
- subject.help
955
- }.to output(
956
- [
957
- " help [COMMAND]\tPrints the list of commands or additional help",
958
- " foo \tFoo command",
959
- " bar \tBar command",
960
- ''
961
- ].join($/)
962
- ).to_stdout
963
- end
964
- end
965
-
966
- context "when the commands defines custom usages" do
967
- let(:shell_class) do
968
- TestCommandShell::ShellWithCommandsWithCustomUsages
969
- end
970
-
971
- it "must print the custom usages next to the command names with extra right-padding" do
972
- expect {
973
- subject.help
974
- }.to output(
975
- [
976
- " help [COMMAND] \tPrints the list of commands or additional help",
977
- " foo ARG \tFoo command",
978
- " bar ARG1 [ARG2]\tBar command",
979
- ''
980
- ].join($/)
981
- ).to_stdout
982
- end
983
- end
984
- end
985
-
986
- context "when called with a command name" do
987
- let(:command) { 'bar' }
988
-
989
- context "but the command does not have a usage string" do
990
- context "nor does the command have any additional help output" do
991
- let(:shell_class) do
992
- TestCommandShell::ShellWithCommandsWithoutUsages
993
- end
994
-
995
- it "must print the command's name and summary" do
996
- expect {
997
- subject.help(command)
998
- }.to output(
999
- [
1000
- "usage: bar",
1001
- '',
1002
- 'Bar command',
1003
- ''
1004
- ].join($/)
1005
- ).to_stdout
1006
- end
1007
- end
1008
-
1009
- context "and the command has additional help output" do
1010
- module TestCommandShell
1011
- class ShellWithCommandsWithNoUsagesButWithHelp < Ronin::Core::CLI::CommandShell
1012
- shell_name 'test'
1013
-
1014
- command :foo, summary: 'Foo command',
1015
- help: 'The foo command that does things.'
1016
- def foo
1017
- end
1018
-
1019
- command :bar, summary: 'Bar command',
1020
- help: 'The bar command that does things.'
1021
- def bar
1022
- end
1023
- end
1024
- end
1025
-
1026
- let(:shell_class) do
1027
- TestCommandShell::ShellWithCommandsWithNoUsagesButWithHelp
1028
- end
1029
-
1030
- it "must print the command name and additional help output" do
1031
- expect {
1032
- subject.help(command)
1033
- }.to output(
1034
- [
1035
- "usage: bar",
1036
- '',
1037
- 'The bar command that does things.',
1038
- ''
1039
- ].join($/)
1040
- ).to_stdout
1041
- end
1042
- end
1043
- end
1044
-
1045
- context "and the command does have a usage string" do
1046
- context "but the command does not have any additional help output" do
1047
- let(:shell_class) do
1048
- TestCommandShell::ShellWithCommandsWithCustomUsages
1049
- end
1050
-
1051
- it "must print the command name, usage, and summary" do
1052
- expect {
1053
- subject.help(command)
1054
- }.to output(
1055
- [
1056
- "usage: bar ARG1 [ARG2]",
1057
- '',
1058
- 'Bar command',
1059
- ''
1060
- ].join($/)
1061
- ).to_stdout
1062
- end
1063
- end
1064
-
1065
- context "and the command does have any additional help output" do
1066
- module TestCommandShell
1067
- class ShellWithCommandsWithUsagesButWithHelp < Ronin::Core::CLI::CommandShell
1068
- shell_name 'test'
1069
-
1070
- command :foo, usage: 'ARG',
1071
- summary: 'Foo command',
1072
- help: 'The foo command that does things.'
1073
- def foo(arg)
1074
- end
1075
-
1076
- command :bar, usage: 'ARG1 [ARG2]',
1077
- summary: 'Bar command',
1078
- help: 'The bar command that does things.'
1079
- def bar(arg1,arg2=nil)
1080
- end
1081
- end
1082
- end
1083
-
1084
- let(:shell_class) do
1085
- TestCommandShell::ShellWithCommandsWithUsagesButWithHelp
1086
- end
1087
-
1088
- it "must print the command name, usage, and additional help output" do
1089
- expect {
1090
- subject.help(command)
1091
- }.to output(
1092
- [
1093
- "usage: bar ARG1 [ARG2]",
1094
- '',
1095
- 'The bar command that does things.',
1096
- ''
1097
- ].join($/)
1098
- ).to_stdout
1099
- end
1100
- end
1101
- end
1102
-
1103
- context "but the command name isn't a defined command" do
1104
- let(:command) { 'does_not_exist' }
1105
-
1106
- it "must print an 'unknown command' error" do
1107
- expect {
1108
- subject.help(command)
1109
- }.to output("help: unknown command: #{command}#{$/}").to_stderr
1110
- end
1111
- end
1112
- end
1113
- end
1114
- end