//go:build !windows // +build !windows package twin import ( "io" "os" "runtime/debug" "testing" "time" "gotest.tools/v3/assert" ) // This test should replace TestInterruptableReader_blockedOnRead if or when // Windows catches up with the shutdown implementation. func TestInterruptableReader_blockedOnReadImmediate(t *testing.T) { // Make a pipe to read from and write to pipeReader, pipeWriter, err := os.Pipe() assert.NilError(t, err) // Make an interruptable reader testMe, err := newInterruptableReader(pipeReader) assert.NilError(t, err) assert.Assert(t, testMe != nil) // Start a thread that reads from the pipe type readResult struct { n int err error } readResultChan := make(chan readResult) go func() { defer func() { panicHandler("TestInterruptableReader_blockedOnReadImmediate()", recover(), debug.Stack()) }() buffer := make([]byte, 1) n, err := testMe.Read(buffer) readResultChan <- readResult{n, err} }() // Give the reader thread some time to start waiting time.Sleep(100 * time.Millisecond) // Interrupt the reader testMe.Interrupt() // Wait for the reader thread to finish result := <-readResultChan // Check the result assert.Equal(t, result.n, 0) assert.Equal(t, result.err, io.EOF) // Another read should return EOF immediately buffer := make([]byte, 1) n, err := testMe.Read(buffer) assert.Equal(t, err, io.EOF) assert.Equal(t, n, 0) // Even if there are bytes, the interrupted reader should still return EOF n, err = pipeWriter.Write([]byte{42}) assert.NilError(t, err) assert.Equal(t, n, 1) n, err = testMe.Read(buffer) assert.Equal(t, err, io.EOF) assert.Equal(t, n, 0) }