File size: 3,984 Bytes
d456972 | 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 | //go:build linux || darwin || freebsd
package motionbricks
import (
"math"
"os"
"testing"
"unsafe"
"github.com/ebitengine/purego"
)
const (
statusOK = uint32(0)
deviceAuto = uint32(0)
deviceVulkan = uint32(2)
abiVersion = uint32(1)
errorCapacity = uint64(256)
)
// TestOpaqueABIRoundTrip intentionally mirrors no C struct. Every object is an
// opaque uintptr and every record field is accessed through a function.
func TestOpaqueABIRoundTrip(t *testing.T) {
library := os.Getenv("MOTIONBRICKS_LIB")
if library == "" {
t.Skip("set MOTIONBRICKS_LIB to the motion-bricks.cpp shared library")
}
handle, err := purego.Dlopen(library, purego.RTLD_NOW|purego.RTLD_LOCAL)
if err != nil {
t.Fatalf("dlopen %s: %v", library, err)
}
defer purego.Dlclose(handle)
var version func() uint32
var optionsCreate func(unsafe.Pointer, unsafe.Pointer, uint64) uint32
var optionsFree func(uintptr)
var optionsSetDevice func(uintptr, uint32, unsafe.Pointer, uint64) uint32
var optionsGetDevice func(uintptr, unsafe.Pointer, unsafe.Pointer, uint64) uint32
var commandCreate func(unsafe.Pointer, unsafe.Pointer, uint64) uint32
var commandFree func(uintptr)
var commandSetMovement func(uintptr, float32, float32, float32, unsafe.Pointer, uint64) uint32
var commandGetMovement func(uintptr, unsafe.Pointer, unsafe.Pointer, unsafe.Pointer, unsafe.Pointer, uint64) uint32
purego.RegisterLibFunc(&version, handle, "mb_abi_version")
purego.RegisterLibFunc(&optionsCreate, handle, "mb_runtime_options_create")
purego.RegisterLibFunc(&optionsFree, handle, "mb_runtime_options_free")
purego.RegisterLibFunc(&optionsSetDevice, handle, "mb_runtime_options_set_device")
purego.RegisterLibFunc(&optionsGetDevice, handle, "mb_runtime_options_get_device")
purego.RegisterLibFunc(&commandCreate, handle, "mb_command_create")
purego.RegisterLibFunc(&commandFree, handle, "mb_command_free")
purego.RegisterLibFunc(&commandSetMovement, handle, "mb_command_set_movement_direction")
purego.RegisterLibFunc(&commandGetMovement, handle, "mb_command_get_movement_direction")
if got := version(); got != abiVersion {
t.Fatalf("ABI version = %d, want %d", got, abiVersion)
}
errorBuffer := make([]byte, errorCapacity)
errorPointer := unsafe.Pointer(&errorBuffer[0])
var options uintptr
if status := optionsCreate(unsafe.Pointer(&options), errorPointer, errorCapacity); status != statusOK {
t.Fatalf("options create status %d: %q", status, errorBuffer)
}
if options == 0 {
t.Fatal("options create returned a null handle")
}
defer optionsFree(options)
var device uint32 = math.MaxUint32
if status := optionsGetDevice(options, unsafe.Pointer(&device), errorPointer, errorCapacity); status != statusOK {
t.Fatalf("get default device status %d", status)
}
if device != deviceAuto {
t.Fatalf("default device = %d, want auto", device)
}
if status := optionsSetDevice(options, deviceVulkan, errorPointer, errorCapacity); status != statusOK {
t.Fatalf("set Vulkan status %d", status)
}
if status := optionsGetDevice(options, unsafe.Pointer(&device), errorPointer, errorCapacity); status != statusOK || device != deviceVulkan {
t.Fatalf("Vulkan round trip status=%d device=%d", status, device)
}
var command uintptr
if status := commandCreate(unsafe.Pointer(&command), errorPointer, errorCapacity); status != statusOK {
t.Fatalf("command create status %d", status)
}
if command == 0 {
t.Fatal("command create returned a null handle")
}
defer commandFree(command)
if status := commandSetMovement(command, 1.0, 0.0, -0.25, errorPointer, errorCapacity); status != statusOK {
t.Fatalf("set movement status %d", status)
}
var x, y, z float32
if status := commandGetMovement(command, unsafe.Pointer(&x), unsafe.Pointer(&y), unsafe.Pointer(&z), errorPointer, errorCapacity); status != statusOK {
t.Fatalf("get movement status %d", status)
}
if x != 1.0 || y != 0.0 || z != -0.25 {
t.Fatalf("movement = (%g, %g, %g)", x, y, z)
}
}
|