github.com/dorkamotorka/go/src@v0.0.0-20230614113921-187095f0e316/runtime/internal/wasitest/nonblock_test.go (about) 1 // Copyright 2023 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 // Not all systems have syscall.Mkfifo. 6 //go:build !aix && !plan9 && !solaris && !wasm && !windows 7 8 package wasi_test 9 10 import ( 11 "bufio" 12 "fmt" 13 "io" 14 "math/rand" 15 "os" 16 "os/exec" 17 "path/filepath" 18 "syscall" 19 "testing" 20 ) 21 22 // This test creates a set of FIFOs and writes to them in reverse order. It 23 // checks that the output order matches the write order. The test binary opens 24 // the FIFOs in their original order and spawns a goroutine for each that reads 25 // from the FIFO and writes the result to stderr. If I/O was blocking, all 26 // goroutines would be blocked waiting for one read call to return, and the 27 // output order wouldn't match. 28 29 type fifo struct { 30 file *os.File 31 path string 32 } 33 34 func TestNonblock(t *testing.T) { 35 if target != "wasip1/wasm" { 36 t.Skip() 37 } 38 39 switch os.Getenv("GOWASIRUNTIME") { 40 case "wazero", "": 41 t.Skip("wazero does not support non-blocking I/O") 42 case "wasmer": 43 t.Skip("wasmer does not support non-blocking I/O") 44 } 45 46 for _, mode := range []string{"os.OpenFile", "os.NewFile"} { 47 t.Run(mode, func(t *testing.T) { 48 args := []string{"run", "./testdata/nonblock.go", mode} 49 50 fifos := make([]*fifo, 8) 51 for i := range fifos { 52 path := filepath.Join(t.TempDir(), fmt.Sprintf("wasip1-nonblock-fifo-%d-%d", rand.Uint32(), i)) 53 if err := syscall.Mkfifo(path, 0666); err != nil { 54 t.Fatal(err) 55 } 56 57 file, err := os.OpenFile(path, os.O_RDWR, 0) 58 if err != nil { 59 t.Fatal(err) 60 } 61 defer file.Close() 62 63 args = append(args, path) 64 fifos[len(fifos)-i-1] = &fifo{file, path} 65 } 66 67 subProcess := exec.Command("go", args...) 68 69 subProcess.Env = append(os.Environ(), "GOOS=wasip1", "GOARCH=wasm") 70 71 pr, pw := io.Pipe() 72 defer pw.Close() 73 74 subProcess.Stderr = pw 75 76 if err := subProcess.Start(); err != nil { 77 t.Fatal(err) 78 } 79 80 scanner := bufio.NewScanner(pr) 81 if !scanner.Scan() { 82 t.Fatal("expected line:", scanner.Err()) 83 } else if scanner.Text() != "waiting" { 84 t.Fatal("unexpected output:", scanner.Text()) 85 } 86 87 for _, fifo := range fifos { 88 if _, err := fifo.file.WriteString(fifo.path + "\n"); err != nil { 89 t.Fatal(err) 90 } 91 if !scanner.Scan() { 92 t.Fatal("expected line:", scanner.Err()) 93 } else if scanner.Text() != fifo.path { 94 t.Fatal("unexpected line:", scanner.Text()) 95 } 96 } 97 98 if err := subProcess.Wait(); err != nil { 99 t.Fatal(err) 100 } 101 }) 102 } 103 }