utilrb 2.0.2.b2 → 2.1.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.boring +40 -0
- data/.gitignore +13 -0
- data/.travis.yml +5 -0
- data/CMakeLists.txt +18 -0
- data/Gemfile +3 -0
- data/Makefile +8 -0
- data/Manifest.txt +0 -8
- data/{README.rd → README.md} +11 -7
- data/Rakefile +16 -63
- data/benchmarks/validate_options.rb +79 -0
- data/ext/utilrb/extconf.rb +1 -17
- data/ext/utilrb/utilrb.cc +0 -23
- data/lib/utilrb/column_formatter.rb +8 -5
- data/lib/utilrb/common.rb +1 -6
- data/lib/utilrb/enumerable/uniq.rb +2 -8
- data/lib/utilrb/event_loop.rb +5 -10
- data/lib/utilrb/kernel/load_dsl_file.rb +1 -2
- data/lib/utilrb/kernel/options.rb +25 -29
- data/lib/utilrb/logger/hierarchy.rb +0 -1
- data/lib/utilrb/logger/io.rb +3 -3
- data/lib/utilrb/logger/root.rb +12 -6
- data/lib/utilrb/module/ancestor_p.rb +0 -12
- data/lib/utilrb/module/is_singleton.rb +6 -0
- data/lib/utilrb/module/singleton_class_p.rb +14 -0
- data/lib/utilrb/object/attribute.rb +33 -65
- data/lib/utilrb/object/singleton_class.rb +1 -20
- data/lib/utilrb/pkgconfig.rb +21 -10
- data/lib/utilrb/socket/tcp_server.rb +2 -2
- data/lib/utilrb/spawn.rb +1 -1
- data/lib/utilrb/test.rb +65 -0
- data/lib/utilrb/thread_pool.rb +11 -13
- data/lib/utilrb/timepoints.rb +15 -0
- data/lib/utilrb/value_set.rb +10 -1
- data/lib/utilrb/version.rb +4 -0
- data/lib/utilrb/weakref.rb +11 -12
- data/lib/utilrb/yard.rb +0 -111
- data/lib/utilrb.rb +6 -1
- data/lib/yard-utilrb.rb +1 -0
- data/manifest.xml +19 -0
- data/package.xml +29 -0
- data/utilrb.gemspec +27 -0
- metadata +56 -107
- data/ext/utilrb/proc.c +0 -39
- data/ext/utilrb/readline.c +0 -52
- data/ext/utilrb/weakref.cc +0 -143
- data/lib/utilrb/models/inherited_enumerable.rb +0 -341
- data/lib/utilrb/models/registration.rb +0 -115
- data/lib/utilrb/module/inherited_enumerable.rb +0 -6
- data/lib/utilrb/objectstats.rb +0 -193
- data/lib/utilrb/ruby_object_graph.rb +0 -384
- data/test/data/test_pkgconfig.pc +0 -9
- data/test/data/test_pkgconfig_empty.pc +0 -10
- data/test/test_array.rb +0 -15
- data/test/test_config.rb +0 -4
- data/test/test_dir.rb +0 -22
- data/test/test_enumerable.rb +0 -119
- data/test/test_event_loop.rb +0 -407
- data/test/test_exception.rb +0 -38
- data/test/test_gc.rb +0 -34
- data/test/test_hash.rb +0 -102
- data/test/test_kernel.rb +0 -300
- data/test/test_logger.rb +0 -204
- data/test/test_misc.rb +0 -42
- data/test/test_models.rb +0 -212
- data/test/test_module.rb +0 -126
- data/test/test_object.rb +0 -77
- data/test/test_objectstats.rb +0 -26
- data/test/test_pkgconfig.rb +0 -84
- data/test/test_proc.rb +0 -31
- data/test/test_set.rb +0 -19
- data/test/test_thread_pool.rb +0 -409
- data/test/test_time.rb +0 -47
- data/test/test_unbound_method.rb +0 -23
- data/test/test_weakref.rb +0 -81
@@ -1,384 +0,0 @@
|
|
1
|
-
require 'stringio'
|
2
|
-
require 'utilrb/value_set'
|
3
|
-
require 'utilrb/kernel/options'
|
4
|
-
module Utilrb
|
5
|
-
begin
|
6
|
-
require 'roby/graph'
|
7
|
-
has_roby_graph = true
|
8
|
-
rescue LoadError
|
9
|
-
has_roby_graph = false
|
10
|
-
end
|
11
|
-
|
12
|
-
if has_roby_graph
|
13
|
-
class RubyObjectGraph
|
14
|
-
module GraphGenerationObjectMaker
|
15
|
-
def __ruby_object_graph_internal__; end
|
16
|
-
end
|
17
|
-
attr_reader :graph
|
18
|
-
attr_reader :references
|
19
|
-
|
20
|
-
# Takes a snapshot of all objects currently live
|
21
|
-
def self.snapshot
|
22
|
-
# Doing any Ruby code that do not modify the heap is impossible. List
|
23
|
-
# all existing objects once, and only then do the processing.
|
24
|
-
# +live_objects+ will be referenced in itself, but we are going to
|
25
|
-
# remove it later
|
26
|
-
GC.disable
|
27
|
-
live_objects = Array.new
|
28
|
-
ObjectSpace.each_object do |obj|
|
29
|
-
if obj.object_id != live_objects.object_id
|
30
|
-
live_objects << obj
|
31
|
-
end
|
32
|
-
end
|
33
|
-
GC.enable
|
34
|
-
live_objects
|
35
|
-
end
|
36
|
-
|
37
|
-
# Generates a graph of all the objects currently live, in dot format
|
38
|
-
def self.dot_snapshot(options = Hash.new)
|
39
|
-
r, w = IO.pipe
|
40
|
-
live_objects = RubyObjectGraph.snapshot
|
41
|
-
fork do
|
42
|
-
options, register_options = Kernel.filter_options options,
|
43
|
-
:collapse => nil
|
44
|
-
ruby_graph = RubyObjectGraph.new
|
45
|
-
ruby_graph.register_references_to(live_objects, register_options)
|
46
|
-
if options[:collapse]
|
47
|
-
ruby_graph.collapse(*options[:collapse])
|
48
|
-
end
|
49
|
-
w.write ruby_graph.to_dot
|
50
|
-
exit! true
|
51
|
-
end
|
52
|
-
w.close
|
53
|
-
r.read
|
54
|
-
end
|
55
|
-
|
56
|
-
def initialize
|
57
|
-
@graph = BGL::Graph.new
|
58
|
-
@references = Hash.new
|
59
|
-
end
|
60
|
-
|
61
|
-
def clear
|
62
|
-
graph.each_edge do |from, to, info|
|
63
|
-
info.clear
|
64
|
-
end
|
65
|
-
graph.clear
|
66
|
-
references.clear
|
67
|
-
end
|
68
|
-
|
69
|
-
# This class is used to store any ruby object into a BGL::Graph (i.e.
|
70
|
-
# the live graph)
|
71
|
-
class ObjectRef
|
72
|
-
# The referenced object
|
73
|
-
attr_reader :obj
|
74
|
-
|
75
|
-
def __ruby_object_graph_internal__; end
|
76
|
-
|
77
|
-
def initialize(obj)
|
78
|
-
@obj = obj
|
79
|
-
end
|
80
|
-
include BGL::Vertex
|
81
|
-
end
|
82
|
-
|
83
|
-
def test_and_add_reference(obj_ref, var, desc)
|
84
|
-
var_ref = references[var.object_id]
|
85
|
-
if graph.include?(var_ref)
|
86
|
-
add_reference(obj_ref, var_ref, desc)
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
# Register a ruby object reference
|
91
|
-
#
|
92
|
-
# @param [ObjectRef] obj_ref the object that is referencing
|
93
|
-
# @param [ObjectRef] var_ref the object that is referenced
|
94
|
-
# @param desc the description for the link. For instance, if obj_ref
|
95
|
-
# references var_ref because of an instance variable, this is going to
|
96
|
-
# be the name of the instance variable
|
97
|
-
# @return [void]
|
98
|
-
def add_reference(obj_ref, var_ref, desc)
|
99
|
-
if graph.linked?(obj_ref, var_ref)
|
100
|
-
desc_set = obj_ref[var_ref, graph]
|
101
|
-
if !desc_set.include?(desc)
|
102
|
-
desc_set << desc
|
103
|
-
end
|
104
|
-
else
|
105
|
-
desc_set = [desc]
|
106
|
-
graph.link(obj_ref, var_ref, desc_set)
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
# Creates a BGL::Graph of ObjectRef objects which stores the current
|
111
|
-
# ruby object graph
|
112
|
-
#
|
113
|
-
# @param [Class] klass seed
|
114
|
-
# @option options [Array<Object>] roots (nil) if given, the list of root
|
115
|
-
# objects. Objects that are not referenced by one of these roots will
|
116
|
-
# not be included in the final graph
|
117
|
-
def register_references_to(live_objects, options = Hash.new)
|
118
|
-
orig_options = options # to exclude it from the graph
|
119
|
-
options = Kernel.validate_options options,
|
120
|
-
:roots => [Object], :excluded_classes => [], :excluded_objects => [],
|
121
|
-
:include_class_relation => false
|
122
|
-
roots_class, roots = options[:roots].partition { |obj| obj.kind_of?(Class) }
|
123
|
-
excluded_classes = options[:excluded_classes]
|
124
|
-
excluded_objects = options[:excluded_objects]
|
125
|
-
include_class_relation = options[:include_class_relation]
|
126
|
-
|
127
|
-
# Create a single ObjectRef per (interesting) live object, so that we
|
128
|
-
# can use a BGL::Graph to represent the reference graph. This will be
|
129
|
-
# what we are going to access later on. Use object IDs since we really
|
130
|
-
# want to refer to objects and not use eql? comparisons
|
131
|
-
desired_seeds = roots.map(&:object_id)
|
132
|
-
excludes = [live_objects, self, graph, references, orig_options, options, roots, roots_class].to_value_set
|
133
|
-
live_objects_total = live_objects.size
|
134
|
-
live_objects.delete_if do |obj|
|
135
|
-
if obj.kind_of?(DRbObject)
|
136
|
-
true
|
137
|
-
elsif excludes.include?(obj) || obj.respond_to?(:__ruby_object_graph_internal__)
|
138
|
-
true
|
139
|
-
else
|
140
|
-
references[obj.object_id] ||= ObjectRef.new(obj)
|
141
|
-
if roots_class.any? { |k| obj.kind_of?(k) }
|
142
|
-
if !excluded_classes.any? { |k| obj.kind_of?(k) }
|
143
|
-
if !excluded_objects.include?(obj)
|
144
|
-
desired_seeds << obj.object_id
|
145
|
-
end
|
146
|
-
end
|
147
|
-
end
|
148
|
-
false
|
149
|
-
end
|
150
|
-
end
|
151
|
-
|
152
|
-
desired_seeds.each do |obj_id|
|
153
|
-
graph.insert(references[obj_id])
|
154
|
-
end
|
155
|
-
ignored_enumeration = Hash.new
|
156
|
-
|
157
|
-
names = Hash[
|
158
|
-
:array => "Array",
|
159
|
-
:value_set => "ValueSet[]",
|
160
|
-
:vertex => "Vertex[]",
|
161
|
-
:edge => "Edge[]",
|
162
|
-
:hash_key => "Hash[key]",
|
163
|
-
:hash_value => "Hash[value]",
|
164
|
-
:proc => "Proc",
|
165
|
-
:ancestor => "Ancestor"]
|
166
|
-
puts "RubyObjectGraph: #{live_objects.size} objects found, #{desired_seeds.size} seeds and #{live_objects_total} total live objects"
|
167
|
-
loop do
|
168
|
-
old_graph_size = graph.size
|
169
|
-
live_objects.each do |obj|
|
170
|
-
obj_ref = references[obj.object_id]
|
171
|
-
|
172
|
-
if include_class_relation
|
173
|
-
test_and_add_reference(obj_ref, obj.class, "class")
|
174
|
-
end
|
175
|
-
|
176
|
-
for var_name in obj.instance_variables
|
177
|
-
var = obj.instance_variable_get(var_name)
|
178
|
-
test_and_add_reference(obj_ref, var, var_name.to_s)
|
179
|
-
end
|
180
|
-
|
181
|
-
case obj
|
182
|
-
when Array
|
183
|
-
for var in obj
|
184
|
-
test_and_add_reference(obj_ref, var, names[:array])
|
185
|
-
end
|
186
|
-
when ValueSet
|
187
|
-
for var in obj
|
188
|
-
test_and_add_reference(obj_ref, var, names[:value_set])
|
189
|
-
end
|
190
|
-
when BGL::Graph
|
191
|
-
obj.each_vertex do
|
192
|
-
test_and_add_reference(obj_ref, var, names[:vertex])
|
193
|
-
end
|
194
|
-
obj.each_edge do |_, _, info|
|
195
|
-
test_and_add_reference(obj_ref, info, names[:edge])
|
196
|
-
end
|
197
|
-
when Hash
|
198
|
-
for var in obj
|
199
|
-
test_and_add_reference(obj_ref, var[0], names[:hash_key])
|
200
|
-
test_and_add_reference(obj_ref, var[1], names[:hash_value])
|
201
|
-
end
|
202
|
-
when Proc
|
203
|
-
if obj.respond_to?(:references)
|
204
|
-
for var in obj.references
|
205
|
-
begin
|
206
|
-
test_and_add_reference(obj_ref, ObjectSpace._id2ref(var), names[:proc])
|
207
|
-
rescue RangeError
|
208
|
-
end
|
209
|
-
end
|
210
|
-
end
|
211
|
-
when Class
|
212
|
-
for ref in obj.ancestors
|
213
|
-
test_and_add_reference(obj_ref, ref, names[:ancestor])
|
214
|
-
end
|
215
|
-
else
|
216
|
-
if obj.respond_to?(:each)
|
217
|
-
if obj.kind_of?(Module) || obj.kind_of?(Class)
|
218
|
-
if !ignored_enumeration[obj]
|
219
|
-
ignored_enumeration[obj] = true
|
220
|
-
puts "ignoring enumerator class/module #{obj}"
|
221
|
-
end
|
222
|
-
else
|
223
|
-
if !ignored_enumeration[obj.class]
|
224
|
-
ignored_enumeration[obj.class] = true
|
225
|
-
puts "ignoring enumerator object of class #{obj.class}"
|
226
|
-
end
|
227
|
-
end
|
228
|
-
end
|
229
|
-
end
|
230
|
-
end
|
231
|
-
if old_graph_size == graph.size
|
232
|
-
break
|
233
|
-
end
|
234
|
-
end
|
235
|
-
live_objects.clear # to avoid making it a central node in future calls
|
236
|
-
return graph
|
237
|
-
end
|
238
|
-
|
239
|
-
def collapse(*klasses)
|
240
|
-
vertices = graph.vertices.dup
|
241
|
-
vertices.each do |v|
|
242
|
-
case v.obj
|
243
|
-
when *klasses
|
244
|
-
next if v.root?(graph) || v.leaf?(graph)
|
245
|
-
|
246
|
-
v.each_parent_vertex(graph) do |parent|
|
247
|
-
all_parent_info = parent[v, graph]
|
248
|
-
v.each_child_vertex(graph) do |child|
|
249
|
-
all_child_info = v[child, graph]
|
250
|
-
all_parent_info.each do |parent_info|
|
251
|
-
all_child_info.each do |child_info|
|
252
|
-
add_reference(parent, child, parent_info + "." + child_info)
|
253
|
-
end
|
254
|
-
end
|
255
|
-
end
|
256
|
-
end
|
257
|
-
graph.remove(v)
|
258
|
-
end
|
259
|
-
end
|
260
|
-
end
|
261
|
-
|
262
|
-
def live_chain_for(obj)
|
263
|
-
result = []
|
264
|
-
|
265
|
-
# Find one Roby task and look at the chain
|
266
|
-
ref = references[obj.object_id]
|
267
|
-
stack = [[ref.obj]]
|
268
|
-
graph.reverse.each_dfs(ref, BGL::Graph::TREE) do |source, target, info, kind|
|
269
|
-
source = source.obj
|
270
|
-
target = target.obj
|
271
|
-
if stack.last.first.object_id != source.object_id && stack.any? { |obj, _| obj.object_id == source.object_id }
|
272
|
-
result << stack.dup if stack.size != 1
|
273
|
-
while stack.last.first.object_id != source.object_id
|
274
|
-
stack.pop
|
275
|
-
end
|
276
|
-
end
|
277
|
-
stack.push [target, info]
|
278
|
-
end
|
279
|
-
if stack.size != 1
|
280
|
-
result << stack
|
281
|
-
end
|
282
|
-
result
|
283
|
-
end
|
284
|
-
|
285
|
-
|
286
|
-
def display_live_chains(chains)
|
287
|
-
chains.each do |stack|
|
288
|
-
puts stack.map { |obj, link| "#{link} #{obj}" }.join("\n >")
|
289
|
-
end
|
290
|
-
end
|
291
|
-
|
292
|
-
def to_dot
|
293
|
-
roots = graph.vertices.find_all do |v|
|
294
|
-
v.root?(graph)
|
295
|
-
end.to_value_set
|
296
|
-
|
297
|
-
io = StringIO.new("")
|
298
|
-
|
299
|
-
colors = Hash[
|
300
|
-
:green => 'green',
|
301
|
-
:magenta => 'magenta',
|
302
|
-
:black => 'black'
|
303
|
-
]
|
304
|
-
obj_label_format = "obj%i [label=\"%s\",color=%s];"
|
305
|
-
obj_label_format_elements = []
|
306
|
-
edge_label_format_0 = "obj%i -> obj%i [label=\""
|
307
|
-
edge_label_format_1 = "\"];"
|
308
|
-
edge_label_format_elements = []
|
309
|
-
|
310
|
-
all_seen = ValueSet.new
|
311
|
-
seen = ValueSet.new
|
312
|
-
io.puts "digraph {"
|
313
|
-
roots.each do |obj_ref|
|
314
|
-
graph.each_dfs(obj_ref, BGL::Graph::ALL) do |from_ref, to_ref, all_info, kind|
|
315
|
-
info = []
|
316
|
-
for str in all_info
|
317
|
-
info << str
|
318
|
-
end
|
319
|
-
|
320
|
-
if all_seen.include?(from_ref)
|
321
|
-
graph.prune
|
322
|
-
else
|
323
|
-
from_id = from_ref.obj.object_id
|
324
|
-
to_id = to_ref.obj.object_id
|
325
|
-
|
326
|
-
edge_label_format_elements.clear
|
327
|
-
edge_label_format_elements << from_id << to_id
|
328
|
-
str = edge_label_format_0 % edge_label_format_elements
|
329
|
-
first = true
|
330
|
-
for edge_info in all_info
|
331
|
-
if !first
|
332
|
-
str << ","
|
333
|
-
end
|
334
|
-
str << edge_info
|
335
|
-
first = false
|
336
|
-
end
|
337
|
-
str << edge_label_format_1
|
338
|
-
|
339
|
-
io.puts str
|
340
|
-
end
|
341
|
-
seen << from_ref << to_ref
|
342
|
-
end
|
343
|
-
|
344
|
-
for obj_ref in seen
|
345
|
-
if !all_seen.include?(obj_ref)
|
346
|
-
obj = obj_ref.obj
|
347
|
-
obj_id = obj_ref.obj.object_id
|
348
|
-
str =
|
349
|
-
if obj.respond_to?(:each)
|
350
|
-
"#{obj.class}: #{obj.object_id}"
|
351
|
-
else
|
352
|
-
obj.to_s
|
353
|
-
end
|
354
|
-
|
355
|
-
str = str.encode('UTF-8', :invalid => :replace, :undef => :replace, :replace => "")
|
356
|
-
str = str.gsub(/[^\w\.:<>]/, "")
|
357
|
-
|
358
|
-
color =
|
359
|
-
if obj.kind_of?(BGL::Graph)
|
360
|
-
:magenta
|
361
|
-
elsif obj.kind_of?(Hash) || obj.kind_of?(Array) || obj.kind_of?(ValueSet)
|
362
|
-
:green
|
363
|
-
else
|
364
|
-
:black
|
365
|
-
end
|
366
|
-
|
367
|
-
obj_label_format_elements = [obj_id, str.gsub(/[\\"\n]/, " "), colors[color]]
|
368
|
-
str = obj_label_format % obj_label_format_elements
|
369
|
-
io.puts(str)
|
370
|
-
end
|
371
|
-
end
|
372
|
-
all_seen.merge(seen)
|
373
|
-
seen.clear
|
374
|
-
end
|
375
|
-
roots.clear
|
376
|
-
all_seen.clear
|
377
|
-
seen.clear
|
378
|
-
io.puts "}"
|
379
|
-
io.string
|
380
|
-
end
|
381
|
-
end
|
382
|
-
end
|
383
|
-
end
|
384
|
-
|
data/test/data/test_pkgconfig.pc
DELETED
data/test/test_array.rb
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
require './test/test_config'
|
2
|
-
require 'utilrb/array'
|
3
|
-
|
4
|
-
class TC_Array < Test::Unit::TestCase
|
5
|
-
def test_to_s
|
6
|
-
assert_equal("[1, 2]", [1, 2].to_s)
|
7
|
-
end
|
8
|
-
def test_to_s_recursive
|
9
|
-
obj = [1, 2]
|
10
|
-
obj << obj
|
11
|
-
assert_equal("[1, 2, ...]", obj.to_s)
|
12
|
-
end
|
13
|
-
|
14
|
-
end
|
15
|
-
|
data/test/test_config.rb
DELETED
data/test/test_dir.rb
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
require './test/test_config'
|
2
|
-
|
3
|
-
require 'utilrb/dir'
|
4
|
-
require 'enumerator'
|
5
|
-
|
6
|
-
class TC_Dir < Test::Unit::TestCase
|
7
|
-
def test_empty
|
8
|
-
this_dir = File.dirname(__FILE__)
|
9
|
-
assert(!Dir.new(this_dir).empty?)
|
10
|
-
|
11
|
-
begin
|
12
|
-
Dir.mkdir(test_dir_path = File.join(this_dir, 'test_empty') )
|
13
|
-
rescue Errno::EEXIST
|
14
|
-
end
|
15
|
-
|
16
|
-
test_dir = Dir.new(test_dir_path)
|
17
|
-
assert(test_dir.empty?)
|
18
|
-
ensure
|
19
|
-
Dir.delete(test_dir_path) if test_dir_path
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
data/test/test_enumerable.rb
DELETED
@@ -1,119 +0,0 @@
|
|
1
|
-
require './test/test_config'
|
2
|
-
|
3
|
-
require 'utilrb/enumerable'
|
4
|
-
require 'utilrb/value_set'
|
5
|
-
|
6
|
-
class TC_Enumerable < Test::Unit::TestCase
|
7
|
-
|
8
|
-
def test_enum_uniq
|
9
|
-
# Test the enum_uniq enumerator
|
10
|
-
assert_equal([:a, :b, :c], [:a, :b, :a, :c].enum_uniq { |k| k }.to_a)
|
11
|
-
assert_equal([:a, :b, :c], [:a, :b, :a, :c].enum_uniq.to_a)
|
12
|
-
enum = [:a, :b, :a, :c].enum_uniq
|
13
|
-
assert_equal(enum, enum.each)
|
14
|
-
|
15
|
-
a, b, c, d = [1, 2], [1, 3], [2, 3], [3, 4]
|
16
|
-
|
17
|
-
test = [a, b, c, d]
|
18
|
-
assert_equal([a, c, d], test.enum_uniq { |x, y| x }.to_a)
|
19
|
-
assert_equal([a, b, d], test.enum_uniq { |x, y| y }.to_a)
|
20
|
-
|
21
|
-
klass = Class.new do
|
22
|
-
def initialize(base); @base = base end
|
23
|
-
def each(&iterator); @base.each { |x, y| yield [x, y] } end
|
24
|
-
include Enumerable
|
25
|
-
end
|
26
|
-
test = klass.new(test)
|
27
|
-
assert_equal([a, c, d], test.enum_uniq { |x, y| x }.to_a)
|
28
|
-
assert_equal([a, b, d], test.enum_uniq { |x, y| y }.to_a)
|
29
|
-
|
30
|
-
klass = Struct.new :x, :y
|
31
|
-
test = test.map { |x, y| klass.new(x, y) }
|
32
|
-
a, b, c, d = *test
|
33
|
-
assert_equal([a, c, d], [a, b, c, d].enum_uniq { |v| v.x }.to_a)
|
34
|
-
assert_equal([a, b, d], [a, b, c, d].enum_uniq { |v| v.y }.to_a)
|
35
|
-
end
|
36
|
-
|
37
|
-
def test_each_uniq
|
38
|
-
assert_equal([:a, :b, :c], [:a, :b, :a, :c].enum_for(:each_uniq).to_a)
|
39
|
-
end
|
40
|
-
|
41
|
-
def test_enum_sequence
|
42
|
-
c1 = [:a, :b, :c]
|
43
|
-
c2 = [:d, :e, :f]
|
44
|
-
assert_equal([:a, :b, :c, :d, :e, :f], (c1.to_enum + c2.to_enum).to_a)
|
45
|
-
assert_equal([:a, :b, :c, :d, :e, :f], [c1, c2].inject(null_enum) { |a, b| a + b }.to_a)
|
46
|
-
assert_equal([:a, :b, :c, :d, :e, :f], [c1, c2].inject(SequenceEnumerator.new) { |a, b| a << b }.to_a)
|
47
|
-
end
|
48
|
-
|
49
|
-
def test_random_element
|
50
|
-
# Test on arrays
|
51
|
-
set = (1..100).to_a
|
52
|
-
100.times { set.delete(set.random_element) }
|
53
|
-
assert(set.empty?)
|
54
|
-
assert_equal(nil, [].random_element)
|
55
|
-
|
56
|
-
# Test on non-empty collection which defines #size
|
57
|
-
set = Hash[*(1..100).map { |i| [i.to_s, i] }.flatten]
|
58
|
-
100.times { set.delete(set.random_element.first) }
|
59
|
-
assert(set.empty?)
|
60
|
-
assert_equal(nil, {}.random_element)
|
61
|
-
end
|
62
|
-
|
63
|
-
Utilrb.require_ext('test_value_set') do
|
64
|
-
def test_value_set
|
65
|
-
a = [1, 3, 3, 4, 6, 8].to_value_set
|
66
|
-
b = [1, 2, 4, 3, 11, 11].to_value_set
|
67
|
-
assert_equal(5, a.size)
|
68
|
-
assert_equal([1, 3, 4, 6, 8], a.to_a)
|
69
|
-
assert(a.include?(1))
|
70
|
-
assert(a.include_all?([4, 1, 8].to_value_set))
|
71
|
-
assert(!a.include_all?(b))
|
72
|
-
|
73
|
-
assert(a.intersects?(b))
|
74
|
-
assert(b.intersects?(a))
|
75
|
-
assert(!a.intersects?([2, 9, 12].to_value_set))
|
76
|
-
|
77
|
-
assert(a.object_id == a.to_value_set.object_id)
|
78
|
-
|
79
|
-
assert_equal([1, 2, 3, 4, 6, 8, 11], (a.union(b)).to_a)
|
80
|
-
assert_equal([1, 3, 4], (a.intersection(b)).to_a)
|
81
|
-
assert_equal([6, 8], (a.difference(b)).to_a)
|
82
|
-
assert(! (a == :bla)) # check #== behaves correctly with a non-enumerable
|
83
|
-
|
84
|
-
a.delete(1)
|
85
|
-
assert(! a.include?(1))
|
86
|
-
a.merge(b);
|
87
|
-
assert_equal([1, 2, 3, 4, 6, 8, 11].to_value_set, a)
|
88
|
-
|
89
|
-
assert([].to_value_set.empty?)
|
90
|
-
|
91
|
-
assert([1, 2, 4, 3].to_value_set.clear.empty?)
|
92
|
-
|
93
|
-
assert_equal([1,3,5].to_value_set, [1, 2, 3, 4, 5, 6].to_value_set.delete_if { |v| v % 2 == 0 })
|
94
|
-
end
|
95
|
-
|
96
|
-
def test_value_set_hash
|
97
|
-
a = [(obj = Object.new), 3, 4, [(obj2 = Object.new), Hash.new]].to_value_set
|
98
|
-
b = [obj, 3, 4, [obj2, Hash.new]].to_value_set
|
99
|
-
assert_equal a.hash, b.hash
|
100
|
-
end
|
101
|
-
|
102
|
-
def test_value_set_to_s
|
103
|
-
obj = ValueSet.new
|
104
|
-
obj << 1
|
105
|
-
obj << 2
|
106
|
-
assert(obj.to_s =~ /\{(.*)\}/)
|
107
|
-
values = $1.split(", ")
|
108
|
-
assert_equal(["1", "2"].to_set, values.to_set)
|
109
|
-
|
110
|
-
obj << obj
|
111
|
-
assert(obj.to_s =~ /^(.+)\{(.*)\}>$/)
|
112
|
-
|
113
|
-
base_s = $1
|
114
|
-
values = $2.split(", ")
|
115
|
-
assert_equal(["1", "2", "#{base_s}...>"].to_set, values.to_set)
|
116
|
-
end
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|