1require_relative 'test_base.rb'
2require 'dl/callback'
3require 'dl/func'
4require 'dl/pack'
5
6module DL
7class TestDL < TestBase
8  def ptr2num(*list)
9    list.pack("p*").unpack(PackInfo::PACK_MAP[TYPE_VOIDP] + "*")
10  end
11
12  # TODO: refactor test repetition
13
14  def test_free_secure
15    assert_raises(SecurityError) do
16      Thread.new do
17        $SAFE = 4
18        DL.free(0)
19      end.join
20    end
21  end
22
23  def test_realloc
24    str = "abc"
25    ptr_id = DL.realloc(0, 4)
26    ptr    = CPtr.new(ptr_id, 4)
27
28    assert_equal ptr_id, ptr.to_i
29
30    cfunc  = CFunc.new(@libc['strcpy'], TYPE_VOIDP, 'strcpy')
31             cfunc.call([ptr_id,str].pack("l!p").unpack("l!*"))
32    assert_equal("abc\0", ptr[0,4])
33    DL.free ptr_id
34  end
35
36  def test_realloc_secure
37    assert_raises(SecurityError) do
38      Thread.new do
39        $SAFE = 4
40        DL.realloc(0, 4)
41      end.join
42    end
43  end
44
45  def test_malloc
46    str = "abc"
47
48    ptr_id = DL.malloc(4)
49    ptr    = CPtr.new(ptr_id, 4)
50
51    assert_equal ptr_id, ptr.to_i
52
53    cfunc  = CFunc.new(@libc['strcpy'], TYPE_VOIDP, 'strcpy')
54             cfunc.call([ptr_id,str].pack("l!p").unpack("l!*"))
55    assert_equal("abc\0", ptr[0,4])
56    DL.free ptr_id
57  end
58
59  def test_malloc_security
60    assert_raises(SecurityError) do
61      Thread.new do
62        $SAFE = 4
63        DL.malloc(4)
64      end.join
65    end
66  end
67
68  def test_call_int()
69    cfunc = CFunc.new(@libc['atoi'], TYPE_INT, 'atoi')
70    x = cfunc.call(["100"].pack("p").unpack("l!*"))
71    assert_equal(100, x)
72
73    cfunc = CFunc.new(@libc['atoi'], TYPE_INT, 'atoi')
74    x = cfunc.call(["-100"].pack("p").unpack("l!*"))
75    assert_equal(-100, x)
76  end
77
78  def test_call_long()
79    cfunc = CFunc.new(@libc['atol'], TYPE_LONG, 'atol')
80    x = cfunc.call(["100"].pack("p").unpack("l!*"))
81    assert_equal(100, x)
82    cfunc = CFunc.new(@libc['atol'], TYPE_LONG, 'atol')
83    x = cfunc.call(["-100"].pack("p").unpack("l!*"))
84    assert_equal(-100, x)
85  end
86
87  def test_call_double()
88    cfunc = CFunc.new(@libc['atof'], TYPE_DOUBLE, 'atof')
89    x = cfunc.call(["0.1"].pack("p").unpack("l!*"))
90    assert_in_delta(0.1, x)
91
92    cfunc = CFunc.new(@libc['atof'], TYPE_DOUBLE, 'atof')
93    x = cfunc.call(["-0.1"].pack("p").unpack("l!*"))
94    assert_in_delta(-0.1, x)
95  end
96
97  def test_sin
98    return if /x86_64/ =~ RUBY_PLATFORM
99    pi_2 = Math::PI/2
100    cfunc = Function.new(CFunc.new(@libm['sin'], TYPE_DOUBLE, 'sin'),
101                        [TYPE_DOUBLE])
102    x = cfunc.call(pi_2)
103    assert_equal(Math.sin(pi_2), x)
104
105    cfunc = Function.new(CFunc.new(@libm['sin'], TYPE_DOUBLE, 'sin'),
106                        [TYPE_DOUBLE])
107    x = cfunc.call(-pi_2)
108    assert_equal(Math.sin(-pi_2), x)
109  end
110
111  def test_strlen()
112    cfunc = CFunc.new(@libc['strlen'], TYPE_INT, 'strlen')
113    x = cfunc.call(["abc"].pack("p").unpack("l!*"))
114    assert_equal("abc".size, x)
115  end
116
117  def test_strcpy()
118    buff = "xxxx"
119    str  = "abc"
120    cfunc = CFunc.new(@libc['strcpy'], TYPE_VOIDP, 'strcpy')
121    x = cfunc.call(ptr2num(buff,str))
122    assert_equal("abc\0", buff)
123    assert_equal("abc\0", CPtr.new(x).to_s(4))
124
125    buff = "xxxx"
126    str  = "abc"
127    cfunc = CFunc.new(@libc['strncpy'], TYPE_VOIDP, 'strncpy')
128    x = cfunc.call(ptr2num(buff,str) + [3])
129    assert_equal("abcx", buff)
130    assert_equal("abcx", CPtr.new(x).to_s(4))
131
132    ptr = CPtr.malloc(4)
133    str = "abc"
134    cfunc = CFunc.new(@libc['strcpy'], TYPE_VOIDP, 'strcpy')
135    x = cfunc.call([ptr.to_i, *ptr2num(str)])
136    assert_equal("abc\0", ptr[0,4])
137    assert_equal("abc\0", CPtr.new(x).to_s(4))
138  end
139
140  def test_callback()
141    buff = "foobarbaz"
142    cb = set_callback(TYPE_INT,2){|x,y| CPtr.new(x)[0] <=> CPtr.new(y)[0]}
143    cfunc = CFunc.new(@libc['qsort'], TYPE_VOID, 'qsort')
144    cfunc.call(ptr2num(buff) + [buff.size, 1, cb])
145    assert_equal('aabbfoorz', buff)
146  end
147
148  def test_dlwrap()
149    ary = [0,1,2,4,5]
150    addr = dlwrap(ary)
151    ary2 = dlunwrap(addr)
152    assert_equal(ary, ary2)
153  end
154
155  def test_type_size_t
156    assert_equal(DL::TYPE_SSIZE_T, DL::TYPE_SIZE_T.abs)
157  end
158
159  def test_type_uintptr_t
160    assert_equal(-DL::TYPE_INTPTR_T, DL::TYPE_UINTPTR_T)
161  end
162
163  def test_sizeof_uintptr_t
164    assert_equal(DL::SIZEOF_VOIDP, DL::SIZEOF_INTPTR_T)
165  end
166end
167end # module DL
168