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