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