1// Copyright 2012 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5//go:build !windows && !static && !(darwin && internal)
6
7// Excluded in darwin internal linking PIE (which is the default) mode,
8// as dynamic export is not supported.
9
10package cgotest
11
12/*
13#include <stdint.h>
14#include <dlfcn.h>
15#cgo linux LDFLAGS: -ldl
16
17extern uintptr_t dlopen4029(char*, int);
18extern uintptr_t dlsym4029(uintptr_t, char*);
19extern int dlclose4029(uintptr_t);
20
21extern void call4029(uintptr_t arg);
22*/
23import "C"
24
25import (
26	"testing"
27)
28
29var callbacks int
30
31//export IMPIsOpaque
32func IMPIsOpaque() {
33	callbacks++
34}
35
36//export IMPInitWithFrame
37func IMPInitWithFrame() {
38	callbacks++
39}
40
41//export IMPDrawRect
42func IMPDrawRect() {
43	callbacks++
44}
45
46//export IMPWindowResize
47func IMPWindowResize() {
48	callbacks++
49}
50
51func test4029(t *testing.T) {
52	loadThySelf(t, "IMPWindowResize")
53	loadThySelf(t, "IMPDrawRect")
54	loadThySelf(t, "IMPInitWithFrame")
55	loadThySelf(t, "IMPIsOpaque")
56	if callbacks != 4 {
57		t.Errorf("got %d callbacks, expected 4", callbacks)
58	}
59}
60
61func loadThySelf(t *testing.T, symbol string) {
62	this_process := C.dlopen4029(nil, C.RTLD_NOW)
63	if this_process == 0 {
64		t.Error("dlopen:", C.GoString(C.dlerror()))
65		return
66	}
67	defer C.dlclose4029(this_process)
68
69	symbol_address := C.dlsym4029(this_process, C.CString(symbol))
70	if symbol_address == 0 {
71		t.Error("dlsym:", C.GoString(C.dlerror()))
72		return
73	}
74	t.Log(symbol, symbol_address)
75	C.call4029(symbol_address)
76}
77