1// Copyright 2011 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// Test cases for cgo.
6// Both the import "C" prologue and the main file are sorted by issue number.
7// This file contains //export directives on Go functions
8// and so it must NOT contain C definitions (only declarations).
9// See test.go for C definitions.
10
11package cgotest
12
13import (
14	"runtime"
15	"runtime/cgo"
16	"runtime/debug"
17	"strings"
18	"sync"
19	"sync/atomic"
20	"testing"
21	"unsafe"
22)
23
24/*
25// threads
26extern void doAdd(int, int);
27extern int callGoInCThread(int);
28
29// issue 1328
30void IntoC(void);
31
32// issue 1560
33extern void Issue1560InC(void);
34
35// twoSleep returns the absolute start time of the first sleep
36// in ms.
37long long twoSleep(int);
38
39// issue 3775
40void lockOSThreadC(void);
41int usleep(unsigned usec);
42
43// issue 4054 part 2 - part 1 in test.go
44typedef enum {
45	A = 0,
46	B,
47	C,
48	D,
49	E,
50	F,
51	G,
52	H,
53	II,
54	J,
55} issue4054b;
56
57// issue 5548
58
59extern int issue5548_in_c(void);
60
61// issue 6833
62
63extern unsigned long long issue6833Func(unsigned int, unsigned long long);
64
65// issue 6907
66
67extern int CheckIssue6907C(_GoString_);
68
69// issue 7665
70
71extern void f7665(void);
72
73// issue 7978
74// Stack tracing didn't work during cgo code after calling a Go
75// callback.  Make sure GC works and the stack trace is correct.
76
77#include <stdint.h>
78
79// use ugly atomic variable sync since that doesn't require calling back into
80// Go code or OS dependencies
81void issue7978c(uint32_t *sync);
82
83// issue 8331 part 2 - part 1 in test.go
84// A typedef of an unnamed struct is the same struct when
85// #include'd twice.  No runtime test; just make sure it compiles.
86#include "issue8331.h"
87
88// issue 8945
89
90typedef void (*PFunc8945)();
91extern PFunc8945 func8945; // definition is in test.go
92
93// issue 20910
94void callMulti(void);
95
96// issue 28772 part 2 - part 1 in issuex.go
97#define issue28772Constant2 2
98
99
100// issue 31891
101typedef struct {
102	long obj;
103} Issue31891A;
104
105typedef struct {
106	long obj;
107} Issue31891B;
108
109void callIssue31891(void);
110
111typedef struct {
112	int i;
113} Issue38408, *PIssue38408;
114
115extern void cfunc49633(void*); // definition is in test.go
116*/
117import "C"
118
119// exports
120
121//export ReturnIntLong
122func ReturnIntLong() (int, C.long) {
123	return 1, 2
124}
125
126//export gc
127func gc() {
128	runtime.GC()
129}
130
131// threads
132
133var sum struct {
134	sync.Mutex
135	i int
136}
137
138//export Add
139func Add(x int) {
140	defer func() {
141		recover()
142	}()
143	sum.Lock()
144	sum.i += x
145	sum.Unlock()
146	var p *int
147	*p = 2
148}
149
150//export goDummy
151func goDummy() {
152}
153
154func testCthread(t *testing.T) {
155	if (runtime.GOOS == "darwin" || runtime.GOOS == "ios") && runtime.GOARCH == "arm64" {
156		t.Skip("the iOS exec wrapper is unable to properly handle the panic from Add")
157	}
158	sum.i = 0
159	C.doAdd(10, 6)
160
161	want := 10 * (10 - 1) / 2 * 6
162	if sum.i != want {
163		t.Fatalf("sum=%d, want %d", sum.i, want)
164	}
165}
166
167// Benchmark measuring overhead from C to Go in a C thread.
168// Create a new C thread and invoke Go function repeatedly in the new C thread.
169func benchCGoInCthread(b *testing.B) {
170	n := C.callGoInCThread(C.int(b.N))
171	if int(n) != b.N {
172		b.Fatal("unmatch loop times")
173	}
174}
175
176// issue 1328
177
178//export BackIntoGo
179func BackIntoGo() {
180	x := 1
181
182	for i := 0; i < 10000; i++ {
183		xvariadic(x)
184		if x != 1 {
185			panic("x is not 1?")
186		}
187	}
188}
189
190func xvariadic(x ...interface{}) {
191}
192
193func test1328(t *testing.T) {
194	C.IntoC()
195}
196
197// issue 1560
198// Test that C functions and Go functions run in parallel.
199
200var (
201	issue1560 int32
202
203	issue1560Ch = make(chan bool, 2)
204)
205
206//export Issue1560FromC
207func Issue1560FromC() {
208	for atomic.LoadInt32(&issue1560) != 1 {
209		runtime.Gosched()
210	}
211	atomic.AddInt32(&issue1560, 1)
212	for atomic.LoadInt32(&issue1560) != 3 {
213		runtime.Gosched()
214	}
215	issue1560Ch <- true
216}
217
218func Issue1560FromGo() {
219	atomic.AddInt32(&issue1560, 1)
220	for atomic.LoadInt32(&issue1560) != 2 {
221		runtime.Gosched()
222	}
223	atomic.AddInt32(&issue1560, 1)
224	issue1560Ch <- true
225}
226
227func test1560(t *testing.T) {
228	go Issue1560FromGo()
229	go C.Issue1560InC()
230	<-issue1560Ch
231	<-issue1560Ch
232}
233
234// issue 2462
235
236//export exportbyte
237func exportbyte() byte {
238	return 0
239}
240
241//export exportbool
242func exportbool() bool {
243	return false
244}
245
246//export exportrune
247func exportrune() rune {
248	return 0
249}
250
251//export exporterror
252func exporterror() error {
253	return nil
254}
255
256//export exportint
257func exportint() int {
258	return 0
259}
260
261//export exportuint
262func exportuint() uint {
263	return 0
264}
265
266//export exportuintptr
267func exportuintptr() uintptr {
268	return (uintptr)(0)
269}
270
271//export exportint8
272func exportint8() int8 {
273	return 0
274}
275
276//export exportuint8
277func exportuint8() uint8 {
278	return 0
279}
280
281//export exportint16
282func exportint16() int16 {
283	return 0
284}
285
286//export exportuint16
287func exportuint16() uint16 {
288	return 0
289}
290
291//export exportint32
292func exportint32() int32 {
293	return 0
294}
295
296//export exportuint32
297func exportuint32() uint32 {
298	return 0
299}
300
301//export exportint64
302func exportint64() int64 {
303	return 0
304}
305
306//export exportuint64
307func exportuint64() uint64 {
308	return 0
309}
310
311//export exportfloat32
312func exportfloat32() float32 {
313	return 0
314}
315
316//export exportfloat64
317func exportfloat64() float64 {
318	return 0
319}
320
321//export exportcomplex64
322func exportcomplex64() complex64 {
323	return 0
324}
325
326//export exportcomplex128
327func exportcomplex128() complex128 {
328	return 0
329}
330
331// issue 3741
332
333//export exportSliceIn
334func exportSliceIn(s []byte) bool {
335	return len(s) == cap(s)
336}
337
338//export exportSliceOut
339func exportSliceOut() []byte {
340	return []byte{1}
341}
342
343//export exportSliceInOut
344func exportSliceInOut(s []byte) []byte {
345	return s
346}
347
348// issue 3775
349
350func init() {
351	if runtime.GOOS == "android" {
352		return
353	}
354	// Same as test3775 but run during init so that
355	// there are two levels of internal runtime lock
356	// (1 for init, 1 for cgo).
357	// This would have been broken by CL 11663043.
358	C.lockOSThreadC()
359}
360
361func test3775(t *testing.T) {
362	if runtime.GOOS == "android" {
363		return
364	}
365	// Used to panic because of the UnlockOSThread below.
366	C.lockOSThreadC()
367}
368
369//export lockOSThreadCallback
370func lockOSThreadCallback() {
371	runtime.LockOSThread()
372	runtime.UnlockOSThread()
373	go C.usleep(10000)
374	runtime.Gosched()
375}
376
377// issue 4054 part 2 - part 1 in test.go
378
379var issue4054b = []int{C.A, C.B, C.C, C.D, C.E, C.F, C.G, C.H, C.II, C.J}
380
381//export issue5548FromC
382func issue5548FromC(s string, i int) int {
383	if len(s) == 4 && s == "test" && i == 42 {
384		return 12345
385	}
386	println("got", len(s), i)
387	return 9876
388}
389
390func test5548(t *testing.T) {
391	if x := C.issue5548_in_c(); x != 12345 {
392		t.Errorf("issue5548_in_c = %d, want %d", x, 12345)
393	}
394}
395
396// issue 6833
397
398//export GoIssue6833Func
399func GoIssue6833Func(aui uint, aui64 uint64) uint64 {
400	return aui64 + uint64(aui)
401}
402
403func test6833(t *testing.T) {
404	ui := 7
405	ull := uint64(0x4000300020001000)
406	v := uint64(C.issue6833Func(C.uint(ui), C.ulonglong(ull)))
407	exp := uint64(ui) + ull
408	if v != exp {
409		t.Errorf("issue6833Func() returns %x, expected %x", v, exp)
410	}
411}
412
413// issue 6907
414
415const CString = "C string"
416
417//export CheckIssue6907Go
418func CheckIssue6907Go(s string) C.int {
419	if s == CString {
420		return 1
421	}
422	return 0
423}
424
425func test6907Go(t *testing.T) {
426	if got := C.CheckIssue6907C(CString); got != 1 {
427		t.Errorf("C.CheckIssue6907C() == %d, want %d", got, 1)
428	}
429}
430
431// issue 7665
432
433var bad7665 unsafe.Pointer = C.f7665
434var good7665 uintptr = uintptr(C.f7665)
435
436func test7665(t *testing.T) {
437	if bad7665 == nil || uintptr(bad7665) != good7665 {
438		t.Errorf("ptrs = %p, %#x, want same non-nil pointer", bad7665, good7665)
439	}
440}
441
442// issue 7978
443
444var issue7978sync uint32
445
446func issue7978check(t *testing.T, wantFunc string, badFunc string, depth int) {
447	runtime.GC()
448	buf := make([]byte, 65536)
449	trace := string(buf[:runtime.Stack(buf, true)])
450	for _, goroutine := range strings.Split(trace, "\n\n") {
451		if strings.Contains(goroutine, "test.issue7978go") {
452			trace := strings.Split(goroutine, "\n")
453			// look for the expected function in the stack
454			for i := 0; i < depth; i++ {
455				if badFunc != "" && strings.Contains(trace[1+2*i], badFunc) {
456					t.Errorf("bad stack: found %s in the stack:\n%s", badFunc, goroutine)
457					return
458				}
459				if strings.Contains(trace[1+2*i], wantFunc) {
460					return
461				}
462			}
463			t.Errorf("bad stack: didn't find %s in the stack:\n%s", wantFunc, goroutine)
464			return
465		}
466	}
467	t.Errorf("bad stack: goroutine not found. Full stack dump:\n%s", trace)
468}
469
470func issue7978wait(store uint32, wait uint32) {
471	if store != 0 {
472		atomic.StoreUint32(&issue7978sync, store)
473	}
474	for atomic.LoadUint32(&issue7978sync) != wait {
475		runtime.Gosched()
476	}
477}
478
479//export issue7978cb
480func issue7978cb() {
481	// Force a stack growth from the callback to put extra
482	// pressure on the runtime. See issue #17785.
483	growStack(64)
484	issue7978wait(3, 4)
485}
486
487func growStack(n int) int {
488	var buf [128]int
489	if n == 0 {
490		return 0
491	}
492	return buf[growStack(n-1)]
493}
494
495func issue7978go() {
496	C.issue7978c((*C.uint32_t)(&issue7978sync))
497	issue7978wait(7, 8)
498}
499
500func test7978(t *testing.T) {
501	if runtime.Compiler == "gccgo" {
502		t.Skip("gccgo can not do stack traces of C code")
503	}
504	debug.SetTraceback("2")
505	issue7978sync = 0
506	go issue7978go()
507	// test in c code, before callback
508	issue7978wait(0, 1)
509	issue7978check(t, "_Cfunc_issue7978c(", "", 1)
510	// test in go code, during callback
511	issue7978wait(2, 3)
512	issue7978check(t, "test.issue7978cb(", "test.issue7978go", 3)
513	// test in c code, after callback
514	issue7978wait(4, 5)
515	issue7978check(t, "_Cfunc_issue7978c(", "_cgoexpwrap", 1)
516	// test in go code, after return from cgo
517	issue7978wait(6, 7)
518	issue7978check(t, "test.issue7978go(", "", 3)
519	atomic.StoreUint32(&issue7978sync, 8)
520}
521
522// issue 8331 part 2
523
524var issue8331Var C.issue8331
525
526// issue 8945
527
528//export Test8945
529func Test8945() {
530	_ = C.func8945
531}
532
533// issue 20910
534
535//export multi
536func multi() (*C.char, C.int) {
537	return C.CString("multi"), 0
538}
539
540func test20910(t *testing.T) {
541	C.callMulti()
542}
543
544// issue 28772 part 2
545
546const issue28772Constant2 = C.issue28772Constant2
547
548// issue 31891
549
550//export useIssue31891A
551func useIssue31891A(c *C.Issue31891A) {}
552
553//export useIssue31891B
554func useIssue31891B(c *C.Issue31891B) {}
555
556func test31891(t *testing.T) {
557	C.callIssue31891()
558}
559
560// issue 37033, check if cgo.Handle works properly
561
562var issue37033 = 42
563
564//export GoFunc37033
565func GoFunc37033(handle C.uintptr_t) {
566	h := cgo.Handle(handle)
567	ch := h.Value().(chan int)
568	ch <- issue37033
569}
570
571// issue 38408
572// A typedef pointer can be used as the element type.
573// No runtime test; just make sure it compiles.
574var _ C.PIssue38408 = &C.Issue38408{i: 1}
575
576// issue 49633, example use of cgo.Handle with void*
577
578type data49633 struct {
579	msg string
580}
581
582//export GoFunc49633
583func GoFunc49633(context unsafe.Pointer) {
584	h := *(*cgo.Handle)(context)
585	v := h.Value().(*data49633)
586	v.msg = "hello"
587}
588
589func test49633(t *testing.T) {
590	v := &data49633{}
591	h := cgo.NewHandle(v)
592	defer h.Delete()
593	C.cfunc49633(unsafe.Pointer(&h))
594	if v.msg != "hello" {
595		t.Errorf("msg = %q, want 'hello'", v.msg)
596	}
597}
598