ronin-core 0.1.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (109) hide show
  1. checksums.yaml +7 -0
  2. data/.document +5 -0
  3. data/.github/workflows/ruby.yml +41 -0
  4. data/.gitignore +12 -0
  5. data/.rspec +1 -0
  6. data/.rubocop.yml +160 -0
  7. data/.ruby-version +1 -0
  8. data/.yardopts +1 -0
  9. data/COPYING.txt +165 -0
  10. data/ChangeLog.md +11 -0
  11. data/Gemfile +30 -0
  12. data/README.md +299 -0
  13. data/Rakefile +34 -0
  14. data/examples/ruby_shell.rb +11 -0
  15. data/gemspec.yml +28 -0
  16. data/lib/ronin/core/class_registry.rb +246 -0
  17. data/lib/ronin/core/cli/command.rb +87 -0
  18. data/lib/ronin/core/cli/command_shell/command.rb +110 -0
  19. data/lib/ronin/core/cli/command_shell.rb +345 -0
  20. data/lib/ronin/core/cli/generator/options/author.rb +106 -0
  21. data/lib/ronin/core/cli/generator/options/description.rb +54 -0
  22. data/lib/ronin/core/cli/generator/options/reference.rb +60 -0
  23. data/lib/ronin/core/cli/generator/options/summary.rb +54 -0
  24. data/lib/ronin/core/cli/generator.rb +238 -0
  25. data/lib/ronin/core/cli/logging.rb +59 -0
  26. data/lib/ronin/core/cli/options/param.rb +68 -0
  27. data/lib/ronin/core/cli/options/values/arches.rb +45 -0
  28. data/lib/ronin/core/cli/options/values/oses.rb +32 -0
  29. data/lib/ronin/core/cli/printing/arch.rb +71 -0
  30. data/lib/ronin/core/cli/printing/metadata.rb +113 -0
  31. data/lib/ronin/core/cli/printing/os.rb +54 -0
  32. data/lib/ronin/core/cli/printing/params.rb +69 -0
  33. data/lib/ronin/core/cli/ruby_shell.rb +131 -0
  34. data/lib/ronin/core/cli/shell.rb +186 -0
  35. data/lib/ronin/core/git.rb +73 -0
  36. data/lib/ronin/core/home.rb +86 -0
  37. data/lib/ronin/core/metadata/authors/author.rb +241 -0
  38. data/lib/ronin/core/metadata/authors.rb +120 -0
  39. data/lib/ronin/core/metadata/description.rb +100 -0
  40. data/lib/ronin/core/metadata/id.rb +88 -0
  41. data/lib/ronin/core/metadata/references.rb +87 -0
  42. data/lib/ronin/core/metadata/summary.rb +78 -0
  43. data/lib/ronin/core/metadata/version.rb +74 -0
  44. data/lib/ronin/core/params/exceptions.rb +38 -0
  45. data/lib/ronin/core/params/mixin.rb +317 -0
  46. data/lib/ronin/core/params/param.rb +137 -0
  47. data/lib/ronin/core/params/types/boolean.rb +64 -0
  48. data/lib/ronin/core/params/types/enum.rb +107 -0
  49. data/lib/ronin/core/params/types/float.rb +68 -0
  50. data/lib/ronin/core/params/types/integer.rb +100 -0
  51. data/lib/ronin/core/params/types/numeric.rb +106 -0
  52. data/lib/ronin/core/params/types/regexp.rb +67 -0
  53. data/lib/ronin/core/params/types/string.rb +118 -0
  54. data/lib/ronin/core/params/types/type.rb +54 -0
  55. data/lib/ronin/core/params/types/uri.rb +72 -0
  56. data/lib/ronin/core/params/types.rb +62 -0
  57. data/lib/ronin/core/params.rb +19 -0
  58. data/lib/ronin/core/version.rb +24 -0
  59. data/ronin-core.gemspec +59 -0
  60. data/spec/class_registry_spec.rb +224 -0
  61. data/spec/cli/command_shell/command_spec.rb +113 -0
  62. data/spec/cli/command_shell_spec.rb +1114 -0
  63. data/spec/cli/command_spec.rb +16 -0
  64. data/spec/cli/fixtures/irb_command +8 -0
  65. data/spec/cli/fixtures/template/dir/file1.txt +1 -0
  66. data/spec/cli/fixtures/template/dir/file2.txt +1 -0
  67. data/spec/cli/fixtures/template/file.erb +1 -0
  68. data/spec/cli/fixtures/template/file.txt +1 -0
  69. data/spec/cli/generator/options/author_spec.rb +121 -0
  70. data/spec/cli/generator/options/description_spec.rb +45 -0
  71. data/spec/cli/generator/options/reference_spec.rb +53 -0
  72. data/spec/cli/generator/options/summary_spec.rb +45 -0
  73. data/spec/cli/generator_spec.rb +244 -0
  74. data/spec/cli/logging_spec.rb +95 -0
  75. data/spec/cli/options/param_spec.rb +67 -0
  76. data/spec/cli/options/values/arches_spec.rb +62 -0
  77. data/spec/cli/printing/arch_spec.rb +130 -0
  78. data/spec/cli/printing/metadata_spec.rb +211 -0
  79. data/spec/cli/printing/os_spec.rb +64 -0
  80. data/spec/cli/printing/params_spec.rb +63 -0
  81. data/spec/cli/ruby_shell.rb +99 -0
  82. data/spec/cli/shell_spec.rb +211 -0
  83. data/spec/fixtures/example_class_registry/base_class.rb +9 -0
  84. data/spec/fixtures/example_class_registry/classes/loaded_class.rb +9 -0
  85. data/spec/fixtures/example_class_registry/classes/name_mismatch.rb +9 -0
  86. data/spec/fixtures/example_class_registry/classes/no_module.rb +4 -0
  87. data/spec/fixtures/example_class_registry.rb +8 -0
  88. data/spec/git_spec.rb +58 -0
  89. data/spec/home_spec.rb +64 -0
  90. data/spec/metadata/authors/author_spec.rb +335 -0
  91. data/spec/metadata/authors_spec.rb +126 -0
  92. data/spec/metadata/description_spec.rb +74 -0
  93. data/spec/metadata/id_spec.rb +92 -0
  94. data/spec/metadata/references_spec.rb +100 -0
  95. data/spec/metadata/summary_spec.rb +74 -0
  96. data/spec/metadata/version_spec.rb +72 -0
  97. data/spec/params/mixin_spec.rb +484 -0
  98. data/spec/params/param_spec.rb +164 -0
  99. data/spec/params/types/boolean_spec.rb +56 -0
  100. data/spec/params/types/enum_spec.rb +94 -0
  101. data/spec/params/types/float_spec.rb +107 -0
  102. data/spec/params/types/integer_spec.rb +155 -0
  103. data/spec/params/types/numeric_spec.rb +138 -0
  104. data/spec/params/types/regexp_spec.rb +64 -0
  105. data/spec/params/types/string_spec.rb +174 -0
  106. data/spec/params/types/type_spec.rb +14 -0
  107. data/spec/params/types/uri_spec.rb +62 -0
  108. data/spec/spec_helper.rb +11 -0
  109. metadata +252 -0
@@ -0,0 +1,94 @@
1
+ require 'spec_helper'
2
+ require 'ronin/core/params/types/enum'
3
+
4
+ describe Ronin::Core::Params::Types::Enum do
5
+ let(:values) { [:one, :two, :three] }
6
+
7
+ subject { described_class.new(values) }
8
+
9
+ describe "#initialize" do
10
+ it "must set #values" do
11
+ expect(subject.values).to eq(values)
12
+ end
13
+
14
+ context "when given an empty Array" do
15
+ it do
16
+ expect {
17
+ described_class.new([])
18
+ }.to raise_error(ArgumentError,"cannot initialize an empty Enum")
19
+ end
20
+ end
21
+ end
22
+
23
+ describe ".[]" do
24
+ subject { described_class[*values] }
25
+
26
+ it "must return a new #{described_class}" do
27
+ expect(subject).to be_kind_of(described_class)
28
+ end
29
+
30
+ it "must set #values to the given arguments" do
31
+ expect(subject.values).to eq(values)
32
+ end
33
+
34
+ context "when given no arguments" do
35
+ it do
36
+ expect {
37
+ described_class[]
38
+ }.to raise_error(ArgumentError,"cannot initialize an empty Enum")
39
+ end
40
+ end
41
+ end
42
+
43
+ describe "#coerce" do
44
+ context "when givne a Symbol" do
45
+ context "and when the Symbol is in #values" do
46
+ let(:value) { values[1] }
47
+
48
+ it "must return that Symbol" do
49
+ expect(subject.coerce(value)).to eq(value)
50
+ end
51
+ end
52
+
53
+ context "but the Symbol is not within #values" do
54
+ let(:value) { :foo }
55
+
56
+ it do
57
+ expect {
58
+ subject.coerce(value)
59
+ }.to raise_error(Ronin::Core::Params::ValidationError,"unknown value (#{value.inspect})")
60
+ end
61
+ end
62
+ end
63
+
64
+ context "when given a String" do
65
+ context "and it maps to one of the Symbols in #values" do
66
+ let(:value) { values[1].to_s }
67
+
68
+ it "must return the Symbol version of the String" do
69
+ expect(subject.coerce(value)).to eq(values[1])
70
+ end
71
+ end
72
+
73
+ context "but it does not map to any of the Symbols in #values" do
74
+ let(:value) { "foo" }
75
+
76
+ it "must return the Symbol version of the String" do
77
+ expect {
78
+ subject.coerce(value)
79
+ }.to raise_error(Ronin::Core::Params::ValidationError,"unknown value (#{value.inspect})")
80
+ end
81
+ end
82
+ end
83
+
84
+ context "when given a non-Symbol and non-String object" do
85
+ let(:value) { Object.new }
86
+
87
+ it do
88
+ expect {
89
+ subject.coerce(value)
90
+ }.to raise_error(Ronin::Core::Params::ValidationError,"value must be either a Symbol or a String (#{value.inspect})")
91
+ end
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,107 @@
1
+ require 'spec_helper'
2
+ require 'ronin/core/params/types/float'
3
+
4
+ describe Ronin::Core::Params::Types::Float do
5
+ describe "#coerce" do
6
+ context "when given a Float" do
7
+ let(:value) { 0.5 }
8
+
9
+ it "must return the Float value" do
10
+ expect(subject.coerce(value)).to be(value)
11
+ end
12
+ end
13
+
14
+ context "when given a String" do
15
+ context "and it is in the format of a decimal number" do
16
+ let(:value) { '0.5' }
17
+
18
+ it "must parse the String as a Float" do
19
+ expect(subject.coerce(value)).to eq(value.to_f)
20
+ end
21
+
22
+ context "but it starts with a '+'" do
23
+ let(:value) { '+0.5' }
24
+
25
+ it "must parse the String as a Float" do
26
+ expect(subject.coerce(value)).to eq(value[1..].to_f)
27
+ end
28
+ end
29
+
30
+ context "but it starts with a '-'" do
31
+ let(:value) { '-0.5' }
32
+
33
+ it "must parse the String as a negative Float" do
34
+ expect(subject.coerce(value)).to eq(-value[1..].to_f)
35
+ end
36
+ end
37
+ end
38
+
39
+ context "and it is in the fomrat of a whole number" do
40
+ let(:value) { '1' }
41
+
42
+ it "must parse the String as a Float" do
43
+ expect(subject.coerce(value)).to eq(value.to_f)
44
+ end
45
+
46
+ context "but it starts with a '+'" do
47
+ let(:value) { '+1' }
48
+
49
+ it "must parse the String as a Float" do
50
+ expect(subject.coerce(value)).to eq(value[1..].to_f)
51
+ end
52
+ end
53
+
54
+ context "but it starts with a '-'" do
55
+ let(:value) { '-1' }
56
+
57
+ it "must parse the String as a negative Float" do
58
+ expect(subject.coerce(value)).to eq(-value[1..].to_f)
59
+ end
60
+ end
61
+ end
62
+
63
+ context "but it contains non-numeric characters" do
64
+ let(:value) { "foo" }
65
+
66
+ it do
67
+ expect {
68
+ subject.coerce(value)
69
+ }.to raise_error(Ronin::Core::Params::ValidationError,"value contains non-numeric characters (#{value.inspect})")
70
+ end
71
+ end
72
+ end
73
+
74
+ context "when given a non-Float and non-String object" do
75
+ context "and it defines a #to_f method" do
76
+ module TestTypesFloat
77
+ class ObjectWithToF
78
+ def to_f
79
+ 0.5
80
+ end
81
+ end
82
+ end
83
+
84
+ let(:value) { TestTypesFloat::ObjectWithToF.new }
85
+
86
+ it "must call the #to_f method on the value" do
87
+ expect(subject.coerce(value)).to eq(value.to_f)
88
+ end
89
+ end
90
+
91
+ context "but it does not define a #to_f method" do
92
+ module TestTypesFloat
93
+ class ObjectWithoutToF
94
+ end
95
+ end
96
+
97
+ let(:value) { TestTypesFloat::ObjectWithoutToF.new }
98
+
99
+ it do
100
+ expect {
101
+ subject.coerce(value)
102
+ }.to raise_error(Ronin::Core::Params::ValidationError,"value does not define a #to_f method (#{value.inspect})")
103
+ end
104
+ end
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,155 @@
1
+ require 'spec_helper'
2
+ require 'ronin/core/params/types/integer'
3
+
4
+ describe Ronin::Core::Params::Types::Integer do
5
+ describe "#coerce" do
6
+ context "when given an Integer" do
7
+ let(:value) { 42 }
8
+
9
+ it "must return the Integer value" do
10
+ expect(subject.coerce(value)).to eq(value)
11
+ end
12
+ end
13
+
14
+ context "when given a String" do
15
+ context "and the String contains decimal digits" do
16
+ let(:value) { "42" }
17
+
18
+ it "must parse the String as base 10 and return an Integer" do
19
+ expect(subject.coerce(value)).to eq(value.to_i)
20
+ end
21
+
22
+ context "and the String also starts with a '+'" do
23
+ let(:value) { "+42" }
24
+
25
+ it "must parse the String as base 10 and return an Integer" do
26
+ expect(subject.coerce(value)).to eq(value.to_i)
27
+ end
28
+ end
29
+
30
+ context "and the String also starts with a '-'" do
31
+ let(:value) { "-42" }
32
+
33
+ it "must parse the String as base 10 and return a negative Integer" do
34
+ expect(subject.coerce(value)).to eq(-value[1..].to_i)
35
+ end
36
+ end
37
+ end
38
+
39
+ context "and the String contains hexadecimal digits" do
40
+ let(:value) { "ff" }
41
+
42
+ it "must parse the String as base 16 and return an Integer" do
43
+ expect(subject.coerce(value)).to eq(value.to_i(16))
44
+ end
45
+
46
+ context "and the String also starts with a '+'" do
47
+ let(:value) { "+ff" }
48
+
49
+ it "must parse the String as base 16 and return an Integer" do
50
+ expect(subject.coerce(value)).to eq(value.to_i(16))
51
+ end
52
+ end
53
+
54
+ context "and the String also starts with a '-'" do
55
+ let(:value) { "-ff" }
56
+
57
+ it "must parse the String as base 16 and return a negative Integer" do
58
+ expect(subject.coerce(value)).to eq(-value[1..].to_i(16))
59
+ end
60
+ end
61
+
62
+ context "but the String also starts with '0x'" do
63
+ let(:value) { "0xff" }
64
+
65
+ it "must remove the leading '0x' before parsing the String" do
66
+ expect(subject.coerce(value)).to eq(value[2..].to_i(16))
67
+ end
68
+
69
+ context "and the String also starts with a '+'" do
70
+ let(:value) { "+0xff" }
71
+
72
+ it "must parse the String as base 16 and return a Integer" do
73
+ expect(subject.coerce(value)).to eq(value[3..].to_i(16))
74
+ end
75
+ end
76
+
77
+ context "and the String also starts with a '-'" do
78
+ let(:value) { "-0xff" }
79
+
80
+ it "must parse the String as base 16 and return a negative Integer" do
81
+ expect(subject.coerce(value)).to eq(-value[3..].to_i(16))
82
+ end
83
+ end
84
+ end
85
+ end
86
+
87
+ context "and the String starts with '0b' and only contains chars 0 and 1" do
88
+ let(:value) { "0b111" }
89
+
90
+ it "must parse the String as binary and return an Integer" do
91
+ expect(subject.coerce(value)).to eq(value[2..].to_i(2))
92
+ end
93
+
94
+ context "and the String also starts with a '+'" do
95
+ let(:value) { "+0b111" }
96
+
97
+ it "must parse the String as base 16 and return a Integer" do
98
+ expect(subject.coerce(value)).to eq(value[3..].to_i(2))
99
+ end
100
+ end
101
+
102
+ context "and the String also starts with a '-'" do
103
+ let(:value) { "-0b111" }
104
+
105
+ it "must parse the String as base 16 and return a negative Integer" do
106
+ expect(subject.coerce(value)).to eq(-value[3..].to_i(2))
107
+ end
108
+ end
109
+ end
110
+
111
+ context "but the String contains non-numeric characters" do
112
+ let(:value) { "bar" }
113
+
114
+ it do
115
+ expect {
116
+ subject.coerce(value)
117
+ }.to raise_error(Ronin::Core::Params::ValidationError,"value contains non-numeric characters (#{value.inspect})")
118
+ end
119
+ end
120
+ end
121
+
122
+ context "when given a non-Integer and non-String Object" do
123
+ context "and it defines a #to_i method" do
124
+ module TestTypesInteger
125
+ class ObjectWithToI
126
+ def to_i
127
+ 42
128
+ end
129
+ end
130
+ end
131
+
132
+ let(:value) { TestTypesInteger::ObjectWithToI.new }
133
+
134
+ it "must call #to_i on the given value" do
135
+ expect(subject.coerce(value)).to eq(value.to_i)
136
+ end
137
+ end
138
+
139
+ context "but it does not define a #to_i method" do
140
+ module TestTypesInteger
141
+ class ObjectWithoutToI
142
+ end
143
+ end
144
+
145
+ let(:value) { TestTypesInteger::ObjectWithoutToI.new }
146
+
147
+ it do
148
+ expect {
149
+ subject.coerce(value)
150
+ }.to raise_error(Ronin::Core::Params::ValidationError,"value does not define a #to_i method (#{value.inspect})")
151
+ end
152
+ end
153
+ end
154
+ end
155
+ end
@@ -0,0 +1,138 @@
1
+ require 'spec_helper'
2
+ require 'ronin/core/params/types/numeric'
3
+
4
+ describe Ronin::Core::Params::Types::Numeric do
5
+ describe "#initialize" do
6
+ it "must default #min to nil" do
7
+ expect(subject.min).to be(nil)
8
+ end
9
+
10
+ it "must default #max to nil" do
11
+ expect(subject.max).to be(nil)
12
+ end
13
+
14
+ it "must default #range to nil" do
15
+ expect(subject.range).to be(nil)
16
+ end
17
+
18
+ context "when given the min: keyword argument" do
19
+ let(:min) { 42 }
20
+
21
+ subject { described_class.new(min: min) }
22
+
23
+ it "must set #min" do
24
+ expect(subject.min).to eq(min)
25
+ end
26
+ end
27
+
28
+ context "when given the max: keyword argument" do
29
+ let(:max) { 42 }
30
+
31
+ subject { described_class.new(max: max) }
32
+
33
+ it "must set #max" do
34
+ expect(subject.max).to eq(max)
35
+ end
36
+ end
37
+
38
+ context "when given the range: keyword argument" do
39
+ let(:range) { 1..42 }
40
+
41
+ subject { described_class.new(range: range) }
42
+
43
+ it "must set #range" do
44
+ expect(subject.range).to eq(range)
45
+ end
46
+ end
47
+ end
48
+
49
+ describe "#coerce" do
50
+ context "when #range is set" do
51
+ let(:range) { 1..10 }
52
+
53
+ subject { described_class.new(range: range) }
54
+
55
+ context "and when the given number is within the range" do
56
+ let(:value) { 5 }
57
+
58
+ it "must return the number" do
59
+ expect(subject.coerce(value)).to eq(value)
60
+ end
61
+ end
62
+
63
+ context "but the given number is not within the range" do
64
+ let(:value) { 20 }
65
+
66
+ it do
67
+ expect {
68
+ subject.coerce(value)
69
+ }.to raise_error(Ronin::Core::Params::ValidationError,"value is not within the range of acceptable values #{range.begin}-#{range.end} (#{value.inspect})")
70
+ end
71
+ end
72
+ end
73
+
74
+ context "when #min is set" do
75
+ let(:min) { 10 }
76
+
77
+ subject { described_class.new(min: min) }
78
+
79
+ context "and when then value is above the #min value" do
80
+ let(:value) { 20 }
81
+
82
+ it "must return the value" do
83
+ expect(subject.coerce(value)).to eq(value)
84
+ end
85
+ end
86
+
87
+ context "and when then value is equal to the #min value" do
88
+ let(:value) { min }
89
+
90
+ it "must return the value" do
91
+ expect(subject.coerce(value)).to eq(value)
92
+ end
93
+ end
94
+
95
+ context "but when the value is below the #min value" do
96
+ let(:value) { 5 }
97
+
98
+ it do
99
+ expect {
100
+ subject.coerce(value)
101
+ }.to raise_error(Ronin::Core::Params::ValidationError,"value is below minimum value of #{min} (#{value.inspect})")
102
+ end
103
+ end
104
+ end
105
+
106
+ context "when #max is set" do
107
+ let(:max) { 10 }
108
+
109
+ subject { described_class.new(max: max) }
110
+
111
+ context "and when then value is below the #max value" do
112
+ let(:value) { 5 }
113
+
114
+ it "must return the value" do
115
+ expect(subject.coerce(value)).to eq(value)
116
+ end
117
+ end
118
+
119
+ context "and when then value is equal to the #max value" do
120
+ let(:value) { max }
121
+
122
+ it "must return the value" do
123
+ expect(subject.coerce(value)).to eq(value)
124
+ end
125
+ end
126
+
127
+ context "but when the value is above the #max value" do
128
+ let(:value) { 20 }
129
+
130
+ it do
131
+ expect {
132
+ subject.coerce(value)
133
+ }.to raise_error(Ronin::Core::Params::ValidationError,"value is above maximum value of #{max} (#{value.inspect})")
134
+ end
135
+ end
136
+ end
137
+ end
138
+ end
@@ -0,0 +1,64 @@
1
+ require 'spec_helper'
2
+ require 'ronin/core/params/types/regexp'
3
+
4
+ describe Ronin::Core::Params::Types::Regexp do
5
+ describe "#coerce" do
6
+ context "when given a Regexp value" do
7
+ let(:value) { /foo/ }
8
+
9
+ it "must return the Regexp" do
10
+ expect(subject.coerce(value)).to eq(value)
11
+ end
12
+ end
13
+
14
+ context "when given a String value" do
15
+ context "and the String is of the format '/.../'" do
16
+ let(:value) { "/foo/" }
17
+
18
+ it "must parse the contents of the String as a Regexp" do
19
+ expect(subject.coerce(value)).to eq(Regexp.new(value[1..-2]))
20
+ end
21
+ end
22
+
23
+ context "but the String does not parse to a valid Regexp" do
24
+ let(:value) { "/foo[/" }
25
+
26
+ it do
27
+ expect {
28
+ subject.coerce(value)
29
+ }.to raise_error(Ronin::Core::Params::ValidationError,"value is not a valid Regexp (#{value.inspect})")
30
+ end
31
+ end
32
+
33
+ context "but the String does not start with a '/' character" do
34
+ let(:value) { "foo/" }
35
+
36
+ it do
37
+ expect {
38
+ subject.coerce(value)
39
+ }.to raise_error(Ronin::Core::Params::ValidationError,"value must be of the format '/.../' (#{value.inspect})")
40
+ end
41
+ end
42
+
43
+ context "but the String does not end with a '/' character" do
44
+ let(:value) { "/foo" }
45
+
46
+ it do
47
+ expect {
48
+ subject.coerce(value)
49
+ }.to raise_error(Ronin::Core::Params::ValidationError,"value must be of the format '/.../' (#{value.inspect})")
50
+ end
51
+ end
52
+ end
53
+
54
+ context "when given a non-Regexp and non-String value" do
55
+ let(:value) { Object.new }
56
+
57
+ it do
58
+ expect {
59
+ subject.coerce(value)
60
+ }.to raise_error(Ronin::Core::Params::ValidationError,"value must be either a String or a Regexp (#{value.inspect})")
61
+ end
62
+ end
63
+ end
64
+ end