@@ -27,10 +27,16 @@ type ptrTest struct {
27
27
imports []string // a list of imports
28
28
support string // supporting functions
29
29
body string // the body of the main function
30
+ extra []extra // extra files
30
31
fail bool // whether the test should fail
31
32
expensive bool // whether the test requires the expensive check
32
33
}
33
34
35
+ type extra struct {
36
+ name string
37
+ contents string
38
+ }
39
+
34
40
var ptrTests = []ptrTest {
35
41
{
36
42
// Passing a pointer to a struct that contains a Go pointer.
@@ -237,19 +243,61 @@ var ptrTests = []ptrTest{
237
243
func GoFn() *byte { return (*byte)(C.malloc(1)) }` ,
238
244
body : `C.GoFn()` ,
239
245
},
246
+ {
247
+ // Passing a Go string is fine.
248
+ name : "pass-string" ,
249
+ c : `#include <stddef.h>
250
+ typedef struct { const char *p; ptrdiff_t n; } gostring;
251
+ gostring f(gostring s) { return s; }` ,
252
+ imports : []string {"unsafe" },
253
+ body : `s := "a"; r := C.f(*(*C.gostring)(unsafe.Pointer(&s))); if *(*string)(unsafe.Pointer(&r)) != s { panic(r) }` ,
254
+ },
255
+ {
256
+ // Passing a slice of Go strings fails.
257
+ name : "pass-string-slice" ,
258
+ c : `void f(void *p) {}` ,
259
+ imports : []string {"strings" , "unsafe" },
260
+ support : `type S struct { a [1]string }` ,
261
+ body : `s := S{a:[1]string{strings.Repeat("a", 2)}}; C.f(unsafe.Pointer(&s.a[0]))` ,
262
+ fail : true ,
263
+ },
264
+ {
265
+ // Exported functions may not return strings.
266
+ name : "ret-string" ,
267
+ c : `extern void f();` ,
268
+ imports : []string {"strings" },
269
+ support : `//export GoStr
270
+ func GoStr() string { return strings.Repeat("a", 2) }` ,
271
+ body : `C.f()` ,
272
+ extra : []extra {
273
+ {
274
+ "call.c" ,
275
+ `#include <stddef.h>
276
+ typedef struct { const char *p; ptrdiff_t n; } gostring;
277
+ extern gostring GoStr();
278
+ void f() { GoStr(); }` ,
279
+ },
280
+ },
281
+ fail : true ,
282
+ },
240
283
}
241
284
242
285
func main () {
243
286
os .Exit (doTests ())
244
287
}
245
288
246
289
func doTests () int {
247
- dir , err := ioutil .TempDir ("" , "cgoerrors" )
290
+ gopath , err := ioutil .TempDir ("" , "cgoerrors" )
248
291
if err != nil {
249
292
fmt .Fprintln (os .Stderr , err )
250
293
return 2
251
294
}
252
- defer os .RemoveAll (dir )
295
+ defer os .RemoveAll (gopath )
296
+
297
+ if err := os .MkdirAll (filepath .Join (gopath , "src" ), 0777 ); err != nil {
298
+ fmt .Fprintln (os .Stderr , err )
299
+ return 2
300
+ }
253
301
254
302
workers := runtime .NumCPU () + 1
255
303
@@ -259,7 +307,7 @@ func doTests() int {
259
307
for i := 0 ; i < workers ; i ++ {
260
308
wg .Add (1 )
261
309
go func () {
262
- worker (dir , c , errs )
310
+ worker (gopath , c , errs )
263
311
wg .Done ()
264
312
}()
265
313
}
@@ -281,10 +329,10 @@ func doTests() int {
281
329
return tot
282
330
}
283
331
284
- func worker (dir string , c , errs chan int ) {
332
+ func worker (gopath string , c , errs chan int ) {
285
333
e := 0
286
334
for i := range c {
287
- if ! doOne (dir , i ) {
335
+ if ! doOne (gopath , i ) {
288
336
e ++
289
337
}
290
338
}
@@ -293,9 +341,15 @@ func worker(dir string, c, errs chan int) {
293
341
}
294
342
}
295
343
296
- func doOne (dir string , i int ) bool {
344
+ func doOne (gopath string , i int ) bool {
297
345
t := & ptrTests [i ]
298
346
347
+ dir := filepath .Join (gopath , "src" , fmt .Sprintf ("dir%d" , i ))
348
+ if err := os .Mkdir (dir , 0777 ); err != nil {
349
+ fmt .Fprintln (os .Stderr , err )
350
+ return false
351
+ }
352
+
299
353
name := filepath .Join (dir , fmt .Sprintf ("t%d.go" , i ))
300
354
f , err := os .Create (name )
301
355
if err != nil {
@@ -330,13 +384,30 @@ func doOne(dir string, i int) bool {
330
384
return false
331
385
}
332
386
if err := f .Close (); err != nil {
333
- fmt .Fprintln (os .Stderr , "closing %s: %v\n " , name , err )
387
+ fmt .Fprintf (os .Stderr , "closing %s: %v\n " , name , err )
334
388
return false
335
389
}
336
390
391
+ for _ , e := range t .extra {
392
+ if err := ioutil .WriteFile (filepath .Join (dir , e .name ), []byte (e .contents ), 0644 ); err != nil {
393
+ fmt .Fprintf (os .Stderr , "writing %s: %v\n " , e .name , err )
394
+ return false
395
+ }
396
+ }
397
+
337
398
ok := true
338
399
339
- cmd := exec .Command ("go" , "run" , name )
400
+ cmd := exec .Command ("go" , "build" )
401
+ cmd .Dir = dir
402
+ cmd .Env = addEnv ("GOPATH" , gopath )
403
+ buf , err := cmd .CombinedOutput ()
404
+ if err != nil {
405
+ fmt .Fprintf (os .Stderr , "test %s failed to build: %v\n %s" , t .name , err , buf )
406
+ return false
407
+ }
408
+
409
+ exe := filepath .Join (dir , filepath .Base (dir ))
410
+ cmd = exec .Command (exe )
340
411
cmd .Dir = dir
341
412
342
413
if t .expensive {
@@ -354,15 +425,15 @@ func doOne(dir string, i int) bool {
354
425
ok = false
355
426
}
356
427
357
- cmd = exec .Command ("go" , "run" , name )
428
+ cmd = exec .Command (exe )
358
429
cmd .Dir = dir
359
430
}
360
431
361
432
if t .expensive {
362
433
cmd .Env = cgocheckEnv ("2" )
363
434
}
364
435
365
- buf , err : = cmd .CombinedOutput ()
436
+ buf , err = cmd .CombinedOutput ()
366
437
367
438
if t .fail {
368
439
if err == nil {
@@ -389,7 +460,7 @@ func doOne(dir string, i int) bool {
389
460
390
461
if ! t .expensive && ok {
391
462
// Make sure it passes with the expensive checks.
392
- cmd := exec .Command ("go" , "run" , name )
463
+ cmd := exec .Command (exe )
393
464
cmd .Dir = dir
394
465
cmd .Env = cgocheckEnv ("2" )
395
466
buf , err := cmd .CombinedOutput ()
@@ -404,7 +475,7 @@ func doOne(dir string, i int) bool {
404
475
}
405
476
406
477
if t .fail && ok {
407
- cmd = exec .Command ("go" , "run" , name )
478
+ cmd = exec .Command (exe )
408
479
cmd .Dir = dir
409
480
cmd .Env = cgocheckEnv ("0" )
410
481
buf , err := cmd .CombinedOutput ()
@@ -427,9 +498,14 @@ func reportTestOutput(w io.Writer, name string, buf []byte) {
427
498
}
428
499
429
500
func cgocheckEnv (val string ) []string {
430
- env := []string {"GODEBUG=cgocheck=" + val }
501
+ return addEnv ("GODEBUG" , "cgocheck=" + val )
502
+ }
503
+
504
+ func addEnv (key , val string ) []string {
505
+ env := []string {key + "=" + val }
506
+ look := key + "="
431
507
for _ , e := range os .Environ () {
432
- if ! strings .HasPrefix (e , "GODEBUG=" ) {
508
+ if ! strings .HasPrefix (e , look ) {
433
509
env = append (env , e )
434
510
}
435
511
}
0 commit comments