Source file src/runtime/internal/wasitest/nonblock_test.go

     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 "wasmer":
    41  		t.Skip("wasmer does not support non-blocking I/O")
    42  	}
    43  
    44  	for _, mode := range []string{"os.OpenFile", "os.NewFile"} {
    45  		t.Run(mode, func(t *testing.T) {
    46  			args := []string{"run", "./testdata/nonblock.go", mode}
    47  
    48  			fifos := make([]*fifo, 8)
    49  			for i := range fifos {
    50  				path := filepath.Join(t.TempDir(), fmt.Sprintf("wasip1-nonblock-fifo-%d-%d", rand.Uint32(), i))
    51  				if err := syscall.Mkfifo(path, 0666); err != nil {
    52  					t.Fatal(err)
    53  				}
    54  
    55  				file, err := os.OpenFile(path, os.O_RDWR, 0)
    56  				if err != nil {
    57  					t.Fatal(err)
    58  				}
    59  				defer file.Close()
    60  
    61  				args = append(args, path)
    62  				fifos[len(fifos)-i-1] = &fifo{file, path}
    63  			}
    64  
    65  			subProcess := exec.Command("go", args...)
    66  
    67  			subProcess.Env = append(os.Environ(), "GOOS=wasip1", "GOARCH=wasm")
    68  
    69  			pr, pw := io.Pipe()
    70  			defer pw.Close()
    71  
    72  			subProcess.Stderr = pw
    73  
    74  			if err := subProcess.Start(); err != nil {
    75  				t.Fatal(err)
    76  			}
    77  
    78  			scanner := bufio.NewScanner(pr)
    79  			if !scanner.Scan() {
    80  				t.Fatal("expected line:", scanner.Err())
    81  			} else if scanner.Text() != "waiting" {
    82  				t.Fatal("unexpected output:", scanner.Text())
    83  			}
    84  
    85  			for _, fifo := range fifos {
    86  				if _, err := fifo.file.WriteString(fifo.path + "\n"); err != nil {
    87  					t.Fatal(err)
    88  				}
    89  				if !scanner.Scan() {
    90  					t.Fatal("expected line:", scanner.Err())
    91  				} else if scanner.Text() != fifo.path {
    92  					t.Fatal("unexpected line:", scanner.Text())
    93  				}
    94  			}
    95  
    96  			if err := subProcess.Wait(); err != nil {
    97  				t.Fatal(err)
    98  			}
    99  		})
   100  	}
   101  }
   102  

View as plain text