1package live23import (4 "context"5 "errors"6 "io"7 "testing"8 "time"9)1011// A stream's rows come as the program prints them, a line cut in two12// waiting for its end; Reload gives them all again, and the end is13// reported once, with the error it ended on.14func TestStreamRowsAsPrinted(t *testing.T) {15 next := make(chan string)16 s := NewStream(func(ctx context.Context, w io.Writer) error {17 for text := range next {18 io.WriteString(w, text)19 }20 return errors.New("tail: app.log: no such file")21 })22 defer s.Close()23 s.Wait = time.Second24 ctx := context.Background()2526 next <- "{x: a, y: 1}\n{x: b"27 u, ok := s.Poll(ctx)28 if !ok || len(u.Rows) != 1 || u.Header == nil || u.Header[0].V.Str != "x" || u.Rows[0][1].V.Num != 1 {29 t.Fatalf("first poll: %v %+v", ok, u)30 }31 next <- ", y: 2}\n"32 if u, ok = s.Poll(ctx); !ok || len(u.Rows) != 1 || u.Rows[0][0].V.Str != "b" || u.Header != nil {33 t.Fatalf("second poll: %v %+v", ok, u)34 }35 if got := string(s.NUON()); got != "[{x: a, y: 1}, {x: b, y: 2}]" {36 t.Errorf("NUON %s", got)37 }38 s.Reload()39 next <- "{x: c, y: 3}\n"40 if u, ok = s.Poll(ctx); !ok || !u.Reset || len(u.Rows) != 3 || u.Header == nil {41 t.Fatalf("after Reload: %v %+v", ok, u)42 }43 if done, _ := s.Ended(); done {44 t.Fatal("ended too soon")45 }46 close(next)47 u, ok = s.Poll(ctx)48 if !ok || u.Err != "tail: app.log: no such file" {49 t.Fatalf("the end: %v %+v", ok, u)50 }51 if done, err := s.Ended(); !done || err == nil || s.Rows() != 3 {52 t.Errorf("ended %v %v, %d rows", done, err, s.Rows())53 }54 if _, ok := s.Poll(ctx); ok {55 t.Error("polled after the end")56 }57}5859// Closing a stream stops its program, which ends without an error.60func TestStreamClose(t *testing.T) {61 s := NewStream(func(ctx context.Context, w io.Writer) error {62 io.WriteString(w, "1\n")63 <-ctx.Done()64 return ctx.Err()65 })66 s.Wait = time.Second67 if u, ok := s.Poll(context.Background()); !ok || len(u.Rows) != 1 {68 t.Fatalf("%v %+v", ok, u)69 }70 s.Close()71 u, ok := s.Poll(context.Background())72 if !ok || u.Err != "" {73 t.Fatalf("after Close: %v %+v", ok, u)74 }75 if done, err := s.Ended(); !done || err != nil {76 t.Errorf("ended %v %v", done, err)77 }78}7980// Only the last Keep values are kept.81func TestStreamKeepsTheLast(t *testing.T) {82 s := NewStream(func(ctx context.Context, w io.Writer) error {83 io.WriteString(w, "1\n2\n3\n")84 return nil85 })86 s.Keep = 287 for done := false; !done; done, _ = s.Ended() {88 s.Poll(context.Background())89 }90 if got := string(s.NUON()); got != "[2, 3]" {91 t.Errorf("NUON %s", got)92 }93}