1# coding: US-ASCII
2begin
3  require_relative 'helper'
4  require 'fiddle/import'
5rescue LoadError
6end
7
8module Fiddle
9  module LIBC
10    extend Importer
11    dlload LIBC_SO, LIBM_SO
12
13    typealias 'string', 'char*'
14    typealias 'FILE*', 'void*'
15
16    extern "void *strcpy(char*, char*)"
17    extern "int isdigit(int)"
18    extern "double atof(string)"
19    extern "unsigned long strtoul(char*, char **, int)"
20    extern "int qsort(void*, unsigned long, unsigned long, void*)"
21    extern "int fprintf(FILE*, char*)"
22    extern "int gettimeofday(timeval*, timezone*)" rescue nil
23
24    BoundQsortCallback = bind("void *bound_qsort_callback(void*, void*)"){|ptr1,ptr2| ptr1[0] <=> ptr2[0]}
25    Timeval = struct [
26      "long tv_sec",
27      "long tv_usec",
28    ]
29    Timezone = struct [
30      "int tz_minuteswest",
31      "int tz_dsttime",
32    ]
33    MyStruct = struct [
34      "short num[5]",
35      "char c",
36      "unsigned char buff[7]",
37    ]
38
39    CallCallback = bind("void call_callback(void*, void*)"){ | ptr1, ptr2|
40      f = Function.new(ptr1.to_i, [TYPE_VOIDP], TYPE_VOID)
41      f.call(ptr2)
42    }
43  end
44
45  class TestImport < TestCase
46    def test_ensure_call_dlload
47      err = assert_raises(RuntimeError) do
48        Class.new do
49          extend Importer
50          extern "void *strcpy(char*, char*)"
51        end
52      end
53      assert_match(/call dlload before/, err.message)
54    end
55
56    def test_malloc()
57      s1 = LIBC::Timeval.malloc()
58      s2 = LIBC::Timeval.malloc()
59      refute_equal(s1.to_ptr.to_i, s2.to_ptr.to_i)
60    end
61
62    def test_sizeof()
63      assert_equal(SIZEOF_VOIDP, LIBC.sizeof("FILE*"))
64      assert_equal(LIBC::MyStruct.size(), LIBC.sizeof(LIBC::MyStruct))
65      assert_equal(LIBC::MyStruct.size(), LIBC.sizeof(LIBC::MyStruct.malloc()))
66    end
67
68    def test_unsigned_result()
69      d = (2 ** 31) + 1
70
71      r = LIBC.strtoul(d.to_s, 0, 0)
72      assert_equal(d, r)
73    end
74
75    def test_io()
76      if( RUBY_PLATFORM != BUILD_RUBY_PLATFORM )
77        return
78      end
79      io_in,io_out = IO.pipe()
80      LIBC.fprintf(io_out, "hello")
81      io_out.flush()
82      io_out.close()
83      str = io_in.read()
84      io_in.close()
85      assert_equal("hello", str)
86    end
87
88    def test_value()
89      i = LIBC.value('int', 2)
90      assert_equal(2, i.value)
91
92      d = LIBC.value('double', 2.0)
93      assert_equal(2.0, d.value)
94
95      ary = LIBC.value('int[3]', [0,1,2])
96      assert_equal([0,1,2], ary.value)
97    end
98
99    def test_struct()
100      s = LIBC::MyStruct.malloc()
101      s.num = [0,1,2,3,4]
102      s.c = ?a.ord
103      s.buff = "012345\377"
104      assert_equal([0,1,2,3,4], s.num)
105      assert_equal(?a.ord, s.c)
106      assert_equal([?0.ord,?1.ord,?2.ord,?3.ord,?4.ord,?5.ord,?\377.ord], s.buff)
107    end
108
109    def test_gettimeofday()
110      if( defined?(LIBC.gettimeofday) )
111        timeval = LIBC::Timeval.malloc()
112        timezone = LIBC::Timezone.malloc()
113        LIBC.gettimeofday(timeval, timezone)
114        cur = Time.now()
115        assert(cur.to_i - 2 <= timeval.tv_sec && timeval.tv_sec <= cur.to_i)
116      end
117    end
118
119    def test_strcpy()
120      buff = "000"
121      str = LIBC.strcpy(buff, "123")
122      assert_equal("123", buff)
123      assert_equal("123", str.to_s)
124    end
125
126    def test_isdigit
127      r1 = LIBC.isdigit(?1.ord)
128      r2 = LIBC.isdigit(?2.ord)
129      rr = LIBC.isdigit(?r.ord)
130      assert_operator(r1, :>, 0)
131      assert_operator(r2, :>, 0)
132      assert_equal(0, rr)
133    end
134
135    def test_atof
136      r = LIBC.atof("12.34")
137      assert_includes(12.00..13.00, r)
138    end
139  end
140end if defined?(Fiddle)
141