diff go/godc/godc_test.go @ 0:0cfcc391201f

initial from svn dyncall-1745
author Daniel Adler
date Thu, 19 Mar 2015 22:26:28 +0100
parents
children 9943c30ee2aa
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/go/godc/godc_test.go	Thu Mar 19 22:26:28 2015 +0100
@@ -0,0 +1,229 @@
+/*
+
+ godc_test.go
+ Copyright (c) 2014 Tassilo Philipp <tphilipp@potion-studios.com>
+
+ Permission to use, copy, modify, and distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+*/
+
+
+package godc
+
+import (
+	"testing"
+	"fmt"
+	"unsafe"
+	"math"
+)
+
+func TestGoDC(t *testing.T) {
+	lm := new(ExtLib)
+	if err := lm.Load("/usr/lib/libm.so"); err != nil {
+		t.FailNow()
+	}
+	defer lm.Free()
+
+	if err := lm.SymsInit("/usr/lib/libm.so"); err != nil {
+		t.FailNow()
+	}
+	defer lm.SymsCleanup()
+
+	fmt.Printf("Testing dl:\n")
+	fmt.Printf("-----------\n")
+	fmt.Printf("Loaded library at address: %p\n", lm.lib)
+	fmt.Printf("C sqrt function at address: %p\n", lm.FindSymbol("sqrt"))
+	fmt.Printf("C pow function at address: %p\n\n", lm.FindSymbol("pow"))
+
+	fmt.Printf("Testing dlSyms:\n")
+	fmt.Printf("---------------\n")
+	fmt.Printf("Symbols in libm: %d\n", lm.SymsCount())
+	fmt.Printf("Symbol name for address %p: %s\n", lm.FindSymbol("pow"), lm.SymsNameFromValue(lm.FindSymbol("pow")))
+	fmt.Printf("All symbol names in libm:\n")
+	for i, n := 0, lm.SymsCount(); i<n; i++ {
+		fmt.Printf("  %s\n", lm.SymsName(i))
+	}
+	fmt.Printf("\n")
+
+
+
+	// Another lib
+	lc := new(ExtLib)
+	if err := lc.Load("/usr/lib/libc.so"); err != nil {
+		t.FailNow()
+	}
+	defer lc.Free()
+
+	if err := lc.SymsInit("/usr/lib/libc.so"); err != nil {
+		t.FailNow()
+	}
+	defer lc.SymsCleanup()
+
+	fmt.Printf("Symbols in libc: %d (not listing them here, too many)\n\n", lc.SymsCount())
+
+
+
+	// Call some functions
+	fmt.Printf("Testing dc:\n")
+	fmt.Printf("-----------\n")
+	vm := new(CallVM)
+	if err := vm.InitCallVM(); err != nil {
+		t.FailNow()
+	}
+	defer vm.Free()
+
+	vm.Mode(DC_CALL_C_DEFAULT)
+
+
+	// Float
+	vm.Reset()
+	vm.ArgFloat(36)
+	rf := vm.CallFloat(lm.FindSymbol("sqrtf"))
+	fmt.Printf("sqrtf(36) = %f\n", rf)
+	if(rf != 6.0) { t.FailNow() }
+
+	vm.Reset() // Test reset, reusing VM
+	vm.ArgDouble(3.6)
+	rd := vm.CallDouble(lm.FindSymbol("floor"))
+	fmt.Printf("floor(3.6) = %f\n", rd)
+	if(rd != 3.0) { t.FailNow() }
+
+
+	// Double
+	vm.Reset()
+	vm.ArgDouble(4.2373)
+	rd = vm.CallDouble(lm.FindSymbol("sqrt"))
+	fmt.Printf("sqrt(4.2373) = %f\n", rd)
+	if(math.Abs(rd - 2.05847) > 0.00001) { t.FailNow() }
+
+	vm.Reset()
+	vm.ArgDouble(2.373)
+	vm.ArgDouble(-1000) // 2 args
+	rd = vm.CallDouble(lm.FindSymbol("copysign"))
+	fmt.Printf("copysign(2.373, -1000) = %f\n", rd)
+	if(rd != -2.373) { t.FailNow() }
+
+
+	// Strings
+	vm.Reset()
+	cs1 := vm.AllocCString("/return/only/this_here")
+	defer vm.FreeCString(cs1)
+
+	vm.ArgPointer(cs1)
+	rs := vm.CallPointerToStr(lc.FindSymbol("basename"))
+	fmt.Printf("basename(\"/return/only/this_here\") = %s\n", rs)
+	if(rs != "this_here") { t.FailNow() }
+	// Reuse path
+	rs = vm.CallPointerToStr(lc.FindSymbol("dirname"))
+	fmt.Printf("dirname(\"/return/only/this_here\") = %s\n", rs)
+	if(rs != "/return/only") { t.FailNow() }
+
+
+	// Integer
+	vm.Reset()
+	vm.ArgInt('a')
+	ri := vm.CallInt(lc.FindSymbol("toupper"))
+	fmt.Printf("toupper('a') = %c\n", ri)
+	if(ri != 'A') { t.FailNow() }
+
+	vm.Reset()
+	vm.ArgInt('a')
+	ri = vm.CallInt(lc.FindSymbol("tolower"))
+	fmt.Printf("tolower('a') = %c\n", ri)
+	if(ri != 'a') { t.FailNow() }
+
+	vm.Reset()
+	vm.ArgInt('R')
+	ri = vm.CallInt(lc.FindSymbol("toupper"))
+	fmt.Printf("toupper('R') = %c\n", vm.CallInt(lc.FindSymbol("toupper")))
+	if(ri != 'R') { t.FailNow() }
+
+	vm.Reset()
+	vm.ArgInt('R')
+	ri = vm.CallInt(lc.FindSymbol("tolower"))
+	fmt.Printf("tolower('R') = %c\n", vm.CallInt(lc.FindSymbol("tolower")))
+	if(ri != 'r') { t.FailNow() }
+
+
+	// Integer return
+	vm.Reset()
+	cs2 := vm.AllocCString("Tassilo")
+	defer vm.FreeCString(cs2)
+
+	fmt.Printf("rand() = %d\n", vm.CallInt(lc.FindSymbol("rand")))
+	fmt.Printf("rand() = %d\n", vm.CallInt(lc.FindSymbol("rand")))
+	fmt.Printf("rand() = %d\n", vm.CallInt(lc.FindSymbol("rand")))
+	fmt.Printf("rand() = %d\n", vm.CallInt(lc.FindSymbol("rand")))
+	fmt.Printf("rand() = %d\n", vm.CallInt(lc.FindSymbol("rand")))
+	vm.ArgPointer(cs2)
+	ri = vm.CallInt(lc.FindSymbol("strlen"))
+	fmt.Printf("strlen(\"Tassilo\") = %d\n", ri)
+	if(ri != 7) { t.FailNow() }
+
+
+	// Formatted - with signature/conversion
+	vm.Reset()
+	vm.ArgF("dd)d", 3.14, -2000) // 2 args, second passed as int, but ArgF will convert
+	rd = vm.CallDouble(lm.FindSymbol("copysign"))
+	fmt.Printf("dd)d: copysign(3.14, -2000) = %f\n", rd)
+	if(rd != -3.14) { t.FailNow() }
+
+	// Formatted - without signature/conversion
+	vm.Reset()
+	vm.ArgF("dd)d", -31.4, 42.4) // 2 args, second passed as int, but ArgF will convert
+	rd = vm.CallDouble(lm.FindSymbol("copysign"))
+	fmt.Printf("dd)d: copysign(-31.4, 42.4) = %f\n", rd)
+	if(rd != 31.4) { t.FailNow() }
+
+	// Formatted - use Go's types, pass unsupported type, should return an error
+	vm.Reset()
+	err := vm.ArgF_Go(6.14, vm)
+	fmt.Printf("ArgF_Go: copysign(6.14, <unsupported type>) should return error: %t\n", err != nil)
+	if(err == nil) { t.FailNow() }
+
+	// Formatted - use Go's types
+	vm.Reset()
+	vm.ArgF_Go(-61.4, 42.4) // 2 args, both need to be correct or undefined behaviour
+	rd = vm.CallDouble(lm.FindSymbol("copysign"))
+	fmt.Printf("copysign(-61.4, 42.4) = %f\n", rd)
+	if(rd != 61.4) { t.FailNow() }
+
+
+	// Ellipse
+	vm.Mode(DC_CALL_C_ELLIPSIS)
+	vm.Reset()
+	buf := make([]byte, 1000)
+	bufPtr := unsafe.Pointer(&buf[0])
+	cs3 := vm.AllocCString("Four:%d | \"Hello\":%s | Pi:%f")
+	cs4 := vm.AllocCString("Hello")
+	defer vm.FreeCString(cs4)
+	defer vm.FreeCString(cs3)
+
+	vm.ArgPointer(bufPtr)
+	vm.ArgPointer(cs3)
+	vm.Mode(DC_CALL_C_ELLIPSIS_VARARGS)
+	vm.ArgInt(4)
+	vm.ArgPointer(cs4)
+	vm.ArgDouble(3.14) // Double, b/c of ... promotion rules
+	ri = vm.CallInt(lc.FindSymbol("sprintf"))
+	fmt.Printf("sprintf(bufPtr, \"Four:%%d | \\\"Hello\\\":%%s | Pi:%%f\", 4, \"Hello\", 3.14) = %d:\n", ri)
+	fmt.Printf("  bufPtr: %s\n", string(buf[/*slice printed bytes*/:ri]))
+	if(ri != 36) { t.FailNow() }
+
+
+//@@@ untested:
+// - ArgF and ArgF_Go with strings
+// - ArgF and ArgF_Go with bools
+// - ...
+}
+