rubyment 0.6.25484655 → 0.6.25503334
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.
- checksums.yaml +4 -4
- data/lib/rubyment.rb +656 -78
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1d2807035baddb1234c0afa87f542e51ba5f296d
|
4
|
+
data.tar.gz: 4c07bbab0d4c586d9969d7976b79fea603cc94f5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fa5fa82d9a68feae96c61808c7ee43ed91ab9f5718ffd8bb11621be9f7cb14fe7a0622ee30f7df8331298c5bb3856df379e601514dce8c564e839221edae6a50
|
7
|
+
data.tar.gz: e9f1a8161d423e43e9238bc2c6b24d6a8439498cbf0e807724402a975cdfe665656566ec42808a7935179173c008fe271298d1c492cec63999dd1b4ee2378dfb
|
data/lib/rubyment.rb
CHANGED
@@ -1,30 +1,60 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
3
|
|
4
|
-
class
|
5
|
-
#
|
6
|
-
#
|
7
|
-
|
8
|
-
|
9
|
-
# function interprets "" as false
|
10
|
-
#
|
11
|
-
# @return [String, nil] self or nil
|
12
|
-
def nne
|
13
|
-
!self.empty? && self || nil
|
4
|
+
class TrueClass
|
5
|
+
# returns +false+ (purpose of simplifying
|
6
|
+
# functional programming)
|
7
|
+
def false?
|
8
|
+
false
|
14
9
|
end
|
15
10
|
end
|
16
11
|
|
17
12
|
|
18
|
-
class
|
19
|
-
#
|
13
|
+
class Object
|
14
|
+
# returns +self+ if +self+ is not considered
|
15
|
+
# to be the neutral element of its class.
|
16
|
+
# an object is considered to the neutral
|
17
|
+
# element if it answers +true+ to any of
|
18
|
+
# a global +asserting_methods+ list.
|
19
|
+
# this list is by now the following:
|
20
|
+
# [ empty?, :zero?, :false? ]
|
21
|
+
# but it will grow as more classes are
|
22
|
+
# known to have different +asserting_methods+.
|
23
|
+
# it returns +nil+ when the element is
|
24
|
+
# considered the neutral element.
|
20
25
|
#
|
21
|
-
# data from
|
22
|
-
#
|
23
|
-
#
|
26
|
+
# data from other languagues, like most
|
27
|
+
# shell input, can't be +nil+ so sometimes
|
28
|
+
# "" has to be interpreted as +nil+. so,
|
29
|
+
# one example usage of the neutral element
|
30
|
+
# concept.
|
24
31
|
#
|
25
|
-
|
26
|
-
|
27
|
-
|
32
|
+
def nne default=nil
|
33
|
+
asserting_methods = [
|
34
|
+
:empty?,
|
35
|
+
:zero?,
|
36
|
+
:false?,
|
37
|
+
]
|
38
|
+
responds_false_to = asserting_methods.map { |am|
|
39
|
+
(self.respond_to? am) && (
|
40
|
+
self.method(am).call.negate_me
|
41
|
+
) || nil
|
42
|
+
}
|
43
|
+
responds_false_to.any? && self || default
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
# returns nil out of an object.
|
48
|
+
# usage examples:
|
49
|
+
# "this_parameter_is_nil".to_nil
|
50
|
+
def to_nil
|
51
|
+
nil
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
# returns +!self+
|
56
|
+
def negate_me
|
57
|
+
!self
|
28
58
|
end
|
29
59
|
end
|
30
60
|
|
@@ -92,6 +122,8 @@ class Rubyment
|
|
92
122
|
rv = [e.backtrace.join("\n"), e]
|
93
123
|
stderr.puts "#{__method__} exception backtrace:"
|
94
124
|
stderr.puts rv[0]
|
125
|
+
stderr.puts "#{__method__} exception inspection:"
|
126
|
+
stderr.puts rv[1].inspect
|
95
127
|
stderr.puts "#{__method__} exception message:"
|
96
128
|
stderr.puts rv[1]
|
97
129
|
rv
|
@@ -100,6 +132,29 @@ class Rubyment
|
|
100
132
|
end
|
101
133
|
|
102
134
|
|
135
|
+
# creates a +Proc+ out of a block,
|
136
|
+
# where exceptions may be admissible
|
137
|
+
# or not, and to be printed or not.
|
138
|
+
# it is an interface for the bl*
|
139
|
+
# methods above
|
140
|
+
# @param [splat] +args+, an splat whose elements are expected to be +blea_args+ and +blocks_args+:
|
141
|
+
# +blea_args+:: [Array] args to be used internally, which are expected to be:
|
142
|
+
# +exception_admitted+:: [Boolean]
|
143
|
+
# +output_exception+:: [Boolean]
|
144
|
+
# +blocks_args+:: [splat] args to be forwarded to the block call
|
145
|
+
# @return [Proc]
|
146
|
+
def blea *args, &block
|
147
|
+
blea_args, *block_args = args
|
148
|
+
blea_args ||= blea_args.nne []
|
149
|
+
exception_admitted, output_exception = blea_args
|
150
|
+
exception_admitted ||= exception_admitted.nne
|
151
|
+
output_exception ||= output_exception.nne
|
152
|
+
ble_method = output_exception && :bloe || :blef
|
153
|
+
bl_to_call = exception_admitted && ble_method || :bl
|
154
|
+
send bl_to_call, *block_args, &block
|
155
|
+
end
|
156
|
+
|
157
|
+
|
103
158
|
# runs a block error free
|
104
159
|
# (returns nil if exception happens)
|
105
160
|
def runef *args, &block
|
@@ -146,6 +201,22 @@ class Rubyment
|
|
146
201
|
end
|
147
202
|
|
148
203
|
|
204
|
+
# creates and runs a +Proc+ out of a block,
|
205
|
+
# where exceptions may be admissible
|
206
|
+
# or not, and to be printed or not.
|
207
|
+
# it is an interface for the run*
|
208
|
+
# methods above
|
209
|
+
# @param [splat] +args+, an splat whose elements are expected to be +blea_args+ and +blocks_args+:
|
210
|
+
# +blea_args+:: [Array] args to be used internally, which are expected to be:
|
211
|
+
# +exception_admitted+:: [Boolean]
|
212
|
+
# +output_exception+:: [Boolean]
|
213
|
+
# +blocks_args+:: [splat] args to be forwarded to the block call
|
214
|
+
# @return the value returned by the block
|
215
|
+
def runea *args, &block
|
216
|
+
(blea *args, &block).call
|
217
|
+
end
|
218
|
+
|
219
|
+
|
149
220
|
# invoke first arg with following args
|
150
221
|
# used by initialize
|
151
222
|
def invoke args=ARGV
|
@@ -220,6 +291,19 @@ class Rubyment
|
|
220
291
|
end
|
221
292
|
|
222
293
|
|
294
|
+
# compares the version of current rubyment with a given version.
|
295
|
+
# so users of rubyment can test if their code will run with
|
296
|
+
# the rubyment installed on the system.
|
297
|
+
# @param [splat] args, a list of object whose elements are expected to be:
|
298
|
+
# +major_version+:: [String]
|
299
|
+
# +minor_version+:: [String]
|
300
|
+
#
|
301
|
+
# @return [Bool] +true+ if rubyment (+self+) version is at least the version give as parameter, +false+ otherwise
|
302
|
+
def version_at_least *args
|
303
|
+
Gem::Version.new(version []) >= Gem::Version.new(version args)
|
304
|
+
end
|
305
|
+
|
306
|
+
|
223
307
|
# enables the possibility to inkove a second method with
|
224
308
|
# the results of a first one. eg, the results of a method
|
225
309
|
# called file_permissions_octal which returns without output
|
@@ -240,6 +324,21 @@ class Rubyment
|
|
240
324
|
end
|
241
325
|
|
242
326
|
|
327
|
+
# returns an enumeration of +method_name+ for each element in
|
328
|
+
# the enumeration +a+. Useful for heterogeneous arrays
|
329
|
+
# (like arrays of Strings, of Hashes, of Arrays and so on
|
330
|
+
def array_map a, method_name, method_args = nil
|
331
|
+
a.map {|e| e.method(method_name).call *method_args }
|
332
|
+
end
|
333
|
+
|
334
|
+
|
335
|
+
# the same as #array_map (but takes all arguments at once)
|
336
|
+
def array_maps args=ARGV
|
337
|
+
a, method_name, method_args = args
|
338
|
+
array_map a, method_name, method_args
|
339
|
+
end
|
340
|
+
|
341
|
+
|
243
342
|
# reads a uri (if 'open-uri' available, otherwise, just do a normal File.read)
|
244
343
|
# @param [Array] args, an +Array+ whose elements are expected to be:
|
245
344
|
# +uri+:: [String, nil] uri or path of the file
|
@@ -270,6 +369,31 @@ class Rubyment
|
|
270
369
|
end
|
271
370
|
|
272
371
|
|
372
|
+
# reads the contents of a file. if the file
|
373
|
+
# doesn't exist, writes to the file.
|
374
|
+
# note: the file may get overwritten with the
|
375
|
+
# same contents in some situations (not if
|
376
|
+
# +contents+ is +nil+).
|
377
|
+
# @param [splat] +args+::, an splat whose elements are expected to be:
|
378
|
+
# +filepath+:: [String] uri (if +'open-uri'+ installed) or local path to a file
|
379
|
+
# +username+:: [String] basic http authentication username
|
380
|
+
# +password+:: [String] basic http authentication password
|
381
|
+
# @return [String] file contents at the end of the process.
|
382
|
+
def file_read_or_write *args
|
383
|
+
filepath, contents, username, password = args
|
384
|
+
existing_file = file_read [
|
385
|
+
filepath,
|
386
|
+
username,
|
387
|
+
password,
|
388
|
+
"return on rescue".to_nil,
|
389
|
+
"return on dir".to_nil,
|
390
|
+
]
|
391
|
+
file_contents ||= existing_file || contents
|
392
|
+
contents && (File.write filepath, file_contents)
|
393
|
+
file_contents
|
394
|
+
end
|
395
|
+
|
396
|
+
|
273
397
|
# if file is a nonexisting filepath, or by any reason
|
274
398
|
# throws any exception, it will be treated as contents
|
275
399
|
# instead, and the filename will treated as ""
|
@@ -315,11 +439,57 @@ class Rubyment
|
|
315
439
|
end
|
316
440
|
|
317
441
|
|
442
|
+
def files_in_paths paths, reject_dirs=false
|
443
|
+
require 'find'
|
444
|
+
paths = paths.map {|path| Find.find(path).entries rescue [] }.flatten 1
|
445
|
+
reject_dirs && paths.reject{|path| File.directory? path} || paths
|
446
|
+
end
|
447
|
+
|
448
|
+
|
449
|
+
def files_in_paths_reject_dirs paths
|
450
|
+
files_in_paths paths, true
|
451
|
+
end
|
452
|
+
|
453
|
+
|
454
|
+
def files_call_in_paths paths, method, reject_dirs=false
|
455
|
+
paths = reject_dirs && (files_in_paths_reject_dirs paths) || paths
|
456
|
+
(files_in_paths paths).map {|path| method.call path }
|
457
|
+
end
|
458
|
+
|
459
|
+
|
460
|
+
def files_dirnames_in_paths paths, reject_dirs=false
|
461
|
+
# (files_in_paths paths).map {|path| File.dirname path }
|
462
|
+
files_call_in_paths paths, File.method(:dirname), reject_dirs
|
463
|
+
end
|
464
|
+
|
465
|
+
|
466
|
+
def files_basenames_in_paths paths, reject_dirs=false
|
467
|
+
files_call_in_paths paths, File.method(:basename), reject_dirs
|
468
|
+
end
|
469
|
+
|
470
|
+
|
471
|
+
def filename_replacer
|
472
|
+
[/[^0-9A-Za-z\-\.\/]/, "_" ]
|
473
|
+
end
|
474
|
+
|
475
|
+
|
318
476
|
# returns a string having the current backtrace, for debugging.
|
319
477
|
def backtrace
|
320
478
|
Thread.current.backtrace.join("\n")
|
321
479
|
end
|
322
480
|
|
481
|
+
def caller_labels begin_range=1, range_size=1
|
482
|
+
caller_locations(begin_range, range_size).map(&:label)
|
483
|
+
end
|
484
|
+
|
485
|
+
# return the last_called function
|
486
|
+
def caller_label *args
|
487
|
+
default, reserved = *args
|
488
|
+
default ||= 3
|
489
|
+
caller_labels(default, 1)[0]
|
490
|
+
end
|
491
|
+
|
492
|
+
|
323
493
|
# returns a Class object out of class_name (or itself if it is already
|
324
494
|
# a class)
|
325
495
|
def to_class args=ARGV
|
@@ -333,17 +503,18 @@ class Rubyment
|
|
333
503
|
|
334
504
|
|
335
505
|
# returns a Method (object.method if object is
|
336
|
-
# given).
|
337
|
-
# at the current context
|
338
|
-
# args:
|
339
|
-
#
|
340
|
-
#
|
506
|
+
# given) matching the name. Give +self+ as object
|
507
|
+
# to look up at the current context
|
508
|
+
# @param [Array] args, whose elements are:
|
509
|
+
# +name+:: [String, nil]
|
510
|
+
# +object+:: [Object]
|
511
|
+
# @returns:
|
341
512
|
# method_object (Method)
|
342
513
|
def to_object_method args=ARGV
|
343
514
|
stderr = @memory[:stderr]
|
344
515
|
name, object = containerize args
|
345
516
|
begin
|
346
|
-
|
517
|
+
object.method("method").call(name.to_s)
|
347
518
|
rescue NameError => nameError
|
348
519
|
# every object (even nil) has :method,
|
349
520
|
# and every Method has :call: exception
|
@@ -2032,8 +2203,7 @@ require '#{gem_name}'
|
|
2032
2203
|
prepend ||= ""
|
2033
2204
|
expected_new_filename = dest_dir + filename
|
2034
2205
|
existing_file = (file_read [filename, nil, user, pw])
|
2035
|
-
file_contents
|
2036
|
-
File.write filename, file_contents
|
2206
|
+
file_contents = file_read_or_write filename, "contents_of:#{filename}", user, pw
|
2037
2207
|
file_backup filename, dest_dir, append, prepend
|
2038
2208
|
new_file_contents = File.read expected_new_filename
|
2039
2209
|
original_permissions = file_permissions_octal filename
|
@@ -2045,6 +2215,7 @@ require '#{gem_name}'
|
|
2045
2215
|
].map(&method("expect_equal")).all?
|
2046
2216
|
(!existing_file) && (FileUtils.rm filename)
|
2047
2217
|
(!keep_new) && (FileUtils.rm expected_new_filename)
|
2218
|
+
judgement
|
2048
2219
|
end
|
2049
2220
|
|
2050
2221
|
|
@@ -2069,8 +2240,13 @@ require '#{gem_name}'
|
|
2069
2240
|
#
|
2070
2241
|
# @return [Method] a method
|
2071
2242
|
def to_method args = ARGV
|
2072
|
-
method_name_or_method, reserved = args
|
2073
|
-
|
2243
|
+
method_name_or_method, object, reserved = args
|
2244
|
+
(
|
2245
|
+
to_object_method [object, method_name_or_method]
|
2246
|
+
) || (
|
2247
|
+
method_name_or_method.respond_to?(:call) && method_name_or_method
|
2248
|
+
) ||
|
2249
|
+
method(method_name_or_method)
|
2074
2250
|
end
|
2075
2251
|
|
2076
2252
|
|
@@ -2088,13 +2264,16 @@ require '#{gem_name}'
|
|
2088
2264
|
# @param [Array] +args+, an +Array+ whose elements are expected to be:
|
2089
2265
|
# +processing_arg+:: [Object]
|
2090
2266
|
# +method+:: [Method, String]
|
2091
|
-
# +method_args+:: [
|
2267
|
+
# +method_args+:: [Array] args to be given to the +transform_method_name+
|
2268
|
+
# +on_object+:: [String, Boolean]
|
2092
2269
|
#
|
2093
2270
|
# @return [String] +processing_arg+
|
2094
|
-
def
|
2095
|
-
processing_arg, method, method_args = args
|
2271
|
+
def test__transform_call args = ARGV
|
2272
|
+
processing_arg, method, method_args, on_object = args
|
2273
|
+
object_arg = on_object.nne && processing_arg || nil
|
2274
|
+
p args
|
2096
2275
|
to_method(
|
2097
|
-
[method]).call(
|
2276
|
+
[method, object_arg]).call(
|
2098
2277
|
[processing_arg] + method_args
|
2099
2278
|
)
|
2100
2279
|
end
|
@@ -2106,23 +2285,32 @@ require '#{gem_name}'
|
|
2106
2285
|
# +content_type+:: [String, nil] mime type of payload (default +text/plain+)
|
2107
2286
|
# +version+:: [String, nil] http protocol version (+1.1+ by default)
|
2108
2287
|
# +code+:: [String, nil] response code (+"200 OK"+ by default)
|
2109
|
-
# +
|
2288
|
+
# +keep_alive+:: [Boolean] right not unsupported, always close the connection
|
2289
|
+
# +eol+:: [String, nil] response code (+"\r\n"+ by default/on +nil+)
|
2110
2290
|
#
|
2111
|
-
# @return [
|
2291
|
+
# @return [Array] response with proper headers in an array where each element is a response line
|
2112
2292
|
def http_OK_response args = ARGV
|
2113
|
-
payload, content_type, code, version, eol = args
|
2293
|
+
payload, content_type, code, version, keep_alive, debug, eol = args
|
2294
|
+
stderr = @memory[:stderr]
|
2295
|
+
debug.nne && (stderr.puts "#{__method__} starting")
|
2296
|
+
debug.nne && (stderr.puts args.inspect)
|
2114
2297
|
payload ||= ""
|
2298
|
+
payload = payload.to_s
|
2115
2299
|
content_type ||= "text/plain"
|
2116
2300
|
version ||= "1.1"
|
2117
2301
|
code ||= "200 OK"
|
2118
2302
|
eol ||= "\r\n"
|
2119
|
-
[
|
2303
|
+
rv = [
|
2120
2304
|
"HTTP/#{version} #{code}",
|
2121
2305
|
"Content-Type: #{content_type};" +
|
2122
2306
|
" charset=#{payload.encoding.name.downcase}",
|
2123
2307
|
"Content-Length: #{payload.bytesize}",
|
2124
|
-
|
2125
|
-
|
2308
|
+
keep_alive.negate_me && "Connection: close",
|
2309
|
+
"",
|
2310
|
+
"#{payload}"
|
2311
|
+
]
|
2312
|
+
debug.nne && (stderr.puts "#{__method__} returning")
|
2313
|
+
rv.join eol
|
2126
2314
|
end
|
2127
2315
|
|
2128
2316
|
|
@@ -2153,6 +2341,40 @@ require '#{gem_name}'
|
|
2153
2341
|
end
|
2154
2342
|
|
2155
2343
|
|
2344
|
+
# gets an input from +io+ and writes it back to the same +io+
|
2345
|
+
# supports an optional +replace+ and +replacement+ parameter
|
2346
|
+
# that can be used to make simple changes to the echoing output
|
2347
|
+
# @param [Array] +args+, an +Array+ whose elements are expected to be:
|
2348
|
+
# +io+:: [IO] any +IO+, like a +Socket+, returned by #TCPServer::accept
|
2349
|
+
# +debug+:: [Object] if evals to false (or empty string), won't print debug information
|
2350
|
+
# +transform_method_name+:: [String]
|
2351
|
+
# +transform_method_args+:: [Array] args to be given to the ++transform_method_name+
|
2352
|
+
# +happy_with_request+:: [String, nil] if nil, +eol+ is used.
|
2353
|
+
#
|
2354
|
+
# @return [nil]
|
2355
|
+
def io_transform args = ARGV
|
2356
|
+
io,
|
2357
|
+
debug,
|
2358
|
+
happy_with_request,
|
2359
|
+
transform_method_name,
|
2360
|
+
transform_method_args,
|
2361
|
+
reserved = args
|
2362
|
+
stderr = @memory[:stderr]
|
2363
|
+
debug.nne && (stderr.puts "#{__method__} starting")
|
2364
|
+
debug.nne && (stderr.puts "transform_method_name: #{transform_method_name}")
|
2365
|
+
debug.nne && (stderr.puts "transform_method_args: #{transform_method_args.inspect}")
|
2366
|
+
io_forward [[io], io, debug, happy_with_request, reserved,
|
2367
|
+
:test__transform_call, [
|
2368
|
+
transform_method_name,
|
2369
|
+
transform_method_args,
|
2370
|
+
"on_object:true",
|
2371
|
+
]
|
2372
|
+
]
|
2373
|
+
debug.nne && (stderr.puts "#{__method__} returning")
|
2374
|
+
nil
|
2375
|
+
end
|
2376
|
+
|
2377
|
+
|
2156
2378
|
# gets and forwards the input from one IO to a list of IOs
|
2157
2379
|
# @param [Array] +args+, an +Array+ whose elements are expected to be:
|
2158
2380
|
# +ios_out+:: [Array] array of +IO+, where data will be written to.
|
@@ -2186,9 +2408,9 @@ require '#{gem_name}'
|
|
2186
2408
|
ios_out.map{ |shared_io_out|
|
2187
2409
|
runoe_threaded(shared_io_out) {|io_out|
|
2188
2410
|
io_out = shared_io_out
|
2189
|
-
io_out.
|
2411
|
+
io_out.print processed_input
|
2190
2412
|
debug.nne && (
|
2191
|
-
stderr.puts "#{io_out}: response writen."
|
2413
|
+
stderr.puts "#{io_out}: #{processed_input.size} bytes: response writen."
|
2192
2414
|
)
|
2193
2415
|
io_out.close
|
2194
2416
|
debug.nne && (
|
@@ -2202,29 +2424,41 @@ require '#{gem_name}'
|
|
2202
2424
|
end
|
2203
2425
|
|
2204
2426
|
|
2205
|
-
# gets and
|
2427
|
+
# gets an input from +io+ and writes it back to the same +io+
|
2428
|
+
# supports an optional +replace+ and +replacement+ parameter
|
2429
|
+
# that can be used to make simple changes to the echoing output
|
2206
2430
|
# @param [Array] +args+, an +Array+ whose elements are expected to be:
|
2207
2431
|
# +io+:: [IO] any +IO+, like a +Socket+, returned by #TCPServer::accept
|
2208
|
-
# +method_name_or_method+:: [String, Method] method name or method object
|
2209
2432
|
# +debug+:: [Object] if evals to false (or empty string), won't print debug information
|
2433
|
+
# +replace+:: [String]
|
2434
|
+
# +replacement+:: [String]
|
2210
2435
|
# +happy_with_request+:: [String, nil] if nil, +eol+ is used.
|
2211
2436
|
#
|
2212
2437
|
# @return [nil]
|
2213
2438
|
def io_echo args = ARGV
|
2214
|
-
io, debug, happy_with_request, reserved = args
|
2439
|
+
io, debug, happy_with_request, replace, replacement, reserved = args
|
2440
|
+
# this is an inefficient replacement:
|
2441
|
+
replace ||= " "
|
2442
|
+
replacement ||= " "
|
2215
2443
|
stderr = @memory[:stderr]
|
2216
2444
|
debug.nne && (stderr.puts "#{__method__} starting")
|
2217
|
-
|
2218
|
-
|
2219
|
-
|
2445
|
+
io_transform [
|
2446
|
+
io,
|
2447
|
+
debug,
|
2448
|
+
happy_with_request,
|
2449
|
+
:array_maps,
|
2450
|
+
[
|
2451
|
+
:gsub!, [replace, replacement]
|
2452
|
+
],
|
2220
2453
|
]
|
2454
|
+
|
2455
|
+
debug.nne && (stderr.puts "#{__method__} returning")
|
2221
2456
|
nil
|
2222
2457
|
end
|
2223
2458
|
|
2224
2459
|
|
2225
2460
|
# writes a response to an IO (e.g.: socket)
|
2226
2461
|
# @param [Array] +args+, an +Array+ whose elements are expected to be:
|
2227
|
-
# +method_name_or_method+:: [String, Method] method name or method object
|
2228
2462
|
# +debug+:: [Object] if evals to false (or empty string), won't print debug information
|
2229
2463
|
# +reserved+:: [Object] for future use
|
2230
2464
|
# +args_for_http_OK_response+:: [splat] args to be forwarded to #http_OK_response (check it for specification)
|
@@ -2233,15 +2467,17 @@ require '#{gem_name}'
|
|
2233
2467
|
def io_http_OK_response args = ARGV
|
2234
2468
|
io, debug, reserved, *args_for_http_OK_response = args
|
2235
2469
|
stderr = @memory[:stderr]
|
2470
|
+
debug.nne && (stderr.puts "#{__method__} starting")
|
2236
2471
|
debug.nne && (stderr.puts args.inspect)
|
2237
2472
|
response = http_OK_response args_for_http_OK_response
|
2238
2473
|
debug.nne && (
|
2239
2474
|
stderr.puts response.inspect
|
2240
2475
|
)
|
2241
|
-
io.
|
2476
|
+
io.puts response
|
2242
2477
|
debug.nne && (stderr.puts "response writen.")
|
2243
2478
|
io.close
|
2244
2479
|
debug.nne && (stderr.puts "IO closed.")
|
2480
|
+
debug.nne && (stderr.puts "#{__method__} returning")
|
2245
2481
|
nil
|
2246
2482
|
end
|
2247
2483
|
|
@@ -2266,8 +2502,108 @@ require '#{gem_name}'
|
|
2266
2502
|
debug,
|
2267
2503
|
callback_method,
|
2268
2504
|
*callback_method_args = args
|
2505
|
+
|
2506
|
+
tcp_ssl_server [
|
2507
|
+
listening_port,
|
2508
|
+
ip_addr,
|
2509
|
+
debug,
|
2510
|
+
"admit non ssl server",
|
2511
|
+
callback_method,
|
2512
|
+
callback_method_args
|
2513
|
+
]
|
2514
|
+
end
|
2515
|
+
|
2516
|
+
|
2517
|
+
# makes an OpenSSL server
|
2518
|
+
# @param [splat] +args+, an splat whose elements are expected to be:
|
2519
|
+
# +listening_port+:: [String, Integer] port to listen
|
2520
|
+
# +ip_addr+:: [String, nil] ip (no hostname) to bind the server. 0, nil, false, empty string will bind to all addresses possible. 0.0.0.0 => binds to all ipv4 . ::0 to all ipv4 and ipv6
|
2521
|
+
# +admit_plain+:: [Boolean] if +true+, tries to create a normal +TCPServer+, if not possible to create +SSLServer+ (default: +false+, for preventing unadvertnt non-SSL server creation)
|
2522
|
+
# +debug+:: [Object] for future use
|
2523
|
+
# +priv_pemfile+:: [String] argument to be given to +OpenSSL::SSL::SSLContext.key+ method, after calling +OpenSSL::PKey::RSA.new+ with it. It's the private key file. letsencrypt example: +"/etc/letsencrypt/live/#{domain}/privkey.pem"+
|
2524
|
+
# +cert_pem_file+:: [String] argument to be given to +OpenSSL::SSL::SSLContext.cert+ method, after calling +OpenSSL::X509::Certificate+. It's the "Context certificate" accordingly to its ruby-doc page. letsencrypt example: +"/etc/letsencrypt/live/scatologies.com/fullchain.pem"+
|
2525
|
+
# +extra_cert_pem_files+:: [Array] array of strings. Each string will be mapped with +OpenSSL::SSL::SSLContext.new+, and the resulting array is given to +OpenSSL::SSL::SSLContext.extra_chain_cert+. "An Array of extra X509 certificates to be added to the certificate chain" accordingly to its ruby-doc. letsencryptexample: +["/etc/letsencrypt/live/#{domain}/chain.pem"]+
|
2526
|
+
# +output_exception+:: [Bool] output exceptions even if they are admitted?
|
2527
|
+
#
|
2528
|
+
# @return [OpenSSL::SSL::SSLServer] returns an ssl server, which can be used to accept connections.
|
2529
|
+
def ssl_make_server *args
|
2530
|
+
stderr = @memory[:stderr]
|
2531
|
+
listening_port,
|
2532
|
+
ip_addr,
|
2533
|
+
debug,
|
2534
|
+
admit_plain,
|
2535
|
+
priv_pemfile,
|
2536
|
+
cert_pem_file,
|
2537
|
+
extra_cert_pem_files,
|
2538
|
+
output_exception,
|
2539
|
+
reserved = args
|
2540
|
+
debug ||= debug.nne
|
2541
|
+
extra_cert_pem_files ||= extra_cert_pem_files.nne []
|
2542
|
+
admit_plain ||= admit_plain.nne
|
2543
|
+
output_exception ||= (
|
2544
|
+
output_exception.nne || admit_plain.negate_me
|
2545
|
+
)
|
2546
|
+
debug && (stderr.puts "#{__method__} starting")
|
2547
|
+
|
2269
2548
|
require 'socket'
|
2270
|
-
|
2549
|
+
plain_server = TCPServer.new ip_addr, listening_port
|
2550
|
+
ssl_server = runea [admit_plain, output_exception] {
|
2551
|
+
require 'openssl'
|
2552
|
+
ssl_context = OpenSSL::SSL::SSLContext.new
|
2553
|
+
ssl_context.extra_chain_cert =
|
2554
|
+
extra_cert_pem_files
|
2555
|
+
.map(&File.method(:read))
|
2556
|
+
.map(&OpenSSL::X509::Certificate.method(:new))
|
2557
|
+
ssl_context.cert = OpenSSL::X509::Certificate
|
2558
|
+
.new File.read cert_pem_file
|
2559
|
+
ssl_context.key = OpenSSL::PKey::RSA
|
2560
|
+
.new File.read priv_pemfile
|
2561
|
+
ssl_server = OpenSSL::SSL::SSLServer
|
2562
|
+
.new plain_server, ssl_context
|
2563
|
+
ssl_server
|
2564
|
+
}
|
2565
|
+
|
2566
|
+
debug && (stderr.puts "#{__method__} returning")
|
2567
|
+
ssl_server || admit_plain && plain_server
|
2568
|
+
end
|
2569
|
+
|
2570
|
+
|
2571
|
+
# opens an SSL server accepting connections.
|
2572
|
+
# @param [Array] +args+, an +Array+ whose elements are expected to be:
|
2573
|
+
# +listening_port+:: [String, Integer] port to listen
|
2574
|
+
# +ip_addr+:: [String, nil] ip (no hostname) to bind the server. 0, nil, false, empty string will bind to all addresses possible. 0.0.0.0 => binds to all ipv4 . ::0 to all ipv4 and ipv6
|
2575
|
+
# +admit_plain+:: [Boolean] if +true+, tries to create a normal +TCPServer+, if not possible to create +SSLServer+ (default: +false+, for preventing unadvertnt non-SSL server creation)
|
2576
|
+
# +debug+:: [Object] for future use
|
2577
|
+
# +callback_method+:: [String, Method] method to call when a client connects. The method must accept a socket as parameter.
|
2578
|
+
# +callback_method_args+:: [Array] args to be given to the call_back_method. Note that the type differs from #tcp_server_plain (which takes splat)
|
2579
|
+
#
|
2580
|
+
# @return [Thread] returns a Thread object looping for accepting
|
2581
|
+
# incoming connections (call join on that object for waiting for its
|
2582
|
+
# completion).
|
2583
|
+
def tcp_ssl_server args = ARGV
|
2584
|
+
stderr = @memory[:stderr]
|
2585
|
+
listening_port,
|
2586
|
+
ip_addr,
|
2587
|
+
debug,
|
2588
|
+
admit_plain,
|
2589
|
+
callback_method,
|
2590
|
+
callback_method_args,
|
2591
|
+
priv_pemfile,
|
2592
|
+
cert_pem_file,
|
2593
|
+
extra_cert_pem_files,
|
2594
|
+
output_exception,
|
2595
|
+
reserved = args
|
2596
|
+
|
2597
|
+
server = ssl_make_server(
|
2598
|
+
listening_port,
|
2599
|
+
ip_addr,
|
2600
|
+
debug,
|
2601
|
+
admit_plain,
|
2602
|
+
priv_pemfile,
|
2603
|
+
cert_pem_file,
|
2604
|
+
extra_cert_pem_files,
|
2605
|
+
output_exception,
|
2606
|
+
)
|
2271
2607
|
debug.nne && (stderr.puts server)
|
2272
2608
|
Thread.start {
|
2273
2609
|
loop {
|
@@ -2284,54 +2620,296 @@ require '#{gem_name}'
|
|
2284
2620
|
end
|
2285
2621
|
|
2286
2622
|
|
2287
|
-
# opens a TCP client (TCPsocket) to connect to a server
|
2288
|
-
# @param [Array] +args+, an +Array+ whose elements are expected to be:
|
2289
|
-
#
|
2290
|
-
# @return [nil]
|
2291
|
-
def tcp_client_plain args = ARGV
|
2292
|
-
listening_port,
|
2293
|
-
ip_addr,
|
2294
|
-
reserved,
|
2295
|
-
debug,
|
2296
|
-
callback_method,
|
2297
|
-
*callback_method_args = args
|
2298
|
-
require 'socket'
|
2299
|
-
client = TCPSocket.new ip_addr, listening_port
|
2300
|
-
=begin
|
2301
|
-
Thread.start {
|
2302
|
-
to_method([callback_method])
|
2303
|
-
.call [client]
|
2304
|
-
}
|
2305
|
-
=end
|
2306
|
-
Thread.start {}
|
2307
|
-
end
|
2308
|
-
|
2309
|
-
|
2310
2623
|
# test for tcp_server_plain
|
2311
2624
|
def test__tcp_server_plain args = ARGV
|
2312
|
-
thread = tcp_server_plain [8003,
|
2625
|
+
thread = tcp_server_plain [8003,
|
2626
|
+
"0",
|
2627
|
+
"reserved".to_nil,
|
2628
|
+
"debug",
|
2629
|
+
"io_echo",
|
2630
|
+
"debug_io_echo",
|
2631
|
+
"default happy_with_request".to_nil,
|
2632
|
+
" ", #replace
|
2633
|
+
"__", #replacement -- will replace empty spaces
|
2634
|
+
]
|
2313
2635
|
thread.join
|
2636
|
+
true
|
2314
2637
|
end
|
2315
2638
|
|
2639
|
+
# test for tcp_server_plain (call io_transform)
|
2640
|
+
def test__tcp_server_plain__with_io_transform args = ARGV
|
2641
|
+
thread = tcp_server_plain [
|
2642
|
+
8003,
|
2643
|
+
"0",
|
2644
|
+
"",
|
2645
|
+
"debug",
|
2646
|
+
"io_transform",
|
2647
|
+
"debug_io_transform",
|
2648
|
+
"default happy_with_request".to_nil,
|
2649
|
+
:array_maps,
|
2650
|
+
[
|
2651
|
+
:gsub!, [" ", "_____"]
|
2652
|
+
]
|
2653
|
+
]
|
2654
|
+
thread.join
|
2655
|
+
true
|
2656
|
+
end
|
2316
2657
|
|
2317
2658
|
# test for tcp_server_plain
|
2318
2659
|
def test__tcp_server_plain__with_io_http_response args = ARGV
|
2319
2660
|
thread = tcp_server_plain [
|
2320
2661
|
8003, # listening_port
|
2321
2662
|
"0", # ip_addr: all possible
|
2322
|
-
"",
|
2663
|
+
"reserved".to_nil,
|
2323
2664
|
"debug_tcp_server_plain_arg",
|
2324
2665
|
"io_http_OK_response",
|
2325
2666
|
"debug_io_http_OK_response_arg",
|
2326
|
-
"reserved_io_http_OK_response_arg",
|
2327
|
-
"This is the response payload"
|
2667
|
+
"reserved_io_http_OK_response_arg".to_nil,
|
2668
|
+
"This is the response payload",
|
2669
|
+
"dont_keep_alive".to_nil,
|
2670
|
+
]
|
2671
|
+
thread.join
|
2672
|
+
true
|
2673
|
+
end
|
2674
|
+
|
2675
|
+
|
2676
|
+
# test for tcp_server_plain (call #io_transform with
|
2677
|
+
# a function that processes an http request and returns
|
2678
|
+
# an http_response, by default #http_OK_response)
|
2679
|
+
def test__tcp_server_plain__with_http_OK_response args = ARGV
|
2680
|
+
http_processing_method,
|
2681
|
+
http_processing_method_args,
|
2682
|
+
http_server_port,
|
2683
|
+
http_ip_addr,
|
2684
|
+
reserved = args
|
2685
|
+
http_processing_method ||= http_processing_method.nne :http_OK_response
|
2686
|
+
http_processing_method_args ||= http_processing_method_args.nne []
|
2687
|
+
http_server_port ||= http_server_port.nne 8003
|
2688
|
+
http_ip_addr ||= http_ip_addr.nne "0"
|
2689
|
+
thread = tcp_server_plain [
|
2690
|
+
http_server_port,
|
2691
|
+
http_ip_addr,
|
2692
|
+
"reserved".to_nil,
|
2693
|
+
"debug",
|
2694
|
+
"io_transform",
|
2695
|
+
"debug_io_transform",
|
2696
|
+
"default happy_with_request".to_nil,
|
2697
|
+
http_processing_method,
|
2698
|
+
http_processing_method_args
|
2328
2699
|
]
|
2329
2700
|
thread.join
|
2701
|
+
true
|
2702
|
+
end
|
2703
|
+
|
2704
|
+
|
2705
|
+
# test for tcp_ssl_server (call #io_transform with
|
2706
|
+
# a function that processes an http request and returns
|
2707
|
+
# an http_response, by default #http_OK_response)
|
2708
|
+
# just like #test__tcp_server_plain__with_http_OK_response
|
2709
|
+
# but calling directly #tcp_ssl_server
|
2710
|
+
def test__tcp_ssl_server__non_ssl args = ARGV
|
2711
|
+
http_processing_method,
|
2712
|
+
http_processing_method_args,
|
2713
|
+
http_server_port,
|
2714
|
+
http_ip_addr,
|
2715
|
+
reserved = args
|
2716
|
+
http_processing_method ||= http_processing_method.nne :http_OK_response
|
2717
|
+
http_processing_method_args ||= http_processing_method_args.nne []
|
2718
|
+
http_server_port ||= http_server_port.nne 8003
|
2719
|
+
http_ip_addr ||= http_ip_addr.nne "0"
|
2720
|
+
thread = tcp_ssl_server [
|
2721
|
+
http_server_port,
|
2722
|
+
http_ip_addr,
|
2723
|
+
"debug",
|
2724
|
+
"admit non ssl server",
|
2725
|
+
"io_transform",
|
2726
|
+
[
|
2727
|
+
"debug_io_transform",
|
2728
|
+
"default happy_with_request".to_nil,
|
2729
|
+
http_processing_method,
|
2730
|
+
http_processing_method_args
|
2731
|
+
],
|
2732
|
+
]
|
2733
|
+
thread.join
|
2734
|
+
true
|
2735
|
+
end
|
2736
|
+
|
2737
|
+
|
2738
|
+
# returns a sample self signed certificate-private key pair
|
2739
|
+
# that once was created with the command (no password, no
|
2740
|
+
# expire date):
|
2741
|
+
# + openssl req -x509 -nodes -newkey rsa:1024 -keyout pkey.pem -out cert.crt+
|
2742
|
+
# @param [splat] +args+::, an splat whose elements are expected to be:
|
2743
|
+
# +reserved+:: [splat] reserved for future use
|
2744
|
+
# @return [Array] where the first element is a certificate (suitable to be the contents of +cert_pem_file+ in #ssl_make_server) and the second a private key (suitable to be the contents of +priv_pemfile+ in #ssl_make_server)
|
2745
|
+
def ssl_sample_self_signed_cert *args
|
2746
|
+
self_signed_certificate = <<-ENDHEREDOC
|
2747
|
+
-----BEGIN CERTIFICATE-----
|
2748
|
+
MIICWDCCAcGgAwIBAgIJAPa0EXsH2MwsMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
|
2749
|
+
BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
|
2750
|
+
aWRnaXRzIFB0eSBMdGQwHhcNMTgwNjI3MDkzMTEyWhcNMTgwNzI3MDkzMTEyWjBF
|
2751
|
+
MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
|
2752
|
+
ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB
|
2753
|
+
gQCplOo6dvbM1650qMYLQ8tRycYlHEZH95kUR5E5EEA8yqgimBtx6InpGQi/PejK
|
2754
|
+
tk+IXbDrxinXMXqjZxAhCjd7+frSUFwUTZ669PuRaptlkjV1KojXBW5kRERAgYId
|
2755
|
+
H7z7QRuK/gWHqTt9zl3WpW2spfWjHY+cnkYdZIWqDBOggwIDAQABo1AwTjAdBgNV
|
2756
|
+
HQ4EFgQUAIq0u116/WmTFQ8HC7/XrKl6wB8wHwYDVR0jBBgwFoAUAIq0u116/WmT
|
2757
|
+
FQ8HC7/XrKl6wB8wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOBgQBgA9ID
|
2758
|
+
JcreAgjYLxiaAd7fCfLQ1/RYM8YdP9R4Lzg2cu0dCjXoLZqzAEwUg424rPOvf0Pj
|
2759
|
+
wnZ3DFJkg1CoN2fH3yLXQ75mhfM7PJXeWoWLTS2wIG/+VIVI+nKJU0RPOM87Mdlq
|
2760
|
+
+b6TI5LsGxlJhaxTmzPtkHZLIRdW6iCJTwP+5Q==
|
2761
|
+
-----END CERTIFICATE-----
|
2762
|
+
ENDHEREDOC
|
2763
|
+
private_key = <<-ENDHEREDOC
|
2764
|
+
-----BEGIN PRIVATE KEY-----
|
2765
|
+
MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAKmU6jp29szXrnSo
|
2766
|
+
xgtDy1HJxiUcRkf3mRRHkTkQQDzKqCKYG3HoiekZCL896Mq2T4hdsOvGKdcxeqNn
|
2767
|
+
ECEKN3v5+tJQXBRNnrr0+5Fqm2WSNXUqiNcFbmRERECBgh0fvPtBG4r+BYepO33O
|
2768
|
+
Xdalbayl9aMdj5yeRh1khaoME6CDAgMBAAECgYB+Z80spU6UJFUbCk8NSIx+u6ui
|
2769
|
+
L/BHZs1Ja4tZgL6RUfKATuduQgrCoPF/NBOZPsoL+OKO7Nh1WqFyubkxF5+A6BlI
|
2770
|
+
BRe/E4K3cChBWyR5ZQyldYUNVV1HBrAhpurW/OX7FInPGo0I5TkR/CJt6xZPgK1n
|
2771
|
+
4lNXFV29gz/LPTJN4QJBANxnUn2xbtBH0xaTX4iIGEH2keLaUftg0b29Ou/MIPn3
|
2772
|
+
+z7Ln9K6eknf/OGXAvBP2cnWkTGXAOBmB95s9XDrORMCQQDE+FcWTlSKFywFaxhp
|
2773
|
+
nVkDOL+k7Vpn/rKvqKB3JQOrPkovPSo/CHsUVe/r2NEsdJt1SKOs0/xzNe7wSXBa
|
2774
|
+
1tjRAkAHVbTsE+yRJ+LBfJQQUh8kitUeDI/v4q/4NYTxmAR87SDCXTprY+NP9BFR
|
2775
|
+
XJovbyjbS7W3RcQ0s5CNeWjNojZbAkA5u3SDJDhhNUOA3xALvMPfTt3VMICkJKIp
|
2776
|
+
HGrUITQ/GAXUbMAaM5knr7yfyzAcMJ10NfNLb+L5veAn686TwY9RAkArqoX6cWrd
|
2777
|
+
GflH+FhUggqgVrr9XaXkpPUxcpNqAQH/3Yl5pt9jV2VE7eD3chijMGzGJrMUsqFG
|
2778
|
+
n8mFEtUKobsK
|
2779
|
+
-----END PRIVATE KEY-----
|
2780
|
+
ENDHEREDOC
|
2781
|
+
[self_signed_certificate, private_key]
|
2782
|
+
end
|
2783
|
+
|
2784
|
+
|
2785
|
+
# test for tcp_ssl_server (call #io_transform with
|
2786
|
+
# a function that processes an http request and returns
|
2787
|
+
# an http_response, by default #http_OK_response)
|
2788
|
+
# just like #test__tcp_ssl_server__non_ssl,
|
2789
|
+
# calling directly #tcp_ssl_server, but making
|
2790
|
+
# mandatory the server to be ssl one.
|
2791
|
+
# requires, by default that the certificate and its
|
2792
|
+
# private key are found in the current dir, which
|
2793
|
+
# can be achieved with:
|
2794
|
+
# +openssl req -x509 -nodes -days 365 -newkey rsa:1024 -keyout pkey.pem -out cert.crt+
|
2795
|
+
# but if the files don't exist, they will be created
|
2796
|
+
# with a sample self signed certificate.
|
2797
|
+
def test__tcp_ssl_server__ssl_self_signed args = ARGV
|
2798
|
+
http_processing_method,
|
2799
|
+
http_processing_method_args,
|
2800
|
+
http_server_port,
|
2801
|
+
http_ip_addr,
|
2802
|
+
priv_pemfile,
|
2803
|
+
cert_pem_file,
|
2804
|
+
extra_cert_pem_files,
|
2805
|
+
reserved = args
|
2806
|
+
http_processing_method ||= http_processing_method.nne :http_OK_response
|
2807
|
+
http_processing_method_args ||= http_processing_method_args.nne []
|
2808
|
+
http_server_port ||= http_server_port.nne 8003
|
2809
|
+
http_ip_addr ||= http_ip_addr.nne "0"
|
2810
|
+
priv_pemfile ||= priv_pemfile.nne "pkey.pem"
|
2811
|
+
cert_pem_file ||= cert_pem_file.nne "cert.crt"
|
2812
|
+
cert_contents, pkey_contents = ssl_sample_self_signed_cert
|
2813
|
+
file_read_or_write cert_pem_file, cert_contents
|
2814
|
+
file_read_or_write priv_pemfile, pkey_contents
|
2815
|
+
extra_cert_pem_files ||= extra_cert_pem_files.nne
|
2816
|
+
thread = tcp_ssl_server [
|
2817
|
+
http_server_port,
|
2818
|
+
http_ip_addr,
|
2819
|
+
"debug",
|
2820
|
+
"admit non ssl server".negate_me,
|
2821
|
+
"io_transform",
|
2822
|
+
[
|
2823
|
+
"debug_io_transform",
|
2824
|
+
"default happy_with_request".to_nil,
|
2825
|
+
http_processing_method,
|
2826
|
+
http_processing_method_args
|
2827
|
+
],
|
2828
|
+
priv_pemfile,
|
2829
|
+
cert_pem_file,
|
2830
|
+
extra_cert_pem_files,
|
2831
|
+
"yes, output exceptions",
|
2832
|
+
]
|
2833
|
+
thread.join
|
2834
|
+
true
|
2330
2835
|
end
|
2331
2836
|
|
2332
2837
|
|
2333
|
-
# test for
|
2334
|
-
def
|
2838
|
+
# test for Object::nne
|
2839
|
+
def test__object_nne args = ARGV
|
2840
|
+
string_neutral = ""
|
2841
|
+
string_non_neutral = "xxx"
|
2842
|
+
fixnum_neutral = 0
|
2843
|
+
fixnum_non_neutral = 1
|
2844
|
+
array_neutral = []
|
2845
|
+
array_non_neutral = [1, 2]
|
2846
|
+
hash_neutral = {}
|
2847
|
+
hash_non_neutral = { 1 => 2 }
|
2848
|
+
judgement =
|
2849
|
+
[
|
2850
|
+
[string_neutral.nne, nil, "string_neutral.nne"],
|
2851
|
+
[string_non_neutral.nne, string_non_neutral, "string_non_neutral.nne"],
|
2852
|
+
[fixnum_neutral.nne, nil, "fixnum_neutral.nne"],
|
2853
|
+
[fixnum_non_neutral.nne, fixnum_non_neutral, "fixnum_non_neutral.nne"],
|
2854
|
+
[array_neutral.nne, nil, "array_neutral.nne"],
|
2855
|
+
[array_non_neutral.nne, array_non_neutral, "array_non_neutral.nne"],
|
2856
|
+
[hash_neutral.nne, nil, "hash_neutral.nne"],
|
2857
|
+
[hash_non_neutral.nne, hash_non_neutral, "hash_non_neutral.nne"],
|
2858
|
+
].map(&method("expect_equal")).all?
|
2859
|
+
end
|
2860
|
+
|
2861
|
+
|
2862
|
+
# test for functions that adds syntatic sugar to
|
2863
|
+
# exceptions.
|
2864
|
+
def test__rune_functions args = ARGV
|
2865
|
+
do_rescue = "rescue"
|
2866
|
+
do_output = "output"
|
2867
|
+
no_rescue = "no rescue"
|
2868
|
+
no_output = "no output"
|
2869
|
+
actual = {}
|
2870
|
+
expectation = {}
|
2871
|
+
|
2872
|
+
#working case
|
2873
|
+
expected_return = [1, 2, 3]
|
2874
|
+
test_case = :rescue_and_output_work
|
2875
|
+
actual[test_case] = runea([do_rescue, do_output], expected_return ) {|args| puts "test_case=#{test_case}"; p args }
|
2876
|
+
expectation[test_case] = expected_return
|
2877
|
+
test_case = :rescue_but_no_output_work
|
2878
|
+
actual[test_case] = runea([do_rescue, no_output.to_nil], expected_return ) {|args| puts "test_case=#{test_case}"; p args }
|
2879
|
+
expectation[test_case] = expected_return
|
2880
|
+
test_case = :effectless_output_but_no_rescue_work
|
2881
|
+
actual[test_case] = runea([no_rescue.to_nil, do_output], expected_return ) {|args| puts "test_case=#{test_case}"; p args }
|
2882
|
+
expectation[test_case] = expected_return
|
2883
|
+
test_case = :no_output_and_no_rescue_work
|
2884
|
+
actual[test_case] = runea([no_rescue.to_nil, no_output.to_nil], expected_return ) {|args| puts "test_case=#{test_case}"; p args }
|
2885
|
+
expectation[test_case] = expected_return
|
2886
|
+
|
2887
|
+
# failure cases
|
2888
|
+
expected_return = "no_such_method"
|
2889
|
+
test_case = :rescue_and_output_fail
|
2890
|
+
actual[test_case] = runea([do_rescue, do_output], [1, 2, 3] ) {|args| puts "test_case=#{test_case}"; p args; args.to_nil.no_such_method }[1].name.to_s
|
2891
|
+
expectation[test_case] = expected_return
|
2892
|
+
test_case = :rescue_but_no_output_fail
|
2893
|
+
actual[test_case] = runea([do_rescue, no_output.to_nil], [1, 2, 3] ) {|args| puts "test_case=#{test_case}"; p args ; args.to_nil.no_such_method }.nil? && expected_return
|
2894
|
+
expectation[test_case] = expected_return
|
2895
|
+
test_case = :effectless_output_but_no_rescue_fail
|
2896
|
+
actual[test_case] = begin
|
2897
|
+
runea([no_rescue.to_nil, do_output], [1, 2, 3] ) {|args| puts "test_case=#{test_case}"; p args ; args.to_nil.no_such_method }
|
2898
|
+
rescue NoMethodError => noMethodError
|
2899
|
+
noMethodError.name.to_s
|
2900
|
+
end
|
2901
|
+
expectation[test_case] = expected_return
|
2902
|
+
test_case = :no_output_and_no_rescue_fail
|
2903
|
+
actual[test_case] = begin
|
2904
|
+
runea([no_rescue.to_nil, no_output.to_nil], [1, 2, 3] ) {|args| puts "test_case=#{test_case}"; p args ; args.to_nil.no_such_method }
|
2905
|
+
rescue NoMethodError => noMethodError
|
2906
|
+
noMethodError.name.to_s
|
2907
|
+
end
|
2908
|
+
expectation[test_case] = expected_return
|
2909
|
+
|
2910
|
+
judgement = actual.keys.map {|test_case|
|
2911
|
+
[expectation[test_case], actual[test_case] , test_case]
|
2912
|
+
}.map(&method("expect_equal")).all?
|
2335
2913
|
end
|
2336
2914
|
|
2337
2915
|
|