github.com/dorkamotorka/go/src@v0.0.0-20230614113921-187095f0e316/runtime/internal/wasitest/tcpecho_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 package wasi_test 6 7 import ( 8 "bytes" 9 "fmt" 10 "math/rand" 11 "net" 12 "os" 13 "os/exec" 14 "testing" 15 "time" 16 ) 17 18 func TestTCPEcho(t *testing.T) { 19 if target != "wasip1/wasm" { 20 t.Skip() 21 } 22 23 // We're unable to pass port 0 here (let the OS choose a spare port). 24 // Although wasmtime accepts port 0, and testdata/main.go successfully 25 // listens, there's no way for this test case to query the chosen port 26 // so that it can connect to the WASM module. The WASM module itself 27 // cannot access any information about the socket due to limitations 28 // with WASI preview 1 networking, and wasmtime does not log the address 29 // when you preopen a socket. Instead, we probe for a free port here. 30 var host string 31 port := rand.Intn(10000) + 40000 32 for attempts := 0; attempts < 10; attempts++ { 33 host = fmt.Sprintf("127.0.0.1:%d", port) 34 l, err := net.Listen("tcp", host) 35 if err == nil { 36 l.Close() 37 break 38 } 39 port++ 40 } 41 42 subProcess := exec.Command("go", "run", "./testdata/tcpecho.go") 43 44 subProcess.Env = append(os.Environ(), "GOOS=wasip1", "GOARCH=wasm") 45 46 switch os.Getenv("GOWASIRUNTIME") { 47 case "wasmtime": 48 subProcess.Env = append(subProcess.Env, "GOWASIRUNTIMEARGS=--tcplisten="+host) 49 default: 50 t.Skip("WASI runtime does not support sockets") 51 } 52 53 var b bytes.Buffer 54 subProcess.Stdout = &b 55 subProcess.Stderr = &b 56 57 if err := subProcess.Start(); err != nil { 58 t.Log(b.String()) 59 t.Fatal(err) 60 } 61 defer subProcess.Process.Kill() 62 63 var conn net.Conn 64 var err error 65 for attempts := 0; attempts < 5; attempts++ { 66 conn, err = net.Dial("tcp", host) 67 if err == nil { 68 break 69 } 70 time.Sleep(500 * time.Millisecond) 71 } 72 if err != nil { 73 t.Log(b.String()) 74 t.Fatal(err) 75 } 76 defer conn.Close() 77 78 payload := []byte("foobar") 79 if _, err := conn.Write(payload); err != nil { 80 t.Fatal(err) 81 } 82 var buf [256]byte 83 n, err := conn.Read(buf[:]) 84 if err != nil { 85 t.Fatal(err) 86 } 87 if string(buf[:n]) != string(payload) { 88 t.Error("unexpected payload") 89 t.Logf("expect: %d bytes (%v)", len(payload), payload) 90 t.Logf("actual: %d bytes (%v)", n, buf[:n]) 91 } 92 }