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,67 @@
1
+ require 'spec_helper'
2
+ require 'ronin/core/cli/options/param'
3
+ require 'ronin/core/cli/command'
4
+
5
+ describe Ronin::Core::CLI::Options::Param do
6
+ module TestParamOption
7
+ class TestCommand < Ronin::Core::CLI::Command
8
+ include Ronin::Core::CLI::Options::Param
9
+ end
10
+ end
11
+
12
+ let(:command_class) { TestParamOption::TestCommand }
13
+
14
+ describe ".included" do
15
+ subject { command_class }
16
+
17
+ it "must add a -p,--param option to the options" do
18
+ expect(subject.options[:param]).to_not be_nil
19
+ expect(subject.options[:param].value?).to be(true)
20
+ expect(subject.options[:param].value.type).to be_kind_of(Regexp)
21
+ expect(subject.options[:param].value.usage).to eq('NAME=VALUE')
22
+ expect(subject.options[:param].desc).to eq('Sets a param')
23
+ end
24
+ end
25
+
26
+ subject { command_class.new }
27
+
28
+ describe "#initialize" do
29
+ it "must set #params to an empty Hash" do
30
+ expect(subject.params).to eq({})
31
+ end
32
+ end
33
+
34
+ describe "options" do
35
+ context "when given --param foo=bar" do
36
+ before { subject.option_parser.parse(%w[--param foo=bar]) }
37
+
38
+ it "must set the :foo key to 'bar' in #params" do
39
+ expect(subject.params[:foo]).to eq('bar')
40
+ end
41
+ end
42
+
43
+ context "when given --param foo=" do
44
+ it do
45
+ expect {
46
+ subject.option_parser.parse(%w[--param foo=])
47
+ }.to raise_error(OptionParser::InvalidArgument)
48
+ end
49
+ end
50
+
51
+ context "when given --param =bar" do
52
+ it do
53
+ expect {
54
+ subject.option_parser.parse(%w[--param =bar])
55
+ }.to raise_error(OptionParser::InvalidArgument)
56
+ end
57
+ end
58
+
59
+ context "when given --param =" do
60
+ it do
61
+ expect {
62
+ subject.option_parser.parse(%w[--param =])
63
+ }.to raise_error(OptionParser::InvalidArgument)
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,62 @@
1
+ require 'spec_helper'
2
+ require 'ronin/core/cli/options/values/arches'
3
+
4
+ describe "Ronin::Core::CLI::Options::Values::ARCHES" do
5
+ subject { Ronin::Core::CLI::Options::Values::ARCHES }
6
+
7
+ it "must map 'x86' to :x86" do
8
+ expect(subject['x86']).to eq(:x86)
9
+ end
10
+
11
+ it "must map 'x86-64' to :x86_64" do
12
+ expect(subject['x86-64']).to eq(:x86_64)
13
+ end
14
+
15
+ it "must map 'amd64' to :x86_64" do
16
+ expect(subject['amd64']).to eq(:x86_64)
17
+ end
18
+
19
+ it "must map 'ia64' to :ia64" do
20
+ expect(subject['ia64']).to eq(:ia64)
21
+ end
22
+
23
+ it "must map 'ppc' to :ppc" do
24
+ expect(subject['ppc']).to eq(:ppc)
25
+ end
26
+
27
+ it "must map 'ppc64' to :ppc64" do
28
+ expect(subject['ppc64']).to eq(:ppc64)
29
+ end
30
+
31
+ it "must map 'arm' to :arm" do
32
+ expect(subject['arm']).to eq(:arm)
33
+ end
34
+
35
+ it "must map 'armbe' to :arm_be" do
36
+ expect(subject['armbe']).to eq(:arm_be)
37
+ end
38
+
39
+ it "must map 'arm64' to :arm64" do
40
+ expect(subject['arm64']).to eq(:arm64)
41
+ end
42
+
43
+ it "must map 'arm64be' to :arm64_be" do
44
+ expect(subject['arm64be']).to eq(:arm64_be)
45
+ end
46
+
47
+ it "must map 'mips' to :mips" do
48
+ expect(subject['mips']).to eq(:mips)
49
+ end
50
+
51
+ it "must map 'mipsle' to :mips_le" do
52
+ expect(subject['mipsle']).to eq(:mips_le)
53
+ end
54
+
55
+ it "must map 'mips64' to :mips64" do
56
+ expect(subject['mips64']).to eq(:mips64)
57
+ end
58
+
59
+ it "must map 'mips64le' to :mips64_le" do
60
+ expect(subject['mips64le']).to eq(:mips64_le)
61
+ end
62
+ end
@@ -0,0 +1,130 @@
1
+ require 'spec_helper'
2
+ require 'ronin/core/cli/printing/arch'
3
+ require 'ronin/core/cli/command'
4
+
5
+ describe Ronin::Core::CLI::Printing::Arch do
6
+ module TestPrintingArch
7
+ class TestCommand < Ronin::Core::CLI::Command
8
+ include Ronin::Core::CLI::Printing::Arch
9
+ end
10
+ end
11
+
12
+ let(:command_class) { TestPrintingArch::TestCommand }
13
+ subject { command_class.new }
14
+
15
+ describe "#arch_name" do
16
+ context "when given :x86" do
17
+ it "must return 'x86'" do
18
+ expect(subject.arch_name(:x86)).to eq('x86')
19
+ end
20
+ end
21
+
22
+ context "when given :x86_64" do
23
+ it "must return 'x86-64'" do
24
+ expect(subject.arch_name(:x86_64)).to eq('x86-64')
25
+ end
26
+ end
27
+
28
+ context "when given :ia64" do
29
+ it "must return 'ia64'" do
30
+ expect(subject.arch_name(:ia64)).to eq('IA64')
31
+ end
32
+ end
33
+
34
+ context "when given :amd64" do
35
+ it "must return 'x86-64'" do
36
+ expect(subject.arch_name(:amd64)).to eq('x86-64')
37
+ end
38
+ end
39
+
40
+ context "when given :ppc" do
41
+ it "must return 'PPC'" do
42
+ expect(subject.arch_name(:ppc)).to eq('PPC')
43
+ end
44
+ end
45
+
46
+ context "when given :ppc64" do
47
+ it "must return 'PPC64'" do
48
+ expect(subject.arch_name(:ppc64)).to eq('PPC64')
49
+ end
50
+ end
51
+
52
+ context "when given :mips" do
53
+ it "must return 'MIPS'" do
54
+ expect(subject.arch_name(:mips)).to eq('MIPS')
55
+ end
56
+ end
57
+
58
+ context "when given :mips_le" do
59
+ it "must return 'MIPS (LE)'" do
60
+ expect(subject.arch_name(:mips_le)).to eq('MIPS (LE)')
61
+ end
62
+ end
63
+
64
+ context "when given :mips_be" do
65
+ it "must return 'MIPS'" do
66
+ expect(subject.arch_name(:mips_be)).to eq('MIPS')
67
+ end
68
+ end
69
+
70
+ context "when given :mips64" do
71
+ it "must return 'MIPS64'" do
72
+ expect(subject.arch_name(:mips64)).to eq('MIPS64')
73
+ end
74
+ end
75
+
76
+ context "when given :mips64_le" do
77
+ it "must return 'MIPS64 (LE)'" do
78
+ expect(subject.arch_name(:mips64_le)).to eq('MIPS64 (LE)')
79
+ end
80
+ end
81
+
82
+ context "when given :mips64_be" do
83
+ it "must return 'MIPS64'" do
84
+ expect(subject.arch_name(:mips64_be)).to eq('MIPS64')
85
+ end
86
+ end
87
+
88
+ context "when given :arm" do
89
+ it "must return 'ARM'" do
90
+ expect(subject.arch_name(:arm)).to eq('ARM')
91
+ end
92
+ end
93
+
94
+ context "when given :arm_le" do
95
+ it "must return 'ARM'" do
96
+ expect(subject.arch_name(:arm_le)).to eq('ARM')
97
+ end
98
+ end
99
+
100
+ context "when given :arm_be" do
101
+ it "must return 'ARM (BE)'" do
102
+ expect(subject.arch_name(:arm_be)).to eq('ARM (BE)')
103
+ end
104
+ end
105
+
106
+ context "when given :arm64" do
107
+ it "must return 'ARM64'" do
108
+ expect(subject.arch_name(:arm64)).to eq('ARM64')
109
+ end
110
+ end
111
+
112
+ context "when given :arm64_le" do
113
+ it "must return 'ARM64'" do
114
+ expect(subject.arch_name(:arm64_le)).to eq('ARM64')
115
+ end
116
+ end
117
+
118
+ context "when given :arm64_be" do
119
+ it "must return 'ARM64 (BE)'" do
120
+ expect(subject.arch_name(:arm64_be)).to eq('ARM64 (BE)')
121
+ end
122
+ end
123
+
124
+ context "when given an unknown architecture" do
125
+ it "must return the String version of the architecture" do
126
+ expect(subject.arch_name(:foo)).to eq('foo')
127
+ end
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,211 @@
1
+ require 'spec_helper'
2
+ require 'ronin/core/cli/printing/metadata'
3
+ require 'ronin/core/cli/command'
4
+ require 'ronin/core/metadata/authors'
5
+ require 'ronin/core/metadata/description'
6
+ require 'ronin/core/metadata/references'
7
+
8
+ describe Ronin::Core::CLI::Printing::Metadata do
9
+ module TestPrintingMetadata
10
+ class TestCommand < Ronin::Core::CLI::Command
11
+ include Ronin::Core::CLI::Printing::Metadata
12
+ end
13
+ end
14
+
15
+ let(:command_class) { TestPrintingMetadata::TestCommand }
16
+ subject { command_class.new }
17
+
18
+ describe ".included" do
19
+ subject { command_class }
20
+
21
+ it "must add a -v,--verbose option" do
22
+ expect(subject.options[:verbose]).to_not be_nil
23
+ end
24
+ end
25
+
26
+ describe "#print_authors" do
27
+ module TestPrintingAuthors
28
+ class WithoutAuthors
29
+ include Ronin::Core::Metadata::Authors
30
+ end
31
+
32
+ class WithAuthors
33
+ include Ronin::Core::Metadata::Authors
34
+
35
+ author 'John Doe', email: 'john.doe@example.com',
36
+ pgp: '0x123456789',
37
+ website: 'https://johndoe.name',
38
+ blog: 'https://johndoe.name/blog',
39
+ github: '@johndoe',
40
+ gitlab: '@johndoe',
41
+ twitter: '@johndoe',
42
+ discord: 'https://discord.gg/1234'
43
+
44
+ author 'John Smith', email: 'john.smith@example.com',
45
+ pgp: '0xABCDEF',
46
+ website: 'https://johnsmith.name',
47
+ blog: 'https://johnsmith.name/blog',
48
+ github: '@john.smith',
49
+ gitlab: '@john.smith',
50
+ twitter: '@john.smith',
51
+ discord: 'https://discord.gg/ABCDEF'
52
+ end
53
+ end
54
+
55
+ context "when the class does not have any authors" do
56
+ let(:klass) { TestPrintingAuthors::WithoutAuthors }
57
+
58
+ it "must not print anything" do
59
+ expect {
60
+ subject.print_authors(klass)
61
+ }.to_not output.to_stdout
62
+ end
63
+ end
64
+
65
+ context "when the class does have authors" do
66
+ let(:klass) { TestPrintingAuthors::WithAuthors }
67
+
68
+ it "must print 'Authors:' and a list of authors" do
69
+ expect {
70
+ subject.print_authors(klass)
71
+ }.to output(
72
+ [
73
+ 'Authors:',
74
+ '',
75
+ " * #{klass.authors[0]}",
76
+ " * #{klass.authors[1]}",
77
+ '',
78
+ ''
79
+ ].join($/)
80
+ ).to_stdout
81
+ end
82
+
83
+ context "when --verbose mode is enabled" do
84
+ before { allow(subject).to receive(:verbose?).and_return(true) }
85
+
86
+ it "must print the authors and any author metadata as indented lists" do
87
+ expect {
88
+ subject.print_authors(klass)
89
+ }.to output(
90
+ [
91
+ 'Authors:',
92
+ '',
93
+ " * #{klass.authors[0]}",
94
+ " * PGP: #{klass.authors[0].pgp}",
95
+ " * Website: #{klass.authors[0].website}",
96
+ " * Blog: #{klass.authors[0].blog}",
97
+ " * GitHub: #{klass.authors[0].github_url}",
98
+ " * GitLab: #{klass.authors[0].gitlab_url}",
99
+ " * Twitter: #{klass.authors[0].twitter_url}",
100
+ " * Discord: #{klass.authors[0].discord}",
101
+ " * #{klass.authors[1]}",
102
+ " * PGP: #{klass.authors[1].pgp}",
103
+ " * Website: #{klass.authors[1].website}",
104
+ " * Blog: #{klass.authors[1].blog}",
105
+ " * GitHub: #{klass.authors[1].github_url}",
106
+ " * GitLab: #{klass.authors[1].gitlab_url}",
107
+ " * Twitter: #{klass.authors[1].twitter_url}",
108
+ " * Discord: #{klass.authors[1].discord}",
109
+ '',
110
+ ''
111
+ ].join($/)
112
+ ).to_stdout
113
+ end
114
+ end
115
+ end
116
+ end
117
+
118
+ describe "#print_description" do
119
+ module TestPrintingDescription
120
+ class WithoutDescription
121
+ include Ronin::Core::Metadata::Description
122
+ end
123
+
124
+ class WithDescription
125
+ include Ronin::Core::Metadata::Description
126
+
127
+ description <<~DESC
128
+ Foo bar baz
129
+
130
+ Qux quux gorge
131
+ DESC
132
+ end
133
+ end
134
+
135
+ context "when the class does not have a description" do
136
+ let(:klass) { TestPrintingDescription::WithoutDescription }
137
+
138
+ it "must not print anything" do
139
+ expect {
140
+ subject.print_description(klass)
141
+ }.to_not output.to_stdout
142
+ end
143
+ end
144
+
145
+ context "when the class does have a description" do
146
+ let(:klass) { TestPrintingDescription::WithDescription }
147
+
148
+ it "must print 'Description:' and the indented description text" do
149
+ expect {
150
+ subject.print_description(klass)
151
+ }.to output(
152
+ [
153
+ 'Description:',
154
+ '',
155
+ " #{klass.description.lines[0].chomp}",
156
+ " #{klass.description.lines[1].chomp}",
157
+ " #{klass.description.lines[2].chomp}",
158
+ '',
159
+ ''
160
+ ].join($/)
161
+ ).to_stdout
162
+ end
163
+ end
164
+ end
165
+
166
+ describe "#print_references" do
167
+ module TestPrintingReferences
168
+ class WithoutReferences
169
+ include Ronin::Core::Metadata::References
170
+ end
171
+
172
+ class WithReferences
173
+ include Ronin::Core::Metadata::References
174
+
175
+ references [
176
+ 'https://example.com/url1',
177
+ 'https://example.com/url2'
178
+ ]
179
+ end
180
+ end
181
+
182
+ context "when the class has no references" do
183
+ let(:klass) { TestPrintingReferences::WithoutReferences }
184
+
185
+ it "must not print anything" do
186
+ expect {
187
+ subject.print_references(klass)
188
+ }.to_not output.to_stdout
189
+ end
190
+ end
191
+
192
+ context "when the class has references" do
193
+ let(:klass) { TestPrintingReferences::WithReferences }
194
+
195
+ it "must print 'References:' and the list of reference URLs" do
196
+ expect {
197
+ subject.print_references(klass)
198
+ }.to output(
199
+ [
200
+ 'References:',
201
+ '',
202
+ " * #{klass.references[0]}",
203
+ " * #{klass.references[1]}",
204
+ '',
205
+ ''
206
+ ].join($/)
207
+ ).to_stdout
208
+ end
209
+ end
210
+ end
211
+ end
@@ -0,0 +1,64 @@
1
+ require 'spec_helper'
2
+ require 'ronin/core/cli/printing/os'
3
+ require 'ronin/core/cli/command'
4
+
5
+ describe Ronin::Core::CLI::Printing::OS do
6
+ module TestPrintingOS
7
+ class TestCommand < Ronin::Core::CLI::Command
8
+ include Ronin::Core::CLI::Printing::OS
9
+ end
10
+ end
11
+
12
+ let(:command_class) { TestPrintingOS::TestCommand }
13
+ subject { command_class.new }
14
+
15
+ describe "#os_name" do
16
+ context "when given :unix" do
17
+ it "must return 'UNIX'" do
18
+ expect(subject.os_name(:unix)).to eq('UNIX')
19
+ end
20
+ end
21
+
22
+ context "when given :bsd" do
23
+ it "must return 'BSD'" do
24
+ expect(subject.os_name(:bsd)).to eq('BSD')
25
+ end
26
+ end
27
+
28
+ context "when given :freebsd" do
29
+ it "must return 'FreeBSD'" do
30
+ expect(subject.os_name(:freebsd)).to eq('FreeBSD')
31
+ end
32
+ end
33
+
34
+ context "when given :openbsd" do
35
+ it "must return 'OpenBSD'" do
36
+ expect(subject.os_name(:openbsd)).to eq('OpenBSD')
37
+ end
38
+ end
39
+
40
+ context "when given :netbsd" do
41
+ it "must return 'NetBSD'" do
42
+ expect(subject.os_name(:netbsd)).to eq('NetBSD')
43
+ end
44
+ end
45
+
46
+ context "when given :linux" do
47
+ it "must return 'Linux'" do
48
+ expect(subject.os_name(:linux)).to eq('Linux')
49
+ end
50
+ end
51
+
52
+ context "when given :macos" do
53
+ it "must return 'macOS'" do
54
+ expect(subject.os_name(:macos)).to eq('macOS')
55
+ end
56
+ end
57
+
58
+ context "when given :windows" do
59
+ it "must return 'Windows'" do
60
+ expect(subject.os_name(:windows)).to eq('Windows')
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,63 @@
1
+ require 'spec_helper'
2
+ require 'ronin/core/cli/printing/params'
3
+ require 'ronin/core/cli/command'
4
+ require 'ronin/core/params/mixin'
5
+
6
+ describe Ronin::Core::CLI::Printing::Params do
7
+ module TestPrintingParams
8
+ class TestClass
9
+
10
+ include Ronin::Core::Params::Mixin
11
+
12
+ param :foo, String, required: true,
13
+ desc: 'Foo param'
14
+ param :bar, Integer, default: 42,
15
+ desc: 'Bar param'
16
+
17
+ end
18
+
19
+ class TestClassWithoutParams
20
+ include Ronin::Core::Params::Mixin
21
+ end
22
+
23
+ class TestCommand < Ronin::Core::CLI::Command
24
+ include Ronin::Core::CLI::Printing::Params
25
+ end
26
+ end
27
+
28
+ let(:test_class) { TestPrintingParams::TestClass }
29
+ let(:test_command) { TestPrintingParams::TestCommand }
30
+ subject { test_command.new }
31
+
32
+ describe "#print_params" do
33
+ context "when the class has defined params" do
34
+ it "must print Params: and the params table" do
35
+ expect {
36
+ subject.print_params(test_class)
37
+ }.to output(
38
+ [
39
+ "Params:",
40
+ "",
41
+ " ┌──────┬─────────┬──────────┬─────────┬─────────────┐",
42
+ " │ Name │ Type │ Required │ Default │ Description │",
43
+ " ├──────┼─────────┼──────────┼─────────┼─────────────┤",
44
+ " │ foo │ String │ Yes │ │ Foo param │",
45
+ " │ bar │ Integer │ No │ 42 │ Bar param │",
46
+ " └──────┴─────────┴──────────┴─────────┴─────────────┘",
47
+ ""
48
+ ].join($/)
49
+ ).to_stdout
50
+ end
51
+ end
52
+
53
+ context "when the class does not have any defined params" do
54
+ let(:test_class) { TestPrintingParams::TestClassWithoutParams }
55
+
56
+ it "must not print anything" do
57
+ expect {
58
+ subject.print_params(test_class)
59
+ }.to_not output.to_stdout
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,99 @@
1
+ require 'spec_helper'
2
+ require 'ronin/core/cli/ruby_shell'
3
+
4
+ describe Ronin::Core::CLI::RubyShell do
5
+ describe "#initialize" do
6
+ it "must default #name to 'ronin'" do
7
+ expect(subject.name).to eq('ronin')
8
+ end
9
+
10
+ context "when given a name: keyword argument" do
11
+ let(:name) { 'ronin-foo' }
12
+
13
+ subject { described_class.new(name: name) }
14
+
15
+ it "must set #name" do
16
+ expect(subject.name).to eq(name)
17
+ end
18
+ end
19
+
20
+ it "must default #context to nil" do
21
+ expect(subject.context).to be(nil)
22
+ end
23
+
24
+ context "when given a context: keyword argument" do
25
+ let(:context) { Object.new }
26
+
27
+ subject { described_class.new(context: context) }
28
+
29
+ it "must set #context" do
30
+ expect(subject.context).to be(context)
31
+ end
32
+ end
33
+ end
34
+
35
+ describe "#configure" do
36
+ before { subject.configure }
37
+
38
+ it "must call IRB.setup" do
39
+ expect(IRB.conf.length).to be > 1
40
+ end
41
+
42
+ it "must set IRB.conf[:IRB_NAME] to #name" do
43
+ expect(IRB.conf[:IRB_NAME]).to eq(subject.name)
44
+ end
45
+
46
+ let(:colors) { subject.colors(STDOUT) }
47
+ let(:red) { colors::RED }
48
+ let(:bright_red) { colors::BRIGHT_RED }
49
+ let(:bold) { colors::BOLD }
50
+ let(:reset_intensity) { colors::RESET_INTENSITY }
51
+ let(:reset_color) { colors::RESET_COLOR }
52
+
53
+ it "must set IRB.conf[:PROMPT][:RONIN]" do
54
+ expect(IRB.conf[:PROMPT][:RONIN]).to eq(
55
+ {
56
+ AUTO_INDENT: true,
57
+ PROMPT_I: "#{red}irb#{reset_color}#{bold}#{bright_red}(#{reset_color}#{reset_intensity}#{red}%N#{reset_color}#{bold}#{bright_red})#{reset_color}#{reset_intensity}#{bold}#{bright_red}>#{reset_color}#{reset_intensity} ",
58
+ PROMPT_S: "#{red}irb#{reset_color}#{bold}#{bright_red}(#{reset_color}#{reset_intensity}#{red}%N#{reset_color}#{bold}#{bright_red})#{reset_color}#{reset_intensity}%l ",
59
+ PROMPT_C: "#{red}irb#{reset_color}#{bold}#{bright_red}(#{reset_color}#{reset_intensity}#{red}%N#{reset_color}#{bold}#{bright_red})#{reset_color}#{reset_intensity}* ",
60
+ RETURN: "=> %s#{$/}"
61
+ }
62
+ )
63
+ end
64
+
65
+ it "must set IRB.conf[:PROMPT_MODE] to :RONIN" do
66
+ expect(IRB.conf[:PROMPT_MODE]).to eq(:RONIN)
67
+ end
68
+
69
+ after do
70
+ IRB.conf[:IRB_NAME] = nil
71
+ IRB.conf[:PROMPT].delete(:RONIN)
72
+ IRB.conf[:PROMPT_MODE] = :DEFAULT
73
+ end
74
+ end
75
+
76
+ describe "#start" do
77
+ let(:fixtures_dir) { File.expand_path(File.join(__dir__,'fixtures')) }
78
+ let(:console_bin) { File.join(fixtures_dir,'irb_command') }
79
+
80
+ it "must print a prompt then read and evaluate Ruby" do
81
+ output = nil
82
+
83
+ IO.popen(console_bin,'r+') do |io|
84
+ io.puts "1 + 1"
85
+ io.puts "exit"
86
+
87
+ output = io.read
88
+ end
89
+
90
+ expect(output).to eq([
91
+ "Switch to inspect mode.",
92
+ "irb(ronin)> 1 + 1",
93
+ "=> 2",
94
+ "irb(ronin)> exit",
95
+ ''
96
+ ].join($/))
97
+ end
98
+ end
99
+ end