Home > OS >  Problem with testing cli prompts interactively, scanner is not waiting for user input
Problem with testing cli prompts interactively, scanner is not waiting for user input

Time:02-02

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)
    }
  • Related