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 }