command_mapper 0.1.0.pre1

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.
Files changed (55) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/ruby.yml +27 -0
  3. data/.gitignore +10 -0
  4. data/.rspec +1 -0
  5. data/.yardopts +1 -0
  6. data/ChangeLog.md +25 -0
  7. data/Gemfile +15 -0
  8. data/LICENSE.txt +20 -0
  9. data/README.md +369 -0
  10. data/Rakefile +12 -0
  11. data/commnad_mapper.gemspec +61 -0
  12. data/gemspec.yml +23 -0
  13. data/lib/command_mapper/arg.rb +75 -0
  14. data/lib/command_mapper/argument.rb +142 -0
  15. data/lib/command_mapper/command.rb +606 -0
  16. data/lib/command_mapper/exceptions.rb +19 -0
  17. data/lib/command_mapper/option.rb +282 -0
  18. data/lib/command_mapper/option_value.rb +21 -0
  19. data/lib/command_mapper/sudo.rb +73 -0
  20. data/lib/command_mapper/types/enum.rb +35 -0
  21. data/lib/command_mapper/types/hex.rb +82 -0
  22. data/lib/command_mapper/types/input_dir.rb +35 -0
  23. data/lib/command_mapper/types/input_file.rb +35 -0
  24. data/lib/command_mapper/types/input_path.rb +29 -0
  25. data/lib/command_mapper/types/key_value.rb +131 -0
  26. data/lib/command_mapper/types/key_value_list.rb +45 -0
  27. data/lib/command_mapper/types/list.rb +90 -0
  28. data/lib/command_mapper/types/map.rb +64 -0
  29. data/lib/command_mapper/types/num.rb +50 -0
  30. data/lib/command_mapper/types/str.rb +85 -0
  31. data/lib/command_mapper/types/type.rb +102 -0
  32. data/lib/command_mapper/types.rb +6 -0
  33. data/lib/command_mapper/version.rb +4 -0
  34. data/lib/command_mapper.rb +2 -0
  35. data/spec/arg_spec.rb +137 -0
  36. data/spec/argument_spec.rb +513 -0
  37. data/spec/commnad_spec.rb +1175 -0
  38. data/spec/exceptions_spec.rb +14 -0
  39. data/spec/option_spec.rb +882 -0
  40. data/spec/option_value_spec.rb +17 -0
  41. data/spec/spec_helper.rb +6 -0
  42. data/spec/sudo_spec.rb +24 -0
  43. data/spec/types/enum_spec.rb +31 -0
  44. data/spec/types/hex_spec.rb +158 -0
  45. data/spec/types/input_dir_spec.rb +30 -0
  46. data/spec/types/input_file_spec.rb +34 -0
  47. data/spec/types/input_path_spec.rb +32 -0
  48. data/spec/types/key_value_list_spec.rb +100 -0
  49. data/spec/types/key_value_spec.rb +272 -0
  50. data/spec/types/list_spec.rb +143 -0
  51. data/spec/types/map_spec.rb +62 -0
  52. data/spec/types/num_spec.rb +90 -0
  53. data/spec/types/str_spec.rb +232 -0
  54. data/spec/types/type_spec.rb +59 -0
  55. 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
@@ -0,0 +1,6 @@
1
+ require 'rspec'
2
+ require 'command_mapper/version'
3
+ include CommandMapper
4
+
5
+ require 'simplecov'
6
+ SimpleCov.start
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