Source file misc/cgo/test/testx.go

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

View as plain text