command_mapper 0.1.0.pre1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.github/workflows/ruby.yml +27 -0
- data/.gitignore +10 -0
- data/.rspec +1 -0
- data/.yardopts +1 -0
- data/ChangeLog.md +25 -0
- data/Gemfile +15 -0
- data/LICENSE.txt +20 -0
- data/README.md +369 -0
- data/Rakefile +12 -0
- data/commnad_mapper.gemspec +61 -0
- data/gemspec.yml +23 -0
- data/lib/command_mapper/arg.rb +75 -0
- data/lib/command_mapper/argument.rb +142 -0
- data/lib/command_mapper/command.rb +606 -0
- data/lib/command_mapper/exceptions.rb +19 -0
- data/lib/command_mapper/option.rb +282 -0
- data/lib/command_mapper/option_value.rb +21 -0
- data/lib/command_mapper/sudo.rb +73 -0
- data/lib/command_mapper/types/enum.rb +35 -0
- data/lib/command_mapper/types/hex.rb +82 -0
- data/lib/command_mapper/types/input_dir.rb +35 -0
- data/lib/command_mapper/types/input_file.rb +35 -0
- data/lib/command_mapper/types/input_path.rb +29 -0
- data/lib/command_mapper/types/key_value.rb +131 -0
- data/lib/command_mapper/types/key_value_list.rb +45 -0
- data/lib/command_mapper/types/list.rb +90 -0
- data/lib/command_mapper/types/map.rb +64 -0
- data/lib/command_mapper/types/num.rb +50 -0
- data/lib/command_mapper/types/str.rb +85 -0
- data/lib/command_mapper/types/type.rb +102 -0
- data/lib/command_mapper/types.rb +6 -0
- data/lib/command_mapper/version.rb +4 -0
- data/lib/command_mapper.rb +2 -0
- data/spec/arg_spec.rb +137 -0
- data/spec/argument_spec.rb +513 -0
- data/spec/commnad_spec.rb +1175 -0
- data/spec/exceptions_spec.rb +14 -0
- data/spec/option_spec.rb +882 -0
- data/spec/option_value_spec.rb +17 -0
- data/spec/spec_helper.rb +6 -0
- data/spec/sudo_spec.rb +24 -0
- data/spec/types/enum_spec.rb +31 -0
- data/spec/types/hex_spec.rb +158 -0
- data/spec/types/input_dir_spec.rb +30 -0
- data/spec/types/input_file_spec.rb +34 -0
- data/spec/types/input_path_spec.rb +32 -0
- data/spec/types/key_value_list_spec.rb +100 -0
- data/spec/types/key_value_spec.rb +272 -0
- data/spec/types/list_spec.rb +143 -0
- data/spec/types/map_spec.rb +62 -0
- data/spec/types/num_spec.rb +90 -0
- data/spec/types/str_spec.rb +232 -0
- data/spec/types/type_spec.rb +59 -0
- metadata +118 -0
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'command_mapper/option_value'
|
3
|
+
require 'command_mapper/types/list'
|
4
|
+
|
5
|
+
describe CommandMapper::OptionValue do
|
6
|
+
describe "#format" do
|
7
|
+
let(:type) { Types::List.new }
|
8
|
+
|
9
|
+
subject { described_class.new(type: type) }
|
10
|
+
|
11
|
+
let(:value) { [1,2,3] }
|
12
|
+
|
13
|
+
it "must call the #type.format" do
|
14
|
+
expect(subject.format(value)).to eq(type.format(value))
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/spec/spec_helper.rb
ADDED
data/spec/sudo_spec.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'command_mapper/sudo'
|
3
|
+
|
4
|
+
describe CommandMapper::Sudo do
|
5
|
+
let(:command) { %w[ls -la /root] }
|
6
|
+
|
7
|
+
subject { described_class.new({command: command}) }
|
8
|
+
|
9
|
+
describe "#initialize" do
|
10
|
+
it "must accept a command keyword" do
|
11
|
+
expect(subject.command).to eq(command)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "#argv" do
|
16
|
+
it "the first argument must be 'sudo'" do
|
17
|
+
expect(subject.command_argv.first).to eq('sudo')
|
18
|
+
end
|
19
|
+
|
20
|
+
it "must end with the command arguments" do
|
21
|
+
expect(subject.command_argv[-command.length..-1]).to eq(command)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'command_mapper/types/enum'
|
3
|
+
|
4
|
+
describe CommandMapper::Types::Enum do
|
5
|
+
let(:values) { [:foo, 42, :bar] }
|
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
|
+
it "must populate #map with the values and their String forms" do
|
15
|
+
expect(subject.map).to eq(
|
16
|
+
Hash[values.map { |value|
|
17
|
+
[value, value.to_s]
|
18
|
+
}]
|
19
|
+
)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe ".[]" do
|
24
|
+
subject { described_class[*values] }
|
25
|
+
|
26
|
+
it "must create a new Enum with the given values" do
|
27
|
+
expect(subject).to be_kind_of(described_class)
|
28
|
+
expect(subject.values).to eq(values)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,158 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'command_mapper/types/hex'
|
3
|
+
|
4
|
+
describe CommandMapper::Types::Hex do
|
5
|
+
describe "#initialize" do
|
6
|
+
it "must default #leading_zero? to false" do
|
7
|
+
expect(subject.leading_zero?).to be(false)
|
8
|
+
end
|
9
|
+
|
10
|
+
context "when initialized with leading_zero: true" do
|
11
|
+
subject { described_class.new(leading_zero: true) }
|
12
|
+
|
13
|
+
it "must set #leading_zero? to true" do
|
14
|
+
expect(subject.leading_zero?).to be(true)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "#leading_zero?" do
|
20
|
+
context "when initialized with leading_zero: true" do
|
21
|
+
subject { described_class.new(leading_zero: true) }
|
22
|
+
|
23
|
+
it "must return true" do
|
24
|
+
expect(subject.leading_zero?).to be(true)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context "when initialized with leading_zero: false" do
|
29
|
+
subject { described_class.new(leading_zero: false) }
|
30
|
+
|
31
|
+
it "must return false" do
|
32
|
+
expect(subject.leading_zero?).to be(false)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "#validate" do
|
38
|
+
context "when given a String" do
|
39
|
+
context "and the String only contains decimal digits" do
|
40
|
+
let(:value) { "0123456789" }
|
41
|
+
|
42
|
+
it "must return true" do
|
43
|
+
expect(subject.validate(value)).to be(true)
|
44
|
+
end
|
45
|
+
|
46
|
+
context "and the String begins with a '0x'" do
|
47
|
+
let(:value) { "0x0123456789" }
|
48
|
+
|
49
|
+
it "must return true" do
|
50
|
+
expect(subject.validate(value)).to be(true)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context "and the String contains a newline" do
|
55
|
+
let(:value) { "01234\n56789" }
|
56
|
+
|
57
|
+
it "must return [false, \"not in hex format (...)\"]" do
|
58
|
+
expect(subject.validate(value)).to eq(
|
59
|
+
[false, "not in hex format (#{value.inspect})"]
|
60
|
+
)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
context "and the String only contains hex digits" do
|
66
|
+
let(:value) { "abcdef" }
|
67
|
+
|
68
|
+
it "must return true" do
|
69
|
+
expect(subject.validate(value)).to be(true)
|
70
|
+
end
|
71
|
+
|
72
|
+
context "and the String begins with a '0x'" do
|
73
|
+
let(:value) { "0xabcdef" }
|
74
|
+
|
75
|
+
it "must return true" do
|
76
|
+
expect(subject.validate(value)).to be(true)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
context "and the String contains a newline" do
|
81
|
+
let(:value) { "abc\ndef" }
|
82
|
+
|
83
|
+
it "must return [false, \"not in hex format (...)\"]" do
|
84
|
+
expect(subject.validate(value)).to eq(
|
85
|
+
[false, "not in hex format (#{value.inspect})"]
|
86
|
+
)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
context "but the String does not contain other characters" do
|
92
|
+
let(:value) { "foo" }
|
93
|
+
|
94
|
+
it "must return [false, \"not in hex format (...)\"]" do
|
95
|
+
expect(subject.validate(value)).to eq(
|
96
|
+
[false, "not in hex format (#{value.inspect})"]
|
97
|
+
)
|
98
|
+
end
|
99
|
+
|
100
|
+
context "and the String contains a newline" do
|
101
|
+
let(:value) { "foo\nbar" }
|
102
|
+
|
103
|
+
it "must return [false, \"not in hex format (...)\"]" do
|
104
|
+
expect(subject.validate(value)).to eq(
|
105
|
+
[false, "not in hex format (#{value.inspect})"]
|
106
|
+
)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
describe "#format" do
|
114
|
+
context "when given an Integer" do
|
115
|
+
let(:value) { 255 }
|
116
|
+
|
117
|
+
it "must return the hexadecimal form of the Integer" do
|
118
|
+
expect(subject.format(value)).to eq("ff")
|
119
|
+
end
|
120
|
+
|
121
|
+
context "when initialized with leading_zero: true" do
|
122
|
+
subject { described_class.new(leading_zero: true) }
|
123
|
+
|
124
|
+
it "must prepend the hexadecimal number with '0x'" do
|
125
|
+
expect(subject.format(value)).to eq("0xff")
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
context "when given a String" do
|
131
|
+
context "and it contains hexadecimal digits" do
|
132
|
+
let(:value) { "ff" }
|
133
|
+
|
134
|
+
it "must return the String" do
|
135
|
+
expect(subject.format(value)).to eq("ff")
|
136
|
+
end
|
137
|
+
|
138
|
+
context "but the String does start with '0x'" do
|
139
|
+
let(:value) { "0xff" }
|
140
|
+
|
141
|
+
it "must remove '0x' prefix" do
|
142
|
+
expect(subject.format(value)).to eq("ff")
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
context "when #leading_zero? is true" do
|
147
|
+
subject { described_class.new(leading_zero: true) }
|
148
|
+
|
149
|
+
context "but the String does not start with '0x'" do
|
150
|
+
it "must prepend the String with '0x'" do
|
151
|
+
expect(subject.format(value)).to eq("0xff")
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'command_mapper/types/input_dir'
|
3
|
+
|
4
|
+
describe CommandMapper::Types::InputDir do
|
5
|
+
describe "#validate" do
|
6
|
+
context "when given a valid file path" do
|
7
|
+
let(:value) { __FILE__ }
|
8
|
+
|
9
|
+
it "must return [false, 'directory does not exist (...)']" do
|
10
|
+
expect(subject.validate(value)).to eq([false, "directory does not exist (#{value.inspect})"])
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
context "when given a valid directory path" do
|
15
|
+
let(:value) { __dir__ }
|
16
|
+
|
17
|
+
it "must return true" do
|
18
|
+
expect(subject.validate(value)).to eq(true)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context "when given a path that does not exist" do
|
23
|
+
let(:value) { "/path/does/not/exist" }
|
24
|
+
|
25
|
+
it "must return [false, 'path does not exist (...)']" do
|
26
|
+
expect(subject.validate(value)).to eq([false, "path does not exist (#{value.inspect})"])
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'command_mapper/types/input_file'
|
3
|
+
|
4
|
+
describe CommandMapper::Types::InputFile do
|
5
|
+
describe "#validate" do
|
6
|
+
context "when given a valid file path" do
|
7
|
+
let(:value) { __FILE__ }
|
8
|
+
|
9
|
+
it "must return true" do
|
10
|
+
expect(subject.validate(value)).to be(true)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
context "when given a valid directory path" do
|
15
|
+
let(:value) { __dir__ }
|
16
|
+
|
17
|
+
it "must return [false, 'file does not exist (...)']" do
|
18
|
+
expect(subject.validate(value)).to eq(
|
19
|
+
[false, "file does not exist (#{value.inspect})"]
|
20
|
+
)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
context "when given a path that does not exist" do
|
25
|
+
let(:value) { "/path/does/not/exist" }
|
26
|
+
|
27
|
+
it "must return [false, 'path does not exist (...)']" do
|
28
|
+
expect(subject.validate(value)).to eq(
|
29
|
+
[false, "path does not exist (#{value.inspect})"]
|
30
|
+
)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'command_mapper/types/input_path'
|
3
|
+
|
4
|
+
describe CommandMapper::Types::InputPath do
|
5
|
+
describe "#validate" do
|
6
|
+
context "when given a valid file path" do
|
7
|
+
let(:value) { __FILE__ }
|
8
|
+
|
9
|
+
it "must return true" do
|
10
|
+
expect(subject.validate(value)).to be(true)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
context "when given a valid directory path" do
|
15
|
+
let(:value) { __dir__ }
|
16
|
+
|
17
|
+
it "must return true" do
|
18
|
+
expect(subject.validate(value)).to be(true)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context "when given a path that does not exist" do
|
23
|
+
let(:value) { "/path/does/not/exist" }
|
24
|
+
|
25
|
+
it "must return [false, 'path does not exist (...)']" do
|
26
|
+
expect(subject.validate(value)).to eq(
|
27
|
+
[false, "path does not exist (#{value.inspect})"]
|
28
|
+
)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'command_mapper/types/key_value_list'
|
3
|
+
|
4
|
+
describe CommandMapper::Types::KeyValueList do
|
5
|
+
describe "#initialize" do
|
6
|
+
it "must default #separator to ','" do
|
7
|
+
expect(subject.separator).to eq(',')
|
8
|
+
end
|
9
|
+
|
10
|
+
it "must initialize #type to a Types::KeyValue object" do
|
11
|
+
expect(subject.type).to be_kind_of(Types::KeyValue)
|
12
|
+
end
|
13
|
+
|
14
|
+
it "must default #type.separator to '='" do
|
15
|
+
expect(subject.type.separator).to eq('=')
|
16
|
+
end
|
17
|
+
|
18
|
+
context "when given the separator: keyword" do
|
19
|
+
let(:separator) { ';' }
|
20
|
+
|
21
|
+
subject { described_class.new(separator: separator) }
|
22
|
+
|
23
|
+
it "must set #separator" do
|
24
|
+
expect(subject.separator).to eq(separator)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context "when given the key_value_separator: keyword" do
|
29
|
+
let(:separator) { ':' }
|
30
|
+
|
31
|
+
subject { described_class.new(key_value_separator: separator) }
|
32
|
+
|
33
|
+
it "must set #type.separator" do
|
34
|
+
expect(subject.type.separator).to eq(separator)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe "#format" do
|
40
|
+
context "when given an Array" do
|
41
|
+
context "containing a single key:value pair" do
|
42
|
+
let(:key) { "foo" }
|
43
|
+
let(:value) { 42 }
|
44
|
+
|
45
|
+
let(:array) { [[key, value]] }
|
46
|
+
|
47
|
+
it "must join the key and value with #type.separator" do
|
48
|
+
expect(subject.format(array)).to eq(
|
49
|
+
"#{key}#{subject.type.separator}#{value}"
|
50
|
+
)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context "when given multiple key:value pairs" do
|
55
|
+
let(:key1) { "foo" }
|
56
|
+
let(:value1) { 42 }
|
57
|
+
let(:key2) { "bar" }
|
58
|
+
let(:value2) { 100 }
|
59
|
+
|
60
|
+
let(:array) { [[key1, value1], [key2, value2]] }
|
61
|
+
|
62
|
+
it "must join the keys and values with #type.separator, and then with #separator" do
|
63
|
+
expect(subject.format(array)).to eq(
|
64
|
+
"#{key1}#{subject.type.separator}#{value1}#{subject.separator}#{key2}#{subject.type.separator}#{value2}"
|
65
|
+
)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
context "when given an Hash" do
|
71
|
+
context "containing a single key:value pair" do
|
72
|
+
let(:key) { "foo" }
|
73
|
+
let(:value) { 42 }
|
74
|
+
|
75
|
+
let(:hash) { {key => value} }
|
76
|
+
|
77
|
+
it "must join the key and value with #type.separator" do
|
78
|
+
expect(subject.format(hash)).to eq(
|
79
|
+
"#{key}#{subject.type.separator}#{value}"
|
80
|
+
)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
context "containing multiple key:value pairs" do
|
85
|
+
let(:key1) { "foo" }
|
86
|
+
let(:value1) { 42 }
|
87
|
+
let(:key2) { "bar" }
|
88
|
+
let(:value2) { 100 }
|
89
|
+
|
90
|
+
let(:hash) { {key1 => value1, key2 => value2} }
|
91
|
+
|
92
|
+
it "must join the keys and values with #type.separator, and then with #separator" do
|
93
|
+
expect(subject.format(hash)).to eq(
|
94
|
+
"#{key1}#{subject.type.separator}#{value1}#{subject.separator}#{key2}#{subject.type.separator}#{value2}"
|
95
|
+
)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|