1require "test/unit"
2require "objspace"
3require_relative "../ruby/envutil"
4
5class TestObjSpace < Test::Unit::TestCase
6  def test_memsize_of
7    assert_equal(0, ObjectSpace.memsize_of(true))
8    assert_equal(0, ObjectSpace.memsize_of(nil))
9    assert_equal(0, ObjectSpace.memsize_of(1))
10    assert_kind_of(Integer, ObjectSpace.memsize_of(Object.new))
11    assert_kind_of(Integer, ObjectSpace.memsize_of(Class))
12    assert_kind_of(Integer, ObjectSpace.memsize_of(""))
13    assert_kind_of(Integer, ObjectSpace.memsize_of([]))
14    assert_kind_of(Integer, ObjectSpace.memsize_of({}))
15    assert_kind_of(Integer, ObjectSpace.memsize_of(//))
16    f = File.new(__FILE__)
17    assert_kind_of(Integer, ObjectSpace.memsize_of(f))
18    f.close
19    assert_kind_of(Integer, ObjectSpace.memsize_of(/a/.match("a")))
20    assert_kind_of(Integer, ObjectSpace.memsize_of(Struct.new(:a)))
21
22    assert_operator(ObjectSpace.memsize_of(Regexp.new("(a)"*1000).match("a"*1000)),
23                    :>,
24                    ObjectSpace.memsize_of(//.match("")))
25  end
26
27  def test_argf_memsize
28    size = ObjectSpace.memsize_of(ARGF)
29    assert_kind_of(Integer, size)
30    assert_operator(size, :>, 0)
31    argf = ARGF.dup
32    argf.inplace_mode = nil
33    size = ObjectSpace.memsize_of(argf)
34    argf.inplace_mode = "inplace_mode_suffix"
35    assert_equal(size + 20, ObjectSpace.memsize_of(argf))
36  end
37
38  def test_memsize_of_all
39    assert_kind_of(Integer, a = ObjectSpace.memsize_of_all)
40    assert_kind_of(Integer, b = ObjectSpace.memsize_of_all(String))
41    assert(a > b)
42    assert(a > 0)
43    assert(b > 0)
44    assert_raise(TypeError) {ObjectSpace.memsize_of_all('error')}
45  end
46
47  def test_count_objects_size
48    res = ObjectSpace.count_objects_size
49    assert_equal(false, res.empty?)
50    assert_equal(true, res[:TOTAL] > 0)
51    arg = {}
52    ObjectSpace.count_objects_size(arg)
53    assert_equal(false, arg.empty?)
54  end
55
56  def test_count_nodes
57    res = ObjectSpace.count_nodes
58    assert_equal(false, res.empty?)
59    arg = {}
60    ObjectSpace.count_nodes(arg)
61    assert_not_empty(arg)
62    bug8014 = '[ruby-core:53130] [Bug #8014]'
63    assert_empty(arg.select {|k, v| !(Symbol === k && Integer === v)}, bug8014)
64  end
65
66  def test_count_tdata_objects
67    res = ObjectSpace.count_tdata_objects
68    assert_equal(false, res.empty?)
69    arg = {}
70    ObjectSpace.count_tdata_objects(arg)
71    assert_equal(false, arg.empty?)
72  end
73
74  def test_reachable_objects_from
75    assert_separately %w[--disable-gem -robjspace], __FILE__, __LINE__, <<-'eom'
76    assert_equal(nil, ObjectSpace.reachable_objects_from(nil))
77    assert_equal([Array, 'a', 'b', 'c'], ObjectSpace.reachable_objects_from(['a', 'b', 'c']))
78
79    assert_equal([Array, 'a', 'a', 'a'], ObjectSpace.reachable_objects_from(['a', 'a', 'a']))
80    assert_equal([Array, 'a', 'a'], ObjectSpace.reachable_objects_from(['a', v = 'a', v]))
81    assert_equal([Array, 'a'], ObjectSpace.reachable_objects_from([v = 'a', v, v]))
82
83    long_ary = Array.new(1_000){''}
84    max = 0
85
86    ObjectSpace.each_object{|o|
87      refs = ObjectSpace.reachable_objects_from(o)
88      max = [refs.size, max].max
89
90      unless refs.nil?
91        refs.each_with_index {|ro, i|
92          assert_not_nil(ro, "#{i}: this referenced object is internal object")
93        }
94      end
95    }
96    assert_operator(max, :>=, long_ary.size+1, "1000 elems + Array class")
97    eom
98  end
99
100  def test_reachable_objects_size
101    assert_separately %w[--disable-gem -robjspace], __FILE__, __LINE__, <<-'eom'
102    ObjectSpace.each_object{|o|
103      ObjectSpace.reachable_objects_from(o).each{|reached_obj|
104        size = ObjectSpace.memsize_of(reached_obj)
105        assert_kind_of(Integer, size)
106        assert_operator(size, :>=, 0)
107      }
108    }
109    eom
110  end
111end
112