github.com/bir3/gocompiler@v0.9.2202/src/cmd/cgo/internal/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/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 }