1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
|
package stream
import (
"context"
"io"
"testing"
"time"
"gotest.tools/v3/assert"
)
// Make sure when there is no I/O on a stream that the goroutines do not get blocked after the container exits.
func TestAttachNoIO(t *testing.T) {
t.Run("stdin only", func(t *testing.T) {
stdinR, _ := io.Pipe()
defer stdinR.Close()
testStreamCopy(t, stdinR, nil, nil)
})
t.Run("stdout only", func(t *testing.T) {
_, w := io.Pipe()
defer w.Close()
testStreamCopy(t, nil, w, nil)
})
t.Run("stderr only", func(t *testing.T) {
_, w := io.Pipe()
defer w.Close()
testStreamCopy(t, nil, nil, w)
})
t.Run("stdout+stderr", func(t *testing.T) {
_, stdoutW := io.Pipe()
defer stdoutW.Close()
_, stderrW := io.Pipe()
defer stderrW.Close()
testStreamCopy(t, nil, stdoutW, stderrW)
})
t.Run("stdin+stdout", func(t *testing.T) {
stdin, _ := io.Pipe()
defer stdin.Close()
_, stdout := io.Pipe()
defer stdout.Close()
testStreamCopy(t, stdin, stdout, nil)
})
t.Run("stdin+stderr", func(t *testing.T) {
stdin, _ := io.Pipe()
defer stdin.Close()
_, stderr := io.Pipe()
defer stderr.Close()
testStreamCopy(t, stdin, nil, stderr)
})
t.Run("stdin+stdout+stderr", func(t *testing.T) {
stdinR, _ := io.Pipe()
defer stdinR.Close()
stdoutR, stdoutW := io.Pipe()
defer stdoutR.Close()
stderrR, stderrW := io.Pipe()
defer stderrR.Close()
testStreamCopy(t, stdinR, stdoutW, stderrW)
})
}
func testStreamCopy(t *testing.T, stdin io.ReadCloser, stdout, stderr io.WriteCloser) {
cfg := AttachConfig{
UseStdin: stdin != nil,
UseStdout: stdout != nil,
UseStderr: stderr != nil,
Stdin: stdin,
Stdout: stdout,
Stderr: stderr,
}
sc := NewConfig()
sc.AttachStreams(&cfg)
defer sc.CloseStreams()
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
chErr := sc.CopyStreams(ctx, &cfg)
select {
case err := <-chErr:
assert.NilError(t, err)
default:
}
cancel()
select {
case err := <-chErr:
assert.ErrorIs(t, err, context.Canceled)
case <-time.After(10 * time.Second):
t.Fatal("timeout waiting for CopyStreams to exit")
}
}
|