y_support 2.1.18 → 2.4.4

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.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/lib/y_support/all.rb +2 -32
  3. data/lib/y_support/core_ext/array.rb +2 -2
  4. data/lib/y_support/core_ext/class.rb +2 -2
  5. data/lib/y_support/core_ext/enumerable.rb +2 -2
  6. data/lib/y_support/core_ext/hash/misc.rb +23 -10
  7. data/lib/y_support/core_ext/hash.rb +2 -2
  8. data/lib/y_support/core_ext/module/misc.rb +9 -0
  9. data/lib/y_support/core_ext/module.rb +2 -2
  10. data/lib/y_support/core_ext/numeric.rb +2 -2
  11. data/lib/y_support/core_ext/object/inspection.rb +8 -2
  12. data/lib/y_support/core_ext/object.rb +3 -3
  13. data/lib/y_support/core_ext/string/misc.rb +9 -12
  14. data/lib/y_support/core_ext/string.rb +2 -2
  15. data/lib/y_support/core_ext/symbol.rb +2 -2
  16. data/lib/y_support/core_ext.rb +1 -1
  17. data/lib/y_support/flex_coerce/class_methods.rb +49 -0
  18. data/lib/y_support/flex_coerce/flex_proxy.rb +121 -0
  19. data/lib/y_support/flex_coerce/module_methods.rb +37 -0
  20. data/lib/y_support/flex_coerce.rb +24 -0
  21. data/lib/y_support/kde.rb +1 -1
  22. data/lib/y_support/literate.rb +253 -0
  23. data/lib/y_support/local_object.rb +1 -1
  24. data/lib/y_support/name_magic/array_methods.rb +48 -0
  25. data/lib/y_support/name_magic/class_methods.rb +205 -161
  26. data/lib/y_support/name_magic/hash_methods.rb +33 -0
  27. data/lib/y_support/name_magic/namespace.rb +449 -0
  28. data/lib/y_support/name_magic.rb +358 -100
  29. data/lib/y_support/null_object.rb +1 -1
  30. data/lib/y_support/respond_to.rb +1 -1
  31. data/lib/y_support/stdlib_ext/matrix/misc.rb +2 -2
  32. data/lib/y_support/stdlib_ext/matrix.rb +2 -2
  33. data/lib/y_support/stdlib_ext.rb +1 -1
  34. data/lib/y_support/typing/array.rb +1 -1
  35. data/lib/y_support/typing/enumerable.rb +1 -1
  36. data/lib/y_support/typing/hash.rb +1 -1
  37. data/lib/y_support/typing/module.rb +1 -1
  38. data/lib/y_support/typing/object/typing.rb +17 -15
  39. data/lib/y_support/typing/object.rb +1 -1
  40. data/lib/y_support/typing.rb +14 -10
  41. data/lib/y_support/unicode.rb +1 -1
  42. data/lib/y_support/version.rb +1 -1
  43. data/lib/y_support/x.rb +2 -1
  44. data/test/flex_coerce_test.rb +134 -0
  45. data/test/literate_test.rb +231 -0
  46. data/test/misc_test.rb +49 -27
  47. data/test/name_magic_test.rb +907 -60
  48. data/test/typing_test.rb +7 -7
  49. metadata +14 -13
  50. data/lib/y_support/abstract_algebra.rb +0 -234
  51. data/lib/y_support/name_magic/array.rb +0 -38
  52. data/lib/y_support/name_magic/hash.rb +0 -31
  53. data/lib/y_support/name_magic/namespace_methods.rb +0 -260
  54. data/lib/y_support/try.rb +0 -133
  55. data/test/abstract_algebra_test.rb +0 -138
  56. data/test/performance_test_example.rb +0 -23
  57. data/test/try_test.rb +0 -102
@@ -1,260 +0,0 @@
1
- # encoding: utf-8
2
-
3
- # Module methods for the modules serving as +NameMagic+ namespaces. A namespace
4
- # for a certain class featuring +NameMagic+ holds "civil registry" of all its
5
- # instances, be they named or nameless. For this purpose, the namespace owns
6
- # +@instances+ hash of pairs <tt>{ instance => name }</tt>, with _nil_ values
7
- # denoting nameless instances. For named instances, the namespace also holds
8
- # references to them in constants in the style <tt>Namespace::Name</tt>. This
9
- # is one of the reasons why instance names in +NameMagic+ must start with
10
- # a capital letter and generally must be usable as constant names. The list of
11
- # instances is accessible via +#instances+ method. Individual instances can be
12
- # queried by +#instance+ method, eg. by their names.
13
- #
14
- # === Life cycle of instances of classes featuring +NameMagic+
15
- #
16
- # +NameMagic+ offers 3 hooks for the instances of its user classes. These hooks
17
- # are closures invoked at the relevant points of the instances' life cycle:
18
- #
19
- # * new instance hook -- when the instance is created
20
- # * name set hook -- when the instance is offered a name
21
- # * name get hook -- when the instance's name is queried
22
- #
23
- # These three hooks are stored in instance variables owned by the namespace,
24
- # accesible by methods +#new_instance_hook, +#name_set_hook+ and
25
- # +#name_get_hook+. If called with a block, these methods also serve to set
26
- # their respective hook closures.
27
- #
28
- # When an instance is first created, unary +new_instance_hook+ is called.
29
- # When an instance is offered a name, +name_set_hook+ is called. It is a
30
- # ternary closure with 3 ordered arguments +name+, +instance+ and +old_name+,
31
- # receiving respectively the name offered, the instance, and the previous
32
- # name of the instance (if any). The return value of the closure will be used
33
- # to actually name the instance. This closure can thus be used to check and
34
- # modify the names before they are actually used. Finally, when the instances'
35
- # name is queried, third closure, unary +name_get_hook+ is applied to modify
36
- # the name output. The purpose of the name get hook is not to really change
37
- # the name upon reading, but mainly to tweak the preferred form or spelling
38
- # where multiple forms of are possible for the same name. (For example, the
39
- # standard form in the +@instances+ hash could be in camel case, such as
40
- # "AcinonyxJubatus", while preferred querying output would be a binomial name
41
- # with whitespaces, "Acinonyx jubatus".)
42
- #
43
- # === Avidity of the instances
44
- #
45
- # After the offered name is checked and modified by the name set hook closure,
46
- # there is one more remaining problem to worry about: Whether the name is
47
- # already used by another instance in the same namespace. If the name is taken,
48
- # the ensuing action depends on whether the instance being named is _avid_.
49
- # Avid instances are so eager to get a name, that they will steal the offered
50
- # name even if it is already in use, making the conflicting instance nameless
51
- # in the process. In +NameMagic+, it turns out to be convenient to make the
52
- # new instances avid by default, unless the name was explicitly supplied to the
53
- # constructor by +:name+ argument, or avidity suppressed by setting +:name_avid
54
- # option to _false_.
55
- #
56
- # Techincally, avid instances are registered as an array kept by the namespace
57
- # under the variable +@avid_instances+.
58
- #
59
- # === Forgetting instances
60
- #
61
- # A namespace can de-register, or forget instances. For this purpose, see
62
- # methods +#forget+, +#__forget__, +#forget_nameless_instances+,
63
- # +#forget_all_instances+.
64
- #
65
- # === Ersatz constant magic
66
- #
67
- # To imitate built-in constant magic of some Ruby classes, +NamespaceMethods+
68
- # provides ersatz method +#const_magic+, that searches all the modules in the
69
- # object space for the pertinent instances newly assigned to constants. Method
70
- # +#const_magic+ is then called before executing almost every public method of
71
- # +NameMagic+, thus keeping the "civil registry" up-to-date. While not exactly
72
- # computationally efficient, it tends to make the user code more readable and
73
- # pays off in most usecases. For efficiency, we are looking forward to the
74
- # +#const_assigned+ hook promised by Ruby core team...
75
- #
76
- # The namespace method versions that _do_ _not_ perform ersatz constant magic
77
- # are generally denoted by underlines: Eg. methods +#__instances__+ and
78
- # +#__forget__+ do not perform constant magic, while +#instances+ and +#forget+
79
- # do.
80
- #
81
- module NameMagic::NamespaceMethods
82
- # Presents the instances registered in this namespace.
83
- #
84
- def instances *args
85
- const_magic
86
- __instances__.keys
87
- end
88
-
89
- # Deprecated method to get full names of the named instances.
90
- #
91
- def instance_names
92
- warn "Method #instance_names is deprecated. Use 'instances._names_' or 'instances.names' instead!"
93
- instances.names false
94
- end
95
-
96
- # Presents namespace-owned +@instances+ hash. The hash consists of pairs
97
- # <code>{ instance => instance_name }</code>. Unnamed instances have +nil+
98
- # assigned to them as their name. (The method does not trigger
99
- # +#const_magic+.)
100
- #
101
- def __instances__
102
- @instances ||= {}
103
- end
104
-
105
- # Avid instances registered in this namespace. ("Avid" means that the
106
- # instance is able to steal (overwrite) a name from another registered
107
- # instance. (The method does not trigger +#const_magic+.)
108
- #
109
- def __avid_instances__
110
- @avid_instances ||= []
111
- end
112
-
113
- # Returns the instance identified by the argument, which can be typically
114
- # a name (string/symbol). If a registered instance is supplied, it will be
115
- # returned unchanged.
116
- #
117
- def instance id, *args
118
- # puts "#instance( #{identifier} )" if DEBUG
119
- # In @instances hash, value 'nil' indicates a nameless instance!
120
- fail TypeError, "'nil' is not an instance identifier!" if id.nil?
121
- ii = instances
122
- return id if ii.include? id # return the instance back
123
- begin # identifier not a registered instance -- treat it as a name
124
- ary = [id, id.to_sym]
125
- ihsh = __instances__
126
- ii.find { |inst| ary.include? ihsh[ inst ] or ary.include? inst.name }
127
- rescue NoMethodError
128
- end or fail NameError, "No instance #{id} in #{self}."
129
- end
130
-
131
- # Searches all the modules in the the object space for constants referring
132
- # to receiver class objects, and names the found instances accordingly.
133
- # Internally, it works by invoking private procedure +#search_all_modules.
134
- # The return value is the remaining number of nameless instances.
135
- #
136
- def const_magic
137
- puts "#{self}#const_magic invoked!" if ::NameMagic::DEBUG
138
- return 0 if nameless_instances.size == 0
139
- search_all_modules
140
- return nameless_instances.size
141
- end
142
-
143
- # Returns those instances, which are nameless (whose name is set to nil).
144
- #
145
- def nameless_instances *args
146
- __instances__.select { |key, val| val.nil? }.keys
147
- end
148
-
149
- # Clears namespace-owned references to a specified instance. (This is
150
- # different from "unnaming" an instance by setting <code>inst.name =
151
- # nil</code>, which makes the instance anonymous, but still registered.)
152
- #
153
- def forget instance_identifier, *args
154
- inst = begin; instance( instance_identifier ); rescue ArgumentError
155
- return nil # nothing to forget
156
- end
157
- ɴ = inst.nil? ? nil : inst.name
158
- namespace.send :remove_const, ɴ if ɴ # clear constant assignment
159
- __instances__.delete( inst ) # remove @instances entry
160
- __avid_instances__.delete( inst ) # remove if any
161
- return inst # return the forgotten instance
162
- end
163
-
164
- # Clears namespace-owned references to an instance, without performing
165
- # #const_magic first. The argument should be a registered instance. Returns
166
- # the instance name, or _false_, if there was no such registered instance.
167
- #
168
- def __forget__( instance, *args )
169
- return false unless __instances__.keys.include? instance
170
- namespace.send :remove_const, instance.name if instance.name
171
- __avid_instances__.delete( instance )
172
- __instances__.delete instance
173
- end
174
-
175
- # Clears namespace-owned references to all the anonymous instances.
176
- #
177
- def forget_nameless_instances
178
- nameless_instances.each { |inst|
179
- __instances__.delete( inst )
180
- __avid_instances__.delete( inst ) # also from avid instances
181
- }
182
- end
183
-
184
- # Clears namespace-owned references to all the instances.
185
- #
186
- def forget_all_instances
187
- __instances__.clear
188
- constants( false ).each { |sym|
189
- namespace.send :remove_const, sym if const_get( sym ).is_a? self
190
- }
191
- end
192
-
193
- # Registers a hook to execute upon instantiation. Expects a unary block, whose
194
- # argument represents the new instance. It is called right after instantiation,
195
- # but before naming the instance. Without a block, it acts as a getter.
196
- #
197
- def new_instance_hook &block
198
- @new_instance_hook = block if block
199
- @new_instance_hook ||= -> instance { instance }
200
- end
201
-
202
- # Registers a hook to execute upon instance naming. Expects a ternary block,
203
- # with arguments name, instance and old_name, representing respectively the
204
- # the requested name, the instance to be named, and the previous name of that
205
- # instance (if any). The output of the block should be the name to actually
206
- # be used. In other words, the hook can be used (among other things) to check
207
- # and/or modify the requested name when christening the instance. It is the
208
- # responsibility of this block to output a symbol that can be used as a Ruby
209
- # constant name. Without a block, this method acts as a getter.
210
- #
211
- def name_set_hook &block
212
- @name_set_hook = block if block
213
- @name_set_hook ||= -> name, instance, old_name=nil { name }
214
- end
215
-
216
- # Registers a hook to execute whenever the instance is asked its name. The
217
- # instance names are objects that are kept in a hash referred to by
218
- # +@instances+ variable owned by the namespace. Normally, +NameMagic#name+
219
- # simply returns the name of the instance, as found in the +@instances+ hash.
220
- # When +name_get_hook+ is defined, this name is transformed by it before being
221
- # returned. Without a block, this method acts as a getter.
222
- #
223
- def name_get_hook &block
224
- @name_get_hook = block if block
225
- @name_get_hook ||= -> name { name }
226
- end
227
-
228
- # Checks whether a name is acceptable as a constant name.
229
- #
230
- def validate_name name
231
- name.to_s.tap do |ɴ| # check if the name starts with 'A'..'Z'
232
- fail NameError, "#{self}-registered name must start with a capital " +
233
- " letter 'A'..'Z' ('#{ɴ}' given)!" unless ( ?A..?Z ) === ɴ[0]
234
- end
235
- end
236
-
237
- private
238
-
239
- # Checks all the constants in some module's namespace, recursively.
240
- #
241
- def search_all_modules
242
- todo = ( nameless_instances + __avid_instances__ ).map( &:object_id ).uniq
243
- ObjectSpace.each_object Module do |ɱ|
244
- ɱ.constants( false ).each do |const_ß|
245
- begin; instance = ɱ.const_get( const_ß ) # Some constants cause
246
- rescue LoadError, StandardError; next end # errors upon loading.
247
- next unless todo.include? instance.object_id
248
- # puts "NameMagic: Anonymous object under #{const_ß}!" if DEBUG
249
- if instance.avid? then # puts "NameMagic: It is avid." if DEBUG
250
- instance.make_not_avid! # Remove from the avid list.
251
- instance.name! const_ß # Name it rudely.
252
- else # puts "NameMagic: It is not avid." if DEBUG
253
- instance.name = const_ß # Name it cautiously.
254
- end
255
- todo.delete instance.object_id # Remove from todo list.
256
- break if todo.empty? # Abandon the loop if done.
257
- end
258
- end
259
- end
260
- end # module NameMagic::NamespaceMethods
data/lib/y_support/try.rb DELETED
@@ -1,133 +0,0 @@
1
- # encoding: utf-8
2
-
3
- require 'y_support'
4
- require 'y_support/core_ext/array/misc'
5
-
6
- # Provides +Try+ class, and +Object#try+ method that constructs and calls a
7
- # +Consciously::Try+ instance. This +#try+ method has nothing to do with the
8
- # error-swallowing +#try+ method frequently seen elsewhere. On the contrary,
9
- # our +#try+ method _facilitates_ raising and ultimately, correcting errors
10
- # by providing well-formed error messages.
11
- #
12
- # Constructing error messages is labor-intensive. +Consciously::Try+ allows one
13
- # to construct verbose error messages with +#note+ statements inside the block,
14
- # that act as comments at the same time.
15
- #
16
- # "FooBar".try "to do something" do
17
- # note has: "#{size} letters", is: "a #{self.class} instance"
18
- # unless include? "Quux"
19
- # note "Quux", is: "not a part of it"
20
- # try "to append Quux to it" do
21
- # self << "Quux"
22
- # fail "EPIC FAIL"
23
- # end
24
- # end
25
- # end
26
- #
27
- # Should produce an automatic error message like this: "When trying to do
28
- # something, FooBar having 6 letters, being a String instance, Quux being
29
- # not a part of it, RuntimeError occurred: When trying to append Quux to it,
30
- # RuntimeError occurred: EPIC FAIL"
31
- #
32
- module Consciously
33
- class Try < BasicObject
34
- DECORATE = -> str, prefix: '', postfix: '' {
35
- str.to_s.tap { |ς| return ς.empty? ? '' : prefix + ς + postfix }
36
- }
37
- TRANSITIVE = ::Hash.new do |ꜧ, key| "#{key}ing %s" end
38
- .update( is: "being %s",
39
- has: "having %s" )
40
- STATE = ::Hash.new do |ꜧ, key| "#{key} %s" end
41
- .update( is: "%s",
42
- has: "has %s" )
43
-
44
- attr_reader :__obj__, :__txt__, :__bl__, :__facts__
45
-
46
- # This
47
- def initialize( object: nil, text: nil, &block )
48
- @__obj__, @__txt__, @__bl__ = object, text, block
49
- @__facts__ = ::Hash.new do |hsh, key| hsh[key] = [ {} ] end
50
- end
51
-
52
- # The syntax of this method, available inside the #try block, is:
53
- #
54
- # note "Concatenation of Foo and Bar", is: "FooBar", has: "6 letters"
55
- #
56
- def note *subjects, **statements, &block
57
- return Array( subjects ).each { |s| __facts__[s].push_ordered s } if
58
- statements.empty?
59
- subjects << __obj__ if subjects.empty?
60
- Array( subjects ).each { |subj|
61
- statements.each { |verb, obj| __facts__[subj].push_named verb => obj }
62
- }
63
- return statements.first[1]
64
- end
65
-
66
- # Invokes the Try object's block.
67
- #
68
- def __invoke__ *args
69
- begin
70
- instance_exec *args, &__bl__
71
- rescue ::StandardError => err
72
- txt1 = "When trying #{__txt__}"
73
- thing, statements = __describe__
74
- txt2 = DECORATE.( thing, prefix: ' ' )
75
- txt3 = DECORATE.( statements.map { |verb, object|
76
- STATE[verb] % object
77
- }.join( ', ' ),
78
- prefix: ' (', postfix: ')' )
79
- txt4 = DECORATE.( __circumstances__, prefix: ', ' )
80
- txt5 = DECORATE.( "#{err.class} occurred: #{err}", prefix: ', ' )
81
- raise err, txt1 + txt2 + txt3 + txt4 + txt5
82
- end
83
- end
84
-
85
- def try *args, &block
86
- __obj__.try *args, &block
87
- end
88
-
89
- def method_missing sym, *args
90
- __obj__.send sym, *args
91
- end
92
-
93
- def __describe__ obj=__obj__
94
- facts = __facts__[obj].dup
95
- statements = if facts.last.is_a? ::Hash then facts.pop else {} end
96
- fs = facts.join ', '
97
- if statements.empty? then
98
- return fs, statements
99
- else
100
- return facts.empty? ? obj.to_s : fs, statements
101
- end
102
- end
103
-
104
- def __circumstances__
105
- __facts__.reject { |subj, _| subj == __obj__ }.map { |subj, _|
106
- thing, statements = __describe__( subj )
107
- thing + DECORATE.( statements.map { |v, o|
108
- TRANSITIVE[v] % o
109
- }.join( ', ' ),
110
- prefix: ' ' )
111
- }.join( ', ' )
112
- end
113
- end
114
- end
115
-
116
-
117
- class Object
118
- # Try method takes two textual arguments and one block. The first (optional)
119
- # argument is a natural language description of the method's receiver (with
120
- # #to_s of the receiver used by default). The second argument is a natural
121
- # language description of the supplied block's _contract_ -- in other words,
122
- # what the supplied block tries to do. Finally, the block contains the code
123
- # to perform the described risky action. Inside the block, +#note+ method is
124
- # available, which builds up the context information for a good error message,
125
- # should the risky action raise one.
126
- #
127
- def try receiver_NL_description=self, attempt_NL_description, &block
128
- Consciously::Try.new( object: receiver_NL_description,
129
- text: attempt_NL_description,
130
- &block ).__invoke__
131
- end
132
- alias consciously try
133
- end
@@ -1,138 +0,0 @@
1
- #! /usr/bin/ruby
2
- #encoding: utf-8
3
-
4
- fail NotImplementedError # TODO: This part doesn't work yet
5
-
6
- require 'minitest/autorun'
7
-
8
- describe "Algebra" do
9
- before do
10
- require './../lib/y_support/abstract_algebra'
11
- # Define the stupidest monoid:
12
- @monoid = Class.new { include Algebra::Monoid } # make some class
13
- zero = @monoid.new # call arbitrary instance zero
14
- @monoid.class_exec {
15
- # Define the stupidest #add method.
16
- define_method :add do |other|
17
- if self == zero then other
18
- elsif other == zero then self
19
- else self.class.addition_table[[self, other]] end
20
- end
21
- # Define the stupidest addition table.
22
- instance_variable_set :@addition_table,
23
- Hash.new { |ꜧ, k|
24
- ꜧ[k] = if k[0].object_id <= k[1].object_id
25
- new # just make up an instance
26
- else
27
- ꜧ[k[1], k[0]] # swap operands
28
- end
29
- }
30
- }
31
- # And refine the @monoid's singleton class.
32
- @monoid.singleton_class.class_exec { attr_reader :addition_table }
33
- @monoid.define_singleton_method :additive_identity do zero end
34
- end
35
-
36
- describe "Algebra" do
37
- it "should have working Monoid" do
38
- m = @monoid.random # choose an instance
39
-
40
- # #== method
41
- assert m == m
42
-
43
- # closure
44
- # (not tested)
45
-
46
- # associativity
47
- n, o = @monoid.random, @monoid.random
48
- assert ( m + n ) + o == m + ( n + o )
49
-
50
- # identity element
51
- assert m + @monoid.zero == m
52
- assert @monoid.zero + m == m
53
- end
54
-
55
- it "should have working Group" do
56
- g = @group.random
57
-
58
- # (monoid properties not tested)
59
-
60
- # inverse element
61
- assert g + (-g) == @group.zero
62
- assert (-g) + g == @group.zero
63
- end
64
-
65
- it "should define AbelianGroup" do
66
- ag = @abelian_group.random
67
-
68
- # (group properties not tested)
69
-
70
- # commutativity
71
- bh = @abelian_group.random
72
- assert ag + bh == bh + ag
73
- end
74
-
75
- it "should define Ring" do
76
- r = @ring.random
77
-
78
- # (abelian group properties with respect to addition not tested)
79
-
80
- # (multiplication closure not tested)
81
-
82
- # multiplication associativity
83
- s, t = @ring.random, @ring.random
84
- assert r * ( s * t ) == ( r * s ) * t
85
-
86
- # multiplication identity
87
- mi = @ring.one
88
- assert r * mi == r
89
- assert mi * r == r
90
-
91
- # distributivity
92
- assert r * ( s + t ) == ( r * s ) + ( s * t )
93
- end
94
-
95
- it "should define Field" do
96
- f = @field.random
97
-
98
- # (ring properties not tested)
99
-
100
- # multiplicative inverse
101
- mi = @ring.multiplicative_identity
102
- assert f * f.multiplicative_inverse == mi
103
- assert f.multiplicative_inverse * f == mi
104
- end
105
- end
106
-
107
- describe "numerics" do
108
- it "should have patched Integer" do
109
- assert Integer.zero.equal? 0
110
- end
111
-
112
- it "should have patched Float" do
113
- assert Float.zero.equal? 0.0
114
- end
115
-
116
- it "should have patched Rational" do
117
- assert Rational.zero.equal? Rational( 0, 0 )
118
- end
119
-
120
- it "should have patched Complex" do
121
- assert Complex.zero.equal? Complex( 0, 0 )
122
- end
123
- end
124
-
125
- describe "Matrix" do
126
- it "should have Matrix.wildcard_zero public instance method" do
127
- # FIXME
128
- end
129
-
130
- it "should be able to perform #* with nonnumerics in the matrix" do
131
- # FIXME
132
- end
133
-
134
- it "should numeric matrix multiplication still be working normally" do
135
- # FIXME
136
- end
137
- end # context Matrix
138
- end
@@ -1,23 +0,0 @@
1
- #! /usr/bin/ruby
2
-
3
- require 'minitest/autorun'
4
- require 'minitest/benchmark'
5
-
6
- class TestCoreMethods < Minitest::Benchmark
7
- def setup
8
- @arrays = ( 1 .. 11_000 ).map { |n| [ 42 ] * n }
9
- end
10
-
11
- # Override self.bench_range or default range is [1, 10, 100, 1_000, 10_000]
12
- def bench_size
13
- assert_performance_linear 0.99 do |n| ( [ 0 ] * n ).reduce :+ end
14
- assert_performance_constant 0.99 do |n| 42.times { 42 } end
15
- # assert_performance_linear 0.99 do |n| @arrays[ n ].size end
16
- assert_performance_constant 0.99 do |n| @arrays[ n ].size end
17
- # TODO: For some reason, assert_performance_constant doesn't fail even if
18
- # I artificially introduce eg. quadratic algorithm. All the while, the
19
- # line assert_performance_linear does fail if uncommented (since the perf.
20
- # here is constant).
21
- # TODO: In other words, I'm not very experienced in performance testing yet.
22
- end
23
- end
data/test/try_test.rb DELETED
@@ -1,102 +0,0 @@
1
- #! /usr/bin/ruby
2
-
3
- require 'minitest/autorun'
4
- # require 'y_support/try' # tested component itself
5
- require './../lib/y_support/try'
6
-
7
- describe Consciously do
8
- before do
9
- @try = Consciously::Try.new object: "Dummy", text: "to fire" do
10
- note is: "dummy"
11
- note has: "no care in the world"
12
- n = note "its number", is: 42
13
- raise TypeError, 'foo'
14
- end
15
- end
16
-
17
- it "should have basic functionality" do
18
- assert_equal "to fire", @try.__txt__
19
- assert_equal "Dummy", @try.__obj__
20
- assert_equal 0, @try.__facts__.size # haven't tried anything yet
21
- @try.__facts__["something"]
22
- assert_equal 1, @try.__facts__.size
23
- @try.note is: 'dummy'
24
- @try.note has: 'no care in the world'
25
- assert_equal 2, @try.__facts__.size
26
- assert_equal ["something", "Dummy"], @try.__facts__.keys
27
- assert_equal( [ { is: "dummy", has: "no care in the world" } ],
28
- @try.__facts__["Dummy"] )
29
- assert_equal " hello!", Consciously::Try::DECORATE.( :hello, prefix: ' ', postfix: '!' )
30
- assert_equal( ['Dummy', {is: 'dummy', has: 'no care in the world'}],
31
- @try.__describe__( "Dummy" ) )
32
- end
33
-
34
- describe 'case 1' do
35
- it "should work" do
36
- begin
37
- @try.__invoke__
38
- rescue TypeError => err
39
- expected_msg = "When trying to fire Dummy (dummy, has no care in " +
40
- "the world), its number being 42, TypeError occurred: foo"
41
- assert_equal expected_msg, err.message
42
- else
43
- flunk "Expected TypeError error not raised!"
44
- end
45
- end
46
- end
47
-
48
- describe 'case 2' do
49
- it "should work" do
50
- begin
51
- try "to call constant Nonexistant" do Nonexistant end
52
- rescue NameError => err
53
- expected_msg = 'When trying to call constant Nonexistant, ' +
54
- 'NameError occurred: uninitialized constant Nonexistant'
55
- assert_equal( expected_msg, err.message )
56
- else
57
- flunk "Expected NameError error not raised!"
58
- end
59
- end
60
- end
61
-
62
- describe 'case 3' do
63
- it "should work" do
64
- o = Object.new
65
- class << o
66
- def to_s; "THIS OBJECT" end
67
- def hello!; "hello hello" end
68
- end
69
- # Object's methods must be callable
70
- o.try "to say hello" do hello! end.must_equal "hello hello"
71
- begin
72
- o.try "to call a weird method" do goodbye! end
73
- rescue NoMethodError => err
74
- err.message.must_include "When trying to call a weird method, " +
75
- "NoMethodError occurred: undefined method"
76
- err.message.must_include "goodbye!"
77
- end
78
- end
79
- end
80
-
81
- describe 'case 4' do
82
- it "should work" do
83
- begin
84
- "FooBar".try "to do something" do
85
- note has: "#{size} letters", is: "a #{self.class} instance"
86
- unless include? "Quux"
87
- note "Quux", is: "not a part of it"
88
- try "to append Quux to it" do
89
- self << "Quux"
90
- fail "EPIC FAIL"
91
- end
92
- end
93
- end
94
- rescue => err
95
- err.message.must_equal 'When trying to do something, FooBar having ' +
96
- '6 letters, being a String instance, Quux being not a part of it, ' +
97
- 'RuntimeError occurred: When trying to append Quux to it, ' +
98
- 'RuntimeError occurred: EPIC FAIL'
99
- end
100
- end
101
- end
102
- end