Skip to content
quarry Artifact [f5a2f2659f]
Login

Artifact [f5a2f2659f]

Artifact f5a2f2659f0edc831a6011c5249c75cf0e513b450f47f6373ee48baaa088a038:


package web

import (
	"bufio"
	"context"
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"
	"time"
)

type tickNotifier struct{ ch chan struct{} }

func (n tickNotifier) Watch(string) (<-chan struct{}, func()) { return n.ch, func() {} }

// A burst of index moves is one revision: a push used to make every open
// page fetch its fragments once per tick (jva saw two fetches 210 ms
// apart). A tick after the burst has settled is the next revision.
func TestABurstOfTicksIsOneRevision(t *testing.T) {
	defer func(d time.Duration) { revCoalesce = d }(revCoalesce)
	revCoalesce = 50 * time.Millisecond
	n := tickNotifier{ch: make(chan struct{}, 8)}
	srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		req.SetPathValue("repo", "alpha")
		timelineRevStream(n, w, req)
	}))
	defer srv.Close()
	ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
	defer cancel()
	req, _ := http.NewRequestWithContext(ctx, "GET", srv.URL, nil)
	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		t.Fatal(err)
	}
	defer resp.Body.Close()
	lines := make(chan string, 16)
	go func() {
		sc := bufio.NewScanner(resp.Body)
		for sc.Scan() {
			if strings.HasPrefix(sc.Text(), "data: signals") {
				lines <- sc.Text()
			}
		}
	}()
	n.ch <- struct{}{}
	n.ch <- struct{}{}
	n.ch <- struct{}{}
	if got := <-lines; !strings.Contains(got, "tlRev: 1}") {
		t.Fatalf("FAIL: first revision %q", got)
	}
	select {
	case got := <-lines:
		t.Fatalf("FAIL: the burst gave a second revision: %q", got)
	case <-time.After(150 * time.Millisecond):
	}
	n.ch <- struct{}{}
	if got := <-lines; !strings.Contains(got, "tlRev: 2}") {
		t.Fatalf("FAIL: a later tick read %q", got)
	}
}