...

Source file src/cmd/cgo/internal/test/testx.go

Documentation: cmd/cgo/internal/test

     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  	"unsafe"
    22  )
    23  
    24  /*
    25  // threads
    26  extern void doAdd(int, int);
    27  extern int callGoInCThread(int);
    28  
    29  // issue 1328
    30  void IntoC(void);
    31  
    32  // issue 1560
    33  extern void Issue1560InC(void);
    34  
    35  // twoSleep returns the absolute start time of the first sleep
    36  // in ms.
    37  long long twoSleep(int);
    38  
    39  // issue 3775
    40  void lockOSThreadC(void);
    41  int usleep(unsigned usec);
    42  
    43  // issue 4054 part 2 - part 1 in test.go
    44  typedef 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  
    59  extern int issue5548_in_c(void);
    60  
    61  // issue 6833
    62  
    63  extern unsigned long long issue6833Func(unsigned int, unsigned long long);
    64  
    65  // issue 6907
    66  
    67  extern int CheckIssue6907C(_GoString_);
    68  
    69  // issue 7665
    70  
    71  extern 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
    81  void 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  
    90  typedef void (*PFunc8945)();
    91  extern PFunc8945 func8945; // definition is in test.go
    92  
    93  // issue 20910
    94  void callMulti(void);
    95  
    96  // issue 28772 part 2 - part 1 in issuex.go
    97  #define issue28772Constant2 2
    98  
    99  
   100  // issue 31891
   101  typedef struct {
   102  	long obj;
   103  } Issue31891A;
   104  
   105  typedef struct {
   106  	long obj;
   107  } Issue31891B;
   108  
   109  void callIssue31891(void);
   110  
   111  typedef struct {
   112  	int i;
   113  } Issue38408, *PIssue38408;
   114  
   115  extern void cfunc49633(void*); // definition is in test.go
   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  //export goDummy
   151  func goDummy() {
   152  }
   153  
   154  func 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.
   169  func 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
   179  func 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  
   190  func xvariadic(x ...interface{}) {
   191  }
   192  
   193  func test1328(t *testing.T) {
   194  	C.IntoC()
   195  }
   196  
   197  // issue 1560
   198  // Test that C functions and Go functions run in parallel.
   199  
   200  var (
   201  	issue1560 int32
   202  
   203  	issue1560Ch = make(chan bool, 2)
   204  )
   205  
   206  //export Issue1560FromC
   207  func 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  
   218  func 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  
   227  func test1560(t *testing.T) {
   228  	go Issue1560FromGo()
   229  	go C.Issue1560InC()
   230  	<-issue1560Ch
   231  	<-issue1560Ch
   232  }
   233  
   234  // issue 2462
   235  
   236  //export exportbyte
   237  func exportbyte() byte {
   238  	return 0
   239  }
   240  
   241  //export exportbool
   242  func exportbool() bool {
   243  	return false
   244  }
   245  
   246  //export exportrune
   247  func exportrune() rune {
   248  	return 0
   249  }
   250  
   251  //export exporterror
   252  func exporterror() error {
   253  	return nil
   254  }
   255  
   256  //export exportint
   257  func exportint() int {
   258  	return 0
   259  }
   260  
   261  //export exportuint
   262  func exportuint() uint {
   263  	return 0
   264  }
   265  
   266  //export exportuintptr
   267  func exportuintptr() uintptr {
   268  	return (uintptr)(0)
   269  }
   270  
   271  //export exportint8
   272  func exportint8() int8 {
   273  	return 0
   274  }
   275  
   276  //export exportuint8
   277  func exportuint8() uint8 {
   278  	return 0
   279  }
   280  
   281  //export exportint16
   282  func exportint16() int16 {
   283  	return 0
   284  }
   285  
   286  //export exportuint16
   287  func exportuint16() uint16 {
   288  	return 0
   289  }
   290  
   291  //export exportint32
   292  func exportint32() int32 {
   293  	return 0
   294  }
   295  
   296  //export exportuint32
   297  func exportuint32() uint32 {
   298  	return 0
   299  }
   300  
   301  //export exportint64
   302  func exportint64() int64 {
   303  	return 0
   304  }
   305  
   306  //export exportuint64
   307  func exportuint64() uint64 {
   308  	return 0
   309  }
   310  
   311  //export exportfloat32
   312  func exportfloat32() float32 {
   313  	return 0
   314  }
   315  
   316  //export exportfloat64
   317  func exportfloat64() float64 {
   318  	return 0
   319  }
   320  
   321  //export exportcomplex64
   322  func exportcomplex64() complex64 {
   323  	return 0
   324  }
   325  
   326  //export exportcomplex128
   327  func exportcomplex128() complex128 {
   328  	return 0
   329  }
   330  
   331  // issue 3741
   332  
   333  //export exportSliceIn
   334  func exportSliceIn(s []byte) bool {
   335  	return len(s) == cap(s)
   336  }
   337  
   338  //export exportSliceOut
   339  func exportSliceOut() []byte {
   340  	return []byte{1}
   341  }
   342  
   343  //export exportSliceInOut
   344  func exportSliceInOut(s []byte) []byte {
   345  	return s
   346  }
   347  
   348  // issue 3775
   349  
   350  func 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  
   361  func 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
   370  func 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  
   379  var 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
   382  func 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  
   390  func 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
   399  func GoIssue6833Func(aui uint, aui64 uint64) uint64 {
   400  	return aui64 + uint64(aui)
   401  }
   402  
   403  func 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  
   415  const CString = "C string"
   416  
   417  //export CheckIssue6907Go
   418  func CheckIssue6907Go(s string) C.int {
   419  	if s == CString {
   420  		return 1
   421  	}
   422  	return 0
   423  }
   424  
   425  func 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  
   433  var bad7665 unsafe.Pointer = C.f7665
   434  var good7665 uintptr = uintptr(C.f7665)
   435  
   436  func 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  
   444  var issue7978sync uint32
   445  
   446  func 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  
   470  func 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
   480  func 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  
   487  func 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  
   495  func issue7978go() {
   496  	C.issue7978c((*C.uint32_t)(&issue7978sync))
   497  	issue7978wait(7, 8)
   498  }
   499  
   500  func 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  
   524  var issue8331Var C.issue8331
   525  
   526  // issue 8945
   527  
   528  //export Test8945
   529  func Test8945() {
   530  	_ = C.func8945
   531  }
   532  
   533  // issue 20910
   534  
   535  //export multi
   536  func multi() (*C.char, C.int) {
   537  	return C.CString("multi"), 0
   538  }
   539  
   540  func test20910(t *testing.T) {
   541  	C.callMulti()
   542  }
   543  
   544  // issue 28772 part 2
   545  
   546  const issue28772Constant2 = C.issue28772Constant2
   547  
   548  // issue 31891
   549  
   550  //export useIssue31891A
   551  func useIssue31891A(c *C.Issue31891A) {}
   552  
   553  //export useIssue31891B
   554  func useIssue31891B(c *C.Issue31891B) {}
   555  
   556  func test31891(t *testing.T) {
   557  	C.callIssue31891()
   558  }
   559  
   560  // issue 37033, check if cgo.Handle works properly
   561  
   562  var issue37033 = 42
   563  
   564  //export GoFunc37033
   565  func 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.
   574  var _ C.PIssue38408 = &C.Issue38408{i: 1}
   575  
   576  // issue 49633, example use of cgo.Handle with void*
   577  
   578  type data49633 struct {
   579  	msg string
   580  }
   581  
   582  //export GoFunc49633
   583  func GoFunc49633(context unsafe.Pointer) {
   584  	h := *(*cgo.Handle)(context)
   585  	v := h.Value().(*data49633)
   586  	v.msg = "hello"
   587  }
   588  
   589  func 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  

View as plain text