benry-cmdopt 2.2.0 → 2.4.0

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.
@@ -0,0 +1,294 @@
1
+ # -*- coding: utf-8 -*-
2
+ # frozen_string_literal: true
3
+
4
+ require_relative './shared'
5
+
6
+
7
+ Oktest.scope do
8
+
9
+
10
+ def new_sample_schema()
11
+ sc = Benry::CmdOpt::Schema.new
12
+ sc.add(:help , "-h, --help" , "show help message.")
13
+ sc.add(:version, "--version" , "print version")
14
+ sc.add(:file , "-f, --file=<FILE>" , "filename")
15
+ sc.add(:indent , "-i, --indent[=<WIDTH>]", "enable indent", type: Integer)
16
+ sc.add(:mode , "-m, --mode=<MODE>" , "mode", enum: ['verbose', 'quiet'])
17
+ sc.add(:include, "-I, --include=<PATH>" , "include path (multiple ok)", multiple: true)
18
+ sc.add(:libpath, "-L, --path=<PATH>" , "library path (multiple ok)") do |optdef, key, val|
19
+ File.directory?(val) or raise "Directory not exist."
20
+ arr = optdef[key] || []
21
+ arr << val
22
+ arr
23
+ end
24
+ sc
25
+ end
26
+
27
+
28
+ topic Benry::CmdOpt::Parser do
29
+
30
+
31
+ topic '#parse_options()' do
32
+
33
+ before do
34
+ @parser = Benry::CmdOpt::Parser.new(new_sample_schema())
35
+ end
36
+
37
+ spec "[!3wmsy] returns command option values as a dict." do
38
+ argv = ["-h", "--version"]
39
+ d = @parser.parse(argv)
40
+ ok {d} == {help: true, version: true}
41
+ end
42
+
43
+ spec "[!uh7j8] parses long options." do
44
+ argv = ["--help", "--file=foo.png", "--indent=10"]
45
+ d = @parser.parse(argv)
46
+ ok {d} == {help: true, file: "foo.png", indent: 10}
47
+ end
48
+
49
+ spec "[!nwnjc] parses short options." do
50
+ argv = ["-h", "-f", "foo.png", "-i10"]
51
+ d = @parser.parse(argv)
52
+ ok {d} == {help: true, file: "foo.png", indent: 10}
53
+ end
54
+
55
+ spec "[!5s5b6] treats '-' as an argument, not an option." do
56
+ argv = ["-h", "-", "xxx", "yyy"]
57
+ d = @parser.parse(argv)
58
+ ok {d} == {help: true}
59
+ ok {argv} == ["-", "xxx", "yyy"]
60
+ end
61
+
62
+ spec "[!q8356] parses options even after arguments when `all: true`." do
63
+ argv = ["-h", "arg1", "-f", "foo.png", "arg2", "-i10", "arg3"]
64
+ d = @parser.parse(argv, all: true)
65
+ ok {d} == {help: true, file: "foo.png", indent: 10}
66
+ ok {argv} == ["arg1", "arg2", "arg3"]
67
+ #
68
+ argv = ["-h", "arg1", "-f", "foo.png", "arg2", "-i10", "arg3"]
69
+ d = @parser.parse(argv)
70
+ ok {d} == {help: true, file: "foo.png", indent: 10}
71
+ ok {argv} == ["arg1", "arg2", "arg3"]
72
+ end
73
+
74
+ spec "[!ryra3] doesn't parse options after arguments when `all: false`." do
75
+ argv = ["-h", "arg1", "-f", "foo.png", "arg2", "-i10", "arg3"]
76
+ d = @parser.parse(argv, all: false)
77
+ ok {d} == {help: true}
78
+ ok {argv} == ["arg1", "-f", "foo.png", "arg2", "-i10", "arg3"]
79
+ end
80
+
81
+ spec "[!y04um] skips rest options when '--' found in argv." do
82
+ argv = ["-h", "--", "-f", "foo.png", "-i10"]
83
+ d = @parser.parse(argv)
84
+ ok {d} == {help: true}
85
+ ok {argv} == ["-f", "foo.png", "-i10"]
86
+ end
87
+
88
+ spec "[!qpuxh] handles only OptionError when block given." do
89
+ errmsg = nil
90
+ errcls = nil
91
+ @parser.parse(["-ix"]) {|err|
92
+ errmsg = err.message
93
+ errcls = err.class
94
+ }
95
+ ok {errmsg} == "-ix: Integer expected."
96
+ ok {errcls} == Benry::CmdOpt::OptionError
97
+ #
98
+ sc = Benry::CmdOpt::Schema.new
99
+ sc.add(:file, "--file=<FILE>", "file") do |val|
100
+ File.open(val) {|f| f.read }
101
+ end
102
+ parser = Benry::CmdOpt::Parser.new(sc)
103
+ pr = proc { parser.parse(["--file=/foo/bar/baz.png"]) }
104
+ ok {pr}.raise?(Errno::ENOENT, /No such file or directory/)
105
+ end
106
+
107
+ spec "[!dhpw1] returns nil when OptionError handled." do
108
+ ret = @parser.parse(["-dx"]) {|err| 1 }
109
+ ok {ret} == nil
110
+ end
111
+
112
+ end
113
+
114
+
115
+ topic '#parse_long_option()' do
116
+
117
+ before do
118
+ @parser = Benry::CmdOpt::Parser.new(new_sample_schema())
119
+ end
120
+
121
+ spec "[!3i994] raises OptionError when invalid long option format." do
122
+ argv = ["--f/o/o"]
123
+ pr = proc { @parser.parse(argv) }
124
+ ok {pr}.raise?(Benry::CmdOpt::OptionError, "--f/o/o: Invalid long option.")
125
+ end
126
+
127
+ spec "[!1ab42] invokes error handler method when unknown long option." do
128
+ def @parser.handle_unknown_long_option(optstr, name, val)
129
+ (@_called_ ||= []) << [optstr, name, val]
130
+ end
131
+ ret = @parser.parse(["--xx=XX", "--yy=YY", "--zz"])
132
+ ok {ret} == {}
133
+ ok {@parser.instance_variable_get('@_called_')} == [
134
+ ["--xx=XX", "xx", "XX"],
135
+ ["--yy=YY", "yy", "YY"],
136
+ ["--zz" , "zz", nil],
137
+ ]
138
+ end
139
+
140
+ spec "[!er7h4] default behavior is to raise OptionError when unknown long option." do
141
+ argv = ["--foo"]
142
+ pr = proc { @parser.parse(argv) }
143
+ ok {pr}.raise?(Benry::CmdOpt::OptionError, "--foo: Unknown long option.")
144
+ end
145
+
146
+ spec "[!2jd9w] raises OptionError when no arguments specified for arg required long option." do
147
+ argv = ["--file"]
148
+ pr = proc { @parser.parse(argv) }
149
+ ok {pr}.raise?(Benry::CmdOpt::OptionError, "--file: Argument required.")
150
+ end
151
+
152
+ spec "[!qyq8n] raises optionError when an argument specified for no arg long option." do
153
+ argv = ["--version=1.0.0"]
154
+ pr = proc { @parser.parse(argv) }
155
+ ok {pr}.raise?(Benry::CmdOpt::OptionError, "--version=1.0.0: Unexpected argument.")
156
+ end
157
+
158
+ spec "[!o596x] validates argument value." do
159
+ argv = ["--indent=abc"]
160
+ pr = proc { @parser.parse(argv) }
161
+ ok {pr}.raise?(Benry::CmdOpt::OptionError, "--indent=abc: Integer expected.")
162
+ #
163
+ argv = ["--path=/foo/bar"]
164
+ pr = proc { @parser.parse(argv) }
165
+ ok {pr}.raise?(Benry::CmdOpt::OptionError, "--path=/foo/bar: Directory not exist.")
166
+ end
167
+
168
+ spec "[!1m87b] supports multiple option." do
169
+ argv = ["--include=/foo", "--include=/bar"]
170
+ opts = @parser.parse(argv)
171
+ ok {opts} == {:include=>["/foo", "/bar"]}
172
+ ok {argv} == []
173
+ end
174
+
175
+ end
176
+
177
+
178
+ topic '#parse_short_option()' do
179
+
180
+ before do
181
+ @parser = Benry::CmdOpt::Parser.new(new_sample_schema())
182
+ end
183
+
184
+ spec "[!4eh49] raises OptionError when unknown short option specified." do
185
+ argv = ["-hxf", "foo.png"]
186
+ pr = proc { @parser.parse(argv) }
187
+ ok {pr}.raise?(Benry::CmdOpt::OptionError, "-x: Unknown option.")
188
+ end
189
+
190
+ spec "[!utdbf] raises OptionError when argument required but not specified." do
191
+ argv = ["-hf"]
192
+ pr = proc { @parser.parse(argv) }
193
+ ok {pr}.raise?(Benry::CmdOpt::OptionError, "-f: Argument required.")
194
+ end
195
+
196
+ spec "[!f63hf] short option arg can be specified without space separator." do
197
+ argv = ["-hfabc.png", "xx"]
198
+ d = @parser.parse(argv)
199
+ ok {d} == {help: true, file: "abc.png"}
200
+ ok {argv} == ["xx"]
201
+ end
202
+
203
+ spec "[!yjq6b] optional arg should be specified without space separator." do
204
+ argv = ["-hi123", "xx"]
205
+ d = @parser.parse(argv)
206
+ ok {d} == {help: true, indent: 123}
207
+ ok {argv} == ['xx']
208
+ end
209
+
210
+ spec "[!wape4] otpional arg can be omit." do
211
+ argv = ["-hi", "xx"]
212
+ d = @parser.parse(argv)
213
+ ok {d} == {help: true, indent: true}
214
+ ok {argv} == ['xx']
215
+ end
216
+
217
+ spec "[!yu0kc] validates short option argument." do
218
+ argv = ["-iaaa"]
219
+ pr = proc { @parser.parse(argv) }
220
+ ok {pr}.raise?(Benry::CmdOpt::OptionError, "-iaaa: Integer expected.")
221
+ #
222
+ argv = ["-L", "/foo/bar"]
223
+ pr = proc { @parser.parse(argv) }
224
+ ok {pr}.raise?(Benry::CmdOpt::OptionError, "-L /foo/bar: Directory not exist.")
225
+ end
226
+
227
+ spec "[!187r2] supports multiple option." do
228
+ argv = ["-I", "/foo", "-I/bar"]
229
+ opts = @parser.parse(argv)
230
+ ok {opts} == {:include=>["/foo", "/bar"]}
231
+ ok {argv} == []
232
+ end
233
+
234
+ end
235
+
236
+
237
+ topic '#new_options_dict()' do
238
+
239
+ spec "[!vm6h0] returns new hash object." do
240
+ parser = Benry::CmdOpt::Parser.new(new_sample_schema())
241
+ ret = parser.__send__(:new_options_dict)
242
+ ok {ret}.is_a?(Hash)
243
+ ok {ret} == {}
244
+ end
245
+
246
+ end
247
+
248
+
249
+ topic '#store_option_value()' do
250
+
251
+ spec "[!my86j] stores multiple values if multiple option item." do
252
+ schema = Benry::CmdOpt::Schema.new()
253
+ item = schema.add(:includes, "-I <path>", "include path", multiple: true)
254
+ parser = Benry::CmdOpt::Parser.new(schema)
255
+ optdict = {}
256
+ parser.instance_eval do
257
+ store_option_value(optdict, item, "/usr/include")
258
+ store_option_value(optdict, item, "/usr/local/include")
259
+ end
260
+ ok {optdict} == {:includes => ["/usr/include", "/usr/local/include"]}
261
+ end
262
+
263
+ spec "[!tm7xw] stores singile value if not multiple option item." do
264
+ schema = Benry::CmdOpt::Schema.new()
265
+ item = schema.add(:include, "-I <path>", "include path")
266
+ parser = Benry::CmdOpt::Parser.new(schema)
267
+ optdict = {}
268
+ parser.instance_eval do
269
+ store_option_value(optdict, item, "/usr/include")
270
+ store_option_value(optdict, item, "/usr/local/include")
271
+ end
272
+ ok {optdict} == {:include => "/usr/local/include"}
273
+ end
274
+
275
+ end
276
+
277
+
278
+ topic '#handle_unknown_long_option()' do
279
+
280
+ spec "[!0q78a] raises OptionError." do
281
+ parser = Benry::CmdOpt::Parser.new(new_sample_schema())
282
+ pr = proc {
283
+ parser.__send__(:handle_unknown_long_option, "--xx=XX", "xx", "XX")
284
+ }
285
+ ok {pr}.raise?(Benry::CmdOpt::OptionError, "--xx=XX: Unknown long option.")
286
+ end
287
+
288
+ end
289
+
290
+
291
+ end
292
+
293
+
294
+ end
data/test/run_all.rb ADDED
@@ -0,0 +1,6 @@
1
+ # -*- coding: utf-8 -*-
2
+ # frozen_string_literal: true
3
+
4
+ Dir.glob(File.dirname(__FILE__) + '/**/*_test.rb').each do |filename|
5
+ require File.absolute_path(filename)
6
+ end