Skip to content
quarry Artifact [145d1ecffc]
Login

Artifact [145d1ecffc]

Artifact 145d1ecffc9c8038d4f3a2882a6b6a5b07bb5b92ece3ebf3f31d8d2d856c993f:


package web

import (
	"fmt"
	"testing"
)

// bigSample is a repository the size the coarsening exists for: years of
// history, many people, one check-in an hour.
func bigSample(days, people int) activityOut {
	act := activityOut{Since: "2019-01-01", Until: "2026-01-01", Window: "all"}
	for i := 0; i < people; i++ {
		act.Authors = append(act.Authors, activityAuthor{Name: fmt.Sprintf("person-%d", i)})
	}
	for p := 0; p < 40; p++ {
		act.Paths = append(act.Paths, fmt.Sprintf("src/module-%02d/file.c", p))
	}
	for d := 0; d < days; d++ {
		for h := 0; h < 24; h += 3 {
			a := (d + h) % people
			act.Rows = append(act.Rows, activityRow{Day: d, Hour: h, Author: a, Files: 3,
				Hash: fmt.Sprintf("%040x", d*100+h), Branch: "trunk"})
			act.Touches = append(act.Touches, activityTouch{Day: d, Path: (d + h) % 40, Author: a})
		}
	}
	return act
}

// The claim: the width is chosen from the data, so the picture is drawn
// ONCE. The page used to render the whole thing, measure it, double the
// bucket and render again — up to five discarded renders of every
// check-in before the one it kept.
//
// Pinned by rendering at the chosen width and checking it fits: if it
// does, the caller's loop breaks on its first pass.
func TestChosenBucketFitsOnTheFirstRender(t *testing.T) {
	act := bigSample(2500, 12)
	b := sampleBucket(act, activityByteBudget)
	got := len(coreSampleSVG("sqlite", act, -1, b))
	if got > activityByteBudget && b < activityBucketMax {
		t.Errorf("chose bucket %d and the drawing is %d bytes over budget, "+
			"so the loop still has to render again", b, got-activityByteBudget)
	}
}

// ...and not needlessly coarse. Choosing 32 for everything would also
// "fit on the first render" while throwing away every picture worth
// looking at, so the other half of the claim is that a small repository
// is still drawn check-in by check-in.
func TestASmallRepositoryIsStillDrawnFine(t *testing.T) {
	act := bigSample(30, 3)
	if b := sampleBucket(act, activityByteBudget); b != 1 {
		t.Errorf("a 30-day repository was coarsened to %d-day buckets", b)
	}
}

// The per-mark costs are measurements, and a measurement rots. Each
// carries headroom over what was measured; this fails if the markup
// grows past that headroom (widths that no longer fit, an extra render
// of everything) or shrinks far below it (widths coarser than the
// picture needed).
func TestMarkCostsMatchTheDrawing(t *testing.T) {
	act := bigSample(120, 4)
	for _, tc := range []struct {
		name   string
		bucket int
		assume int
	}{
		{"clock, per check-in", 1, sampleClockFine},
		{"clock, coarsened", 4, sampleClockCoarse},
	} {
		marks := marksAt(t, act, tc.bucket)
		if marks == 0 {
			t.Fatalf("%s: no marks in the fixture", tc.name)
		}
		per := (len(coreSampleSVG("sqlite", act, -1, tc.bucket)) - sampleFixedBytes) / marks
		switch {
		case per > tc.assume:
			t.Errorf("%s costs %d bytes, past the %d the estimate allows: chosen widths "+
				"will not fit and the page renders everything twice", tc.name, per, tc.assume)
		case per < tc.assume*2/3:
			t.Errorf("%s costs only %d bytes against an assumed %d: the estimate has gone "+
				"pessimistic and coarsens pictures that did not need it", tc.name, per, tc.assume)
		}
	}
}

// marksAt counts what a width would draw, the way sampleBucket does.
func marksAt(t *testing.T, act activityOut, bucket int) int {
	t.Helper()
	type cell struct{ b, y, a int }
	seen := map[cell]struct{}{}
	if bucket == 1 {
		return len(act.Rows)
	}
	for _, r := range act.Rows {
		seen[cell{r.Day / bucket, r.Hour, r.Author}] = struct{}{}
	}
	return len(seen)
}