3
class TestNumeric < Test::Unit::TestCase
5
class NumericWithSomeMethods < Numeric
6
def initialize(value = 0)
15
raise "Expected #{@expected_arg.inspect}, but received #{arg.inspect}" unless @expected_arg == arg
18
def /(arg) check(arg); 543.21 end
19
def %(arg) check(arg); 89 end
20
def to_f() @value.to_f end
21
def <=>(other) @value <=> other end
22
def <(other) @value < other end
23
def >(other) @value > other end
24
def eql?(other) @value.eql?(other) end
25
def to_i() @value.to_i end
37
def test_unary_minus_should_raise_if_self_cannot_be_coerced_to_float
38
assert_raises(TypeError) { -@a }
41
def test_unary_minus_should_coerce_to_float_and_negate_result
42
assert_equal 123.45, NumericWithSomeMethods.new(123.45).to_f
43
assert_equal -123.45, -NumericWithSomeMethods.new(123.45)
46
def test_spaceship_should_return_zero_when_comparting_with_self_and_nil_otherwise
47
assert_equal 0, @a <=> @a
55
def test_abs_should_return_self_if_bigger_than_zero_and_result_of_unitary_minus_on_self_otherwise
56
assert_raises(ArgumentError) { @a.abs }
58
positive = NumericWithSomeMethods.new(1).abs
60
assert_same positive, positive.abs
62
negative = NumericWithSomeMethods.new(-2)
64
# unitary minus operator effectively returns -(self.to_f)
65
assert_equal 2.0, negative.abs
66
assert_equal Float, negative.abs.class
70
def test_ceil_should_delegate_to_self_to_f
71
assert_equal 124, NumericWithSomeMethods.new(123.49).ceil
72
assert_equal -123, NumericWithSomeMethods.new(-123.51).ceil
75
def test_ceil_should_raise_if_self_doesnt_implement_to_f
76
assert_raises(TypeError) { @a.ceil }
80
def test_coerce_should_copy_argument_and_self_if_both_have_the_same_type
81
assert_equal [@b, @a], @a.coerce(@b)
82
assert_equal [0.9, 0.1], 0.1.coerce(0.9)
83
assert_equal [0, 1], 1.coerce(0)
86
def test_coerce_should_call_float_on_self_and_arg_if_they_are_of_different_type
87
bignum = 100000000000000000000000
88
assert bignum.is_a?(Bignum)
89
assert_equal [Float(bignum), 0.0], 0.0.coerce(bignum)
90
assert 0.0.coerce(bignum).first.is_a?(Float)
91
assert 0.0.coerce(bignum).last.is_a?(Float)
93
n = NumericWithSomeMethods.new(123.45)
94
assert_equal [1.0, 123.45], n.coerce(1.0)
97
def test_coerce_should_blow_up_if_self_or_arg_cannot_be_converted_to_float_by_kernel_Float
98
assert_raises(TypeError) { @a.coerce(1.0) }
99
assert_raises(ArgumentError) { 1.coerce("test") }
100
assert_raises(TypeError) { 1.coerce(nil) }
101
assert_raises(TypeError) { 1.coerce(false) }
104
def test_div_should_raise_if_self_doesnt_implement_divison_operator
105
assert_raises(NoMethodError) { @a.div(@b) }
108
def test_div_should_call_division_method_and_floor_it
109
n = NumericWithSomeMethods.new
111
# n / anything returns 543.21
113
assert_equal 543.21, n / :foo
115
assert_equal 543, n.div(@a)
118
def test_divmod_should_return_result_of_div_and_mod_as_array
119
n = NumericWithSomeMethods.new
121
# n.div(anything) returns 543, n % anything returns 89
122
assert_equal [543, 89], n.divmod(:foo)
125
def test_divmod_should_calculate_div_correctly
126
dividends = [-0.58, 0.58, -0.59, 0.59, -0.63, 0.63, -0.66, 0.66, -0.67, 0.67]
128
expected_divs = [-7, 6, -8, 7, -8, 7, -8, 7, -9, 8]
129
dividends.each_with_index { |dividend, idx|
130
assert_equal(expected_divs[idx], dividend.divmod(divisor)[0])
134
def test_divmod_should_raise_when_self_doesnt_implement_div_or_mod
135
assert_raises(NoMethodError) { @a.divmod(@b) }
139
assert_equal true, @a.eql?(@a)
140
assert_equal false, @a.eql?(@b)
143
def test_floor_should_delegate_to_self_to_f
144
assert_equal 123, NumericWithSomeMethods.new(123.51).floor
145
assert_equal -124, NumericWithSomeMethods.new(-123.49).floor
148
def test_floor_should_raise_if_self_doesnt_implement_to_f
149
assert_raises(TypeError) { @a.floor }
152
def test_initialize_copy_should_raise
153
assert_raises(TypeError) { @a.instance_eval("initialize_copy(:foo)") }
156
def test_initialize_copy_should_be_private
157
assert @a.private_methods.include?("initialize_copy")
158
assert_equal false, @a.methods.include?("initialize_copy")
162
assert_equal false, @a.integer?
165
def test_modulo_should_raise_if_self_doesnt_have_percent_operator
166
assert_raises(NoMethodError) { @a.modulo(@b) }
169
def test_modulo_should_call_percent_operator
170
n = NumericWithSomeMethods.new
172
# n % anything returns 89
173
assert_equal 89, n.modulo(:foo)
176
def test_nonzero_should_check_equality_and_returns_self_or_nil
177
assert_same @a, @a.nonzero?
178
assert_nil NumericWithSomeMethods.new(0).nonzero?
179
one = NumericWithSomeMethods.new(1)
180
minus_one = NumericWithSomeMethods.new(1)
182
assert_same one, one.nonzero?
183
assert_same minus_one, minus_one.nonzero?
187
assert_raises(NoMethodError) { @a.quo @b }
190
def test_remainder_should_raise_if_self_doesnt_implement_modulo
191
assert_raises(NoMethodError) { @a.remainder(@b) }
194
def test_remainder_should_return_modulo_if_self_and_arg_have_the_same_sign_and_modulo_minus_arg_otherwise_except_when_modulo_is_zero
195
# Float doesn't override Numeric#remainder, so that's what we are testng here
196
assert_equal 2.0, 5.0.remainder(3)
197
assert_equal 2.0, 5.0.remainder(-3)
199
assert_equal -2.0, -5.0.remainder(-3)
200
assert_equal -2.0, -5.0.remainder(3)
202
# special case, was a bug
203
assert_equal 0.0, 4.0.remainder(2)
204
assert_equal 0.0, 4.0.remainder(-2)
205
assert_equal 0.0, -4.0.remainder(2)
206
assert_equal 0.0, -4.0.remainder(-2)
209
def test_round_should_delegate_to_self_to_f
210
assert_equal 123, NumericWithSomeMethods.new(123.49).round
211
assert_equal 124, NumericWithSomeMethods.new(123.51).round
212
assert_equal -123, NumericWithSomeMethods.new(-123.49).round
213
assert_equal -124, NumericWithSomeMethods.new(-123.51).round
216
def test_round_should_raise_if_self_doesnt_implement_to_f
217
assert_raises(TypeError) { @a.round }
221
# Fixnum doesn't override Numeric#step()
223
# ends exactly at :to
225
1.step(5, 2) { |x| a << x }
226
assert_equal [1, 3, 5], a
230
1.step(4, 2) { |x| a << x }
231
assert_equal [1, 3], a
235
1.step(4, 10) { |x| a << x }
239
assert_raises(ArgumentError) { 1.step(1, 0) }
243
1.step(1, 1) { |x| a << x }
246
# from less than to, positive step value
248
1.step(0, 1) { |x| a << x }
251
# from less than to, negative step value
253
1.step(0, 1) { |x| a << x }
256
# default step value of 1
258
1.step(3) { |x| a << x }
259
assert_equal [1, 2, 3], a
263
def test_step_should_raise_if_step_is_zero
268
def test_to_int_should_call_to_i_or_raise_if_to_i_is_not_implemented
269
assert_equal 123, NumericWithSomeMethods.new(123).to_int
270
assert_raises(NoMethodError) { @a.to_int }
273
def test_truncate_should_delegate_to_self_to_f
274
assert_equal 123, NumericWithSomeMethods.new(123.49).truncate
275
assert_equal 123, NumericWithSomeMethods.new(123.51).truncate
276
assert_equal -123, NumericWithSomeMethods.new(-123.49).truncate
277
assert_equal -123, NumericWithSomeMethods.new(-123.51).truncate
280
def test_truncate_should_raise_if_self_doesnt_implement_to_f
281
assert_raises(TypeError) { @a.truncate }
284
def test_zero_should_check_equality
285
assert_equal false, @a.zero?
286
assert_equal true, NumericWithSomeMethods.new(0).zero?
287
assert_equal false, NumericWithSomeMethods.new(1).zero?
288
assert_equal false, NumericWithSomeMethods.new(-1).zero?
294
class TestNumeric < Test::Unit::TestCase
296
class NumericWithSomeMethods < Numeric
297
def initialize(value = 0)
306
raise "Expected #{@expected_arg.inspect}, but received #{arg.inspect}" unless @expected_arg == arg
309
def /(arg) check(arg); 543.21 end
310
def %(arg) check(arg); 89 end
311
def to_f() @value.to_f end
312
def <=>(other) @value <=> other end
313
def <(other) @value < other end
314
def >(other) @value > other end
315
def eql?(other) @value.eql?(other) end
316
def to_i() @value.to_i end
328
def test_unary_minus_should_raise_if_self_cannot_be_coerced_to_float
329
assert_raises(TypeError) { -@a }
332
def test_unary_minus_should_coerce_to_float_and_negate_result
333
assert_equal 123.45, NumericWithSomeMethods.new(123.45).to_f
334
assert_equal -123.45, -NumericWithSomeMethods.new(123.45)
337
def test_spaceship_should_return_zero_when_comparting_with_self_and_nil_otherwise
338
assert_equal 0, @a <=> @a
343
assert_nil @a <=> nil
346
def test_abs_should_return_self_if_bigger_than_zero_and_result_of_unitary_minus_on_self_otherwise
347
assert_raises(ArgumentError) { @a.abs }
349
positive = NumericWithSomeMethods.new(1).abs
351
assert_same positive, positive.abs
353
negative = NumericWithSomeMethods.new(-2)
355
# unitary minus operator effectively returns -(self.to_f)
356
assert_equal 2.0, negative.abs
357
assert_equal Float, negative.abs.class
361
def test_ceil_should_delegate_to_self_to_f
362
assert_equal 124, NumericWithSomeMethods.new(123.49).ceil
363
assert_equal -123, NumericWithSomeMethods.new(-123.51).ceil
366
def test_ceil_should_raise_if_self_doesnt_implement_to_f
367
assert_raises(TypeError) { @a.ceil }
371
def test_coerce_should_copy_argument_and_self_if_both_have_the_same_type
372
assert_equal [@b, @a], @a.coerce(@b)
373
assert_equal [0.9, 0.1], 0.1.coerce(0.9)
374
assert_equal [0, 1], 1.coerce(0)
377
def test_coerce_should_call_float_on_self_and_arg_if_they_are_of_different_type
378
bignum = 100000000000000000000000
379
assert bignum.is_a?(Bignum)
380
assert_equal [Float(bignum), 0.0], 0.0.coerce(bignum)
381
assert 0.0.coerce(bignum).first.is_a?(Float)
382
assert 0.0.coerce(bignum).last.is_a?(Float)
384
n = NumericWithSomeMethods.new(123.45)
385
assert_equal [1.0, 123.45], n.coerce(1.0)
388
def test_coerce_should_blow_up_if_self_or_arg_cannot_be_converted_to_float_by_kernel_Float
389
assert_raises(TypeError) { @a.coerce(1.0) }
390
assert_raises(ArgumentError) { 1.coerce("test") }
391
assert_raises(TypeError) { 1.coerce(nil) }
392
assert_raises(TypeError) { 1.coerce(false) }
395
def test_div_should_raise_if_self_doesnt_implement_divison_operator
396
assert_raises(NoMethodError) { @a.div(@b) }
399
def test_div_should_call_division_method_and_floor_it
400
n = NumericWithSomeMethods.new
402
# n / anything returns 543.21
404
assert_equal 543.21, n / :foo
406
assert_equal 543, n.div(@a)
409
def test_divmod_should_return_result_of_div_and_mod_as_array
410
n = NumericWithSomeMethods.new
412
# n.div(anything) returns 543, n % anything returns 89
413
assert_equal [543, 89], n.divmod(:foo)
416
def test_divmod_should_raise_when_self_doesnt_implement_div_or_mod
417
assert_raises(NoMethodError) { @a.divmod(@b) }
421
assert_equal true, @a.eql?(@a)
422
assert_equal false, @a.eql?(@b)
425
def test_floor_should_delegate_to_self_to_f
426
assert_equal 123, NumericWithSomeMethods.new(123.51).floor
427
assert_equal -124, NumericWithSomeMethods.new(-123.49).floor
430
def test_floor_should_raise_if_self_doesnt_implement_to_f
431
assert_raises(TypeError) { @a.floor }
434
def test_initialize_copy_should_raise
435
assert_raises(TypeError) { @a.instance_eval("initialize_copy(:foo)") }
438
def test_initialize_copy_should_be_private
439
assert @a.private_methods.include?("initialize_copy")
440
assert_equal false, @a.methods.include?("initialize_copy")
444
assert_equal false, @a.integer?
447
def test_modulo_should_raise_if_self_doesnt_have_percent_operator
448
assert_raises(NoMethodError) { @a.modulo(@b) }
451
def test_modulo_should_call_percent_operator
452
n = NumericWithSomeMethods.new
454
# n % anything returns 89
455
assert_equal 89, n.modulo(:foo)
458
def test_nonzero_should_check_equality_and_returns_self_or_nil
459
assert_same @a, @a.nonzero?
460
assert_nil NumericWithSomeMethods.new(0).nonzero?
461
one = NumericWithSomeMethods.new(1)
462
minus_one = NumericWithSomeMethods.new(1)
464
assert_same one, one.nonzero?
465
assert_same minus_one, minus_one.nonzero?
469
assert_raises(NoMethodError) { @a.quo @b }
472
def test_remainder_should_raise_if_self_doesnt_implement_modulo
473
assert_raises(NoMethodError) { @a.remainder(@b) }
476
def test_remainder_should_return_modulo_if_self_and_arg_have_the_same_sign_and_modulo_minus_arg_otherwise_except_when_modulo_is_zero
477
# Float doesn't override Numeric#remainder, so that's what we are testng here
478
assert_equal 2.0, 5.0.remainder(3)
479
assert_equal 2.0, 5.0.remainder(-3)
481
assert_equal -2.0, -5.0.remainder(-3)
482
assert_equal -2.0, -5.0.remainder(3)
484
# special case, was a bug
485
assert_equal 0.0, 4.0.remainder(2)
486
assert_equal 0.0, 4.0.remainder(-2)
487
assert_equal 0.0, -4.0.remainder(2)
488
assert_equal 0.0, -4.0.remainder(-2)
491
def test_round_should_delegate_to_self_to_f
492
assert_equal 123, NumericWithSomeMethods.new(123.49).round
493
assert_equal 124, NumericWithSomeMethods.new(123.51).round
494
assert_equal -123, NumericWithSomeMethods.new(-123.49).round
495
assert_equal -124, NumericWithSomeMethods.new(-123.51).round
498
def test_round_should_raise_if_self_doesnt_implement_to_f
499
assert_raises(TypeError) { @a.round }
503
# Fixnum doesn't override Numeric#step()
505
# ends exactly at :to
507
1.step(5, 2) { |x| a << x }
508
assert_equal [1, 3, 5], a
512
1.step(4, 2) { |x| a << x }
513
assert_equal [1, 3], a
517
1.step(4, 10) { |x| a << x }
521
assert_raises(ArgumentError) { 1.step(1, 0) }
525
1.step(1, 1) { |x| a << x }
528
# from less than to, positive step value
530
1.step(0, 1) { |x| a << x }
533
# from less than to, negative step value
535
1.step(0, 1) { |x| a << x }
538
# default step value of 1
540
1.step(3) { |x| a << x }
541
assert_equal [1, 2, 3], a
545
def test_step_should_raise_if_step_is_zero
550
def test_to_int_should_call_to_i_or_raise_if_to_i_is_not_implemented
551
assert_equal 123, NumericWithSomeMethods.new(123).to_int
552
assert_raises(NoMethodError) { @a.to_int }
555
def test_truncate_should_delegate_to_self_to_f
556
assert_equal 123, NumericWithSomeMethods.new(123.49).truncate
557
assert_equal 123, NumericWithSomeMethods.new(123.51).truncate
558
assert_equal -123, NumericWithSomeMethods.new(-123.49).truncate
559
assert_equal -123, NumericWithSomeMethods.new(-123.51).truncate
562
def test_truncate_should_raise_if_self_doesnt_implement_to_f
563
assert_raises(TypeError) { @a.truncate }
566
def test_zero_should_check_equality
567
assert_equal false, @a.zero?
568
assert_equal true, NumericWithSomeMethods.new(0).zero?
569
assert_equal false, NumericWithSomeMethods.new(1).zero?
570
assert_equal false, NumericWithSomeMethods.new(-1).zero?