rubyment 0.6.25520645 → 0.6.25524898

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. checksums.yaml +4 -4
  2. data/lib/rubyment.rb +414 -62
  3. metadata +1 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ac992ef2ff77f2b3f5a7e1a392c4a0c36f40c893
4
- data.tar.gz: 87ac55e2f114f278ed74dc13c6f689f265781405
3
+ metadata.gz: 1796154aae62fc1c6039aa65156e3a4d1673be7f
4
+ data.tar.gz: 0c1cc1f4952df5d65a4d0e1ed545dfebc7dcff42
5
5
  SHA512:
6
- metadata.gz: 583ca6633c08eb781326c4abb175c4c56ba4e976029ff373e8bc7e4945ab94769db2add9bf872acf7e9e27bdfdf69aac1c6e48dd44fc96c2a33e97f6d7619d2c
7
- data.tar.gz: 06bae45d3ba2a8c5d3d3cc2845ae2a1b1dd04079c981f04ac0437cf885f3218608bd0b25a5814fb65bc4cb00991dacaf95ed06408f4b6dde619a631eebc4041b
6
+ metadata.gz: b1f36db082abf40f95df2005b3d419922d52dc7ea86e7befbf6d12a639669e959e7dca3b70a4000aca7584198fd29c05714ce312d57c058b0a00b232c5ab32a7
7
+ data.tar.gz: 741062ad9787a496f85af8aaabf3c05d4c16e93e09459e7c8411a52ee875a211499648e94af987450c2a5dc18b2f3cfe84ea12e57126f509c9711042dc9962df
data/lib/rubyment.rb CHANGED
@@ -66,7 +66,7 @@ end
66
66
  # STDOUT, just qualified output:
67
67
  # only if the function is expected
68
68
  # to output something
69
- class Rubyment
69
+ module RubymentModule
70
70
 
71
71
  # this class very often needs to split
72
72
  # first argument and remaining elements.
@@ -2671,8 +2671,8 @@ require '#{gem_name}'
2671
2671
  end
2672
2672
 
2673
2673
 
2674
- # makes an OpenSSL server
2675
- # @param [splat] +args+, an splat whose elements are expected to be:
2674
+ # makes one or more OpenSSL server
2675
+ # @param [Array] +args+, an +Array+ whose elements are expected to be:
2676
2676
  # +listening_port+:: [String, Integer] port to listen
2677
2677
  # +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
2678
2678
  # +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)
@@ -2681,9 +2681,11 @@ require '#{gem_name}'
2681
2681
  # +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/#{domain}/fullchain.pem"+ (now it's accepted to pass the file contents instead, both must work).
2682
2682
  # +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"]+ (now it's accepted to pass the file contents instead, both must work).
2683
2683
  # +output_exception+:: [Bool] output exceptions even if they are admitted?
2684
+ # +plain_servers+:: [TCPServer, Array of TCPServer] if given, ignores +listening_port+ and +ip_addr+, does not create a +TCPServer+ and just creates an +SSLServer+ out of this one. If an +Array+ of +TCPServer+ is provided instead, it will create one +SSLServer+ to each of those +TCPServer+.
2684
2685
  #
2685
- # @return [OpenSSL::SSL::SSLServer] returns an ssl server, which can be used to accept connections.
2686
- def ssl_make_server *args
2686
+ # @return [Array] returns an #Array whose elements are:
2687
+ # +servers+:: [Array of OpenSSL::SSL::SSLServer or of TCPServer] depending on +admit_plain+ and in the success of the creation of +SSLServers+.
2688
+ def ssl_make_servers args=ARGV
2687
2689
  stderr = @memory[:stderr]
2688
2690
  listening_port,
2689
2691
  ip_addr,
@@ -2693,6 +2695,7 @@ require '#{gem_name}'
2693
2695
  cert_pem_file,
2694
2696
  extra_cert_pem_files,
2695
2697
  output_exception,
2698
+ plain_servers,
2696
2699
  reserved = args
2697
2700
  debug = debug.nne
2698
2701
  extra_cert_pem_files = extra_cert_pem_files.nne []
@@ -2713,32 +2716,140 @@ require '#{gem_name}'
2713
2716
  }
2714
2717
  cert_pem_file = file_read [cert_pem_file, nil, nil, cert_pem_file]
2715
2718
  priv_pemfile = file_read [priv_pemfile, nil, nil, priv_pemfile]
2716
-
2717
2719
  require 'socket'
2718
- plain_server = TCPServer.new ip_addr, listening_port
2719
- ssl_server = runea [admit_plain, output_exception, "nil on exception"] {
2720
- require 'openssl'
2721
- ssl_context = OpenSSL::SSL::SSLContext.new
2722
- ssl_context.extra_chain_cert =
2723
- # TODO: extra_cert_pem_files could also accept strings instead
2724
- extra_cert_pem_files
2725
- .map(&OpenSSL::X509::Certificate.method(:new))
2726
- ssl_context.cert = OpenSSL::X509::Certificate
2727
- .new cert_pem_file
2728
- ssl_context.key = OpenSSL::PKey::RSA
2729
- .new priv_pemfile
2730
- ssl_server = OpenSSL::SSL::SSLServer
2731
- .new plain_server, ssl_context
2732
- ssl_server
2720
+ plain_servers ||= TCPServer.new ip_addr, listening_port
2721
+ plain_servers = containerize plain_servers
2722
+
2723
+ servers = plain_servers.map { |plain_server|
2724
+ ssl_server = runea [
2725
+ admit_plain,
2726
+ output_exception,
2727
+ "nil on exception"] {
2728
+ require 'openssl'
2729
+ ssl_context = OpenSSL::SSL::SSLContext.new
2730
+ ssl_context.extra_chain_cert =
2731
+ extra_cert_pem_files
2732
+ .map(&OpenSSL::X509::Certificate.method(:new))
2733
+ ssl_context.cert = OpenSSL::X509::Certificate
2734
+ .new cert_pem_file
2735
+ ssl_context.key = OpenSSL::PKey::RSA
2736
+ .new priv_pemfile
2737
+ ssl_server = OpenSSL::SSL::SSLServer
2738
+ .new plain_server, ssl_context
2739
+ ssl_server
2740
+ }
2741
+ server = ssl_server || admit_plain && plain_server
2733
2742
  }
2743
+ debug && (stderr.puts "will return #{[servers]}")
2744
+ debug && (stderr.puts "#{__method__} returning")
2745
+ [servers]
2746
+ end
2734
2747
 
2735
- rv = ssl_server || admit_plain && plain_server
2748
+
2749
+ # makes an OpenSSL server
2750
+ # just an interface to the more powerful
2751
+ # recommended #ssl_make_servers
2752
+ # (kept for respecting open-closed principle)
2753
+ # @param [splat] +args+, an splat whose elements are expected to be:
2754
+ # +listening_port+:: [String, Integer] port to listen
2755
+ # +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
2756
+ # +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)
2757
+ # +debug+:: [Object] for future use
2758
+ # +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"+ (now it's accepted to pass the file contents instead, both must work).
2759
+ # +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/#{domain}/fullchain.pem"+ (now it's accepted to pass the file contents instead, both must work).
2760
+ # +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"]+ (now it's accepted to pass the file contents instead, both must work).
2761
+ # +output_exception+:: [Bool] output exceptions even if they are admitted?
2762
+ # +plain_server+:: [TCPServer] if given, ignores +listening_port+ and +ip_addr+, does not create a +TCPServer+ and just creates an +SSLServer+ out of this one.
2763
+ #
2764
+ # @return [OpenSSL::SSL::SSLServer] returns an ssl server, which can be used to accept connections.
2765
+ def ssl_make_server *args
2766
+ stderr = @memory[:stderr]
2767
+ listening_port,
2768
+ ip_addr,
2769
+ debug,
2770
+ admit_plain,
2771
+ priv_pemfile,
2772
+ cert_pem_file,
2773
+ extra_cert_pem_files,
2774
+ output_exception,
2775
+ plain_server,
2776
+ reserved = args
2777
+ debug = debug.nne
2778
+ debug && (stderr.puts "#{__method__} starting")
2779
+ rv = (ssl_make_servers [
2780
+ listening_port,
2781
+ ip_addr,
2782
+ debug,
2783
+ admit_plain,
2784
+ priv_pemfile,
2785
+ cert_pem_file,
2786
+ extra_cert_pem_files,
2787
+ output_exception,
2788
+ plain_server,
2789
+ ]).first.first
2736
2790
  debug && (stderr.puts "will return #{rv}")
2737
2791
  debug && (stderr.puts "#{__method__} returning")
2738
2792
  rv
2739
2793
  end
2740
2794
 
2741
2795
 
2796
+ # opens one or more TCP and/or SSL server accepting connections.
2797
+ # @param [Array] +args+, an +Array+ whose elements are expected to be:
2798
+ # +listening_port+:: [String, Integer] port to listen
2799
+ # +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
2800
+ # +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)
2801
+ # +debug+:: [Object] for future use
2802
+ # +callback_method+:: [String, Method] method to call when a client connects. The method must accept a socket as parameter.
2803
+ # +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)
2804
+ #
2805
+ # @return [Array] returns a , an +Array+ whose elements are:
2806
+ # +threads+:: [Array of Thread] returns an Array of Thread object looping for accepting incoming connections (call join on those object for waiting for its completion).
2807
+ def tcp_ssl_servers args = ARGV
2808
+ stderr = @memory[:stderr]
2809
+ listening_port,
2810
+ ip_addr,
2811
+ debug,
2812
+ admit_plain,
2813
+ callback_method,
2814
+ callback_method_args,
2815
+ priv_pemfile,
2816
+ cert_pem_file,
2817
+ extra_cert_pem_files,
2818
+ output_exception,
2819
+ reserved = args
2820
+
2821
+ server = (ssl_make_servers [
2822
+ listening_port,
2823
+ ip_addr,
2824
+ debug,
2825
+ admit_plain,
2826
+ priv_pemfile,
2827
+ cert_pem_file,
2828
+ extra_cert_pem_files,
2829
+ output_exception,
2830
+ ]).first.first
2831
+ debug.nne && (stderr.puts server)
2832
+ Thread.start {
2833
+ loop {
2834
+ client = runea ["yes, rescue",
2835
+ "yes, output exception",
2836
+ "nil on exception"
2837
+ ] {
2838
+ server.accept
2839
+ }
2840
+ Thread.start(client) { |client|
2841
+ debug.nne && (stderr.puts Thread.current)
2842
+ debug.nne && (stderr.puts client)
2843
+ runoe {
2844
+ to_method([callback_method])
2845
+ .call([client] + callback_method_args)
2846
+ }
2847
+ }
2848
+ }
2849
+ }
2850
+ end
2851
+
2852
+
2742
2853
  # opens an SSL server accepting connections.
2743
2854
  # @param [Array] +args+, an +Array+ whose elements are expected to be:
2744
2855
  # +listening_port+:: [String, Integer] port to listen
@@ -2765,7 +2876,7 @@ require '#{gem_name}'
2765
2876
  output_exception,
2766
2877
  reserved = args
2767
2878
 
2768
- server = ssl_make_server(
2879
+ server = (ssl_make_servers [
2769
2880
  listening_port,
2770
2881
  ip_addr,
2771
2882
  debug,
@@ -2774,7 +2885,7 @@ require '#{gem_name}'
2774
2885
  cert_pem_file,
2775
2886
  extra_cert_pem_files,
2776
2887
  output_exception,
2777
- )
2888
+ ]).first.first
2778
2889
  debug.nne && (stderr.puts server)
2779
2890
  Thread.start {
2780
2891
  loop {
@@ -3361,6 +3472,15 @@ n8mFEtUKobsK
3361
3472
  end
3362
3473
 
3363
3474
 
3475
+ # runs a command in a shell (requires 'open3')
3476
+ # returns stdout and stderr output mixed
3477
+ # @param [Array] +args+, an +Array+ whose elements are expected to be:
3478
+ # +command+:: [String] command to be executed
3479
+ # @return [Array] returns an #Array whose elements are:
3480
+ # +stdoutanderr+:: [Array of Strings] mix of stdout and stderr output
3481
+ # +stdin+:: [IO]
3482
+ # +wait_thr+:: [Thread]
3483
+ # +success?+:: [TrueClass, FalseClass]
3364
3484
  def shell_popen2e_command args=[]
3365
3485
  command,
3366
3486
  reserved = args
@@ -3370,6 +3490,16 @@ n8mFEtUKobsK
3370
3490
  end
3371
3491
 
3372
3492
 
3493
+ # runs a command in a shell (requires 'open3')
3494
+ # returns stdout and stderr output separated
3495
+ # @param [Array] +args+, an +Array+ whose elements are expected to be:
3496
+ # +command+:: [String] command to be executed
3497
+ # @return [Array] returns an #Array whose elements are:
3498
+ # +stdout+:: [Array of Strings] stdout output
3499
+ # +stderr+:: [Array of Strings] stderr output
3500
+ # +stdin+:: [IO]
3501
+ # +wait_thr+:: [Thread]
3502
+ # +success?+:: [TrueClass, FalseClass]
3373
3503
  def shell_popen3_command args=[]
3374
3504
  command,
3375
3505
  reserved = args
@@ -3379,6 +3509,51 @@ n8mFEtUKobsK
3379
3509
  end
3380
3510
 
3381
3511
 
3512
+ # test #rest_request
3513
+ # for now, the parameters must still be hardcoded.
3514
+ def test__rest_request__with_ayt args=ARGV
3515
+ require 'json'
3516
+ stderr = @memory[:stderr]
3517
+
3518
+ url = "https://owl.loftweb.nl:55031/4/3-roOomydev"
3519
+ json =<<-ENDHEREDOC
3520
+ {
3521
+ "operation" : "AYT",
3522
+ "version" : {
3523
+ "client" : "X",
3524
+ "protocol" : {
3525
+ "domain_model" : "4",
3526
+ "API" : "3"
3527
+ }
3528
+ }
3529
+ }
3530
+ ENDHEREDOC
3531
+ payload = "#{json}"
3532
+
3533
+ auth_user = "web"
3534
+ password = "vadim"
3535
+ method = :post
3536
+ method = :get
3537
+ timeout = 600
3538
+ verify_ssl = true
3539
+ payload = "#{json}"
3540
+ headers = ""
3541
+ request_execution = send :rest_request, [
3542
+ url,
3543
+ payload,
3544
+ verify_ssl,
3545
+ headers,
3546
+ method,
3547
+ auth_user,
3548
+ password,
3549
+ timeout,
3550
+ ]
3551
+ parsed_json = JSON.parse request_execution.to_s
3552
+ stderr.puts parsed_json
3553
+ [parsed_json]
3554
+ end
3555
+
3556
+
3382
3557
  # test for functions that adds syntatic sugar to
3383
3558
  # exceptions.
3384
3559
  def test__rune_functions args = ARGV
@@ -3433,51 +3608,228 @@ n8mFEtUKobsK
3433
3608
  end
3434
3609
 
3435
3610
 
3436
- # test #rest_request
3437
- # for now, the parameters must still be hardcoded.
3438
- def test__rest_request__with_ayt args=ARGV
3439
- require 'json'
3611
+ # tests if +operand_1+ is only
3612
+ # composed by a repetition of +operand_2+
3613
+ # @param [Array] +args+, an +Array+ whose elements are expected to be:
3614
+ # +operand_1+:: [String]
3615
+ # +operand_2+:: [String]
3616
+ # +min_repetitions+:: [FixNum] minimum of times +operand_2+ is required to appear in +operand_1+ (default: +0+). Note that in +args=["", "X", 0]+, +operand_1=""+ will be returned, because "" is a composition of +0+ times "X".
3617
+ # @return [String, FalseClass] returns +operand_1+ if it is only
3618
+ # composed by a repetition of +operand_2+, otherwise +false+
3619
+ def string_repetition args=[]
3440
3620
  stderr = @memory[:stderr]
3441
-
3442
- url = "https://owl.loftweb.nl:55031/4/3-roOomydev"
3443
- json =<<-ENDHEREDOC
3444
- {
3445
- "operation" : "AYT",
3446
- "version" : {
3447
- "client" : "X",
3448
- "protocol" : {
3449
- "domain_model" : "4",
3450
- "API" : "3"
3451
- }
3452
- }
3621
+ operand_1,
3622
+ operand_2,
3623
+ min_repetitions,
3624
+ reserved = args
3625
+ debug = debug.nne
3626
+ debug.nne && (stderr.puts "#{__method__} starting")
3627
+ debug && (stderr.puts "args=#{args.inspect}")
3628
+ debug.nne && (stderr.puts "#{__method__} starting")
3629
+ debug && (stderr.puts "args=#{args.inspect}")
3630
+ debug && (stderr.puts "will return #{is_string_repetition}")
3631
+ debug && (stderr.puts "#{__method__} returning")
3632
+ matches = operand_1.to_s.scan operand_2
3633
+ amout_of_matches = matches.size
3634
+ min_repetitions = min_repetitions.nne 0
3635
+ is_string_repetition = (
3636
+ debug && (stderr.puts '(#{amout_of_matches} >= #{min_repetitions}) && (#{operand_2.size} * #{amout_of_matches} == #{operand_1.size})')
3637
+ debug && (stderr.puts "(#{amout_of_matches} >= #{min_repetitions}) && (#{operand_2.size} * #{amout_of_matches} == #{operand_1.size})")
3638
+ # if operand_2 was matched N times, and the sum
3639
+ # of those N matched sizes is the same
3640
+ (amout_of_matches >= min_repetitions) && (operand_2.size * amout_of_matches == operand_1.size) || false
3641
+ ) && operand_1
3642
+ debug && (stderr.puts "will return #{is_string_repetition}")
3643
+ debug && (stderr.puts "#{__method__} returning")
3644
+ is_string_repetition
3645
+ end
3646
+
3647
+
3648
+ # takes a flatten array and makes it deeper, starting a new array
3649
+ # everytime it finds the string +"["+. +"]"+ stops the array (and
3650
+ # return to the upper one). To reserve the possibility of
3651
+ # representing "[" or "]", everytime a string contains only those
3652
+ # chars, repeteaded any number of times, starting from 2, one of
3653
+ # them will be removed. So +"[["+ will be left as +"["+ and
3654
+ # +"]]]"+ will be left as +"]]"+.
3655
+ # if the provided array is not flatten, it has an undefined
3656
+ # behaviour (it will either a - transverse the sub-arrays
3657
+ # or b - don't transverse it, leaving it untouched. while
3658
+ # the a is the planned effect, initially only a may will
3659
+ # be implemented).
3660
+ # @param [Array] +args+, the array to be operadated
3661
+ # @return [Array] returns the modified, deep, #Array
3662
+ def array_unflatten_base_shallow args=[]
3663
+ reserved_tokens = [
3664
+ [ "[", :up],
3665
+ [ "]", :down.to_nil],
3666
+ ]
3667
+ rv = []
3668
+ array_operand = []
3669
+ array_operands_stack = []
3670
+ args.each_with_index {|e, index|
3671
+ reserved_tokens.map { |reserved_token|
3672
+ rtoken, is_up_token = reserved_token
3673
+
3674
+ repetition_test = string_repetition [e, rtoken, 1]
3675
+ (
3676
+ # case A: e is exactly the reserved token.
3677
+ # start or finish an array
3678
+ # note: if rtoken is false, it will succeed this
3679
+ # test.
3680
+ (repetition_test == rtoken) && (
3681
+ is_up_token && (
3682
+ array_operands_stack.push array_operand
3683
+ array_operand = Array.new
3684
+ ) || (
3685
+ array_operand = array_operands_stack.pop
3686
+ )
3687
+ )
3688
+ ) || (
3689
+ # case B: is a a repetition with at least 2
3690
+ # occurrences of the reserved token. remove one.
3691
+ # (and add it to the current array)
3692
+ repetition_test && (
3693
+ array_operand.push(e.sub! rtoken, "")
3694
+ )
3695
+ ) || (
3696
+ # case C: no repetition. (just add e to
3697
+ # the current array.)
3698
+ array_operand.push e
3699
+ )
3700
+ }
3453
3701
  }
3454
- ENDHEREDOC
3455
- payload = "#{json}"
3702
+ array_operand
3703
+ end
3704
+
3705
+ # test for #string_repetition
3706
+ def test__array_unflatten_base_shallow args=[]
3707
+ test_cases ||= [
3708
+ # [ :id, :expectation, :actual_params ],
3709
+ # array_unflatten_base_shallow
3710
+ [ "any test", [ :a, [ :b ], :c], [
3711
+ :array_unflatten_base_shallow, [
3712
+ :a, "[", :b, "]", :c
3713
+ ]
3714
+ ],
3715
+ ],
3456
3716
 
3457
- auth_user = "web"
3458
- password = "vadim"
3459
- method = :post
3460
- method = :get
3461
- timeout = 600
3462
- verify_ssl = true
3463
- payload = "#{json}"
3464
- headers = ""
3465
- request_execution = send :rest_request, [
3466
- url,
3467
- payload,
3468
- verify_ssl,
3469
- headers,
3470
- method,
3471
- auth_user,
3472
- password,
3473
- timeout,
3474
3717
  ]
3475
- parsed_json = JSON.parse request_execution.to_s
3476
- stderr.puts parsed_json
3477
- [parsed_json]
3718
+ test__tester test_cases
3719
+ end
3720
+
3721
+ def test__tester args=[]
3722
+ expectation = {}
3723
+ actual = {}
3724
+ test_cases = args
3725
+ test_cases ||= [
3726
+ # [ :id, :expectation, :actual_params ],
3727
+ ]
3728
+ test_cases.each_with_index{ |test_case|
3729
+ test_case_id, test_expectation, actual_params = test_case
3730
+ result = send actual_params[0], actual_params[1]
3731
+ expectation[test_case_id] = test_expectation
3732
+ actual[test_case_id] = result
3733
+ }
3734
+ judgement = actual.keys.map {|test_case|
3735
+ [expectation[test_case], actual[test_case] , test_case]
3736
+ }.map(&method("expect_equal")).all?
3737
+ end
3738
+
3739
+
3740
+ # test for #string_repetition
3741
+ def test__string_repetition args=[]
3742
+ expectation = {}
3743
+ actual = {}
3744
+ test_case = 1
3745
+ operand_1 = "XXX"
3746
+ operand_2 = "X"
3747
+ # expectation and actual inverted.
3748
+ expectation[test_case] = string_repetition [operand_1, operand_2]
3749
+ actual[test_case] = operand_1
3750
+
3751
+ test_case = 2
3752
+ operand_1 = "X"
3753
+ operand_2 = "X"
3754
+ expectation[test_case] = string_repetition [operand_1, operand_2]
3755
+ actual[test_case] = operand_1
3756
+
3757
+ test_case = 3
3758
+ operand_1 = "XyXy"
3759
+ operand_2 = "XyXy"
3760
+ expectation[test_case] = string_repetition [operand_1, operand_2]
3761
+ actual[test_case] = operand_1
3762
+
3763
+ test_case = 4
3764
+ operand_1 = "XyXy"
3765
+ operand_2 = "XXyy"
3766
+ expectation[test_case] = string_repetition [operand_1, operand_2]
3767
+ actual[test_case] = false
3768
+
3769
+ test_case = 6
3770
+ operand_1 = ""
3771
+ operand_2 = ""
3772
+ expectation[test_case] = string_repetition [operand_1, operand_2, 0]
3773
+ actual[test_case] = operand_1
3774
+
3775
+ test_case = 7
3776
+ operand_1 = ""
3777
+ operand_2 = ""
3778
+ expectation[test_case] = string_repetition [operand_1, operand_2, 1]
3779
+ actual[test_case] = operand_1
3780
+
3781
+ test_case = 7
3782
+ operand_1 = ""
3783
+ operand_2 = "X"
3784
+ expectation[test_case] = string_repetition [operand_1, operand_2, 0]
3785
+ # "X"*0 = ""
3786
+ actual[test_case] = operand_1
3787
+
3788
+ test_case = 8
3789
+ operand_1 = ""
3790
+ operand_2 = "X"
3791
+ expectation[test_case] = string_repetition [operand_1, operand_2, 1]
3792
+ # "X"*0 = "", but minimum is set to 1
3793
+ actual[test_case] = false
3794
+
3795
+ test_case = 9
3796
+ operand_1 = "XyXy"
3797
+ operand_2 = "Xy"
3798
+ expectation[test_case] = string_repetition [operand_1, operand_2]
3799
+ actual[test_case] = operand_1
3800
+
3801
+ test_case = 10
3802
+ operand_1 = "XyXy"
3803
+ operand_2 = ""
3804
+ expectation[test_case] = string_repetition [operand_1, operand_2]
3805
+ # clearly "" appears in "XyXy" infinity times, but "XyXy" is no
3806
+ # repetition of ""
3807
+ actual[test_case] = false
3808
+
3809
+ test_case = 11
3810
+ operand_1 = "XyXy"
3811
+ operand_2 = "Xy"
3812
+ expectation[test_case] = string_repetition [operand_1, operand_2]
3813
+ actual[test_case] = operand_1
3814
+
3815
+ test_case = 12
3816
+ operand_1 = "X"
3817
+ operand_2 = "XXX"
3818
+ expectation[test_case] = string_repetition [operand_1, operand_2]
3819
+ actual[test_case] = false
3820
+
3821
+ judgement = actual.keys.map {|test_case|
3822
+ [expectation[test_case], actual[test_case] , test_case]
3823
+ }.map(&method("expect_equal")).all?
3478
3824
  end
3479
3825
 
3480
3826
 
3827
+
3828
+ end
3829
+
3830
+
3831
+ class Rubyment
3832
+ include RubymentModule
3481
3833
  end
3482
3834
 
3483
3835
  (__FILE__ == $0) && Rubyment.new({:invoke => ARGV})
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubyment
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.25520645
4
+ version: 0.6.25524898
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribamar Santarosa