user-choices 1.1.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.
- data/History.txt +17 -0
- data/LICENSE.txt +34 -0
- data/Manifest.txt +40 -0
- data/README.txt +1 -0
- data/Rakefile +19 -0
- data/Rakefile.hoe +24 -0
- data/examples/older/README.txt +133 -0
- data/examples/older/command-line.rb +51 -0
- data/examples/older/default-values.rb +47 -0
- data/examples/older/multiple-sources.rb +63 -0
- data/examples/older/postprocess.rb +45 -0
- data/examples/older/switches.rb +50 -0
- data/examples/older/two-args.rb +37 -0
- data/examples/older/types.rb +67 -0
- data/examples/tutorial/index.html +648 -0
- data/examples/tutorial/tutorial1.rb +48 -0
- data/examples/tutorial/tutorial2.rb +52 -0
- data/examples/tutorial/tutorial3.rb +55 -0
- data/examples/tutorial/tutorial4.rb +55 -0
- data/examples/tutorial/tutorial5.rb +42 -0
- data/examples/tutorial/tutorial6.rb +42 -0
- data/examples/tutorial/tutorial7.rb +48 -0
- data/lib/user-choices/arglist-strategies.rb +178 -0
- data/lib/user-choices/builder.rb +89 -0
- data/lib/user-choices/command-line-source.rb +220 -0
- data/lib/user-choices/command.rb +42 -0
- data/lib/user-choices/conversions.rb +154 -0
- data/lib/user-choices/ruby-extensions.rb +20 -0
- data/lib/user-choices/sources.rb +269 -0
- data/lib/user-choices/version.rb +3 -0
- data/lib/user-choices.rb +131 -0
- data/setup.rb +1585 -0
- data/test/arglist-strategy-tests.rb +42 -0
- data/test/builder-tests.rb +569 -0
- data/test/command-line-source-tests.rb +443 -0
- data/test/conversion-tests.rb +157 -0
- data/test/set-standalone-test-paths.rb +5 -0
- data/test/source-tests.rb +442 -0
- data/test/user-choices-slowtests.rb +274 -0
- data/user-choices.tmproj +575 -0
- metadata +138 -0
@@ -0,0 +1,443 @@
|
|
1
|
+
load "set-standalone-test-paths.rb" unless $started_from_rakefile
|
2
|
+
require 'test/unit'
|
3
|
+
require 's4t-utils'
|
4
|
+
require 'builder'
|
5
|
+
require 'user-choices'
|
6
|
+
include S4tUtils
|
7
|
+
|
8
|
+
### Handling of options with arguments ###
|
9
|
+
|
10
|
+
class CommandLineTestCase < Test::Unit::TestCase
|
11
|
+
include UserChoices
|
12
|
+
|
13
|
+
def setup
|
14
|
+
@cmd_line = CommandLineSource.new
|
15
|
+
end
|
16
|
+
|
17
|
+
def default_test
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class OPTIONS_CommandLineTests < CommandLineTestCase
|
22
|
+
def test_options_can_be_given_in_the_command_line
|
23
|
+
with_command_args('--given-option value') {
|
24
|
+
@cmd_line.uses_option(:given_option, "--given-option VALUE")
|
25
|
+
@cmd_line.fill
|
26
|
+
|
27
|
+
assert_true(@cmd_line.has_key?(:given_option))
|
28
|
+
assert_equal("value", @cmd_line[:given_option])
|
29
|
+
|
30
|
+
assert_false(@cmd_line.has_key?(:unspecified_option))
|
31
|
+
assert_equal(nil, @cmd_line[:unspecified_option])
|
32
|
+
}
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_the_specification_can_describe_options_that_are_not_given
|
36
|
+
# They're really /optional/.
|
37
|
+
with_command_args('') {
|
38
|
+
@cmd_line.uses_option(:unused_option, "--unused-option VALUE")
|
39
|
+
@cmd_line.fill
|
40
|
+
|
41
|
+
assert_false(@cmd_line.has_key?(:unused_option))
|
42
|
+
assert_equal(nil, @cmd_line[:unused_option])
|
43
|
+
}
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_options_can_have_one_letter_abbreviations
|
47
|
+
with_command_args('-s s-value --option=option-value') {
|
48
|
+
@cmd_line.uses_option(:option, "-o", "--option=VALUE")
|
49
|
+
@cmd_line.uses_option(:something, "-s", "--something=VALUE")
|
50
|
+
@cmd_line.fill
|
51
|
+
|
52
|
+
assert_equal("s-value", @cmd_line[:something])
|
53
|
+
assert_equal("option-value", @cmd_line[:option])
|
54
|
+
}
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
|
59
|
+
def test_command_line_list_of_possible_values_checking
|
60
|
+
with_command_args("-n true") do
|
61
|
+
@cmd_line.uses_option(:north_west, "-n", "--north-west=VALUE")
|
62
|
+
@cmd_line.fill
|
63
|
+
output = capturing_stderr do
|
64
|
+
assert_wants_to_exit do
|
65
|
+
@cmd_line.apply({:north_west => [Conversion.for(['low', 'high'])]})
|
66
|
+
end
|
67
|
+
end
|
68
|
+
assert_match(%r{Error in the command line: --north-west's value}, output)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_command_line_integer_value_checking
|
73
|
+
with_command_args("--day-count-max=2d3") do
|
74
|
+
@cmd_line.uses_option(:day_count_max, "--day-count-max=VALUE")
|
75
|
+
@cmd_line.fill
|
76
|
+
output = capturing_stderr do
|
77
|
+
assert_wants_to_exit do
|
78
|
+
@cmd_line.apply({:day_count_max => [Conversion.for(:integer)]})
|
79
|
+
end
|
80
|
+
end
|
81
|
+
assert_match(/^Error in the command line: --day-count-max's value/, output)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
|
86
|
+
def test_integer_conversion
|
87
|
+
with_command_args("--day-count-max 23") do
|
88
|
+
@cmd_line.uses_option(:day_count_max, "--day-count-max=VALUE")
|
89
|
+
@cmd_line.fill
|
90
|
+
@cmd_line.apply({:day_count_max => [Conversion.for(:integer)]})
|
91
|
+
assert_equal(23, @cmd_line[:day_count_max])
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def test_array_value_conversion_with_proper_multivalue_declaration
|
96
|
+
with_command_args("--hosts localhost,foo.com") do
|
97
|
+
@cmd_line.uses_option(:hosts, "--hosts HOST,HOST")
|
98
|
+
@cmd_line.fill
|
99
|
+
@cmd_line.apply({:hosts => [Conversion.for([:string])]})
|
100
|
+
assert_equal(['localhost', 'foo.com'],
|
101
|
+
@cmd_line[:hosts])
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def test_array_value_conversion_without_proper_multivalue_declaration_still_works
|
106
|
+
with_command_args("--hosts localhost,foo.com") do
|
107
|
+
@cmd_line.uses_option(:hosts, "--hosts HOSTS...")
|
108
|
+
@cmd_line.fill
|
109
|
+
@cmd_line.apply({:hosts => [Conversion.for([:string])]})
|
110
|
+
assert_equal(['localhost', 'foo.com'],
|
111
|
+
@cmd_line[:hosts])
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
|
117
|
+
|
118
|
+
|
119
|
+
### Boolean switches ###
|
120
|
+
|
121
|
+
# Note that switches are string-valued for consistency with
|
122
|
+
# other sources (like environment variables).
|
123
|
+
class SWITCHES_CommandLineTest < CommandLineTestCase
|
124
|
+
|
125
|
+
def test_boolean_switches_are_accepted
|
126
|
+
with_command_args("--c") do
|
127
|
+
@cmd_line.uses_switch(:csv, "-c", "--csv")
|
128
|
+
@cmd_line.fill
|
129
|
+
assert_equal("true", @cmd_line[:csv])
|
130
|
+
|
131
|
+
# ... but they can be converted into booleans
|
132
|
+
@cmd_line.apply({:csv => [Conversion.for(:boolean)]})
|
133
|
+
assert_equal(true, @cmd_line[:csv])
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def test_unmentioned_switches_have_no_value
|
138
|
+
with_command_args("") do
|
139
|
+
@cmd_line.uses_switch(:csv, "-c", "--csv")
|
140
|
+
@cmd_line.fill
|
141
|
+
assert_false(@cmd_line.has_key?(:csv))
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def test_switches_can_be_explicitly_false
|
146
|
+
with_command_args("--no-csv") do
|
147
|
+
@cmd_line.uses_switch(:csv, "-c", "--csv")
|
148
|
+
@cmd_line.fill
|
149
|
+
assert_equal("false", @cmd_line[:csv])
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
|
155
|
+
### Argument Lists ###
|
156
|
+
|
157
|
+
# Arguments lists are treated as another option.
|
158
|
+
class ARGLISTS_CommandLineTest < CommandLineTestCase
|
159
|
+
|
160
|
+
def test_by_default_arglists_are_not_allowed
|
161
|
+
# Note that the error check is done at fill time, not apply time.
|
162
|
+
with_command_args("one") {
|
163
|
+
output = capturing_stderr do
|
164
|
+
assert_wants_to_exit do
|
165
|
+
@cmd_line.fill
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
assert_match(/^Error in the command line: No arguments are allowed./, output)
|
170
|
+
}
|
171
|
+
end
|
172
|
+
|
173
|
+
def test_empty_arglists_are_OK_if_arglist_not_described
|
174
|
+
with_command_args("") {
|
175
|
+
output = capturing_stderr do
|
176
|
+
@cmd_line.fill
|
177
|
+
end
|
178
|
+
assert_equal("", output) # No error message
|
179
|
+
}
|
180
|
+
end
|
181
|
+
|
182
|
+
def test_arglist_after_options_can_turned_into_an_option
|
183
|
+
with_command_args("--unused unused arg1 arg2") {
|
184
|
+
@cmd_line.uses_option(:unused, "--unused VALUE") # just for grins
|
185
|
+
@cmd_line.uses_arglist(:args)
|
186
|
+
@cmd_line.fill
|
187
|
+
assert_true(@cmd_line.has_key?(:args))
|
188
|
+
assert_equal(["arg1", "arg2"], @cmd_line[:args])
|
189
|
+
}
|
190
|
+
end
|
191
|
+
|
192
|
+
def test_arglist_can_check_allowable_number_of_arguments
|
193
|
+
with_command_args("--unused unused arg1 arg2") {
|
194
|
+
@cmd_line.uses_option(:unused, "--unused VALUE") # just for grins
|
195
|
+
@cmd_line.uses_arglist(:args)
|
196
|
+
@cmd_line.fill
|
197
|
+
@cmd_line.apply({:args => [Conversion.for({:length => 2})]})
|
198
|
+
assert_true(@cmd_line.has_key?(:args))
|
199
|
+
assert_equal(["arg1", "arg2"], @cmd_line[:args])
|
200
|
+
}
|
201
|
+
end
|
202
|
+
|
203
|
+
def test_error_if_exact_arglist_number_is_wrong
|
204
|
+
with_command_args("arg1 arg2") {
|
205
|
+
@cmd_line.uses_arglist(:args)
|
206
|
+
@cmd_line.fill
|
207
|
+
output = capturing_stderr do
|
208
|
+
assert_wants_to_exit do
|
209
|
+
@cmd_line.apply({:args => [Conversion.for({:length => 3})]})
|
210
|
+
end
|
211
|
+
end
|
212
|
+
assert_match(/^Error in the command line:.*2 arguments given, 3 expected./, output)
|
213
|
+
}
|
214
|
+
end
|
215
|
+
|
216
|
+
def test_arglist_arity_can_be_a_range
|
217
|
+
with_command_args("arg1 arg2") {
|
218
|
+
@cmd_line.uses_arglist(:args)
|
219
|
+
@cmd_line.fill
|
220
|
+
@cmd_line.apply({:args => [Conversion.for({:length => 1..2})]})
|
221
|
+
assert_true(@cmd_line.has_key?(:args))
|
222
|
+
assert_equal(["arg1", "arg2"], @cmd_line[:args])
|
223
|
+
}
|
224
|
+
end
|
225
|
+
|
226
|
+
|
227
|
+
def test_error_if_arglist_does_not_match_range
|
228
|
+
with_command_args("arg1 arg2") {
|
229
|
+
@cmd_line.uses_arglist(:args)
|
230
|
+
@cmd_line.fill
|
231
|
+
output = capturing_stderr do
|
232
|
+
assert_wants_to_exit do
|
233
|
+
@cmd_line.apply({:args => [Conversion.for({:length => 3..6})]})
|
234
|
+
end
|
235
|
+
end
|
236
|
+
assert_match(/^Error in the command line:.*2 arguments given, 3 to 6 expected./, output)
|
237
|
+
}
|
238
|
+
end
|
239
|
+
|
240
|
+
def test_arglist_external_name_is_friendly
|
241
|
+
@cmd_line.uses_arglist(:fred)
|
242
|
+
assert_equal("the argument list", @cmd_line.external_names[:fred])
|
243
|
+
end
|
244
|
+
|
245
|
+
def test_deep_copy_of_conversion_map
|
246
|
+
map = { :choice => [Conversion.for([:string]), Conversion.for(:length => 3)]}
|
247
|
+
copy = @cmd_line.deep_copy(map)
|
248
|
+
assert_not_equal(map[:choice].collect { |c| c.object_id },
|
249
|
+
copy[:choice].collect { |c| c.object_id })
|
250
|
+
assert_true(copy[:choice][0].class.described_by?([:string]))
|
251
|
+
assert_true(copy[:choice][1].class.described_by?(:length => 3))
|
252
|
+
|
253
|
+
map.delete(:choice)
|
254
|
+
assert_false(map.has_key?(:choice))
|
255
|
+
assert_true(copy.has_key?(:choice))
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
class ARG_CommandLineTest < CommandLineTestCase
|
260
|
+
include UserChoices
|
261
|
+
|
262
|
+
|
263
|
+
def test_a_singleton_arg_will_not_be_in_a_list
|
264
|
+
with_command_args("arg-only") {
|
265
|
+
@cmd_line.uses_option(:unused, "--unused VALUE") # just for grins
|
266
|
+
@cmd_line.uses_arg(:arg)
|
267
|
+
@cmd_line.fill
|
268
|
+
assert_true(@cmd_line.has_key?(:arg))
|
269
|
+
assert_equal("arg-only", @cmd_line[:arg])
|
270
|
+
}
|
271
|
+
end
|
272
|
+
|
273
|
+
def test_singleton_args_are_incompatible_with_length_checks
|
274
|
+
# Because the missing argument might be filled in by other chained sources.
|
275
|
+
with_command_args("1") {
|
276
|
+
@cmd_line.uses_arg(:arg)
|
277
|
+
@cmd_line.fill
|
278
|
+
assert_raises_with_matching_message(StandardError, "Don't specify the length of an argument list when it's not treated as an array.") {
|
279
|
+
@cmd_line.apply({:arg => [Conversion.for(:length => 1)]})
|
280
|
+
}
|
281
|
+
}
|
282
|
+
end
|
283
|
+
|
284
|
+
|
285
|
+
|
286
|
+
def test_extra_singleton_args_generate_errors
|
287
|
+
# Note that it's caught in the 'fill' step.
|
288
|
+
with_command_args("1 2") {
|
289
|
+
@cmd_line.uses_arg(:arg)
|
290
|
+
output = capturing_stderr do
|
291
|
+
assert_wants_to_exit do
|
292
|
+
@cmd_line.fill
|
293
|
+
end
|
294
|
+
end
|
295
|
+
assert_match(/^Error in the command line: .*2 arguments given, 1 expected/, output)
|
296
|
+
}
|
297
|
+
end
|
298
|
+
|
299
|
+
def test_singleton_arguments_can_be_optional
|
300
|
+
with_command_args("") {
|
301
|
+
@cmd_line.uses_optional_arg(:arg)
|
302
|
+
@cmd_line.fill
|
303
|
+
assert_false(@cmd_line.has_key?(:arg))
|
304
|
+
assert_equal(nil, @cmd_line[:arg])
|
305
|
+
}
|
306
|
+
end
|
307
|
+
|
308
|
+
def test_optional_arguments_can_be_given
|
309
|
+
with_command_args("only") {
|
310
|
+
@cmd_line.uses_optional_arg(:arg)
|
311
|
+
@cmd_line.fill
|
312
|
+
assert_equal('only', @cmd_line[:arg])
|
313
|
+
}
|
314
|
+
end
|
315
|
+
|
316
|
+
|
317
|
+
def test_that_optional_singleton_arguments_still_precludes_two
|
318
|
+
# Note that the error check is done at fill time, not apply time.
|
319
|
+
with_command_args("one two") {
|
320
|
+
@cmd_line.uses_optional_arg(:arg)
|
321
|
+
output = capturing_stderr do
|
322
|
+
assert_wants_to_exit do
|
323
|
+
@cmd_line.fill
|
324
|
+
end
|
325
|
+
end
|
326
|
+
assert_match(/^Error in the command line:.*2 arguments given, 0 or 1 expected./, output)
|
327
|
+
}
|
328
|
+
end
|
329
|
+
|
330
|
+
def test_arg_external_name_is_friendly
|
331
|
+
@cmd_line.uses_arg(:fred)
|
332
|
+
assert_equal("the argument list", @cmd_line.external_names[:fred])
|
333
|
+
end
|
334
|
+
|
335
|
+
|
336
|
+
def test_optional_arg_external_name_is_friendly
|
337
|
+
@cmd_line.uses_optional_arg(:fred)
|
338
|
+
assert_equal("the argument list", @cmd_line.external_names[:fred])
|
339
|
+
end
|
340
|
+
|
341
|
+
end
|
342
|
+
|
343
|
+
### Option-Handling Style ###
|
344
|
+
|
345
|
+
class OPTION_STYLE_CommandLineTest < CommandLineTestCase
|
346
|
+
include UserChoices
|
347
|
+
|
348
|
+
def define(klass)
|
349
|
+
@cmd_line = klass.new
|
350
|
+
@cmd_line.uses_switch(:switch, "--switch")
|
351
|
+
@cmd_line.uses_arglist(:args)
|
352
|
+
@cmd_line.fill
|
353
|
+
end
|
354
|
+
|
355
|
+
def test_default_style_is_permutation
|
356
|
+
with_command_args('3 --switch 5') {
|
357
|
+
define(CommandLineSource)
|
358
|
+
assert_equal('true', @cmd_line[:switch])
|
359
|
+
assert_equal(['3', '5'], @cmd_line[:args])
|
360
|
+
}
|
361
|
+
end
|
362
|
+
|
363
|
+
def test_subclass_allows_all_options_before_arguments
|
364
|
+
with_command_args('3 --switch 5') {
|
365
|
+
define(PosixCommandLineSource)
|
366
|
+
assert_equal(nil, @cmd_line[:switch])
|
367
|
+
assert_equal(['3', '--switch', '5'], @cmd_line[:args])
|
368
|
+
}
|
369
|
+
end
|
370
|
+
|
371
|
+
def test_choosing_posix_parsing_does_not_override_environment_variable
|
372
|
+
with_environment_vars('POSIXLY_CORRECT' => 'hello') do
|
373
|
+
with_command_args('3 --switch 5') {
|
374
|
+
define(PosixCommandLineSource)
|
375
|
+
assert_equal('hello', ENV['POSIXLY_CORRECT'])
|
376
|
+
}
|
377
|
+
end
|
378
|
+
end
|
379
|
+
|
380
|
+
end
|
381
|
+
|
382
|
+
### Error Handling ###
|
383
|
+
|
384
|
+
# Additional commandline-specific error checking.
|
385
|
+
class ERROR_CommandLineTest < CommandLineTestCase
|
386
|
+
include UserChoices
|
387
|
+
|
388
|
+
def test_invalid_option_produces_error_message_and_exit
|
389
|
+
with_command_args('--doofus 3') {
|
390
|
+
output = capturing_stderr do
|
391
|
+
assert_wants_to_exit do
|
392
|
+
@cmd_line.uses_option(:doofus, "--option VALUE")
|
393
|
+
@cmd_line.fill
|
394
|
+
end
|
395
|
+
end
|
396
|
+
|
397
|
+
assert_match(/invalid option.*doofus/, output)
|
398
|
+
}
|
399
|
+
end
|
400
|
+
|
401
|
+
def test_error_is_identified_as_coming_from_the_command_line
|
402
|
+
with_command_args('--doofus') {
|
403
|
+
output = capturing_stderr do
|
404
|
+
assert_wants_to_exit do
|
405
|
+
@cmd_line.uses_option(:doofus, "--doofus VALUE")
|
406
|
+
@cmd_line.fill
|
407
|
+
end
|
408
|
+
end
|
409
|
+
|
410
|
+
assert_match(/^Error in the command line:.*missing argument.*doofus/, output)
|
411
|
+
}
|
412
|
+
end
|
413
|
+
|
414
|
+
def test_errors_cause_usage_style_output
|
415
|
+
with_command_args('wanted --wanted') {
|
416
|
+
output = capturing_stderr do
|
417
|
+
assert_wants_to_exit do
|
418
|
+
default_isbn = "343"
|
419
|
+
@cmd_line.help_banner("Usage: ruby prog [options] [isbn]",
|
420
|
+
"This and further strings are optional.")
|
421
|
+
@cmd_line.uses_option(:option, "-o", "--option=VALUE",
|
422
|
+
"Message about option",
|
423
|
+
"More about option")
|
424
|
+
@cmd_line.fill
|
425
|
+
end
|
426
|
+
end
|
427
|
+
|
428
|
+
lines = output.split($/)
|
429
|
+
# puts output
|
430
|
+
assert_match(/^Error in the command line: /, lines[0])
|
431
|
+
assert_equal("Usage: ruby prog [options] [isbn]", lines[1])
|
432
|
+
assert_match(/This and further/, lines[2])
|
433
|
+
assert_match(/\s*/, lines[3])
|
434
|
+
assert_match(/Options:/, lines[4])
|
435
|
+
assert_match(/-o.*--option=VALUE.*Message about option/, lines[5])
|
436
|
+
assert_match(/More about option/, lines[6])
|
437
|
+
assert_match(/--help.*Show this message/, lines.last)
|
438
|
+
}
|
439
|
+
end
|
440
|
+
|
441
|
+
end
|
442
|
+
|
443
|
+
|
@@ -0,0 +1,157 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# Created by Brian Marick on 2007-08-06.
|
4
|
+
# Copyright (c) 2007. All rights reserved.
|
5
|
+
|
6
|
+
load "set-standalone-test-paths.rb" unless $started_from_rakefile
|
7
|
+
require 'test/unit'
|
8
|
+
require 's4t-utils'
|
9
|
+
require 'user-choices'
|
10
|
+
include S4tUtils
|
11
|
+
|
12
|
+
|
13
|
+
class TestDefaultsAndTypes < Test::Unit::TestCase
|
14
|
+
include UserChoices
|
15
|
+
|
16
|
+
def test_correct_conversion_objects_are_chosen
|
17
|
+
start = []
|
18
|
+
Conversion.record_for(:integer, start)
|
19
|
+
Conversion.record_for(:boolean, start)
|
20
|
+
Conversion.record_for([:string], start)
|
21
|
+
Conversion.record_for(["one", "two"], start)
|
22
|
+
Conversion.record_for({:length => 1}, start)
|
23
|
+
Conversion.record_for({:length => 1..2}, start)
|
24
|
+
|
25
|
+
assert_equal([ConversionToInteger, ConversionToBoolean,
|
26
|
+
SplittingConversion, ChoiceCheckingConversion,
|
27
|
+
ExactLengthConversion, RangeLengthConversion],
|
28
|
+
start.collect { |c| c.class })
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_nil_conversion_tags_do_nothing
|
32
|
+
start = []
|
33
|
+
Conversion.record_for(nil, start)
|
34
|
+
assert_equal([], start)
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_integer_conversion_checking
|
38
|
+
c2i = Conversion.for(:integer)
|
39
|
+
assert_true(c2i.suitable?("034"))
|
40
|
+
assert_false(c2i.suitable?("0x1d"))
|
41
|
+
assert_false(c2i.suitable?(["0x1d"]))
|
42
|
+
assert_equal('an integer', c2i.description)
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_integer_conversion
|
46
|
+
c2i = Conversion.for(:integer)
|
47
|
+
assert_equal(12, c2i.convert("12"))
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_it_is_ok_for_integers_already_to_be_converted
|
51
|
+
c2i = Conversion.for(:integer)
|
52
|
+
assert_true(c2i.suitable?(12))
|
53
|
+
assert_equal(12, c2i.convert(12))
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
|
58
|
+
def test_boolean_conversion_checking
|
59
|
+
c2b = Conversion.for(:boolean)
|
60
|
+
assert_true(c2b.suitable?("true"))
|
61
|
+
assert_true(c2b.suitable?("false"))
|
62
|
+
# Case insensitive
|
63
|
+
assert_true(c2b.suitable?("False"))
|
64
|
+
assert_true(c2b.suitable?("TRUE"))
|
65
|
+
|
66
|
+
assert_false(c2b.suitable?("tru"))
|
67
|
+
assert_false(c2b.suitable?(1))
|
68
|
+
assert_equal('a boolean', c2b.description)
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_boolean_conversion
|
72
|
+
c = Conversion.for(:boolean)
|
73
|
+
assert_equal(false, c.convert("FalsE"))
|
74
|
+
assert_equal(true, c.convert("true"))
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_it_is_ok_for_booleans_already_to_be_converted
|
78
|
+
c = Conversion.for(:boolean)
|
79
|
+
assert_true(c.suitable?(true))
|
80
|
+
assert_equal(false, c.convert(false))
|
81
|
+
end
|
82
|
+
|
83
|
+
|
84
|
+
|
85
|
+
|
86
|
+
|
87
|
+
def test_any_string_is_accepted_for_splitting_conversion
|
88
|
+
s = Conversion.for([:string])
|
89
|
+
assert_true(s.suitable?("tru calling"))
|
90
|
+
assert_true(s.suitable?("fa,se"))
|
91
|
+
assert_false(s.suitable?(1))
|
92
|
+
end
|
93
|
+
|
94
|
+
def test_splitting
|
95
|
+
c = Conversion.for([:string])
|
96
|
+
assert_equal(["one"], c.convert("one"))
|
97
|
+
assert_equal(["one", "two"], c.convert("one,two"))
|
98
|
+
# Whitespace NOT ignored
|
99
|
+
assert_equal(["one", " two"], c.convert("one, two"))
|
100
|
+
end
|
101
|
+
|
102
|
+
def test_it_is_ok_for_values_already_to_be_split
|
103
|
+
c = Conversion.for([:string])
|
104
|
+
assert_true(c.suitable?(["one", "two"]))
|
105
|
+
assert_equal(["one", "two"], c.convert(["one", "two"]))
|
106
|
+
end
|
107
|
+
|
108
|
+
|
109
|
+
|
110
|
+
|
111
|
+
def test_choice_checking_conversion
|
112
|
+
cc = Conversion.for(["foo", "bar"])
|
113
|
+
assert_true(cc.suitable?("foo"))
|
114
|
+
assert_true(cc.suitable?("bar"))
|
115
|
+
|
116
|
+
assert_false(cc.suitable?("fred"))
|
117
|
+
# Case sensitive
|
118
|
+
assert_false(cc.suitable?("FOO"))
|
119
|
+
assert_equal("one of 'foo' or 'bar'", cc.description)
|
120
|
+
end
|
121
|
+
|
122
|
+
def test_choice_checking_does_no_conversion
|
123
|
+
cc = Conversion.for(["foo", "bar"])
|
124
|
+
assert_equal("foo", cc.convert("foo"))
|
125
|
+
end
|
126
|
+
|
127
|
+
|
128
|
+
def test_length_conversion_with_exact_length
|
129
|
+
c = Conversion.for(:length => 1)
|
130
|
+
assert_true(c.suitable?([1]))
|
131
|
+
assert_false(c.suitable?([]))
|
132
|
+
assert_false(c.suitable?([1, 2]))
|
133
|
+
assert_false(c.suitable?("not array"))
|
134
|
+
|
135
|
+
assert_equal("of length 1", c.description)
|
136
|
+
end
|
137
|
+
|
138
|
+
def test_length_conversion_with_exact_length_does_no_conversion
|
139
|
+
c = Conversion.for(:length => 1)
|
140
|
+
assert_equal(["foo"], c.convert(["foo"]))
|
141
|
+
end
|
142
|
+
|
143
|
+
def test_length_conversion_with_range
|
144
|
+
c = Conversion.for(:length => 0..1)
|
145
|
+
assert_true(c.suitable?([1]))
|
146
|
+
assert_true(c.suitable?([]))
|
147
|
+
assert_false(c.suitable?([1, 2]))
|
148
|
+
|
149
|
+
assert_equal("a list whose length is in this range: 0..1", c.description)
|
150
|
+
end
|
151
|
+
|
152
|
+
def test_length_conversion_with_range_does_no_conversion
|
153
|
+
c = Conversion.for(:length => 0..1)
|
154
|
+
assert_equal(["foo"], c.convert(["foo"]))
|
155
|
+
end
|
156
|
+
|
157
|
+
end
|