1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: 2023 The Ebitengine Authors
3
4//go:build darwin || freebsd || linux || netbsd
5
6package purego_test
7
8import (
9 "os"
10 "path/filepath"
11 "syscall"
12 "testing"
13 "unsafe"
14
15 "github.com/bnema/purego"
16)
17
18func TestSimpleDlsym(t *testing.T) {
19 if _, err := purego.Dlsym(purego.RTLD_DEFAULT, "dlsym"); err != nil {
20 t.Errorf("Dlsym with RTLD_DEFAULT failed: %v", err)
21 }
22}
23
24func TestNestedDlopenCall(t *testing.T) {
25 libFileName := filepath.Join(t.TempDir(), "libdlnested.so")
26 t.Logf("Build %v", libFileName)
27
28 if err := buildSharedLib(t, "CXX", libFileName, filepath.Join("testdata", "libdlnested", "nested_test.cpp")); err != nil {
29 t.Fatal(err)
30 }
31 defer os.Remove(libFileName)
32
33 lib, err := purego.Dlopen(libFileName, purego.RTLD_NOW|purego.RTLD_GLOBAL)
34 if err != nil {
35 t.Fatalf("Dlopen(%q) failed: %v", libFileName, err)
36 }
37
38 purego.Dlclose(lib)
39}
40
41func TestSyscallN(t *testing.T) {
42 var dlsym uintptr
43 var err error
44 if dlsym, err = purego.Dlsym(purego.RTLD_DEFAULT, "dlsym"); err != nil {
45 t.Errorf("Dlsym with RTLD_DEFAULT failed: %v", err)
46 }
47 r1, _, err2 := purego.SyscallN(dlsym, purego.RTLD_DEFAULT, uintptr(unsafe.Pointer(&[]byte("dlsym\x00")[0])))
48 if dlsym != r1 {
49 t.Fatalf("SyscallN didn't return the same result as purego.Dlsym: %d", err2)
50 }
51}
52
53func TestSyscallNErrnoIsNotAnInputArgument(t *testing.T) {
54 if errnoIsCaptured() {
55 t.Skip("this platform saves errno; see TestErrno")
56 }
57
58 openSym, err := purego.Dlsym(purego.RTLD_DEFAULT, "open")
59 if err != nil {
60 t.Fatal(err)
61 }
62
63 path, err := syscall.BytePtrFromString("_file_that_does_not_exist_")
64 if err != nil {
65 t.Fatal(err)
66 }
67
68 // The third argument is non-zero so that echoing it back as errno is visible.
69 const third = uintptr(0o600)
70 r1, _, errno := purego.SyscallN(openSym,
71 uintptr(unsafe.Pointer(path)),
72 uintptr(os.O_RDWR),
73 third)
74 if int32(r1) != -1 {
75 t.Fatalf("open returned %d, wanted -1", r1)
76 }
77 if errno != 0 {
78 t.Errorf("SyscallN returned %d as errno where errno is not captured, wanted 0", errno)
79 }
80}