1begin
2  require_relative 'helper'
3  require_relative '../ruby/envutil'
4rescue LoadError
5end
6
7module Fiddle
8  class TestPointer < TestCase
9    def dlwrap arg
10      Fiddle.dlwrap arg
11    end
12
13    include Test::Unit::Assertions
14
15    def test_cptr_to_int
16      null = Fiddle::NULL
17      assert_equal(null.to_i, null.to_int)
18    end
19
20    def test_malloc_free_func_int
21      free = Fiddle::Function.new(Fiddle::RUBY_FREE, [TYPE_VOIDP], TYPE_VOID)
22      assert_equal free.to_i, Fiddle::RUBY_FREE.to_i
23
24      ptr  = Pointer.malloc(10, free.to_i)
25      assert_equal 10, ptr.size
26      assert_equal free.to_i, ptr.free.to_i
27    end
28
29    def test_malloc_free_func
30      free = Fiddle::Function.new(Fiddle::RUBY_FREE, [TYPE_VOIDP], TYPE_VOID)
31
32      ptr  = Pointer.malloc(10, free)
33      assert_equal 10, ptr.size
34      assert_equal free.to_i, ptr.free.to_i
35    end
36
37    def test_to_str
38      str = "hello world"
39      ptr = Pointer[str]
40
41      assert_equal 3, ptr.to_str(3).length
42      assert_equal str, ptr.to_str
43
44      ptr[5] = 0
45      assert_equal "hello\0world", ptr.to_str
46    end
47
48    def test_to_s
49      str = "hello world"
50      ptr = Pointer[str]
51
52      assert_equal 3, ptr.to_s(3).length
53      assert_equal str, ptr.to_s
54
55      ptr[5] = 0
56      assert_equal 'hello', ptr.to_s
57    end
58
59    def test_minus
60      str = "hello world"
61      ptr = Pointer[str]
62      assert_equal ptr.to_s, (ptr + 3 - 3).to_s
63    end
64
65    # TODO: what if the pointer size is 0?  raise an exception? do we care?
66    def test_plus
67      str = "hello world"
68      ptr = Pointer[str]
69      new_str = ptr + 3
70      assert_equal 'lo world', new_str.to_s
71    end
72
73    def test_inspect
74      ptr = Pointer.new(0)
75      inspect = ptr.inspect
76      assert_match(/size=#{ptr.size}/, inspect)
77      assert_match(/free=#{sprintf("%#x", ptr.free.to_i)}/, inspect)
78      assert_match(/ptr=#{sprintf("%#x", ptr.to_i)}/, inspect)
79    end
80
81    def test_to_ptr_string
82      str = "hello world"
83      ptr = Pointer[str]
84      assert ptr.tainted?, 'pointer should be tainted'
85      assert_equal str.length, ptr.size
86      assert_equal 'hello', ptr[0,5]
87    end
88
89    def test_to_ptr_io
90      buf = Pointer.malloc(10)
91      File.open(__FILE__, 'r') do |f|
92        ptr = Pointer.to_ptr f
93        fread = Function.new(@libc['fread'],
94                             [TYPE_VOIDP, TYPE_INT, TYPE_INT, TYPE_VOIDP],
95                             TYPE_INT)
96        fread.call(buf.to_i, Fiddle::SIZEOF_CHAR, buf.size - 1, ptr.to_i)
97      end
98
99      File.open(__FILE__, 'r') do |f|
100        assert_equal f.read(9), buf.to_s
101      end
102    end
103
104    def test_to_ptr_with_ptr
105      ptr = Pointer.new 0
106      ptr2 = Pointer.to_ptr Struct.new(:to_ptr).new(ptr)
107      assert_equal ptr, ptr2
108
109      assert_raises(Fiddle::DLError) do
110        Pointer.to_ptr Struct.new(:to_ptr).new(nil)
111      end
112    end
113
114    def test_to_ptr_with_num
115      ptr = Pointer.new 0
116      assert_equal ptr, Pointer[0]
117    end
118
119    def test_equals
120      ptr   = Pointer.new 0
121      ptr2  = Pointer.new 0
122      assert_equal ptr2, ptr
123    end
124
125    def test_not_equals
126      ptr = Pointer.new 0
127      refute_equal 10, ptr, '10 should not equal the pointer'
128    end
129
130    def test_cmp
131      ptr = Pointer.new 0
132      assert_nil(ptr <=> 10, '10 should not be comparable')
133    end
134
135    def test_ref_ptr
136      ary = [0,1,2,4,5]
137      addr = Pointer.new(dlwrap(ary))
138      assert_equal addr.to_i, addr.ref.ptr.to_i
139
140      assert_equal addr.to_i, (+ (- addr)).to_i
141    end
142
143    def test_to_value
144      ary = [0,1,2,4,5]
145      addr = Pointer.new(dlwrap(ary))
146      assert_equal ary, addr.to_value
147    end
148
149    def test_free
150      ptr = Pointer.malloc(4)
151      assert_nil ptr.free
152    end
153
154    def test_free=
155      assert_normal_exit(<<-"End", '[ruby-dev:39269]')
156        require 'fiddle'
157        Fiddle::LIBC_SO = #{Fiddle::LIBC_SO.dump}
158        Fiddle::LIBM_SO = #{Fiddle::LIBM_SO.dump}
159        include Fiddle
160        @libc = dlopen(LIBC_SO)
161        @libm = dlopen(LIBM_SO)
162        free = Fiddle::Function.new(Fiddle::RUBY_FREE, [TYPE_VOIDP], TYPE_VOID)
163        ptr = Fiddle::Pointer.malloc(4)
164        ptr.free = free
165        free.ptr
166        ptr.free.ptr
167      End
168
169      free = Function.new(Fiddle::RUBY_FREE, [TYPE_VOIDP], TYPE_VOID)
170      ptr = Pointer.malloc(4)
171      ptr.free = free
172
173      assert_equal free.ptr, ptr.free.ptr
174    end
175
176    def test_null?
177      ptr = Pointer.new(0)
178      assert ptr.null?
179    end
180
181    def test_size
182      ptr = Pointer.malloc(4)
183      assert_equal 4, ptr.size
184      Fiddle.free ptr.to_i
185    end
186
187    def test_size=
188      ptr = Pointer.malloc(4)
189      ptr.size = 10
190      assert_equal 10, ptr.size
191      Fiddle.free ptr.to_i
192    end
193
194    def test_aref_aset
195      check = Proc.new{|str,ptr|
196        assert_equal(str.size(), ptr.size())
197        assert_equal(str, ptr.to_s())
198        assert_equal(str[0,2], ptr.to_s(2))
199        assert_equal(str[0,2], ptr[0,2])
200        assert_equal(str[1,2], ptr[1,2])
201        assert_equal(str[1,0], ptr[1,0])
202        assert_equal(str[0].ord, ptr[0])
203        assert_equal(str[1].ord, ptr[1])
204      }
205      str = 'abc'
206      ptr = Pointer[str]
207      check.call(str, ptr)
208
209      str[0] = "c"
210      assert_equal 'c'.ord, ptr[0] = "c".ord
211      check.call(str, ptr)
212
213      str[0,2] = "aa"
214      assert_equal 'aa', ptr[0,2] = "aa"
215      check.call(str, ptr)
216
217      ptr2 = Pointer['cdeeee']
218      str[0,2] = "cd"
219      assert_equal ptr2, ptr[0,2] = ptr2
220      check.call(str, ptr)
221
222      ptr3 = Pointer['vvvv']
223      str[0,2] = "vv"
224      assert_equal ptr3.to_i, ptr[0,2] = ptr3.to_i
225      check.call(str, ptr)
226    end
227
228    def test_null_pointer
229      nullpo = Pointer.new(0)
230      assert_raise(DLError) {nullpo[0]}
231      assert_raise(DLError) {nullpo[0] = 1}
232    end
233  end
234end if defined?(Fiddle)
235