How would a process read its own output stream? I am writing automated tests which start a few application sub-processes (applications) in the same process as the test. Therefore, the standard out is a mix of test output and application output.
I want to read the output stream at runtime and fail the test if I see errors from the application. Is this possible/feasible? If so, how do I do it?
Note: I know I could start the applications as their own separate processes and then read their output streams. That's a lot of work from where I am now.
Also note, this is not a dupe of How to test a function's output (stdout/stderr) in Go unit tests, although that ticket is similar and helpful. The other ticket is about capturing output for a single function call. This ticket is about reading the entire stream, continuously. The correct answer is also a little different - it requires a pipe.
Yes, You may use os.Pipe()
then process it yourself:
tmp := os.Stdout
r, w, err := os.Pipe()
if err != nil {
panic(err)
}
os.Stdout = w
Or divert os.Stdout
to a another file or strings.Builder
.
Here is the detailed answer:
In Go, how do I capture stdout of a function into a string?
A slightly modified version of an answer given in In Go, how do I capture stdout of a function into a string? using a os.Pipe (a form of IPC):
Pipe returns a connected pair of Files; reads from r return bytes written to w. It returns the files and an error, if any.
As os.Stdout is an *os.File, you could replace it with any file.
package main
import (
"bytes"
"fmt"
"io"
"log"
"os"
)
func main() {
old := os.Stdout
r, w, _ := os.Pipe() // TODO: handle error.
os.Stdout = w
// All stdout will be caputered from here on.
fmt.Println("this will be caputered")
// Access output and restore previous stdout.
outc := make(chan string)
go func() {
var buf bytes.Buffer
io.Copy(&buf, r) // TODO: handle error
outc <- buf.String()
}()
w.Close()
os.Stdout = old
out := <-outc
log.Printf("captured: %s", out)
}