github.com/guyezi/gofrontend@v0.0.0-20200228202240-7a62a49e62c0/libgo/misc/cgo/test/testx.go (about)

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