summaryrefslogtreecommitdiff
path: root/test/dl/test_closure.rb
blob: 965d195df1315c2239aad4cbc96b1fab9744e1fd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
require_relative 'test_base'
require 'dl/func'
require 'dl/closure'

module DL
  class TestClosure < Test::Unit::TestCase
    class Returner < DL::Closure
      attr_accessor :called
      attr_accessor :called_with
      def call *args
        @called = true
        @called_with = args
        a = args.first
        DL::CPtr === a ? a.to_i : a
      end
    end

    if defined?(TYPE_LONG_LONG)
      def test_long_long
        type = TYPE_LONG_LONG
        addr = Returner.new(type, [type]) do |num|
          called = true
          called_with = num
        end
        func = DL::Function.new(addr, [type])
        assert_equal(9223372036854775807, func.call(9223372036854775807))
      end
    end

    def test_with_abi
      called = false
      addr = DL::Closure::BlockCaller.new(
          TYPE_INT,
          [TYPE_INT],
          DL::Function::DEFAULT
      ) do |num|
        called = true
	num
      end
      func = DL::Function.new(addr, [TYPE_INT])
      func.call(50)
      assert called
    end

    def test_block_caller
      called = false
      called_with = nil
      addr = DL::Closure::BlockCaller.new(TYPE_INT, [TYPE_INT]) do |num|
        called = true
        called_with = num
      end
      func = DL::Function.new(addr, [TYPE_INT])
      func.call(50)
      assert called, 'function was called'
      assert_equal 50, called_with
    end

    def test_multival
      adder = Class.new(DL::Closure) {
        def call a, b
          a + b
        end
      }.new(TYPE_INT, [TYPE_INT, TYPE_INT])

      assert_equal [TYPE_INT, TYPE_INT], adder.args
      func = DL::Function.new(adder, adder.args)
      assert_equal 70, func.call(50, 20)
    end

    def test_call
      closure = Class.new(DL::Closure) {
        attr_accessor :called_with
        def call num
          @called_with = num
        end
      }.new(TYPE_INT, [TYPE_INT])

      func = DL::Function.new(closure, [TYPE_INT])
      func.call(50)

      assert_equal 50, closure.called_with
    end

    def test_return_value
      closure = Returner.new(TYPE_INT, [TYPE_INT])

      func = DL::Function.new(closure, [TYPE_INT])
      assert_equal 50, func.call(50)
    end

    def test_float
      closure = Returner.new(TYPE_FLOAT, [TYPE_FLOAT])
      func = DL::Function.new(closure, [TYPE_FLOAT])
      assert_equal 2.0, func.call(2.0)
    end

    def test_char
      closure = Returner.new(TYPE_CHAR, [TYPE_CHAR])
      func = DL::Function.new(closure, [TYPE_CHAR])
      assert_equal 60, func.call(60)
    end

    def test_long
      closure = Returner.new(TYPE_LONG, [TYPE_LONG])
      func = DL::Function.new(closure, [TYPE_LONG])
      assert_equal 60, func.call(60)
    end

    def test_double
      closure = Returner.new(TYPE_DOUBLE, [TYPE_DOUBLE])
      func = DL::Function.new(closure, [TYPE_DOUBLE])
      assert_equal 60, func.call(60)
    end

    def test_voidp
      closure = Returner.new(TYPE_VOIDP, [TYPE_VOIDP])
      func = DL::Function.new(closure, [TYPE_VOIDP])

      voidp = CPtr['foo']
      assert_equal voidp, func.call(voidp)
    end

    def test_void
      closure = Returner.new(TYPE_VOID, [TYPE_VOID])
      func = DL::Function.new(closure, [TYPE_VOID])
      func.call()
      assert closure.called
    end
  end
end