rubyment 0.6.25484655 → 0.6.25503334
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|