I try to write a test to verify cli prompts, emulate user inputs in response to some program outputs.
How to make scanner.Scan
wait for the rest of the writes?
What I have so far:
b := &bytes.Buffer{}
fmt.Fprint(b, "0")
go func() {
time.Sleep(1 * time.Second)
for i := 1; i < 4; i {
fmt.Fprint(b, i)
time.Sleep(1 * time.Second)
}
}()
scanner := bufio.NewScanner(b)
for scanner.Scan() {
log.Print(scanner.Text())
}
if err := scanner.Err(); err != nil {
log.Println("problem while scanning:", err)
}
Expected result is: 0123
Actual result is: 0
I tried a version with io.Pipe
r, w := io.Pipe()
fmt.Fprint(w, "0")
go func() {
time.Sleep(1 * time.Second)
for i := 1; i < 4; i {
fmt.Fprint(w, i)
time.Sleep(1 * time.Second)
}
}()
scanner := bufio.NewScanner(r)
for scanner.Scan() {
log.Print(scanner.Text())
}
if err := scanner.Err(); err != nil {
log.Println("problem while scanning:", err)
}
result: fatal error: all goroutines are asleep - deadlock!
CodePudding user response:
When using a pipe, writes and reads are synchronous. A Write cannot complete without a matching Read. Move the first write into the goroutine. And Close the writing end of the pipe to allow the scanner to stop scanning.
r, w := io.Pipe()
go func() {
defer w.Close()
fmt.Fprint(w, "0")
time.Sleep(1 * time.Second)
for i := 1; i < 4; i {
fmt.Fprint(w, i)
time.Sleep(1 * time.Second)
}
}()
scanner := bufio.NewScanner(r)
for scanner.Scan() {
log.Print(scanner.Text())
}
if err := scanner.Err(); err != nil {
log.Println("problem while scanning:", err)
}