ronin-core 0.1.0.beta1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +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
|