rudy 0.4.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (135) hide show
  1. data/CHANGES.txt +54 -30
  2. data/README.rdoc +100 -12
  3. data/Rakefile +103 -8
  4. data/Rudyfile +119 -0
  5. data/bin/ird +175 -0
  6. data/bin/rudy +259 -156
  7. data/bin/rudy-ec2 +228 -95
  8. data/bin/rudy-s3 +76 -0
  9. data/bin/rudy-sdb +67 -0
  10. data/lib/annoy.rb +270 -0
  11. data/lib/console.rb +30 -9
  12. data/lib/escape.rb +305 -0
  13. data/lib/rudy.rb +151 -182
  14. data/lib/rudy/aws.rb +56 -49
  15. data/lib/rudy/aws/ec2.rb +47 -292
  16. data/lib/rudy/aws/ec2/address.rb +157 -0
  17. data/lib/rudy/aws/ec2/group.rb +301 -0
  18. data/lib/rudy/aws/ec2/image.rb +168 -0
  19. data/lib/rudy/aws/ec2/instance.rb +434 -0
  20. data/lib/rudy/aws/ec2/keypair.rb +104 -0
  21. data/lib/rudy/aws/ec2/snapshot.rb +98 -0
  22. data/lib/rudy/aws/ec2/volume.rb +230 -0
  23. data/lib/rudy/aws/ec2/zone.rb +77 -0
  24. data/lib/rudy/aws/s3.rb +54 -0
  25. data/lib/rudy/aws/sdb.rb +298 -0
  26. data/lib/rudy/aws/sdb/error.rb +46 -0
  27. data/lib/rudy/{metadata/backup.rb → backup.rb} +26 -51
  28. data/lib/rudy/cli.rb +157 -0
  29. data/lib/rudy/cli/aws/ec2/addresses.rb +105 -0
  30. data/lib/rudy/cli/aws/ec2/candy.rb +208 -0
  31. data/lib/rudy/cli/aws/ec2/groups.rb +121 -0
  32. data/lib/rudy/cli/aws/ec2/images.rb +196 -0
  33. data/lib/rudy/cli/aws/ec2/instances.rb +194 -0
  34. data/lib/rudy/cli/aws/ec2/keypairs.rb +53 -0
  35. data/lib/rudy/cli/aws/ec2/snapshots.rb +49 -0
  36. data/lib/rudy/cli/aws/ec2/volumes.rb +104 -0
  37. data/lib/rudy/cli/aws/ec2/zones.rb +22 -0
  38. data/lib/rudy/cli/aws/s3/buckets.rb +50 -0
  39. data/lib/rudy/cli/aws/s3/store.rb +22 -0
  40. data/lib/rudy/cli/aws/sdb/domains.rb +41 -0
  41. data/lib/rudy/cli/candy.rb +8 -0
  42. data/lib/rudy/{command → cli}/config.rb +34 -24
  43. data/lib/rudy/cli/disks.rb +35 -0
  44. data/lib/rudy/cli/machines.rb +94 -0
  45. data/lib/rudy/cli/routines.rb +57 -0
  46. data/lib/rudy/config.rb +77 -72
  47. data/lib/rudy/config/objects.rb +29 -0
  48. data/lib/rudy/disks.rb +248 -0
  49. data/lib/rudy/global.rb +121 -0
  50. data/lib/rudy/huxtable.rb +340 -0
  51. data/lib/rudy/machines.rb +245 -0
  52. data/lib/rudy/metadata.rb +123 -13
  53. data/lib/rudy/routines.rb +47 -0
  54. data/lib/rudy/routines/helpers/diskhelper.rb +101 -0
  55. data/lib/rudy/routines/helpers/scripthelper.rb +91 -0
  56. data/lib/rudy/routines/release.rb +34 -0
  57. data/lib/rudy/routines/shutdown.rb +57 -0
  58. data/lib/rudy/routines/startup.rb +58 -0
  59. data/lib/rudy/scm/svn.rb +1 -1
  60. data/lib/rudy/utils.rb +322 -4
  61. data/lib/storable.rb +26 -17
  62. data/lib/sysinfo.rb +274 -0
  63. data/lib/tryouts.rb +6 -13
  64. data/rudy.gemspec +128 -42
  65. data/support/randomize-root-password +45 -0
  66. data/support/rudy-ec2-startup +9 -9
  67. data/support/update-ec2-ami-tools +20 -0
  68. data/test/05_config/00_setup_test.rb +20 -0
  69. data/test/05_config/30_machines_test.rb +69 -0
  70. data/test/20_sdb/00_setup_test.rb +16 -0
  71. data/test/20_sdb/10_domains_test.rb +115 -0
  72. data/test/25_ec2/00_setup_test.rb +29 -0
  73. data/test/25_ec2/10_keypairs_test.rb +41 -0
  74. data/test/25_ec2/20_groups_test.rb +131 -0
  75. data/test/25_ec2/30_addresses_test.rb +38 -0
  76. data/test/25_ec2/40_volumes_test.rb +49 -0
  77. data/test/25_ec2/50_snapshots_test.rb +74 -0
  78. data/test/26_ec2_instances/00_setup_test.rb +28 -0
  79. data/test/26_ec2_instances/10_instances_test.rb +83 -0
  80. data/test/26_ec2_instances/50_images_test.rb +13 -0
  81. data/test/30_sdb_metadata/00_setup_test.rb +21 -0
  82. data/test/30_sdb_metadata/10_disks_test.rb +109 -0
  83. data/test/30_sdb_metadata/20_backups_test.rb +102 -0
  84. data/test/coverage.txt +51 -0
  85. data/test/helper.rb +36 -0
  86. data/vendor/highline-1.5.1/CHANGELOG +222 -0
  87. data/vendor/highline-1.5.1/INSTALL +35 -0
  88. data/vendor/highline-1.5.1/LICENSE +7 -0
  89. data/vendor/highline-1.5.1/README +63 -0
  90. data/vendor/highline-1.5.1/Rakefile +82 -0
  91. data/vendor/highline-1.5.1/TODO +6 -0
  92. data/vendor/highline-1.5.1/examples/ansi_colors.rb +38 -0
  93. data/vendor/highline-1.5.1/examples/asking_for_arrays.rb +18 -0
  94. data/vendor/highline-1.5.1/examples/basic_usage.rb +75 -0
  95. data/vendor/highline-1.5.1/examples/color_scheme.rb +32 -0
  96. data/vendor/highline-1.5.1/examples/limit.rb +12 -0
  97. data/vendor/highline-1.5.1/examples/menus.rb +65 -0
  98. data/vendor/highline-1.5.1/examples/overwrite.rb +19 -0
  99. data/vendor/highline-1.5.1/examples/page_and_wrap.rb +322 -0
  100. data/vendor/highline-1.5.1/examples/password.rb +7 -0
  101. data/vendor/highline-1.5.1/examples/trapping_eof.rb +22 -0
  102. data/vendor/highline-1.5.1/examples/using_readline.rb +17 -0
  103. data/vendor/highline-1.5.1/lib/highline.rb +758 -0
  104. data/vendor/highline-1.5.1/lib/highline/color_scheme.rb +120 -0
  105. data/vendor/highline-1.5.1/lib/highline/compatibility.rb +17 -0
  106. data/vendor/highline-1.5.1/lib/highline/import.rb +43 -0
  107. data/vendor/highline-1.5.1/lib/highline/menu.rb +395 -0
  108. data/vendor/highline-1.5.1/lib/highline/question.rb +463 -0
  109. data/vendor/highline-1.5.1/lib/highline/system_extensions.rb +193 -0
  110. data/vendor/highline-1.5.1/setup.rb +1360 -0
  111. data/vendor/highline-1.5.1/test/tc_color_scheme.rb +56 -0
  112. data/vendor/highline-1.5.1/test/tc_highline.rb +823 -0
  113. data/vendor/highline-1.5.1/test/tc_import.rb +54 -0
  114. data/vendor/highline-1.5.1/test/tc_menu.rb +429 -0
  115. data/vendor/highline-1.5.1/test/ts_all.rb +15 -0
  116. metadata +141 -38
  117. data/lib/aws_sdb.rb +0 -3
  118. data/lib/aws_sdb/error.rb +0 -42
  119. data/lib/aws_sdb/service.rb +0 -215
  120. data/lib/rudy/aws/simpledb.rb +0 -53
  121. data/lib/rudy/command/addresses.rb +0 -46
  122. data/lib/rudy/command/backups.rb +0 -175
  123. data/lib/rudy/command/base.rb +0 -841
  124. data/lib/rudy/command/deploy.rb +0 -12
  125. data/lib/rudy/command/disks.rb +0 -213
  126. data/lib/rudy/command/environment.rb +0 -73
  127. data/lib/rudy/command/groups.rb +0 -61
  128. data/lib/rudy/command/images.rb +0 -91
  129. data/lib/rudy/command/instances.rb +0 -85
  130. data/lib/rudy/command/machines.rb +0 -161
  131. data/lib/rudy/command/metadata.rb +0 -41
  132. data/lib/rudy/command/release.rb +0 -174
  133. data/lib/rudy/command/volumes.rb +0 -66
  134. data/lib/rudy/metadata/disk.rb +0 -138
  135. data/tryouts/console_tryout.rb +0 -91
@@ -0,0 +1,56 @@
1
+ #!/usr/local/bin/ruby -w
2
+
3
+ # tc_color_scheme.rb
4
+ #
5
+ # Created by Jeremy Hinegardner on 2007-01-24.
6
+ # Copyright 2007 Jeremy Hinegardner. All rights reserved.
7
+ #
8
+ # This is Free Software. See LICENSE and COPYING for details.
9
+
10
+ require "test/unit"
11
+
12
+ require "highline"
13
+ require "stringio"
14
+
15
+ class TestColorScheme < Test::Unit::TestCase
16
+ def setup
17
+ @input = StringIO.new
18
+ @output = StringIO.new
19
+ @terminal = HighLine.new(@input, @output)
20
+
21
+ @old_color_scheme = HighLine.color_scheme
22
+ end
23
+
24
+ def teardown
25
+ HighLine.color_scheme = @old_color_scheme
26
+ end
27
+
28
+ def test_using_color_scheme
29
+ assert_equal(false,HighLine.using_color_scheme?)
30
+
31
+ HighLine.color_scheme = HighLine::ColorScheme.new
32
+ assert_equal(true,HighLine.using_color_scheme?)
33
+ end
34
+
35
+ def test_scheme
36
+ HighLine.color_scheme = HighLine::SampleColorScheme.new
37
+
38
+ @terminal.say("This should be <%= color('warning yellow', :warning) %>.")
39
+ assert_equal("This should be \e[1m\e[33mwarning yellow\e[0m.\n",@output.string)
40
+ @output.rewind
41
+
42
+ @terminal.say("This should be <%= color('warning yellow', 'warning') %>.")
43
+ assert_equal("This should be \e[1m\e[33mwarning yellow\e[0m.\n",@output.string)
44
+ @output.rewind
45
+
46
+ @terminal.say("This should be <%= color('warning yellow', 'WarNing') %>.")
47
+ assert_equal("This should be \e[1m\e[33mwarning yellow\e[0m.\n",@output.string)
48
+ @output.rewind
49
+
50
+ # turn it back off, should raise an exception
51
+ HighLine.color_scheme = @old_color_scheme
52
+ assert_raises(NameError) {
53
+ @terminal.say("This should be <%= color('nothing at all', :error) %>.")
54
+ }
55
+ end
56
+ end
@@ -0,0 +1,823 @@
1
+ #!/usr/local/bin/ruby -w
2
+
3
+ # tc_highline.rb
4
+ #
5
+ # Created by James Edward Gray II on 2005-04-26.
6
+ # Copyright 2005 Gray Productions. All rights reserved.
7
+ #
8
+ # This is Free Software. See LICENSE and COPYING for details.
9
+
10
+ require "test/unit"
11
+
12
+ require "highline"
13
+ require "stringio"
14
+
15
+ if HighLine::CHARACTER_MODE == "Win32API"
16
+ class HighLine
17
+ # Override Windows' character reading so it's not tied to STDIN.
18
+ def get_character( input = STDIN )
19
+ input.getc
20
+ end
21
+ end
22
+ end
23
+
24
+ class TestHighLine < Test::Unit::TestCase
25
+ def setup
26
+ @input = StringIO.new
27
+ @output = StringIO.new
28
+ @terminal = HighLine.new(@input, @output)
29
+ end
30
+
31
+ def test_agree
32
+ @input << "y\nyes\nYES\nHell no!\nNo\n"
33
+ @input.rewind
34
+
35
+ assert_equal(true, @terminal.agree("Yes or no? "))
36
+ assert_equal(true, @terminal.agree("Yes or no? "))
37
+ assert_equal(true, @terminal.agree("Yes or no? "))
38
+ assert_equal(false, @terminal.agree("Yes or no? "))
39
+
40
+ @input.truncate(@input.rewind)
41
+ @input << "yellow"
42
+ @input.rewind
43
+
44
+ assert_equal(true, @terminal.agree("Yes or no? ", :getc))
45
+ end
46
+
47
+ def test_agree_with_block
48
+ @input << "\n\n"
49
+ @input.rewind
50
+
51
+ assert_equal(true, @terminal.agree("Yes or no? ") { |q| q.default = "y" })
52
+ assert_equal(false, @terminal.agree("Yes or no? ") { |q| q.default = "n" })
53
+ end
54
+
55
+ def test_ask
56
+ name = "James Edward Gray II"
57
+ @input << name << "\n"
58
+ @input.rewind
59
+
60
+ assert_equal(name, @terminal.ask("What is your name? "))
61
+
62
+ assert_raise(EOFError) { @terminal.ask("Any input left? ") }
63
+ end
64
+
65
+ def test_bug_fixes
66
+ # auto-complete bug
67
+ @input << "ruby\nRuby\n"
68
+ @input.rewind
69
+
70
+ languages = [:Perl, :Python, :Ruby]
71
+ answer = @terminal.ask( "What is your favorite programming language? ",
72
+ languages )
73
+ assert_equal(languages.last, answer)
74
+
75
+ @input.truncate(@input.rewind)
76
+ @input << "ruby\n"
77
+ @input.rewind
78
+
79
+ answer = @terminal.ask( "What is your favorite programming language? ",
80
+ languages ) do |q|
81
+ q.case = :capitalize
82
+ end
83
+ assert_equal(languages.last, answer)
84
+
85
+ # poor auto-complete error message
86
+ @input.truncate(@input.rewind)
87
+ @input << "lisp\nruby\n"
88
+ @input.rewind
89
+ @output.truncate(@output.rewind)
90
+
91
+ answer = @terminal.ask( "What is your favorite programming language? ",
92
+ languages ) do |q|
93
+ q.case = :capitalize
94
+ end
95
+ assert_equal(languages.last, answer)
96
+ assert_equal( "What is your favorite programming language? " +
97
+ "You must choose one of [:Perl, :Python, :Ruby].\n" +
98
+ "? ", @output.string )
99
+ end
100
+
101
+ def test_case_changes
102
+ @input << "jeg2\n"
103
+ @input.rewind
104
+
105
+ answer = @terminal.ask("Enter your initials ") do |q|
106
+ q.case = :up
107
+ end
108
+ assert_equal("JEG2", answer)
109
+
110
+ @input.truncate(@input.rewind)
111
+ @input << "cRaZY\n"
112
+ @input.rewind
113
+
114
+ answer = @terminal.ask("Enter a search string: ") do |q|
115
+ q.case = :down
116
+ end
117
+ assert_equal("crazy", answer)
118
+ end
119
+
120
+ def test_character_echo
121
+ @input << "password\r"
122
+ @input.rewind
123
+
124
+ answer = @terminal.ask("Please enter your password: ") do |q|
125
+ q.echo = "*"
126
+ end
127
+ assert_equal("password", answer)
128
+ assert_equal("Please enter your password: ********\n", @output.string)
129
+
130
+ @input.truncate(@input.rewind)
131
+ @input << "2"
132
+ @input.rewind
133
+ @output.truncate(@output.rewind)
134
+
135
+ answer = @terminal.ask( "Select an option (1, 2 or 3): ",
136
+ Integer ) do |q|
137
+ q.echo = "*"
138
+ q.character = true
139
+ end
140
+ assert_equal(2, answer)
141
+ assert_equal("Select an option (1, 2 or 3): *\n", @output.string)
142
+ end
143
+
144
+ def test_backspace_does_not_enter_prompt
145
+ @input << "\b\b"
146
+ @input.rewind
147
+ answer = @terminal.ask("Please enter your password: ") do |q|
148
+ q.echo = "*"
149
+ end
150
+ assert_equal("", answer)
151
+ assert_equal("Please enter your password: \n",@output.string)
152
+ end
153
+
154
+ def test_readline_on_non_echo_question_has_prompt
155
+ @input << "you can't see me"
156
+ @input.rewind
157
+ answer = @terminal.ask("Please enter some hidden text: ") do |q|
158
+ q.readline = true
159
+ q.echo = "*"
160
+ end
161
+ assert_equal("you can't see me", answer)
162
+ assert_equal("Please enter some hidden text: ****************\n",@output.string)
163
+ end
164
+
165
+ def test_character_reading
166
+ # WARNING: This method does NOT cover Unix and Windows savvy testing!
167
+ @input << "12345"
168
+ @input.rewind
169
+
170
+ answer = @terminal.ask("Enter a single digit: ", Integer) do |q|
171
+ q.character = :getc
172
+ end
173
+ assert_equal(1, answer)
174
+ end
175
+
176
+ def test_color
177
+ @terminal.say("This should be <%= BLUE %>blue<%= CLEAR %>!")
178
+ assert_equal("This should be \e[34mblue\e[0m!\n", @output.string)
179
+
180
+ @output.truncate(@output.rewind)
181
+
182
+ @terminal.say( "This should be " +
183
+ "<%= BOLD + ON_WHITE %>bold on white<%= CLEAR %>!" )
184
+ assert_equal( "This should be \e[1m\e[47mbold on white\e[0m!\n",
185
+ @output.string )
186
+
187
+ @output.truncate(@output.rewind)
188
+
189
+ @terminal.say("This should be <%= color('cyan', CYAN) %>!")
190
+ assert_equal("This should be \e[36mcyan\e[0m!\n", @output.string)
191
+
192
+ @output.truncate(@output.rewind)
193
+
194
+ @terminal.say( "This should be " +
195
+ "<%= color('blinking on red', :blink, :on_red) %>!" )
196
+ assert_equal( "This should be \e[5m\e[41mblinking on red\e[0m!\n",
197
+ @output.string )
198
+
199
+ @output.truncate(@output.rewind)
200
+
201
+ # turn off color
202
+ old_setting = HighLine.use_color?
203
+ assert_nothing_raised(Exception) { HighLine.use_color = false }
204
+ @terminal.say("This should be <%= color('cyan', CYAN) %>!")
205
+ assert_equal("This should be cyan!\n", @output.string)
206
+ HighLine.use_color = old_setting
207
+ end
208
+
209
+ def test_confirm
210
+ @input << "junk.txt\nno\nsave.txt\ny\n"
211
+ @input.rewind
212
+
213
+ answer = @terminal.ask("Enter a filename: ") do |q|
214
+ q.confirm = "Are you sure you want to overwrite <%= @answer %>? "
215
+ q.responses[:ask_on_error] = :question
216
+ end
217
+ assert_equal("save.txt", answer)
218
+ assert_equal( "Enter a filename: " +
219
+ "Are you sure you want to overwrite junk.txt? " +
220
+ "Enter a filename: " +
221
+ "Are you sure you want to overwrite save.txt? ",
222
+ @output.string )
223
+
224
+ @input.truncate(@input.rewind)
225
+ @input << "junk.txt\nyes\nsave.txt\nn\n"
226
+ @input.rewind
227
+ @output.truncate(@output.rewind)
228
+
229
+ answer = @terminal.ask("Enter a filename: ") do |q|
230
+ q.confirm = "Are you sure you want to overwrite <%= @answer %>? "
231
+ end
232
+ assert_equal("junk.txt", answer)
233
+ assert_equal( "Enter a filename: " +
234
+ "Are you sure you want to overwrite junk.txt? ",
235
+ @output.string )
236
+ end
237
+
238
+ def test_defaults
239
+ @input << "\nNo Comment\n"
240
+ @input.rewind
241
+
242
+ answer = @terminal.ask("Are you sexually active? ") do |q|
243
+ q.validate = /\Ay(?:es)?|no?|no comment\Z/i
244
+ end
245
+ assert_equal("No Comment", answer)
246
+
247
+ @input.truncate(@input.rewind)
248
+ @input << "\nYes\n"
249
+ @input.rewind
250
+ @output.truncate(@output.rewind)
251
+
252
+ answer = @terminal.ask("Are you sexually active? ") do |q|
253
+ q.default = "No Comment"
254
+ q.validate = /\Ay(?:es)?|no?|no comment\Z/i
255
+ end
256
+ assert_equal("No Comment", answer)
257
+ assert_equal( "Are you sexually active? |No Comment| ",
258
+ @output.string )
259
+ end
260
+
261
+ def test_empty
262
+ @input << "\n"
263
+ @input.rewind
264
+
265
+ answer = @terminal.ask("") do |q|
266
+ q.default = "yes"
267
+ q.validate = /\Ay(?:es)?|no?\Z/i
268
+ end
269
+ assert_equal("yes", answer)
270
+ end
271
+
272
+ def test_erb
273
+ @terminal.say( "The integers from 1 to 10 are:\n" +
274
+ "% (1...10).each do |n|\n" +
275
+ "\t<%= n %>,\n" +
276
+ "% end\n" +
277
+ "\tand 10" )
278
+ assert_equal( "The integers from 1 to 10 are:\n" +
279
+ "\t1,\n\t2,\n\t3,\n\t4,\n\t5,\n" +
280
+ "\t6,\n\t7,\n\t8,\n\t9,\n\tand 10\n",
281
+ @output.string )
282
+ end
283
+
284
+ def test_files
285
+ @input << "#{File.basename(__FILE__)[0, 5]}\n"
286
+ @input.rewind
287
+
288
+ file = @terminal.ask("Select a file: ", File) do |q|
289
+ q.directory = File.expand_path(File.dirname(__FILE__))
290
+ q.glob = "*.rb"
291
+ end
292
+ assert_instance_of(File, file)
293
+ assert_equal("#!/usr/local/bin/ruby -w\n", file.gets)
294
+ assert_equal("\n", file.gets)
295
+ assert_equal("# tc_highline.rb\n", file.gets)
296
+ file.close
297
+
298
+ @input.rewind
299
+
300
+ pathname = @terminal.ask("Select a file: ", Pathname) do |q|
301
+ q.directory = File.expand_path(File.dirname(__FILE__))
302
+ q.glob = "*.rb"
303
+ end
304
+ assert_instance_of(Pathname, pathname)
305
+ assert_equal(File.size(__FILE__), pathname.size)
306
+ end
307
+
308
+ def test_gather
309
+ @input << "James\nDana\nStorm\nGypsy\n\n"
310
+ @input.rewind
311
+
312
+ answers = @terminal.ask("Enter four names:") do |q|
313
+ q.gather = 4
314
+ end
315
+ assert_equal(%w{James Dana Storm Gypsy}, answers)
316
+ assert_equal("\n", @input.gets)
317
+ assert_equal("Enter four names:\n", @output.string)
318
+
319
+ @input.rewind
320
+
321
+ answers = @terminal.ask("Enter four names:") do |q|
322
+ q.gather = ""
323
+ end
324
+ assert_equal(%w{James Dana Storm Gypsy}, answers)
325
+
326
+ @input.rewind
327
+
328
+ answers = @terminal.ask("Enter four names:") do |q|
329
+ q.gather = /^\s*$/
330
+ end
331
+ assert_equal(%w{James Dana Storm Gypsy}, answers)
332
+
333
+ @input.truncate(@input.rewind)
334
+ @input << "29\n49\n30\n"
335
+ @input.rewind
336
+ @output.truncate(@output.rewind)
337
+
338
+ answers = @terminal.ask("<%= @key %>: ", Integer) do |q|
339
+ q.gather = { "Age" => 0, "Wife's Age" => 0, "Father's Age" => 0}
340
+ end
341
+ assert_equal( { "Age" => 29, "Wife's Age" => 30, "Father's Age" => 49},
342
+ answers )
343
+ assert_equal("Age: Father's Age: Wife's Age: ", @output.string)
344
+ end
345
+
346
+ def test_lists
347
+ digits = %w{Zero One Two Three Four Five Six Seven Eight Nine}
348
+ erb_digits = digits.dup
349
+ erb_digits[erb_digits.index("Five")] = "<%= color('Five', :blue) %%>"
350
+
351
+ @terminal.say("<%= list(#{digits.inspect}) %>")
352
+ assert_equal(digits.map { |d| "#{d}\n" }.join, @output.string)
353
+
354
+ @output.truncate(@output.rewind)
355
+
356
+ @terminal.say("<%= list(#{digits.inspect}, :inline) %>")
357
+ assert_equal( digits[0..-2].join(", ") + " or #{digits.last}\n",
358
+ @output.string )
359
+
360
+ @output.truncate(@output.rewind)
361
+
362
+ @terminal.say("<%= list(#{digits.inspect}, :inline, ' and ') %>")
363
+ assert_equal( digits[0..-2].join(", ") + " and #{digits.last}\n",
364
+ @output.string )
365
+
366
+ @output.truncate(@output.rewind)
367
+
368
+ @terminal.say("<%= list(#{digits.inspect}, :columns_down, 3) %>")
369
+ assert_equal( "Zero Four Eight\n" +
370
+ "One Five Nine \n" +
371
+ "Two Six \n" +
372
+ "Three Seven\n",
373
+ @output.string )
374
+
375
+ @output.truncate(@output.rewind)
376
+
377
+ @terminal.say("<%= list(#{erb_digits.inspect}, :columns_down, 3) %>")
378
+ assert_equal( "Zero Four Eight\n" +
379
+ "One \e[34mFive\e[0m Nine \n" +
380
+ "Two Six \n" +
381
+ "Three Seven\n",
382
+ @output.string )
383
+
384
+ colums_of_twenty = ["12345678901234567890"] * 5
385
+
386
+ @output.truncate(@output.rewind)
387
+
388
+ @terminal.say("<%= list(#{colums_of_twenty.inspect}, :columns_down) %>")
389
+ assert_equal( "12345678901234567890 12345678901234567890 " +
390
+ "12345678901234567890\n" +
391
+ "12345678901234567890 12345678901234567890\n",
392
+ @output.string )
393
+
394
+ @output.truncate(@output.rewind)
395
+
396
+ @terminal.say("<%= list(#{digits.inspect}, :columns_across, 3) %>")
397
+ assert_equal( "Zero One Two \n" +
398
+ "Three Four Five \n" +
399
+ "Six Seven Eight\n" +
400
+ "Nine \n",
401
+ @output.string )
402
+
403
+ colums_of_twenty.pop
404
+
405
+ @output.truncate(@output.rewind)
406
+
407
+ @terminal.say("<%= list( #{colums_of_twenty.inspect}, :columns_across ) %>")
408
+ assert_equal( "12345678901234567890 12345678901234567890 " +
409
+ "12345678901234567890\n" +
410
+ "12345678901234567890\n",
411
+ @output.string )
412
+ end
413
+
414
+ def test_mode
415
+ assert(%w[Win32API termios stty].include?(HighLine::CHARACTER_MODE))
416
+ end
417
+
418
+ class NameClass
419
+ def self.parse( string )
420
+ if string =~ /^\s*(\w+),\s*(\w+)\s+(\w+)\s*$/
421
+ self.new($2, $3, $1)
422
+ else
423
+ raise ArgumentError, "Invalid name format."
424
+ end
425
+ end
426
+
427
+ def initialize(first, middle, last)
428
+ @first, @middle, @last = first, middle, last
429
+ end
430
+
431
+ attr_reader :first, :middle, :last
432
+ end
433
+
434
+ def test_my_class_conversion
435
+ @input << "Gray, James Edward\n"
436
+ @input.rewind
437
+
438
+ answer = @terminal.ask("Your name? ", NameClass) do |q|
439
+ q.validate = lambda do |name|
440
+ names = name.split(/,\s*/)
441
+ return false unless names.size == 2
442
+ return false if names.first =~ /\s/
443
+ names.last.split.size == 2
444
+ end
445
+ end
446
+ assert_instance_of(NameClass, answer)
447
+ assert_equal("Gray", answer.last)
448
+ assert_equal("James", answer.first)
449
+ assert_equal("Edward", answer.middle)
450
+ end
451
+
452
+ def test_no_echo
453
+ @input << "password\r"
454
+ @input.rewind
455
+
456
+ answer = @terminal.ask("Please enter your password: ") do |q|
457
+ q.echo = false
458
+ end
459
+ assert_equal("password", answer)
460
+ assert_equal("Please enter your password: \n", @output.string)
461
+
462
+ @input.rewind
463
+ @output.truncate(@output.rewind)
464
+
465
+ answer = @terminal.ask("Pick a letter or number: ") do |q|
466
+ q.character = true
467
+ q.echo = false
468
+ end
469
+ assert_equal("p", answer)
470
+ assert_equal("a", @input.getc.chr)
471
+ assert_equal("Pick a letter or number: \n", @output.string)
472
+ end
473
+
474
+ def test_paging
475
+ @terminal.page_at = 22
476
+
477
+ @input << "\n\n"
478
+ @input.rewind
479
+
480
+ @terminal.say((1..50).map { |n| "This is line #{n}.\n"}.join)
481
+ assert_equal( (1..22).map { |n| "This is line #{n}.\n"}.join +
482
+ "\n-- press enter/return to continue or q to stop -- \n\n" +
483
+ (23..44).map { |n| "This is line #{n}.\n"}.join +
484
+ "\n-- press enter/return to continue or q to stop -- \n\n" +
485
+ (45..50).map { |n| "This is line #{n}.\n"}.join,
486
+ @output.string )
487
+ end
488
+
489
+ def test_range_requirements
490
+ @input << "112\n-541\n28\n"
491
+ @input.rewind
492
+
493
+ answer = @terminal.ask("Tell me your age.", Integer) do |q|
494
+ q.in = 0..105
495
+ end
496
+ assert_equal(28, answer)
497
+ assert_equal( "Tell me your age.\n" +
498
+ "Your answer isn't within the expected range " +
499
+ "(included in 0..105).\n" +
500
+ "? " +
501
+ "Your answer isn't within the expected range " +
502
+ "(included in 0..105).\n" +
503
+ "? ", @output.string )
504
+
505
+ @input.truncate(@input.rewind)
506
+ @input << "1\n-541\n28\n"
507
+ @input.rewind
508
+ @output.truncate(@output.rewind)
509
+
510
+ answer = @terminal.ask("Tell me your age.", Integer) do |q|
511
+ q.above = 3
512
+ end
513
+ assert_equal(28, answer)
514
+ assert_equal( "Tell me your age.\n" +
515
+ "Your answer isn't within the expected range " +
516
+ "(above 3).\n" +
517
+ "? " +
518
+ "Your answer isn't within the expected range " +
519
+ "(above 3).\n" +
520
+ "? ", @output.string )
521
+
522
+ @input.truncate(@input.rewind)
523
+ @input << "1\n28\n-541\n"
524
+ @input.rewind
525
+ @output.truncate(@output.rewind)
526
+
527
+ answer = @terminal.ask("Lowest numer you can think of?", Integer) do |q|
528
+ q.below = 0
529
+ end
530
+ assert_equal(-541, answer)
531
+ assert_equal( "Lowest numer you can think of?\n" +
532
+ "Your answer isn't within the expected range " +
533
+ "(below 0).\n" +
534
+ "? " +
535
+ "Your answer isn't within the expected range " +
536
+ "(below 0).\n" +
537
+ "? ", @output.string )
538
+
539
+ @input.truncate(@input.rewind)
540
+ @input << "1\n-541\n6\n"
541
+ @input.rewind
542
+ @output.truncate(@output.rewind)
543
+
544
+ answer = @terminal.ask("Enter a low even number: ", Integer) do |q|
545
+ q.above = 0
546
+ q.below = 10
547
+ q.in = [2, 4, 6, 8]
548
+ end
549
+ assert_equal(6, answer)
550
+ assert_equal( "Enter a low even number: " +
551
+ "Your answer isn't within the expected range " +
552
+ "(above 0, below 10, and included in [2, 4, 6, 8]).\n" +
553
+ "? " +
554
+ "Your answer isn't within the expected range " +
555
+ "(above 0, below 10, and included in [2, 4, 6, 8]).\n" +
556
+ "? ", @output.string )
557
+ end
558
+
559
+ def test_reask
560
+ number = 61676
561
+ @input << "Junk!\n" << number << "\n"
562
+ @input.rewind
563
+
564
+ answer = @terminal.ask("Favorite number? ", Integer)
565
+ assert_kind_of(Integer, number)
566
+ assert_instance_of(Fixnum, number)
567
+ assert_equal(number, answer)
568
+ assert_equal( "Favorite number? " +
569
+ "You must enter a valid Integer.\n" +
570
+ "? ", @output.string )
571
+
572
+ @input.rewind
573
+ @output.truncate(@output.rewind)
574
+
575
+ answer = @terminal.ask("Favorite number? ", Integer) do |q|
576
+ q.responses[:ask_on_error] = :question
577
+ q.responses[:invalid_type] = "Not a valid number!"
578
+ end
579
+ assert_kind_of(Integer, number)
580
+ assert_instance_of(Fixnum, number)
581
+ assert_equal(number, answer)
582
+ assert_equal( "Favorite number? " +
583
+ "Not a valid number!\n" +
584
+ "Favorite number? ", @output.string )
585
+
586
+ @input.truncate(@input.rewind)
587
+ @input << "gen\ngene\n"
588
+ @input.rewind
589
+ @output.truncate(@output.rewind)
590
+
591
+ answer = @terminal.ask("Select a mode: ", [:generate, :gentle])
592
+ assert_instance_of(Symbol, answer)
593
+ assert_equal(:generate, answer)
594
+ assert_equal( "Select a mode: " +
595
+ "Ambiguous choice. " +
596
+ "Please choose one of [:generate, :gentle].\n" +
597
+ "? ", @output.string )
598
+ end
599
+
600
+ def test_response_embedding
601
+ @input << "112\n-541\n28\n"
602
+ @input.rewind
603
+
604
+ answer = @terminal.ask("Tell me your age.", Integer) do |q|
605
+ q.in = 0..105
606
+ q.responses[:not_in_range] = "Need a <%= @question.answer_type %>" +
607
+ " <%= @question.expected_range %>."
608
+ end
609
+ assert_equal(28, answer)
610
+ assert_equal( "Tell me your age.\n" +
611
+ "Need a Integer included in 0..105.\n" +
612
+ "? " +
613
+ "Need a Integer included in 0..105.\n" +
614
+ "? ", @output.string )
615
+ end
616
+
617
+ def test_say
618
+ @terminal.say("This will have a newline.")
619
+ assert_equal("This will have a newline.\n", @output.string)
620
+
621
+ @output.truncate(@output.rewind)
622
+
623
+ @terminal.say("This will also have one newline.\n")
624
+ assert_equal("This will also have one newline.\n", @output.string)
625
+
626
+ @output.truncate(@output.rewind)
627
+
628
+ @terminal.say("This will not have a newline. ")
629
+ assert_equal("This will not have a newline. ", @output.string)
630
+ end
631
+
632
+ def test_type_conversion
633
+ number = 61676
634
+ @input << number << "\n"
635
+ @input.rewind
636
+
637
+ answer = @terminal.ask("Favorite number? ", Integer)
638
+ assert_kind_of(Integer, answer)
639
+ assert_instance_of(Fixnum, answer)
640
+ assert_equal(number, answer)
641
+
642
+ @input.truncate(@input.rewind)
643
+ number = 1_000_000_000_000_000_000_000_000_000_000
644
+ @input << number << "\n"
645
+ @input.rewind
646
+
647
+ answer = @terminal.ask("Favorite number? ", Integer)
648
+ assert_kind_of(Integer, answer)
649
+ assert_instance_of(Bignum, answer)
650
+ assert_equal(number, answer)
651
+
652
+ @input.truncate(@input.rewind)
653
+ number = 10.5002
654
+ @input << number << "\n"
655
+ @input.rewind
656
+
657
+ answer = @terminal.ask( "Favorite number? ",
658
+ lambda { |n| n.to_f.abs.round } )
659
+ assert_kind_of(Integer, answer)
660
+ assert_instance_of(Fixnum, answer)
661
+ assert_equal(11, answer)
662
+
663
+ @input.truncate(@input.rewind)
664
+ animal = :dog
665
+ @input << animal << "\n"
666
+ @input.rewind
667
+
668
+ answer = @terminal.ask("Favorite animal? ", Symbol)
669
+ assert_instance_of(Symbol, answer)
670
+ assert_equal(animal, answer)
671
+
672
+ @input.truncate(@input.rewind)
673
+ @input << "16th June 1976\n"
674
+ @input.rewind
675
+
676
+ answer = @terminal.ask("Enter your birthday.", Date)
677
+ assert_instance_of(Date, answer)
678
+ assert_equal(16, answer.day)
679
+ assert_equal(6, answer.month)
680
+ assert_equal(1976, answer.year)
681
+
682
+ @input.truncate(@input.rewind)
683
+ pattern = "^yes|no$"
684
+ @input << pattern << "\n"
685
+ @input.rewind
686
+
687
+ answer = @terminal.ask("Give me a pattern to match with: ", Regexp)
688
+ assert_instance_of(Regexp, answer)
689
+ assert_equal(/#{pattern}/, answer)
690
+
691
+ @input.truncate(@input.rewind)
692
+ @input << "gen\n"
693
+ @input.rewind
694
+
695
+ answer = @terminal.ask("Select a mode: ", [:generate, :run])
696
+ assert_instance_of(Symbol, answer)
697
+ assert_equal(:generate, answer)
698
+ end
699
+
700
+ def test_validation
701
+ @input << "system 'rm -rf /'\n105\n0b101_001\n"
702
+ @input.rewind
703
+
704
+ answer = @terminal.ask("Enter a binary number: ") do |q|
705
+ q.validate = /\A(?:0b)?[01_]+\Z/
706
+ end
707
+ assert_equal("0b101_001", answer)
708
+ assert_equal( "Enter a binary number: " +
709
+ "Your answer isn't valid " +
710
+ "(must match /\\A(?:0b)?[01_]+\\Z/).\n" +
711
+ "? " +
712
+ "Your answer isn't valid " +
713
+ "(must match /\\A(?:0b)?[01_]+\\Z/).\n" +
714
+ "? ", @output.string )
715
+
716
+ @input.truncate(@input.rewind)
717
+ @input << "Gray II, James Edward\n" +
718
+ "Gray, Dana Ann Leslie\n" +
719
+ "Gray, James Edward\n"
720
+ @input.rewind
721
+
722
+ answer = @terminal.ask("Your name? ") do |q|
723
+ q.validate = lambda do |name|
724
+ names = name.split(/,\s*/)
725
+ return false unless names.size == 2
726
+ return false if names.first =~ /\s/
727
+ names.last.split.size == 2
728
+ end
729
+ end
730
+ assert_equal("Gray, James Edward", answer)
731
+ end
732
+
733
+ def test_whitespace
734
+ @input << " A lot\tof \t space\t \there! \n"
735
+ @input.rewind
736
+
737
+ answer = @terminal.ask("Enter a whitespace filled string: ") do |q|
738
+ q.whitespace = :chomp
739
+ end
740
+ assert_equal(" A lot\tof \t space\t \there! ", answer)
741
+
742
+ @input.rewind
743
+
744
+ answer = @terminal.ask("Enter a whitespace filled string: ")
745
+ assert_equal("A lot\tof \t space\t \there!", answer)
746
+
747
+ @input.rewind
748
+
749
+ answer = @terminal.ask("Enter a whitespace filled string: ") do |q|
750
+ q.whitespace = :strip_and_collapse
751
+ end
752
+ assert_equal("A lot of space here!", answer)
753
+
754
+ @input.rewind
755
+
756
+ answer = @terminal.ask("Enter a whitespace filled string: ") do |q|
757
+ q.whitespace = :remove
758
+ end
759
+ assert_equal("Alotofspacehere!", answer)
760
+
761
+ @input.rewind
762
+
763
+ answer = @terminal.ask("Enter a whitespace filled string: ") do |q|
764
+ q.whitespace = :none
765
+ end
766
+ assert_equal(" A lot\tof \t space\t \there! \n", answer)
767
+ end
768
+
769
+ def test_wrap
770
+ @terminal.wrap_at = 80
771
+
772
+ @terminal.say("This is a very short line.")
773
+ assert_equal("This is a very short line.\n", @output.string)
774
+
775
+ @output.truncate(@output.rewind)
776
+
777
+ @terminal.say( "This is a long flowing paragraph meant to span " +
778
+ "several lines. This text should definitely be " +
779
+ "wrapped at the set limit, in the result. Your code " +
780
+ "does well with things like this.\n\n" +
781
+ " * This is a simple embedded list.\n" +
782
+ " * You're code should not mess with this...\n" +
783
+ " * Because it's already formatted correctly and " +
784
+ "does not\n" +
785
+ " exceed the limit!" )
786
+ assert_equal( "This is a long flowing paragraph meant to span " +
787
+ "several lines. This text should\n" +
788
+ "definitely be wrapped at the set limit, in the " +
789
+ "result. Your code does well with\n" +
790
+ "things like this.\n\n" +
791
+ " * This is a simple embedded list.\n" +
792
+ " * You're code should not mess with this...\n" +
793
+ " * Because it's already formatted correctly and does " +
794
+ "not\n" +
795
+ " exceed the limit!\n", @output.string )
796
+
797
+ @output.truncate(@output.rewind)
798
+
799
+ @terminal.say("-=" * 50)
800
+ assert_equal(("-=" * 40 + "\n") + ("-=" * 10 + "\n"), @output.string)
801
+ end
802
+
803
+ def test_track_eof
804
+ assert_raise(EOFError) { @terminal.ask("Any input left? ") }
805
+
806
+ # turn EOF tracking
807
+ old_setting = HighLine.track_eof?
808
+ assert_nothing_raised(Exception) { HighLine.track_eof = false }
809
+ begin
810
+ @terminal.ask("And now? ") # this will still blow up, nothing available
811
+ rescue
812
+ assert_not_equal(EOFError, $!.class) # but HighLine's safe guards are off
813
+ end
814
+ HighLine.track_eof = old_setting
815
+ end
816
+
817
+ def test_version
818
+ assert_not_nil(HighLine::VERSION)
819
+ assert_instance_of(String, HighLine::VERSION)
820
+ assert(HighLine::VERSION.frozen?)
821
+ assert_match(/\A\d\.\d\.\d\Z/, HighLine::VERSION)
822
+ end
823
+ end