ronin-core 0.1.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.document +5 -0
- data/.github/workflows/ruby.yml +41 -0
- data/.gitignore +12 -0
- data/.rspec +1 -0
- data/.rubocop.yml +160 -0
- data/.ruby-version +1 -0
- data/.yardopts +1 -0
- data/COPYING.txt +165 -0
- data/ChangeLog.md +11 -0
- data/Gemfile +30 -0
- data/README.md +299 -0
- data/Rakefile +34 -0
- data/examples/ruby_shell.rb +11 -0
- data/gemspec.yml +28 -0
- data/lib/ronin/core/class_registry.rb +246 -0
- data/lib/ronin/core/cli/command.rb +87 -0
- data/lib/ronin/core/cli/command_shell/command.rb +110 -0
- data/lib/ronin/core/cli/command_shell.rb +345 -0
- data/lib/ronin/core/cli/generator/options/author.rb +106 -0
- data/lib/ronin/core/cli/generator/options/description.rb +54 -0
- data/lib/ronin/core/cli/generator/options/reference.rb +60 -0
- data/lib/ronin/core/cli/generator/options/summary.rb +54 -0
- data/lib/ronin/core/cli/generator.rb +238 -0
- data/lib/ronin/core/cli/logging.rb +59 -0
- data/lib/ronin/core/cli/options/param.rb +68 -0
- data/lib/ronin/core/cli/options/values/arches.rb +45 -0
- data/lib/ronin/core/cli/options/values/oses.rb +32 -0
- data/lib/ronin/core/cli/printing/arch.rb +71 -0
- data/lib/ronin/core/cli/printing/metadata.rb +113 -0
- data/lib/ronin/core/cli/printing/os.rb +54 -0
- data/lib/ronin/core/cli/printing/params.rb +69 -0
- data/lib/ronin/core/cli/ruby_shell.rb +131 -0
- data/lib/ronin/core/cli/shell.rb +186 -0
- data/lib/ronin/core/git.rb +73 -0
- data/lib/ronin/core/home.rb +86 -0
- data/lib/ronin/core/metadata/authors/author.rb +241 -0
- data/lib/ronin/core/metadata/authors.rb +120 -0
- data/lib/ronin/core/metadata/description.rb +100 -0
- data/lib/ronin/core/metadata/id.rb +88 -0
- data/lib/ronin/core/metadata/references.rb +87 -0
- data/lib/ronin/core/metadata/summary.rb +78 -0
- data/lib/ronin/core/metadata/version.rb +74 -0
- data/lib/ronin/core/params/exceptions.rb +38 -0
- data/lib/ronin/core/params/mixin.rb +317 -0
- data/lib/ronin/core/params/param.rb +137 -0
- data/lib/ronin/core/params/types/boolean.rb +64 -0
- data/lib/ronin/core/params/types/enum.rb +107 -0
- data/lib/ronin/core/params/types/float.rb +68 -0
- data/lib/ronin/core/params/types/integer.rb +100 -0
- data/lib/ronin/core/params/types/numeric.rb +106 -0
- data/lib/ronin/core/params/types/regexp.rb +67 -0
- data/lib/ronin/core/params/types/string.rb +118 -0
- data/lib/ronin/core/params/types/type.rb +54 -0
- data/lib/ronin/core/params/types/uri.rb +72 -0
- data/lib/ronin/core/params/types.rb +62 -0
- data/lib/ronin/core/params.rb +19 -0
- data/lib/ronin/core/version.rb +24 -0
- data/ronin-core.gemspec +59 -0
- data/spec/class_registry_spec.rb +224 -0
- data/spec/cli/command_shell/command_spec.rb +113 -0
- data/spec/cli/command_shell_spec.rb +1114 -0
- data/spec/cli/command_spec.rb +16 -0
- data/spec/cli/fixtures/irb_command +8 -0
- data/spec/cli/fixtures/template/dir/file1.txt +1 -0
- data/spec/cli/fixtures/template/dir/file2.txt +1 -0
- data/spec/cli/fixtures/template/file.erb +1 -0
- data/spec/cli/fixtures/template/file.txt +1 -0
- data/spec/cli/generator/options/author_spec.rb +121 -0
- data/spec/cli/generator/options/description_spec.rb +45 -0
- data/spec/cli/generator/options/reference_spec.rb +53 -0
- data/spec/cli/generator/options/summary_spec.rb +45 -0
- data/spec/cli/generator_spec.rb +244 -0
- data/spec/cli/logging_spec.rb +95 -0
- data/spec/cli/options/param_spec.rb +67 -0
- data/spec/cli/options/values/arches_spec.rb +62 -0
- data/spec/cli/printing/arch_spec.rb +130 -0
- data/spec/cli/printing/metadata_spec.rb +211 -0
- data/spec/cli/printing/os_spec.rb +64 -0
- data/spec/cli/printing/params_spec.rb +63 -0
- data/spec/cli/ruby_shell.rb +99 -0
- data/spec/cli/shell_spec.rb +211 -0
- data/spec/fixtures/example_class_registry/base_class.rb +9 -0
- data/spec/fixtures/example_class_registry/classes/loaded_class.rb +9 -0
- data/spec/fixtures/example_class_registry/classes/name_mismatch.rb +9 -0
- data/spec/fixtures/example_class_registry/classes/no_module.rb +4 -0
- data/spec/fixtures/example_class_registry.rb +8 -0
- data/spec/git_spec.rb +58 -0
- data/spec/home_spec.rb +64 -0
- data/spec/metadata/authors/author_spec.rb +335 -0
- data/spec/metadata/authors_spec.rb +126 -0
- data/spec/metadata/description_spec.rb +74 -0
- data/spec/metadata/id_spec.rb +92 -0
- data/spec/metadata/references_spec.rb +100 -0
- data/spec/metadata/summary_spec.rb +74 -0
- data/spec/metadata/version_spec.rb +72 -0
- data/spec/params/mixin_spec.rb +484 -0
- data/spec/params/param_spec.rb +164 -0
- data/spec/params/types/boolean_spec.rb +56 -0
- data/spec/params/types/enum_spec.rb +94 -0
- data/spec/params/types/float_spec.rb +107 -0
- data/spec/params/types/integer_spec.rb +155 -0
- data/spec/params/types/numeric_spec.rb +138 -0
- data/spec/params/types/regexp_spec.rb +64 -0
- data/spec/params/types/string_spec.rb +174 -0
- data/spec/params/types/type_spec.rb +14 -0
- data/spec/params/types/uri_spec.rb +62 -0
- data/spec/spec_helper.rb +11 -0
- metadata +252 -0
@@ -0,0 +1,484 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'ronin/core/params/mixin'
|
3
|
+
|
4
|
+
describe Ronin::Core::Params::Mixin do
|
5
|
+
describe "Boolean" do
|
6
|
+
it "must equal Ronin::Core::Params::Types::Boolean" do
|
7
|
+
expect(described_class::Boolean).to be(Ronin::Core::Params::Types::Boolean)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "Enum" do
|
12
|
+
it "must equal Ronin::Core::Params::Types::Enum" do
|
13
|
+
expect(described_class::Enum).to be(Ronin::Core::Params::Types::Enum)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe ".params" do
|
18
|
+
subject { test_class }
|
19
|
+
|
20
|
+
context "and when params is not set in the class" do
|
21
|
+
module TestParamsMixin
|
22
|
+
class WithEmptyParams
|
23
|
+
include Ronin::Core::Params::Mixin
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
let(:test_class) { TestParamsMixin::WithEmptyParams }
|
28
|
+
|
29
|
+
it "must default to {}" do
|
30
|
+
expect(subject.params).to eq({})
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context "and when param is called in the class" do
|
35
|
+
module TestParamsMixin
|
36
|
+
class WithParams
|
37
|
+
include Ronin::Core::Params::Mixin
|
38
|
+
|
39
|
+
param :foo, desc: 'Foo param'
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
let(:test_class) { TestParamsMixin::WithParams }
|
44
|
+
|
45
|
+
it "must return the set params" do
|
46
|
+
expect(subject.params).to_not be_empty
|
47
|
+
expect(subject.params[:foo]).to be_kind_of(Ronin::Core::Params::Param)
|
48
|
+
expect(subject.params[:foo].name).to eq(:foo)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context "but when params are set in the superclass" do
|
53
|
+
module TestParamsMixin
|
54
|
+
class BaseClassWithParams
|
55
|
+
include Ronin::Core::Params::Mixin
|
56
|
+
|
57
|
+
param :foo, desc: 'Foo param'
|
58
|
+
end
|
59
|
+
|
60
|
+
class OnlyInheritsParams < BaseClassWithParams
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
let(:test_class) { TestParamsMixin::OnlyInheritsParams }
|
65
|
+
|
66
|
+
it "must return the params set in the superclass" do
|
67
|
+
expect(subject.params).to_not be_empty
|
68
|
+
expect(subject.params[:foo]).to be_kind_of(Ronin::Core::Params::Param)
|
69
|
+
expect(subject.params[:foo].name).to eq(:foo)
|
70
|
+
end
|
71
|
+
|
72
|
+
context "and when additional params are defined in a sub-class" do
|
73
|
+
module TestParamsMixin
|
74
|
+
class AdditionalParamsDefinedInSubClass < BaseClassWithParams
|
75
|
+
param :bar, desc: 'Additional param'
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
let(:test_class) { TestParamsMixin::AdditionalParamsDefinedInSubClass }
|
80
|
+
let(:superclass) { TestParamsMixin::BaseClassWithParams }
|
81
|
+
|
82
|
+
it "must return both the params defined in the superclass and sub-class" do
|
83
|
+
expect(subject.params).to_not be_empty
|
84
|
+
expect(subject.params[:foo]).to be_kind_of(Ronin::Core::Params::Param)
|
85
|
+
expect(subject.params[:foo].name).to eq(:foo)
|
86
|
+
|
87
|
+
expect(subject.params[:bar]).to be_kind_of(Ronin::Core::Params::Param)
|
88
|
+
expect(subject.params[:bar].name).to eq(:bar)
|
89
|
+
end
|
90
|
+
|
91
|
+
it "must not modify the .params in the superclass" do
|
92
|
+
expect(superclass.params).to_not have_key(:bar)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
describe ".param" do
|
99
|
+
context "when only given required arguments" do
|
100
|
+
module TestParamsMixin
|
101
|
+
class DefaultParam
|
102
|
+
include Ronin::Core::Params::Mixin
|
103
|
+
|
104
|
+
param :foo, desc: 'Foo param'
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
subject { TestParamsMixin::DefaultParam }
|
109
|
+
|
110
|
+
it "must define a param with the given name and description" do
|
111
|
+
expect(subject.params[:foo]).to be_kind_of(Ronin::Core::Params::Param)
|
112
|
+
expect(subject.params[:foo].name).to be(:foo)
|
113
|
+
expect(subject.params[:foo].desc).to eq('Foo param')
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
context "when also given the type argument" do
|
118
|
+
context "and it's a Ruby core class" do
|
119
|
+
module TestParamsMixin
|
120
|
+
class ParamWithCoreClassType
|
121
|
+
include Ronin::Core::Params::Mixin
|
122
|
+
|
123
|
+
param :foo, Integer, desc: 'Foo param'
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
subject { TestParamsMixin::ParamWithCoreClassType }
|
128
|
+
|
129
|
+
it "must map the core class to a Ronin::Core::Params::Types:: class" do
|
130
|
+
expect(subject.params[:foo].type).to be_kind_of(Ronin::Core::Params::Types::Integer)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
context "and it's a Ronin::Core::Params::Types:: instance" do
|
135
|
+
module TestParamsMixin
|
136
|
+
class ParamWithTypeInstance
|
137
|
+
include Ronin::Core::Params::Mixin
|
138
|
+
|
139
|
+
param :foo, Enum[:bar, :baz], desc: 'Foo param'
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
subject { TestParamsMixin::ParamWithTypeInstance }
|
144
|
+
|
145
|
+
it "must define a param with the given Ronin::Core::Params::Types:: instance" do
|
146
|
+
expect(subject.params[:foo].type).to be_kind_of(Ronin::Core::Params::Types::Enum)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
context "and when given additional keyword arguments" do
|
151
|
+
module TestParamsMixin
|
152
|
+
class ParamWithTypeAndAdditionalKwargs
|
153
|
+
include Ronin::Core::Params::Mixin
|
154
|
+
|
155
|
+
param :foo, Integer, desc: 'Foo param', min: 1, max: 10
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
subject { TestParamsMixin::ParamWithTypeAndAdditionalKwargs }
|
160
|
+
|
161
|
+
it "must pass them to the Ronin::Core::Params::Types:: class'es #initialize method" do
|
162
|
+
expect(subject.params[:foo].type.min).to eq(1)
|
163
|
+
expect(subject.params[:foo].type.max).to eq(10)
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
context "when also given the required: keyword argument" do
|
169
|
+
module TestParamsMixin
|
170
|
+
class ParamWithRequired
|
171
|
+
include Ronin::Core::Params::Mixin
|
172
|
+
|
173
|
+
param :foo, required: true, desc: 'Foo param'
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
subject { TestParamsMixin::ParamWithRequired }
|
178
|
+
|
179
|
+
it "must define a param with #required set to true" do
|
180
|
+
expect(subject.params[:foo]).to be_kind_of(Ronin::Core::Params::Param)
|
181
|
+
expect(subject.params[:foo].required).to be(true)
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
context "when also given the default: keyword argument" do
|
186
|
+
module TestParamsMixin
|
187
|
+
class ParamWithDefault
|
188
|
+
include Ronin::Core::Params::Mixin
|
189
|
+
|
190
|
+
param :foo, default: 42, desc: 'Foo param'
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
subject { TestParamsMixin::ParamWithDefault }
|
195
|
+
|
196
|
+
it "must define a param with #default set to true" do
|
197
|
+
expect(subject.params[:foo]).to be_kind_of(Ronin::Core::Params::Param)
|
198
|
+
expect(subject.params[:foo].default).to eq(42)
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
module TestParamsMixin
|
204
|
+
class TestParams
|
205
|
+
include Ronin::Core::Params::Mixin
|
206
|
+
|
207
|
+
param :foo, Integer, desc: 'Foo param'
|
208
|
+
param :bar, Integer, desc: 'Bar param'
|
209
|
+
end
|
210
|
+
|
211
|
+
class TestParamsWithDefault
|
212
|
+
include Ronin::Core::Params::Mixin
|
213
|
+
|
214
|
+
param :foo, Integer, desc: 'Foo param'
|
215
|
+
param :bar, Integer, default: 42, desc: 'Bar param'
|
216
|
+
end
|
217
|
+
|
218
|
+
class TestParamsWithRequired
|
219
|
+
include Ronin::Core::Params::Mixin
|
220
|
+
|
221
|
+
param :foo, Integer, required: true, desc: 'Foo param'
|
222
|
+
param :bar, Integer, desc: 'Bar param'
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
let(:test_class) { TestParamsMixin::TestParams }
|
227
|
+
subject { test_class.new }
|
228
|
+
|
229
|
+
describe "#initialize" do
|
230
|
+
context "when not given the params: keyword argument" do
|
231
|
+
it "must default #params to {}" do
|
232
|
+
expect(subject.params).to eq({})
|
233
|
+
end
|
234
|
+
|
235
|
+
context "when a param is defined with a default: value" do
|
236
|
+
let(:test_class) { TestParamsMixin::TestParamsWithDefault }
|
237
|
+
|
238
|
+
it "must initialize the param in #params with the param's default value" do
|
239
|
+
expect(subject.params[:bar]).to eq(test_class.params[:bar].default_value)
|
240
|
+
end
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
context "when given the params: keyword argument" do
|
245
|
+
let(:params) do
|
246
|
+
{foo: 1, bar: 2}
|
247
|
+
end
|
248
|
+
|
249
|
+
subject { test_class.new(params: params) }
|
250
|
+
|
251
|
+
it "must initialize the params using the parmms: Hash" do
|
252
|
+
expect(subject.params).to eq(params)
|
253
|
+
end
|
254
|
+
|
255
|
+
context "but when one of the required param values is missing" do
|
256
|
+
let(:test_class) { TestParamsMixin::TestParamsWithRequired }
|
257
|
+
|
258
|
+
it do
|
259
|
+
expect {
|
260
|
+
test_class.new(params: {})
|
261
|
+
}.to raise_error(Ronin::Core::Params::RequiredParam,"param 'foo' requires a value")
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
context "but params: values do not match the param's types" do
|
266
|
+
let(:params) do
|
267
|
+
{foo: '1', bar: '2'}
|
268
|
+
end
|
269
|
+
|
270
|
+
it "must coerce the values using the param's types" do
|
271
|
+
expect(subject.params[:foo]).to eq(params[:foo].to_i)
|
272
|
+
expect(subject.params[:bar]).to eq(params[:bar].to_i)
|
273
|
+
end
|
274
|
+
|
275
|
+
context "but the values cannot be coerced" do
|
276
|
+
let(:invalid_param) { :bar }
|
277
|
+
let(:invalid_value) { "XYZ" }
|
278
|
+
let(:params) do
|
279
|
+
{foo: 1, invalid_param => invalid_value}
|
280
|
+
end
|
281
|
+
|
282
|
+
it do
|
283
|
+
expect {
|
284
|
+
test_class.new(params: params)
|
285
|
+
}.to raise_error(Ronin::Core::Params::ValidationError,"invalid param value for param '#{invalid_param}': value contains non-numeric characters (#{invalid_value.inspect})")
|
286
|
+
end
|
287
|
+
end
|
288
|
+
end
|
289
|
+
|
290
|
+
context "but the params: value contains an unknown param" do
|
291
|
+
let(:unknown_param) { :xxx }
|
292
|
+
let(:params) do
|
293
|
+
{:foo => 1, unknown_param => 2}
|
294
|
+
end
|
295
|
+
|
296
|
+
it do
|
297
|
+
expect {
|
298
|
+
test_class.new(params: params)
|
299
|
+
}.to raise_error(Ronin::Core::Params::UnknownParam,"unknown param: #{unknown_param.inspect}")
|
300
|
+
end
|
301
|
+
end
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
305
|
+
describe "#params=" do
|
306
|
+
let(:params) do
|
307
|
+
{foo: 1, bar: 2}
|
308
|
+
end
|
309
|
+
|
310
|
+
it "must populate #params using the parmms Hash" do
|
311
|
+
subject.params = params
|
312
|
+
|
313
|
+
expect(subject.params).to eq(params)
|
314
|
+
end
|
315
|
+
|
316
|
+
context "but #params has been previously set" do
|
317
|
+
let(:params) do
|
318
|
+
{foo: 1}
|
319
|
+
end
|
320
|
+
|
321
|
+
before do
|
322
|
+
subject.params = {foo: 111, bar: 222}
|
323
|
+
subject.params = params
|
324
|
+
end
|
325
|
+
|
326
|
+
it "must clear #params before re-populating it" do
|
327
|
+
expect(subject.params).to eq(params)
|
328
|
+
end
|
329
|
+
end
|
330
|
+
|
331
|
+
context "when a param is defined with a default: value" do
|
332
|
+
let(:test_class) { TestParamsMixin::TestParamsWithDefault }
|
333
|
+
|
334
|
+
let(:params) do
|
335
|
+
{foo: 1}
|
336
|
+
end
|
337
|
+
before { subject.params = params }
|
338
|
+
|
339
|
+
it "must initialize the param in #params with the param's default value" do
|
340
|
+
expect(subject.params[:bar]).to eq(test_class.params[:bar].default_value)
|
341
|
+
end
|
342
|
+
|
343
|
+
it "must set the other params" do
|
344
|
+
expect(subject.params[:foo]).to eq(params[:foo])
|
345
|
+
end
|
346
|
+
end
|
347
|
+
|
348
|
+
context "but the params values do not match the param's types" do
|
349
|
+
let(:params) do
|
350
|
+
{foo: '1', bar: '2'}
|
351
|
+
end
|
352
|
+
|
353
|
+
it "must coerce the values using the param's types" do
|
354
|
+
subject.params = params
|
355
|
+
|
356
|
+
expect(subject.params[:foo]).to eq(params[:foo].to_i)
|
357
|
+
expect(subject.params[:bar]).to eq(params[:bar].to_i)
|
358
|
+
end
|
359
|
+
|
360
|
+
context "but the values cannot be coerced" do
|
361
|
+
let(:invalid_param) { :bar }
|
362
|
+
let(:invalid_value) { "XYZ" }
|
363
|
+
let(:params) do
|
364
|
+
{foo: 1, invalid_param => invalid_value}
|
365
|
+
end
|
366
|
+
|
367
|
+
it do
|
368
|
+
expect {
|
369
|
+
subject.params = params
|
370
|
+
}.to raise_error(Ronin::Core::Params::ValidationError,"invalid param value for param '#{invalid_param}': value contains non-numeric characters (#{invalid_value.inspect})")
|
371
|
+
end
|
372
|
+
end
|
373
|
+
end
|
374
|
+
|
375
|
+
context "when a param is defined with required: true" do
|
376
|
+
let(:test_class) { TestParamsMixin::TestParamsWithRequired }
|
377
|
+
|
378
|
+
let(:params) do
|
379
|
+
{bar: 1}
|
380
|
+
end
|
381
|
+
|
382
|
+
context "and the value is not given in the params Hash" do
|
383
|
+
it do
|
384
|
+
expect {
|
385
|
+
subject.params = params
|
386
|
+
}.to raise_error(Ronin::Core::Params::RequiredParam,"param 'foo' requires a value")
|
387
|
+
end
|
388
|
+
end
|
389
|
+
end
|
390
|
+
|
391
|
+
context "but the params value contains an unknown param" do
|
392
|
+
let(:unknown_param) { :xxx }
|
393
|
+
let(:params) do
|
394
|
+
{:foo => 1, unknown_param => 2}
|
395
|
+
end
|
396
|
+
|
397
|
+
it do
|
398
|
+
expect {
|
399
|
+
subject.params = params
|
400
|
+
}.to raise_error(Ronin::Core::Params::UnknownParam,"unknown param: #{unknown_param.inspect}")
|
401
|
+
end
|
402
|
+
end
|
403
|
+
end
|
404
|
+
|
405
|
+
describe "#set_param" do
|
406
|
+
let(:name) { :foo }
|
407
|
+
let(:value) { 42 }
|
408
|
+
|
409
|
+
it "must set the param with the given name and value" do
|
410
|
+
subject.set_param(name,value)
|
411
|
+
|
412
|
+
expect(subject.params[name]).to eq(value)
|
413
|
+
end
|
414
|
+
|
415
|
+
context "when the param name is not unknown" do
|
416
|
+
let(:name) { :xxx }
|
417
|
+
|
418
|
+
it do
|
419
|
+
expect {
|
420
|
+
subject.set_param(name,value)
|
421
|
+
}.to raise_error(Ronin::Core::Params::UnknownParam,"unknown param: #{name.inspect}")
|
422
|
+
end
|
423
|
+
end
|
424
|
+
|
425
|
+
context "but the param value does not match the param's type" do
|
426
|
+
let(:valie) { '42' }
|
427
|
+
|
428
|
+
it "must coerce the value using the param's type" do
|
429
|
+
subject.set_param(name,value)
|
430
|
+
|
431
|
+
expect(subject.params[name]).to eq(value.to_i)
|
432
|
+
end
|
433
|
+
|
434
|
+
context "but the values cannot be coerced" do
|
435
|
+
let(:value) { "XYZ" }
|
436
|
+
|
437
|
+
it do
|
438
|
+
expect {
|
439
|
+
subject.set_param(name,value)
|
440
|
+
}.to raise_error(Ronin::Core::Params::ValidationError,"invalid param value for param '#{name}': value contains non-numeric characters (#{value.inspect})")
|
441
|
+
end
|
442
|
+
end
|
443
|
+
end
|
444
|
+
end
|
445
|
+
|
446
|
+
describe "#validate_params" do
|
447
|
+
context "when there are required params defined" do
|
448
|
+
let(:test_class) { TestParamsMixin::ParamWithRequired }
|
449
|
+
let(:required_param) { :foo }
|
450
|
+
|
451
|
+
context "and one of them is not set in #params" do
|
452
|
+
it do
|
453
|
+
expect {
|
454
|
+
subject.validate_params
|
455
|
+
}.to raise_error(Ronin::Core::Params::ValidationError,"param '#{required_param}' requires a value")
|
456
|
+
end
|
457
|
+
end
|
458
|
+
|
459
|
+
context "and one of them is set to nil in #params" do
|
460
|
+
before { subject.params[required_param] = nil }
|
461
|
+
|
462
|
+
it do
|
463
|
+
expect {
|
464
|
+
subject.validate_params
|
465
|
+
}.to raise_error(Ronin::Core::Params::ValidationError,"param '#{required_param}' requires a value")
|
466
|
+
end
|
467
|
+
end
|
468
|
+
|
469
|
+
context "and it has a non-nil value" do
|
470
|
+
before { subject.params[required_param] = 42 }
|
471
|
+
|
472
|
+
it "must return true" do
|
473
|
+
expect(subject.validate_params).to be(true)
|
474
|
+
end
|
475
|
+
end
|
476
|
+
end
|
477
|
+
|
478
|
+
context "when there are no required params defined" do
|
479
|
+
it "must return true" do
|
480
|
+
expect(subject.validate_params).to be(true)
|
481
|
+
end
|
482
|
+
end
|
483
|
+
end
|
484
|
+
end
|
@@ -0,0 +1,164 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'ronin/core/params/param'
|
3
|
+
require 'ronin/core/params/types/integer'
|
4
|
+
|
5
|
+
describe Ronin::Core::Params::Param do
|
6
|
+
let(:name) { :foo }
|
7
|
+
let(:type) { Ronin::Core::Params::Types::Integer.new }
|
8
|
+
let(:desc) { "Foo param" }
|
9
|
+
|
10
|
+
subject { described_class.new(name,type, desc: desc) }
|
11
|
+
|
12
|
+
describe "#initialize" do
|
13
|
+
it "must set #name" do
|
14
|
+
expect(subject.name).to eq(name)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "must set #type" do
|
18
|
+
expect(subject.type).to eq(type)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "must set #desc" do
|
22
|
+
expect(subject.desc).to eq(desc)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "must require the desc: keyword argument" do
|
26
|
+
expect {
|
27
|
+
described_class.new(name,type)
|
28
|
+
}.to raise_error(ArgumentError)
|
29
|
+
end
|
30
|
+
|
31
|
+
it "must default #required to false" do
|
32
|
+
expect(subject.required).to be(false)
|
33
|
+
end
|
34
|
+
|
35
|
+
it "must default #default to nil" do
|
36
|
+
expect(subject.default).to be(nil)
|
37
|
+
end
|
38
|
+
|
39
|
+
context "when given the required: keyword argument" do
|
40
|
+
subject { described_class.new(name,type, required: true, desc: desc) }
|
41
|
+
|
42
|
+
it "must set #required" do
|
43
|
+
expect(subject.required).to be(true)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context "when given the default: keyword argument" do
|
48
|
+
let(:default) { 42 }
|
49
|
+
|
50
|
+
subject { described_class.new(name,type, default: default, desc: desc) }
|
51
|
+
|
52
|
+
it "must set #default" do
|
53
|
+
expect(subject.default).to eq(default)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe "#required?" do
|
59
|
+
context "when initialized with no required: keyword argument" do
|
60
|
+
subject { described_class.new(name,type, desc: desc) }
|
61
|
+
|
62
|
+
it "must return false" do
|
63
|
+
expect(subject.required?).to be(false)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
context "when initialized with required: true" do
|
68
|
+
subject { described_class.new(name,type, required: true, desc: desc) }
|
69
|
+
|
70
|
+
it "must return true" do
|
71
|
+
expect(subject.required?).to be(true)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
context "when initialized with required: false" do
|
76
|
+
subject { described_class.new(name,type, required: false, desc: desc) }
|
77
|
+
|
78
|
+
it "must return false" do
|
79
|
+
expect(subject.required?).to be(false)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
describe "#has_default?" do
|
85
|
+
context "when initialized with no default: keyword argument" do
|
86
|
+
subject { described_class.new(name,type, desc: desc) }
|
87
|
+
|
88
|
+
it "must return false" do
|
89
|
+
expect(subject.has_default?).to be(false)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
context "when initialized with the default: keyword argument" do
|
94
|
+
subject { described_class.new(name,type, default: 42, desc: desc) }
|
95
|
+
|
96
|
+
it "must return true" do
|
97
|
+
expect(subject.has_default?).to be(true)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
describe "#default_value" do
|
103
|
+
context "when initialized with no default: keyword argument" do
|
104
|
+
subject { described_class.new(name,type, desc: desc) }
|
105
|
+
|
106
|
+
it "must return nil" do
|
107
|
+
expect(subject.default_value).to be(nil)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
context "when initialized with the default: keyword argument" do
|
112
|
+
context "and it's an Object" do
|
113
|
+
let(:default) { 'value' }
|
114
|
+
|
115
|
+
subject { described_class.new(name,type, default: default, desc: desc) }
|
116
|
+
|
117
|
+
it "must return a new copy of the default value" do
|
118
|
+
expect(subject.default_value).to eq(default)
|
119
|
+
expect(subject.default_value).to_not be(default)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
context "and it's a Proc" do
|
124
|
+
let(:default) do
|
125
|
+
proc { "value" }
|
126
|
+
end
|
127
|
+
|
128
|
+
subject { described_class.new(name,type, default: default, desc: desc) }
|
129
|
+
|
130
|
+
it "must call the Proc and return the value" do
|
131
|
+
expect(subject.default_value).to eq(default.call)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
describe "#coerce" do
|
138
|
+
let(:value) { '42' }
|
139
|
+
|
140
|
+
context "when given nil" do
|
141
|
+
context "and when initialize with required: true" do
|
142
|
+
subject { described_class.new(name,type, required: true, desc: desc) }
|
143
|
+
|
144
|
+
it do
|
145
|
+
expect {
|
146
|
+
subject.coerce(nil)
|
147
|
+
}.to raise_error(Ronin::Core::Params::ValidationError,"param requires a non-nil value")
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
context "and when is not initialize with required: true" do
|
152
|
+
it "must return nil" do
|
153
|
+
expect(subject.coerce(nil)).to be(nil)
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
context "when given a non-nil value" do
|
159
|
+
it "must coerce the value using #type" do
|
160
|
+
expect(subject.coerce(value)).to eq(type.coerce(value))
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'ronin/core/params/types/boolean'
|
3
|
+
|
4
|
+
describe Ronin::Core::Params::Types::Boolean do
|
5
|
+
describe "#coerce" do
|
6
|
+
context "when given true" do
|
7
|
+
it "must return true" do
|
8
|
+
expect(subject.coerce(true)).to be(true)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
context "when given false" do
|
13
|
+
it "must return false" do
|
14
|
+
expect(subject.coerce(false)).to be(false)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
context "when given a String" do
|
19
|
+
%w[true True TRUE yes Yes YES y Y on On ON].each do |value|
|
20
|
+
context "and it's #{value.inspect}" do
|
21
|
+
it "must return true" do
|
22
|
+
expect(subject.coerce(value)).to be(true)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
%w[false False FALSE no No NO n N off Off OFF].each do |value|
|
28
|
+
context "and it's #{value.inspect}" do
|
29
|
+
it "must return false" do
|
30
|
+
expect(subject.coerce(value)).to be(false)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context "when given an unrecognized String" do
|
36
|
+
let(:value) { "foo" }
|
37
|
+
|
38
|
+
it do
|
39
|
+
expect {
|
40
|
+
subject.coerce(value)
|
41
|
+
}.to raise_error(Ronin::Core::Params::ValidationError,"value must be either 'true', 'false', 'yes', 'no', 'y', 'n', 'on', or 'off' (#{value.inspect})")
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
context "when given a non-Boolean and non-String object" do
|
47
|
+
let(:value) { Object.new }
|
48
|
+
|
49
|
+
it do
|
50
|
+
expect {
|
51
|
+
subject.coerce(value)
|
52
|
+
}.to raise_error(Ronin::Core::Params::ValidationError,"value must be either true, false, or a String (#{value.inspect})")
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|