Skip to content
quarry Artifact [1fa2e04509]
Login

Artifact [1fa2e04509]

Artifact 1fa2e0450965ec59395dd605c644a16d062956106b197af16f2286558f73005d:


package web

import (
	"fmt"
	"testing"
)

// The strips never draw more lanes than there is room for: files fold
// into their directories, the busy directories open toward their files,
// and the touches follow them.
func TestTreeColumnsFoldIntoDirectoriesToFit(t *testing.T) {
	act := activityOut{Since: "2026-01-01", Until: "2026-01-10"}
	for d := range 10 {
		for f := range 100 {
			act.Paths = append(act.Paths, fmt.Sprintf("src/d%d/f%03d.c", d, f))
		}
	}
	act.Paths = append(act.Paths, "README")
	// d3's files 50 and 51 are touched, and so is README.
	act.Touches = []activityTouch{
		{Day: 2, Path: 350, Author: 0},
		{Day: 2, Path: 351, Author: 0},
		{Day: 4, Path: 1000, Author: 1},
	}
	got, folded := foldColumns(act, 50)
	if !folded {
		t.Fatal("FAIL: 1001 paths against a limit of 50 did not fold")
	}
	if len(got.Paths) > 50 {
		t.Fatalf("FAIL: %d columns after the fold, want at most 50", len(got.Paths))
	}
	// The directories nobody touched stay one column each; the touched
	// one opens down to the two files and gathers the rest.
	has := map[string]bool{}
	for _, n := range got.Paths {
		has[n] = true
	}
	for _, want := range []string{"src/d0/", "src/d9/", "src/d3/f050.c", "src/d3/f051.c", "src/d3/(other)", "README"} {
		if !has[want] {
			t.Fatalf("FAIL: no column %q in %v", want, got.Paths)
		}
	}
	if len(got.Touches) != 3 {
		t.Fatalf("FAIL: %d touches, want 3: %+v", len(got.Touches), got.Touches)
	}
	if p := got.Paths[got.Touches[0].Path]; p != "src/d3/f050.c" {
		t.Fatalf("FAIL: the first touch lands on %q", p)
	}
	if p := got.Paths[got.Touches[2].Path]; p != "README" {
		t.Fatalf("FAIL: the README touch lands on %q", p)
	}

	// Under the limit nothing moves.
	if same, folded := foldColumns(act, 2000); folded || len(same.Paths) != len(act.Paths) {
		t.Fatal("FAIL: a tree under the limit was folded")
	}

	// Touches that land on the same (day, column, person) become one.
	two := activityOut{Paths: []string{"a/x", "a/y", "b/z"}, Touches: []activityTouch{
		{Day: 1, Path: 0, Author: 0}, {Day: 1, Path: 1, Author: 0}, {Day: 1, Path: 2, Author: 0},
	}}
	got, _ = foldColumns(two, 2)
	if len(got.Paths) != 2 || len(got.Touches) != 2 {
		t.Fatalf("FAIL: %v %+v", got.Paths, got.Touches)
	}

	// A flat tree is one column of root files.
	flat := activityOut{}
	for f := range 500 {
		flat.Paths = append(flat.Paths, fmt.Sprintf("f%03d", f))
	}
	flat.Touches = []activityTouch{{Day: 0, Path: 499, Author: 0}}
	got, _ = foldColumns(flat, 50)
	if len(got.Paths) != 1 || got.Touches[0].Path != 0 {
		t.Fatalf("FAIL: flat tree folded to %d columns, touch on %d", len(got.Paths), got.Touches[0].Path)
	}

	// A tree too wide even at its top level keeps its heaviest
	// directories and gathers the rest, the files at the root among them.
	wide := activityOut{}
	for d := range 40 {
		wide.Paths = append(wide.Paths, fmt.Sprintf("d%02d/a.c", d), fmt.Sprintf("d%02d/b.c", d))
	}
	wide.Paths = append(wide.Paths, "zz", "zzz")
	for d := range 40 {
		for k := 0; k < 1+d; k++ {
			wide.Touches = append(wide.Touches, activityTouch{Day: k, Path: d * 2, Author: 0})
		}
	}
	got, folded = foldColumns(wide, 16)
	kept := map[string]bool{}
	for _, n := range got.Paths {
		kept[n] = true
	}
	if !folded || len(got.Paths) > 16 || !kept["(other)"] {
		t.Fatalf("FAIL: %d columns %v", len(got.Paths), got.Paths)
	}
	for _, d := range []string{"d39/", "d38/", "d37/"} {
		if !kept[d] {
			t.Fatalf("FAIL: the busy directory %s was gathered into other: %v", d, got.Paths)
		}
	}
	if kept["d00/"] {
		t.Fatalf("FAIL: a directory with almost no work has a column of its own: %v", got.Paths)
	}
	t.Log("ok")
}