evilr 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ require 'mkmf'
2
+ $CFLAGS << " -DRUBY19" if RUBY_VERSION >= '1.9.0'
3
+ $CFLAGS << " -Wall " unless RUBY_PLATFORM =~ /solaris/
4
+ $CFLAGS << ' -g -ggdb -O0 -DDEBUG' if ENV['DEBUG']
5
+ $CFLAGS << " -Wconversion -Wsign-compare -Wno-unused-parameter -Wwrite-strings -Wpointer-arith -fno-common -pedantic -Wno-long-long" if ENV['STRICT']
6
+ $CFLAGS << (ENV['CFLAGS'] || '')
7
+ create_makefile("evilr")
@@ -0,0 +1,1157 @@
1
+ $:.unshift(File.join(File.dirname(File.dirname(File.expand_path(__FILE__)))), 'lib')
2
+ require 'evilr'
3
+
4
+ describe "" do
5
+ after{GC.start} # GC after spec to make sure nothing broke
6
+
7
+ describe "Proc#self" do
8
+ specify "should be the object the proc will call methods on by default" do
9
+ c = Class.new
10
+ c.class_eval{proc{}}.self.should == c
11
+ c.instance_eval{proc{}}.self.should == c
12
+ o = c.new
13
+ o.instance_eval{proc{}}.self.should == o
14
+ end
15
+ end
16
+
17
+ describe "Proc#self=" do
18
+ specify "should change the object the proc will call methods on by default" do
19
+ o1 = Object.new
20
+ o2 = Object.new
21
+ pr1 = o1.instance_eval{def a() 1 end; proc{a}}
22
+ pr2 = o2.instance_eval{def a() 2 end; proc{a}}
23
+ pr1.call.should == 1
24
+ pr2.call.should == 2
25
+ pr1.self = o2
26
+ pr2.self = o1
27
+ pr1.call.should == 2
28
+ pr2.call.should == 1
29
+ end
30
+ end
31
+
32
+ describe "UnboundMethod#force_bind" do
33
+ specify "should make the method bindable to another object even if the class differs" do
34
+ c = Class.new{def a() self.class end}
35
+ um = c.instance_method(:a)
36
+ c2 = Class.new
37
+ o = c2.new
38
+ proc{um.bind(o)}.should raise_error(TypeError)
39
+ m = um.force_bind(o)
40
+ m.should be_a_kind_of(Method)
41
+ m.call.should == c2
42
+ end
43
+ end
44
+
45
+ describe "Object#class=" do
46
+ before do
47
+ @o = Class.new.new
48
+ @c = Class.new
49
+ end
50
+
51
+ specify "should make given object this object's class" do
52
+ @o.should_not be_a_kind_of(@c)
53
+ @o.class = @c
54
+ @o.should be_a_kind_of(@c)
55
+ end
56
+
57
+ specify "should raise an exception for immediate objects" do
58
+ [0, :a, true, false, nil].each do |x|
59
+ proc{x.class = @c}.should raise_error(TypeError)
60
+ end
61
+ end
62
+
63
+ specify "should raise an exception if a class is not used as an argument" do
64
+ proc{@o.class = @o}.should raise_error(TypeError)
65
+ end
66
+
67
+ specify "should raise an exception if a class used is not the same underlying type" do
68
+ proc{@o.class = Hash}.should raise_error(TypeError)
69
+ end
70
+ end
71
+
72
+ describe "Object#dup_singleton_class" do
73
+ specify "should raise an exception for immediate values" do
74
+ proc{nil.dup_singleton_class}.should raise_error(TypeError)
75
+ end
76
+
77
+ specify "should return nil if the object has no singleton class" do
78
+ Object.new.dup_singleton_class.should == nil
79
+ end
80
+
81
+ specify "should return a copy of the singleton class as a non-singleton class" do
82
+ o = Object.new
83
+ o.instance_eval{def a() 1 end}
84
+ o.dup_singleton_class.new.a.should == 1
85
+ end
86
+
87
+ specify "should make the given class a subclass of Object by default" do
88
+ o = Object.new
89
+ o.instance_eval{def a() 1 end}
90
+ o.dup_singleton_class.superclass.should == Object
91
+ end
92
+
93
+ specify "should accept a class argument to make the dup a subclass of" do
94
+ o = Object.new
95
+ o.instance_eval{def a() 1 end}
96
+ c = Class.new
97
+ o.dup_singleton_class(c).superclass.should == c
98
+ end
99
+
100
+ specify "should handle extended modules by making them included modules in the class" do
101
+ o = Object.new
102
+ o.instance_eval{def a() [1] + super end}
103
+ o.extend(Module.new{def a() [2] + super end})
104
+ c = Class.new{def a() [4] + super end; include Module.new{def a() [8] end}}
105
+ o.dup_singleton_class(c).new.a.should == [1, 2, 4, 8]
106
+ end
107
+ end
108
+
109
+ describe "Object\#{push,pop}_singleton_class" do
110
+ specify "both should raise an exception for immediate values" do
111
+ proc{nil.push_singleton_class(Class.new)}.should raise_error(TypeError)
112
+ proc{nil.pop_singleton_class}.should raise_error(TypeError)
113
+ end
114
+
115
+ specify "push_singleton_class should raise an exception if a class is not given" do
116
+ proc{{}.push_singleton_class(Object.new)}.should raise_error(TypeError)
117
+ end
118
+
119
+ specify "both should return the class" do
120
+ c = Class.new
121
+ o = {}
122
+ o.push_singleton_class(c).should == c
123
+ o.pop_singleton_class.should == c
124
+ end
125
+
126
+ specify "pop_singleton_class should return nil if no singleton class exists" do
127
+ {}.pop_singleton_class.should == nil
128
+ end
129
+
130
+ specify "should add and remove singleton classes" do
131
+ o = Class.new{def a() [1] end}.new
132
+ o.a.should == [1]
133
+ o.push_singleton_class(Class.new{def a() [2] + super end})
134
+ o.a.should == [2, 1]
135
+ o.push_singleton_class(Class.new{def a() [4] + super end})
136
+ o.a.should == [4, 2, 1]
137
+ o.push_singleton_class(Class.new{def a() [8] + super end})
138
+ o.a.should == [8, 4, 2, 1]
139
+ o.pop_singleton_class
140
+ o.a.should == [4, 2, 1]
141
+ o.push_singleton_class(Class.new{def a() [16] + super end})
142
+ o.a.should == [16, 4, 2, 1]
143
+ o.pop_singleton_class
144
+ o.a.should == [4, 2, 1]
145
+ o.pop_singleton_class
146
+ o.a.should == [2, 1]
147
+ o.pop_singleton_class
148
+ o.a.should == [1]
149
+ end
150
+
151
+ specify "should handle modules included in the classes" do
152
+ o = Class.new{def a() [1] end}.new
153
+ o.a.should == [1]
154
+ o.push_singleton_class(Class.new{def a() [2] + super end; include Module.new{def a() [32] + super end}})
155
+ o.a.should == [2, 32, 1]
156
+ o.push_singleton_class(Class.new{def a() [4] + super end; include Module.new{def a() [64] + super end}})
157
+ o.a.should == [4, 64, 2, 32, 1]
158
+ o.push_singleton_class(Class.new{def a() [8] + super end; include Module.new{def a() [128] + super end}})
159
+ o.a.should == [8, 128, 4, 64, 2, 32, 1]
160
+ o.pop_singleton_class
161
+ o.a.should == [4, 64, 2, 32, 1]
162
+ o.push_singleton_class(Class.new{def a() [16] + super end; include Module.new{def a() [256] + super end}})
163
+ o.a.should == [16, 256, 4, 64, 2, 32, 1]
164
+ o.pop_singleton_class
165
+ o.a.should == [4, 64, 2, 32, 1]
166
+ o.pop_singleton_class
167
+ o.a.should == [2, 32, 1]
168
+ o.pop_singleton_class
169
+ o.a.should == [1]
170
+ end
171
+
172
+ specify "pop_singleton_class should have no effect if the object has no singleton class" do
173
+ o = Class.new{def a() [1] end}.new
174
+ o.pop_singleton_class
175
+ o.a.should == [1]
176
+ end
177
+ end
178
+
179
+ describe "Objec#remove_singleton_classes" do
180
+ specify "should raise an exception for immediate values" do
181
+ proc{nil.remove_singleton_classes}.should raise_error(TypeError)
182
+ end
183
+
184
+ specify "should return nil" do
185
+ {}.remove_singleton_classes.should == nil
186
+ end
187
+
188
+ specify "should add and remove singleton classes" do
189
+ o = Class.new{def a() [1] end}.new
190
+ o.a.should == [1]
191
+ o.push_singleton_class(Class.new{def a() [2] + super end})
192
+ o.a.should == [2, 1]
193
+ o.push_singleton_class(Class.new{def a() [4] + super end})
194
+ o.a.should == [4, 2, 1]
195
+ o.push_singleton_class(Class.new{def a() [8] + super end})
196
+ o.a.should == [8, 4, 2, 1]
197
+ o.remove_singleton_classes
198
+ o.a.should == [1]
199
+ end
200
+
201
+ specify "should handle modules included in the classes" do
202
+ o = Class.new{def a() [1] end}.new
203
+ o.a.should == [1]
204
+ o.push_singleton_class(Class.new{def a() [2] + super end; include Module.new{def a() [32] + super end}})
205
+ o.a.should == [2, 32, 1]
206
+ o.push_singleton_class(Class.new{def a() [4] + super end; include Module.new{def a() [64] + super end}})
207
+ o.a.should == [4, 64, 2, 32, 1]
208
+ o.push_singleton_class(Class.new{def a() [8] + super end; include Module.new{def a() [128] + super end}})
209
+ o.a.should == [8, 128, 4, 64, 2, 32, 1]
210
+ o.remove_singleton_classes
211
+ o.a.should == [1]
212
+ end
213
+
214
+ specify "should have no effect if the object has no singleton classes" do
215
+ o = Class.new{def a() [1] end}.new
216
+ o.remove_singleton_classes
217
+ o.a.should == [1]
218
+ end
219
+ end
220
+
221
+ describe "Object#swap_singleton_class" do
222
+ before do
223
+ @o1 = Class.new.new
224
+ @o2 = Class.new.new
225
+ end
226
+
227
+ specify "should swap singleton class with argument" do
228
+ def @o2.a; 1; end
229
+ def @o1.b; 2; end
230
+ @o1.swap_singleton_class(@o2)
231
+ @o1.a.should == 1
232
+ @o2.b.should == 2
233
+ proc{@o1.b}.should raise_error(NoMethodError)
234
+ proc{@o2.a}.should raise_error(NoMethodError)
235
+
236
+ def @o2.c; 3; end
237
+ def @o1.d; 4; end
238
+ @o2.c.should == 3
239
+ @o1.d.should == 4
240
+ proc{@o2.d}.should raise_error(NoMethodError)
241
+ proc{@o1.c}.should raise_error(NoMethodError)
242
+ end
243
+
244
+ specify "should handle singleton classes that don't exist" do
245
+ @o2.swap_singleton_class(@o1)
246
+ def @o2.c; 3; end
247
+ def @o1.d; 4; end
248
+ @o2.c.should == 3
249
+ @o1.d.should == 4
250
+ proc{@o2.d}.should raise_error(NoMethodError)
251
+ proc{@o1.c}.should raise_error(NoMethodError)
252
+ end
253
+
254
+ specify "should raise an exception for immediate objects" do
255
+ [0, :a, true, false, nil].each do |x|
256
+ proc{x.swap_singleton_class(@o2)}.should raise_error(TypeError)
257
+ proc{@o1.swap_singleton_class(x)}.should raise_error(TypeError)
258
+ end
259
+ end
260
+
261
+ specify "should return self" do
262
+ @o2.swap_singleton_class(@o1).should equal(@o2)
263
+ end
264
+
265
+ specify "should keep existing class hierarchy the same, other than the singleton classes" do
266
+ oc1 = Class.new
267
+ oc2 = Class.new
268
+ o1 = oc1.new
269
+ o2 = oc2.new
270
+ o1.swap_singleton_class(o2)
271
+ o1.class.should == oc1
272
+ o2.class.should == oc2
273
+ end
274
+
275
+ specify "should also swap modules that extend the class" do
276
+ oc1 = Class.new{def a() [16] end}
277
+ oc2 = Class.new{def a() [32] end}
278
+ o1 = oc1.new
279
+ o2 = oc2.new
280
+ o1.instance_eval{def a() [1] + super end; extend Module.new{def a() [2] + super end}}
281
+ o2.instance_eval{def a() [4] + super end; extend Module.new{def a() [8] + super end}}
282
+ o1.swap_singleton_class(o2)
283
+ o1.a.should == [4, 8, 16]
284
+ o2.a.should == [1, 2, 32]
285
+ end
286
+ end
287
+
288
+ describe "Object#unfreeze" do
289
+ before do
290
+ @o = Object.new
291
+ @o.freeze
292
+ end
293
+
294
+ specify "should unfreeze object" do
295
+ @o.unfreeze
296
+ @o.frozen?.should == false
297
+ @o.instance_variable_set(:@a, 1)
298
+ @o.instance_variable_get(:@a).should == 1
299
+ end
300
+
301
+ specify "should be idempotent" do
302
+ @o.frozen?.should == true
303
+ @o.unfreeze
304
+ @o.frozen?.should == false
305
+ @o.unfreeze
306
+ @o.frozen?.should == false
307
+ @o.instance_variable_set(:@a, 1)
308
+ @o.instance_variable_get(:@a).should == 1
309
+ end
310
+
311
+ specify "should be no-op for immediate objects" do
312
+ [0, :a, true, false, nil].each do |x|
313
+ proc{x.unfreeze}.should_not raise_error
314
+ end
315
+ end
316
+
317
+ specify "should not be allowed if $SAFE > 0" do
318
+ x = @o
319
+ Thread.new do
320
+ $SAFE = 1
321
+ proc{x.unfreeze}.should raise_error(SecurityError)
322
+ end.join
323
+ end
324
+
325
+ specify "should return self" do
326
+ @o.unfreeze.should equal(@o)
327
+ end
328
+ end
329
+
330
+ describe "Kernel#set_safe_level" do
331
+ specify "should allow the lowering of the $SAFE level" do
332
+ $SAFE = 1
333
+ set_safe_level(0)
334
+ $SAFE.should == 0
335
+ end
336
+ end
337
+
338
+ describe "Module#to_class" do
339
+ specify "should return the module in class form" do
340
+ Module.new{def a() 1 end}.to_class.new.a.should == 1
341
+ end
342
+
343
+ specify "should accept an optional argument for the new class type" do
344
+ Module.new{def a() 1 end}.to_class(Object).new.a.should == 1
345
+ Module.new{def a() super + 2 end}.to_class(Class.new{def a() 1 end}).new.a.should == 3
346
+ end
347
+
348
+ specify "should raise exception if attempting to instantiate a builtin class other than Object" do
349
+ proc{Module.new.to_class(Hash)}.should raise_error(TypeError)
350
+ proc{Module.new.to_class(Array)}.should raise_error(TypeError)
351
+ proc{Module.new.to_class(String)}.should raise_error(TypeError)
352
+ end
353
+
354
+ specify "should return copy of self (possibly reparented) if already a class" do
355
+ Class.new{def a() 1 end}.to_class.new.a.should == 1
356
+ Class.new{def a() 1 end}.to_class(Object).new.a.should == 1
357
+ Class.new{def a() super + 2 end}.to_class(Class.new{def a() 1 end}).new.a.should == 3
358
+
359
+ osc = Class.new
360
+ c = Class.new(osc)
361
+ sc = Class.new
362
+ c.to_class(sc).superclass.should == sc
363
+ c.superclass.should == osc
364
+ end
365
+
366
+ specify "should use Object as the default superclass" do
367
+ Module.new.to_class.superclass.should == Object
368
+ end
369
+
370
+ specify "should use given class as the superclass" do
371
+ c = Class.new
372
+ Module.new.to_class(c).superclass.should == c
373
+ end
374
+ end
375
+
376
+ describe "Class#to_module" do
377
+ specify "should return the class in module form" do
378
+ c = Class.new{def a() 1 end}
379
+ Class.new{include c.to_module}.new.a.should == 1
380
+ end
381
+
382
+ specify "should not modify the class's superclass" do
383
+ c = Class.new{def a() [1] end}
384
+ sc = Class.new(c){def a() [2] + (super rescue [0]) end}
385
+ Class.new{include sc.to_module}.new.a.should == [2, 0]
386
+ sc.superclass.should == c
387
+ sc.new.a.should == [2, 1]
388
+ end
389
+
390
+ specify "should not modify the class's superclass if modules are included" do
391
+ c = Class.new{def a() [1] end}
392
+ sc = Class.new(c){def a() [2] + (super rescue [0]) end; include Module.new}
393
+ Class.new{include sc.to_module}.new.a.should == [2, 0]
394
+ sc.superclass.should == c
395
+ sc.new.a.should == [2, 1]
396
+ end
397
+
398
+ specify "should handle the order of multiple included modules correctly" do
399
+ c = Class.new{def a() [1] end}
400
+ sc = Class.new(c){def a() [2] + (super rescue [0]) end}
401
+ sc.send :include, Module.new{def a() [4] + (super rescue [0]) end}
402
+ sc.send :include, Module.new{def a() [8] + (super rescue [0]) end}
403
+ Class.new{include sc.to_module}.new.a.should == [2, 8, 4, 0]
404
+ sc.superclass.should == c
405
+ sc.new.a.should == [2, 8, 4, 1]
406
+ end
407
+
408
+ specify "should handle singleton classes without modifying them" do
409
+ o = Object.new
410
+ o.instance_eval{def a() 1 end}
411
+ Class.new{include((class << o; self; end).to_module)}.new.a.should == 1
412
+ o.instance_eval{def a() super end}
413
+ proc{o.a}.should raise_error(NoMethodError)
414
+ end
415
+
416
+ specify "should handle singleton classes without modifying them if modules are included" do
417
+ o = Object.new
418
+ o.instance_eval{def a() 1 end}
419
+ o.extend Module.new
420
+ Class.new{include((class << o; self; end).to_module)}.new.a.should == 1
421
+ o.instance_eval{def a() super end}
422
+ proc{o.a}.should raise_error(NoMethodError)
423
+ end
424
+
425
+ specify "should include modules included in class" do
426
+ c = Class.new{def a() [1] + super end; include Module.new{def a() [2] + (super rescue [0]) end}}
427
+ Class.new{def a() [4] + super end; include c.to_module}.new.a.should == [4, 1, 2, 0]
428
+ end
429
+
430
+ specify "should not include superclass or modules included in superclass" do
431
+ c = Class.new{def a() [1] + super end; include Module.new{def a() [2] end}}
432
+ sc = Class.new(c){def a() [4] + super end; include Module.new{def a() [8] + (super rescue [0]) end}}
433
+ Class.new{def a() [16] + super end; include sc.to_module}.new.a.should == [16, 4, 8, 0]
434
+ end
435
+ end
436
+
437
+ describe "Class#detach_singleton" do
438
+ specify "should be a no-op on a non-singleton class" do
439
+ Class.new{def a() 1 end}.detach_singleton.new.a.should == 1
440
+ end
441
+
442
+ specify "should detach singleton class from object" do
443
+ o = Object.new
444
+ o.instance_eval{def a() 1 end}
445
+ sc = (class << o; self; end)
446
+ sc.detach_singleton.singleton_class_instance.should == nil
447
+ end
448
+
449
+ specify "should allow another singleton class to be created" do
450
+ o = Object.new
451
+ o.instance_eval{def a() 1 end}
452
+ sc = (class << o; self; end)
453
+ sc.detach_singleton
454
+ o.instance_eval{def a() super + 2 end}
455
+ o.a.should == 3
456
+ end
457
+ end
458
+
459
+ describe "Object#set_singleton_class" do
460
+ specify "should raise an exception for immediate values" do
461
+ proc{nil.set_singleton_class(Class.new)}.should raise_error(TypeError)
462
+ end
463
+
464
+ specify "should raise an exception for non-class arguments" do
465
+ proc{Object.new.set_singleton_class(Object.new)}.should raise_error(TypeError)
466
+ end
467
+
468
+ specify "should return the class" do
469
+ c = Class.new
470
+ Object.new.set_singleton_class(c).should == c
471
+ end
472
+
473
+ specify "should make object the new singleton class's instance" do
474
+ o = Object.new
475
+ o.set_singleton_class(Class.new).singleton_class_instance.should == o
476
+ end
477
+
478
+ specify "should make class the object's singleton class" do
479
+ o = Object.new
480
+ c = Class.new{def a() 1 end}
481
+ o.set_singleton_class(c)
482
+ (class << o; self; end).should == c
483
+ o.a.should == 1
484
+ end
485
+
486
+ specify "should replace an existing singleton class" do
487
+ o = Object.new
488
+ o.instance_eval{def a() 3 end}
489
+ c = Class.new{def a() 1 + (super rescue 10) end}
490
+ o.set_singleton_class(c)
491
+ o.a.should == 11
492
+ end
493
+
494
+ specify "should remove any modules currently extending the class" do
495
+ o = Object.new
496
+ o.instance_eval{def a() 3 end}
497
+ o.extend(Module.new{def a() 4 end})
498
+ c = Class.new{def a() 1 + (super rescue 10) end}
499
+ o.set_singleton_class(c)
500
+ o.a.should == 11
501
+ end
502
+
503
+ specify "should keep any existing class" do
504
+ oc = Class.new
505
+ o = oc.new
506
+ c = Class.new
507
+ sc = Class.new(c)
508
+ o.set_singleton_class(sc)
509
+ o.class.should == oc
510
+ end
511
+
512
+ specify "should make modules included in class as modules that extend the new class" do
513
+ oc = Class.new{def a() [1] end}
514
+ o = oc.new
515
+ c = Class.new{def a() [2] + super end}
516
+ sc = Class.new(c){def a() [4] + super end; include Module.new{def a() [8] + super end}}
517
+ o.set_singleton_class(sc)
518
+ o.a.should == [4, 8, 1]
519
+ end
520
+ end
521
+
522
+ describe "Object#swap" do
523
+ specify "should raise an exception for immediate values" do
524
+ proc{nil.swap(Object.new)}.should raise_error(TypeError)
525
+ proc{Object.new.swap(nil)}.should raise_error(TypeError)
526
+ end
527
+
528
+ specify "should raise an exception for swapping a class with a non-class value" do
529
+ proc{Object.new.swap(Class.new)}.should raise_error(TypeError)
530
+ proc{Class.new.swap(Object.new)}.should raise_error(TypeError)
531
+ proc{Class.new.swap(Module.new)}.should raise_error(TypeError)
532
+ end
533
+
534
+ specify "should raise an exception for swapping a module with a non-module value" do
535
+ proc{Object.new.swap(Module.new)}.should raise_error(TypeError)
536
+ proc{Module.new.swap(Object.new)}.should raise_error(TypeError)
537
+ proc{Module.new.swap(Class.new)}.should raise_error(TypeError)
538
+ end
539
+
540
+ specify "should swap the objects' classes, singleton classes, and instance variables" do
541
+ c1 = Class.new{attr_accessor :b; def a() 1 end}
542
+ c2 = Class.new{attr_accessor :b; def a() 2 end}
543
+ o1 = c1.new
544
+ o2 = c2.new
545
+ o1.instance_eval{def a() 4 + super end}
546
+ o2.instance_eval{def a() 8 + super end}
547
+ o1.b = 3
548
+ o2.b = 4
549
+ o1.swap(o2)
550
+ o1.b.should == 4
551
+ o1.a.should == 10
552
+ o1.class.should == c2
553
+ o2.b.should == 3
554
+ o2.a.should == 5
555
+ o2.class.should == c1
556
+ end
557
+
558
+ specify "should work for classes" do
559
+ c1 = Class.new{def a() 1 end}
560
+ c2 = Class.new{def a() 2 end}
561
+ c1.instance_eval{@a = 16; def a() 4 end}
562
+ c2.instance_eval{@a = 32; def a() 8 end}
563
+ c1.swap(c2)
564
+ c1.a.should == 8
565
+ c2.a.should == 4
566
+ c1.instance_eval{@a.should == 32}
567
+ c2.instance_eval{@a.should == 16}
568
+ c1.new.a.should == 2
569
+ c2.new.a.should == 1
570
+ end
571
+
572
+ specify "should work for different types of objects" do
573
+ a = {}
574
+ b = []
575
+ a.swap(b)
576
+ a.should == []
577
+ b.should == {}
578
+ end
579
+
580
+ specify "should return self (the new self)" do
581
+ o = Object.new
582
+ i = o.object_id
583
+ no = o.swap(Class.new{def a() 1 end}.new)
584
+ no.should == o
585
+ no.object_id.should == i
586
+ no.a.should == 1
587
+ end
588
+ end
589
+
590
+ describe "Object#detach_singleton_class" do
591
+ specify "should raise an exception for immediate values" do
592
+ proc{nil.detach_singleton_class}.should raise_error(TypeError)
593
+ end
594
+
595
+ specify "should be a no-op an object without a singleton class" do
596
+ a = {:a=>1}
597
+ a.detach_singleton_class
598
+ a[:a].should == 1
599
+ end
600
+
601
+ specify "should return the class" do
602
+ Object.new.detach_singleton_class.should == Object
603
+ o = Object.new
604
+ sc = (class << o; self; end)
605
+ o.detach_singleton_class.should == sc
606
+ end
607
+
608
+ specify "should remove singleton status from singleton class" do
609
+ o = Object.new
610
+ o.instance_eval{def a() 1 end}
611
+ o.detach_singleton_class.new.a.should == 1
612
+ end
613
+
614
+ specify "should detach singleton class from object, becoming the object's actual class" do
615
+ o = Object.new
616
+ o.instance_eval{def a() 1 end}
617
+ sc = (class << o; self; end)
618
+ o.detach_singleton_class
619
+ o.class.should == sc
620
+ end
621
+
622
+ specify "should have singleton class's methods remain in the method chain" do
623
+ o = Object.new
624
+ o.instance_eval{def a() 1 end}
625
+ o.detach_singleton_class
626
+ o.instance_eval{def a() super + 2 end}
627
+ o.a.should == 3
628
+ end
629
+ end
630
+
631
+ describe "Object#remove_singleton_class" do
632
+ specify "should raise an exception for immediate values" do
633
+ proc{nil.remove_singleton_class}.should raise_error(TypeError)
634
+ end
635
+
636
+ specify "should be a no-op an object without a singleton class" do
637
+ a = {:a=>1}
638
+ a.remove_singleton_class
639
+ a[:a].should == 1
640
+ end
641
+
642
+ specify "should return nil if the class does not exist" do
643
+ Object.new.remove_singleton_class.should == nil
644
+ end
645
+
646
+ specify "should return the class if it exists" do
647
+ o = Object.new
648
+ sc = (class << o; self; end)
649
+ o.remove_singleton_class.should == sc
650
+ end
651
+
652
+ specify "should remove singleton status from singleton class" do
653
+ o = Object.new
654
+ o.instance_eval{def a() 1 end}
655
+ o.remove_singleton_class.new.a.should == 1
656
+ end
657
+
658
+ specify "should remove singleton class from object, restoring the object's original class" do
659
+ o = Object.new
660
+ o.instance_eval{def a() 1 end}
661
+ sc = (class << o; self; end)
662
+ o.remove_singleton_class
663
+ o.class.should == Object
664
+ end
665
+
666
+ specify "should have singleton class's methods not remain in the method chain" do
667
+ o = Object.new
668
+ o.instance_eval{def a() 1 end}
669
+ o.remove_singleton_class
670
+ o.instance_eval{def a() super + 2 end}
671
+ proc{o.a}.should raise_error(NoMethodError)
672
+ end
673
+
674
+ specify "should handle modules that extend the object" do
675
+ o = Object.new
676
+ o.instance_eval{def a() 1 end}
677
+ o.extend(Module.new{def b() 2 end})
678
+ o.remove_singleton_class
679
+ proc{o.a}.should raise_error(NoMethodError)
680
+ proc{o.b}.should raise_error(NoMethodError)
681
+ end
682
+ end
683
+
684
+ describe "Class#singleton_class_instance" do
685
+ specify "should return nil for a non-singleton class" do
686
+ Class.new.singleton_class_instance.should == nil
687
+ end
688
+
689
+ specify "should return instance attached to singleton class" do
690
+ o = Object.new.instance_eval{def a() 1 end}
691
+ (class << o; self; end).singleton_class_instance.should equal(o)
692
+ end
693
+ end
694
+
695
+ describe "Class#superclass=" do
696
+ specify "should raise an exception for immediate values" do
697
+ proc{Class.new.superclass = nil}.should raise_error(TypeError)
698
+ end
699
+
700
+ specify "should raise an exception for non-class arguments" do
701
+ proc{Class.new.superclass = Object.new}.should raise_error(TypeError)
702
+ end
703
+
704
+ specify "should raise an exception for incompatible types" do
705
+ proc{Class.new.superclass = String}.should raise_error(TypeError)
706
+ end
707
+
708
+ specify "should change the superclass of the class" do
709
+ c = Class.new
710
+ c2 = Class.new
711
+ c.superclass.should == Object
712
+ c.superclass = c2
713
+ c.superclass.should == c2
714
+ end
715
+
716
+ specify "should keep any included modules" do
717
+ c = Class.new{def a() [1] + super end; include Module.new{def a() [2] + (super rescue [0]) end}}
718
+ c2 = Class.new{def a() [4] + super end; include Module.new{def a() [8] + (super rescue [0]) end}}
719
+ c.new.a.should == [1, 2, 0]
720
+ c2.new.a.should == [4, 8, 0]
721
+ c.superclass = c2
722
+ c.new.a.should == [1, 2, 4, 8, 0]
723
+ end
724
+
725
+ specify "should ignore existing superclasses and modules included in them" do
726
+ c = Class.new{def a() [1] + super end; include Module.new{def a() [2] + (super rescue [0]) end}}
727
+ c2 = Class.new(c){def a() [4] + super end; include Module.new{def a() [8] + (super rescue [0]) end}}
728
+ c2.new.a.should == [4, 8, 1, 2, 0]
729
+ c2.superclass = Object
730
+ c2.new.a.should == [4, 8, 0]
731
+ end
732
+ end
733
+
734
+ describe "Class#inherit" do
735
+ specify "should raise an exception for immediate values" do
736
+ proc{Class.new.inherit nil}.should raise_error(TypeError)
737
+ end
738
+
739
+ specify "should raise an exception for non-class arguments" do
740
+ proc{Class.new.inherit Object.new}.should raise_error(TypeError)
741
+ end
742
+
743
+ specify "should raise an exception for incompatible types" do
744
+ proc{Class.new.inherit String}.should raise_error(TypeError)
745
+ end
746
+
747
+ specify "should include the classes as modules" do
748
+ c = Class.new{def a() [1] + (super rescue [0]) end}
749
+ c2 = Class.new{def a() [2] + super end}
750
+ sc = Class.new{def a() [4] + super end; inherit c, c2}
751
+ sc.new.a.should == [4, 2, 1, 0]
752
+ end
753
+
754
+ specify "should keep any included modules" do
755
+ c = Class.new{def a() [1] + super end; include Module.new{def a() [2] + (super rescue [0]) end}}
756
+ c2 = Class.new{def a() [4] + super end; include Module.new{def a() [8] + (super rescue [0]) end}}
757
+ sc = Class.new{def a() [16] + super end; inherit c, c2}
758
+ sc.new.a.should == [16, 4, 8, 1, 2, 0]
759
+ end
760
+
761
+ specify "should ignore superclasses of arguments, and keep superclass of current class" do
762
+ c = Class.new{def a() [1] + super end; include Module.new{def a() [2] + (super rescue [0]) end}}
763
+ sc1 = Class.new(c){def a() [4] + super end; include Module.new{def a() [8] + (super rescue [0]) end}}
764
+ sc2 = Class.new(c){def a() [16] + super end; include Module.new{def a() [32] + (super rescue [0]) end}}
765
+ Class.new{def a() [64] + super end; inherit sc1, sc2}.new.a.should == [64, 16, 32, 4, 8, 0]
766
+ Class.new(sc2){def a() [64] + super end; inherit sc1}.new.a.should == [64, 4, 8, 16, 32, 1, 2, 0]
767
+ Class.new(sc2){def a() [64] + super end; inherit sc1}.superclass.should == sc2
768
+ end
769
+ end
770
+
771
+ describe "Object#flags" do
772
+ specify "should raise an exception for immediate values" do
773
+ proc{nil.flags}.should raise_error(TypeError)
774
+ end
775
+
776
+ specify "should return a Fixnum" do
777
+ Object.new.flags.should be_a_kind_of(Fixnum)
778
+ Class.new.flags.should be_a_kind_of(Fixnum)
779
+ Module.new.flags.should be_a_kind_of(Fixnum)
780
+ Object.new.flags.should_not == Class.new.flags
781
+ Module.new.flags.should_not == Class.new.flags
782
+ end
783
+ end
784
+
785
+ describe "Object#swap_instance_variables" do
786
+ specify "should raise an exception for immediate values" do
787
+ proc{nil.swap_instance_variables(Object.new)}.should raise_error(TypeError)
788
+ proc{Object.new.swap_instance_variables(nil)}.should raise_error(TypeError)
789
+ end
790
+
791
+ specify "should raise an exception for swapping between modules and objects" do
792
+ proc{Class.new.swap_instance_variables(Object.new)}.should raise_error(TypeError)
793
+ proc{Object.new.swap_instance_variables(Class.new)}.should raise_error(TypeError)
794
+ end
795
+
796
+ specify "should raise an exception for other types" do
797
+ proc{{}.swap_instance_variables([])}.should raise_error(TypeError)
798
+ proc{"".swap_instance_variables(//)}.should raise_error(TypeError)
799
+ end
800
+
801
+ specify "should swap the instance's instance variables" do
802
+ o1 = Object.new
803
+ o2 = Object.new
804
+ o1.instance_eval{@a = 1; @c = 3}
805
+ o2.instance_eval{@a = 4; @b = 2}
806
+ o1.swap_instance_variables(o2)
807
+ o2.instance_eval{@a.should == 1; @c.should == 3}
808
+ o1.instance_eval{@a.should == 4; @b.should == 2}
809
+ end
810
+
811
+ specify "should allow swapping between modules" do
812
+ c = Class.new
813
+ m = Module.new
814
+ c.instance_eval{@a = 1; @c = 3}
815
+ m.instance_eval{@a = 4; @b = 2}
816
+ c.swap_instance_variables(m)
817
+ m.instance_eval{@a.should == 1; @c.should == 3}
818
+ c.instance_eval{@a.should == 4; @b.should == 2}
819
+ end
820
+
821
+ specify "should return self" do
822
+ o = Object.new
823
+ o.swap_instance_variables(Object.new).should equal(o)
824
+ end
825
+ end
826
+
827
+ describe "Module#swap_method_tables" do
828
+ specify "should raise an exception for immediate values" do
829
+ proc{Class.new.swap_method_tables(nil)}.should raise_error(TypeError)
830
+ end
831
+
832
+ specify "should raise an exception for non-module arguments" do
833
+ proc{Class.new.swap_method_tables(Object.new)}.should raise_error(TypeError)
834
+ end
835
+
836
+ specify "should swap the module's method tables" do
837
+ c1 = Class.new{def a() 1 end; def b() 3 end}
838
+ c2 = Class.new{def a() 4 end; def c() 2 end}
839
+ c1.new.a.should == 1
840
+ c2.new.a.should == 4
841
+ c1.new.b.should == 3
842
+ c2.new.c.should == 2
843
+ proc{c1.new.c}.should raise_error(NoMethodError)
844
+ proc{c2.new.b}.should raise_error(NoMethodError)
845
+ c1.swap_method_tables(c2)
846
+ c2.new.a.should == 1
847
+ c1.new.a.should == 4
848
+ c2.new.b.should == 3
849
+ c1.new.c.should == 2
850
+ proc{c2.new.c}.should raise_error(NoMethodError)
851
+ proc{c1.new.b}.should raise_error(NoMethodError)
852
+ end
853
+
854
+ specify "should return self" do
855
+ c = Class.new
856
+ c.swap_method_tables(Class.new).should equal(c)
857
+ end
858
+ end
859
+
860
+ describe "Module#uninclude" do
861
+ specify "should raise an exception for immediate values" do
862
+ proc{Module.new.uninclude nil}.should raise_error(TypeError)
863
+ end
864
+
865
+ specify "should raise an exception for non-module arguments" do
866
+ proc{Module.new.uninclude Object.new}.should raise_error(TypeError)
867
+ proc{Module.new.uninclude Class.new}.should raise_error(TypeError)
868
+ end
869
+
870
+ specify "should uninclude the given module from the module/class" do
871
+ m1 = Module.new{def a() [1] + (super rescue [0]) end}
872
+ m2 = Module.new{def a() [2] + (super rescue [0]) end}
873
+ m3 = Module.new{def a() [4] + (super rescue [0]) end}
874
+ m1.send :include, m2
875
+ m1.send :include, m3
876
+
877
+ c = Class.new{include m1}
878
+ c.new.a.should == [1, 4, 2, 0]
879
+ c.uninclude m1
880
+ c.new.a.should == [4, 2, 0]
881
+ c.uninclude m2
882
+ c.new.a.should == [4, 0]
883
+
884
+ m1.uninclude m3
885
+ Class.new{include m1}.new.a.should == [1, 2, 0]
886
+ m1.uninclude m2
887
+ Class.new{include m1}.new.a.should == [1, 0]
888
+ end
889
+
890
+ specify "should traverse into superclasses" do
891
+ m1 = Module.new{def a() [1] + (super rescue [0]) end}
892
+ m2 = Module.new{def a() [2] + (super rescue [0]) end}
893
+ m3 = Module.new{def a() [4] + (super rescue [0]) end}
894
+ m1.send :include, m2
895
+
896
+ c = Class.new{def a() [8] + (super rescue [0]) end; include m1}
897
+ c = Class.new(c){def a() [16] + (super rescue [0]) end; include m3}
898
+ c.new.a.should == [16, 4, 8, 1, 2, 0]
899
+ c.uninclude m1
900
+ c.new.a.should == [16, 4, 8, 2, 0]
901
+ c.uninclude m2
902
+ c.new.a.should == [16, 4, 8, 0]
903
+ c.uninclude m3
904
+ c.new.a.should == [16, 8, 0]
905
+ end
906
+
907
+ specify "should return module if module included" do
908
+ m = Module.new
909
+ m2 = Module.new{include m}
910
+ m2.uninclude(m).should == m
911
+ end
912
+
913
+ specify "should return nil if module not included" do
914
+ Module.new.uninclude(Module.new).should == nil
915
+ end
916
+ end
917
+
918
+ describe "Module#include_between" do
919
+ specify "should raise an exception for immediate values" do
920
+ proc{Module.new.include_between(nil){|p,c|}}.should raise_error(TypeError)
921
+ end
922
+
923
+ specify "should raise an exception for non-module arguments" do
924
+ proc{Module.new.include_between(Object.new){|p,c|}}.should raise_error(TypeError)
925
+ proc{Module.new.include_between(Class.new){|p,c|}}.should raise_error(TypeError)
926
+ end
927
+
928
+ specify "should raise an exception if a block is not given" do
929
+ proc{Module.new.include_between(Module.new)}.should raise_error(LocalJumpError)
930
+ end
931
+
932
+ specify "should include the module between the block's modules if the block returns true" do
933
+ m1 = Module.new{def a() [1] + (super rescue [0]) end}
934
+ m2 = Module.new{def a() [2] + (super rescue [0]) end}
935
+ m3 = Module.new{def a() [4] + (super rescue [0]) end}
936
+
937
+ c = Class.new
938
+ c.include_between(m1){|prev, cur| true}
939
+ c.include_between(m2){|prev, cur| cur == Object}
940
+ c.include_between(m3){|prev, cur| prev == m1}
941
+ c.new.a.should == [1, 4, 2, 0]
942
+ end
943
+
944
+ specify "should traverse into superclasses" do
945
+ m1 = Module.new{def a() [1] + (super rescue [0]) end}
946
+ m2 = Module.new{def a() [2] + (super rescue [0]) end}
947
+ m3 = Module.new{def a() [4] + (super rescue [0]) end}
948
+
949
+ c = Class.new{def a() [8] + (super rescue [0]) end}
950
+ sc = Class.new(c){def a() [16] + (super rescue [0]) end}
951
+ sc.include_between(m1){|prev, cur| prev == c}
952
+ sc.include_between(m2){|prev, cur| cur == m1}
953
+ sc.include_between(m3){|prev, cur| true}
954
+ c.new.a.should == [8, 2, 1, 0]
955
+ sc.new.a.should == [16, 4, 8, 2, 1, 0]
956
+ end
957
+
958
+ specify "should have first block call first argument be current module/class" do
959
+ c = Class.new
960
+ c.include_between(Module.new){|prev, cur| prev.should == c; break}
961
+ end
962
+
963
+ specify "should have last block call last argument be nil" do
964
+ c = Class.new
965
+ x = 1
966
+ c.include_between(Module.new){|prev, cur| x = cur}
967
+ x.should == nil
968
+ end
969
+
970
+ specify "should have superclass as both last and first argument at some point, if not returned" do
971
+ c = Class.new
972
+ a = []
973
+ c.include_between(Module.new){|prev, cur| a << :prev if prev == c.superclass; a << :cur if cur == c.superclass}
974
+ a.should == [:cur, :prev]
975
+ end
976
+
977
+ specify "should return module if module included" do
978
+ m = Module.new
979
+ m2 = Module.new{include m}
980
+ m2.include_between(m){|p, c| true}.should == m
981
+ end
982
+
983
+ specify "should return nil if module not included" do
984
+ Module.new.include_between(Module.new){|p, c|}.should == nil
985
+ end
986
+ end
987
+
988
+ describe "Object#unextend" do
989
+ specify "should raise an exception if called on immediate values" do
990
+ proc{nil.unextend Module.new}.should raise_error(TypeError)
991
+ end
992
+
993
+ specify "should raise an exception for immediate value arguments" do
994
+ proc{Object.new.unextend nil}.should raise_error(TypeError)
995
+ end
996
+
997
+ specify "should raise an exception for non-module arguments" do
998
+ proc{Object.new.unextend Object.new}.should raise_error(TypeError)
999
+ proc{Object.new.unextend Class.new}.should raise_error(TypeError)
1000
+ end
1001
+
1002
+ specify "should unextend the given module from the object" do
1003
+ m1 = Module.new{def a() [1] + (super rescue [0]) end}
1004
+ m2 = Module.new{def a() [2] + (super rescue [0]) end}
1005
+ m3 = Module.new{def a() [4] + (super rescue [0]) end}
1006
+ m1.send :include, m2
1007
+ m1.send :include, m3
1008
+
1009
+ o = Object.new
1010
+ o.extend m1
1011
+ o.a.should == [1, 4, 2, 0]
1012
+ o.unextend m1
1013
+ o.a.should == [4, 2, 0]
1014
+ o.unextend m2
1015
+ o.a.should == [4, 0]
1016
+ end
1017
+
1018
+ specify "should not traverse above the object's class" do
1019
+ m1 = Module.new{def a() [1] + (super rescue [0]) end}
1020
+ m2 = Module.new{def a() [2] + (super rescue [0]) end}
1021
+ m3 = Module.new{def a() [4] + (super rescue [0]) end}
1022
+ m1.send :include, m2
1023
+
1024
+ c = Class.new{def a() [8] + (super rescue [0]) end; include m1}
1025
+ o = c.new
1026
+ o.extend m3
1027
+ o.a.should == [4, 8, 1, 2, 0]
1028
+ o.unextend m3
1029
+ o.a.should == [8, 1, 2, 0]
1030
+ o.unextend m2
1031
+ o.a.should == [8, 1, 2, 0]
1032
+ end
1033
+
1034
+ specify "should return module if module extended the object" do
1035
+ m = Module.new
1036
+ o = Object.new
1037
+ o.extend(m)
1038
+ o.unextend(m).should == m
1039
+ end
1040
+
1041
+ specify "should return nil if module did not extend the object" do
1042
+ Object.new.unextend(Module.new).should == nil
1043
+ end
1044
+
1045
+ specify "should correctly handle objects without existing singleton classes" do
1046
+ m = Module.new{def a() [2] + (super rescue [0]) end}
1047
+ c = Class.new{def a() [1] + (super rescue [0]) end; include m}
1048
+ o = c.new
1049
+ o.unextend(Module.new).should == nil
1050
+ o.a.should == [1, 2, 0]
1051
+ end
1052
+ end
1053
+
1054
+ describe "Object#extend_between" do
1055
+ specify "should raise an exception if called on an immediate value" do
1056
+ proc{nil.extend_between(Module.new){|p,c|}}.should raise_error(TypeError)
1057
+ end
1058
+
1059
+ specify "should raise an exception for immediate value arguments" do
1060
+ proc{Object.new.extend_between(nil){|p,c|}}.should raise_error(TypeError)
1061
+ end
1062
+
1063
+ specify "should raise an exception for non-module arguments" do
1064
+ proc{Object.new.extend_between(Object.new){|p,c|}}.should raise_error(TypeError)
1065
+ proc{Object.new.extend_between(Class.new){|p,c|}}.should raise_error(TypeError)
1066
+ end
1067
+
1068
+ specify "should raise an exception if a block is not given" do
1069
+ proc{Object.new.extend_between(Module.new)}.should raise_error(LocalJumpError)
1070
+ end
1071
+
1072
+ specify "should raise an exception if module already included in object's class or superclass" do
1073
+ m = Module.new
1074
+ c = Class.new{include m}
1075
+ proc{c.new.extend_between(m){|p, c|}}.should raise_error(ArgumentError)
1076
+ end
1077
+
1078
+ specify "should include the module between the block's modules if the block returns true" do
1079
+ m1 = Module.new{def a() [1] + (super rescue [0]) end}
1080
+ m2 = Module.new{def a() [2] + (super rescue [0]) end}
1081
+ m3 = Module.new{def a() [4] + (super rescue [0]) end}
1082
+
1083
+ o = Object.new
1084
+ o.extend_between(m1){|prev, cur| true}
1085
+ o.extend_between(m2){|prev, cur| cur == Object}
1086
+ o.extend_between(m3){|prev, cur| prev == m1}
1087
+ o.a.should == [1, 4, 2, 0]
1088
+ def o.a() [8] + super end
1089
+ o.a.should == [8, 1, 4, 2, 0]
1090
+ end
1091
+
1092
+ specify "should have first block call first argument be the receiver's singleton class" do
1093
+ o = Object.new
1094
+ o.extend_between(Module.new){|prev, cur| prev.should == class << o; self end; break}
1095
+ end
1096
+
1097
+ specify "should have last block call last argument be object's class" do
1098
+ c = Class.new
1099
+ x = 1
1100
+ c.new.extend_between(Module.new){|prev, cur| x = cur}
1101
+ x.should == c
1102
+ end
1103
+
1104
+ specify "should have extended modules as both last and first argument at some point" do
1105
+ m = Module.new
1106
+ c = Class.new
1107
+ o = c.new
1108
+ o.extend m
1109
+ a = []
1110
+ o.extend_between(Module.new){|prev, cur| a << :prev if prev == m; a << :cur if cur == m}
1111
+ a.should == [:cur, :prev]
1112
+ end
1113
+
1114
+ specify "should return module if module included" do
1115
+ m = Module.new
1116
+ Object.new.extend_between(m){|p, c| true}.should == m
1117
+ end
1118
+
1119
+ specify "should return nil if module not included" do
1120
+ Object.new.extend_between(Module.new){|p, c|}.should == nil
1121
+ end
1122
+
1123
+ specify "should handle objects without existing singleton classes" do
1124
+ o = Object.new
1125
+ i = 0
1126
+ o.extend_between(Module.new){|p, c| p.should == (class << o; self end); c.should == Object; i += 1}
1127
+ i.should == 1
1128
+ end
1129
+ end
1130
+
1131
+ describe "Empty" do
1132
+ specify "should be able to be instantiated" do
1133
+ proc{Empty.new}.should_not raise_error
1134
+ end
1135
+
1136
+ specify "should raise an error if instantiated with arguments" do
1137
+ proc{Empty.new 1}.should raise_error(ArgumentError)
1138
+ end
1139
+
1140
+ specify "should not raise an error if subclass instantiated with arguments and supports those arguments" do
1141
+ c = Class.new(Empty){def initialize(*) end}
1142
+ proc{c.new 1, 2, 3}.should_not raise_error
1143
+ end
1144
+
1145
+ specify "should have nil superclass" do
1146
+ Empty.superclass.should == nil
1147
+ end
1148
+
1149
+ specify "subclasses should have correct superclass" do
1150
+ Class.new(Empty).superclass.should == Empty
1151
+ end
1152
+
1153
+ specify "should have instances that aren't objects" do
1154
+ Object.instance_method(:is_a?).force_bind(Empty.new).call(Object).should be_false
1155
+ end
1156
+ end
1157
+ end