测试命令行提示时出现问题,扫描器不等待用户输入。

huangapple go评论112阅读模式
英文:

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

问题

我尝试编写一个测试来验证命令行提示,模拟用户对某些程序输出的响应中的输入。

如何使scanner.Scan等待其他写入?

我目前的代码如下:

  1. b := &bytes.Buffer{}
  2. fmt.Fprint(b, "0")
  3. go func() {
  4. time.Sleep(1 * time.Second)
  5. for i := 1; i < 4; i++ {
  6. fmt.Fprint(b, i)
  7. time.Sleep(1 * time.Second)
  8. }
  9. }()
  10. scanner := bufio.NewScanner(b)
  11. for scanner.Scan() {
  12. log.Print(scanner.Text())
  13. }
  14. if err := scanner.Err(); err != nil {
  15. log.Println("扫描时出现问题:", err)
  16. }

期望的结果是:0123

实际结果是:0

我尝试了一个使用io.Pipe的版本

  1. r, w := io.Pipe()
  2. fmt.Fprint(w, "0")
  3. go func() {
  4. time.Sleep(1 * time.Second)
  5. for i := 1; i < 4; i++ {
  6. fmt.Fprint(w, i)
  7. time.Sleep(1 * time.Second)
  8. }
  9. }()
  10. scanner := bufio.NewScanner(r)
  11. for scanner.Scan() {
  12. log.Print(scanner.Text())
  13. }
  14. if err := scanner.Err(); err != nil {
  15. log.Println("扫描时出现问题:", err)
  16. }

结果:致命错误:所有goroutine都处于休眠状态-死锁!

英文:

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:

  1. b := &bytes.Buffer{}
  2. fmt.Fprint(b, "0")
  3. go func() {
  4. time.Sleep(1 * time.Second)
  5. for i := 1; i < 4; i++ {
  6. fmt.Fprint(b, i)
  7. time.Sleep(1 * time.Second)
  8. }
  9. }()
  10. scanner := bufio.NewScanner(b)
  11. for scanner.Scan() {
  12. log.Print(scanner.Text())
  13. }
  14. if err := scanner.Err(); err != nil {
  15. log.Println("problem while scanning:", err)
  16. }

Expected result is: 0123

Actual result is: 0

I tried a version with io.Pipe

  1. r, w := io.Pipe()
  2. fmt.Fprint(w, "0")
  3. go func() {
  4. time.Sleep(1 * time.Second)
  5. for i := 1; i < 4; i++ {
  6. fmt.Fprint(w, i)
  7. time.Sleep(1 * time.Second)
  8. }
  9. }()
  10. scanner := bufio.NewScanner(r)
  11. for scanner.Scan() {
  12. log.Print(scanner.Text())
  13. }
  14. if err := scanner.Err(); err != nil {
  15. log.Println("problem while scanning:", err)
  16. }

result: fatal error: all goroutines are asleep - deadlock!

答案1

得分: 0

使用管道时,写入和读取是同步的。没有匹配的读取操作,写入操作无法完成。将第一个写入操作移到goroutine中,并关闭管道的写入端,以允许扫描器停止扫描。

  1. r, w := io.Pipe()
  2. go func() {
  3. defer w.Close()
  4. fmt.Fprint(w, "0")
  5. time.Sleep(1 * time.Second)
  6. for i := 1; i < 4; i++ {
  7. fmt.Fprint(w, i)
  8. time.Sleep(1 * time.Second)
  9. }
  10. }()
  11. scanner := bufio.NewScanner(r)
  12. for scanner.Scan() {
  13. log.Print(scanner.Text())
  14. }
  15. if err := scanner.Err(); err != nil {
  16. log.Println("扫描时出现问题:", err)
  17. }
英文:

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.

  1. r, w := io.Pipe()
  2. go func() {
  3. defer w.Close()
  4. fmt.Fprint(w, &quot;0&quot;)
  5. time.Sleep(1 * time.Second)
  6. for i := 1; i &lt; 4; i++ {
  7. fmt.Fprint(w, i)
  8. time.Sleep(1 * time.Second)
  9. }
  10. }()
  11. scanner := bufio.NewScanner(r)
  12. for scanner.Scan() {
  13. log.Print(scanner.Text())
  14. }
  15. if err := scanner.Err(); err != nil {
  16. log.Println(&quot;problem while scanning:&quot;, err)
  17. }

huangapple
  • 本文由 发表于 2023年2月1日 17:48:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/75308283.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定