Files
moby/daemon/internal/stream/attach_test.go
Derek McGowan a02ba3c7df Move container/stream to daemon/internal/stream
Signed-off-by: Derek McGowan <derek@mcg.dev>
2025-06-27 14:27:05 -07:00

103 lines
2.1 KiB
Go

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")
}
}