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