Skip to content
quarry Artifact [a2d406bacc]
Login

Artifact [a2d406bacc]

Artifact a2d406bacc97d069eabcfc834b1693b6ec91b7b5e4394774b68b8cd040dd81e1:


package api

import (
	"context"
	"path/filepath"
	"strings"
	"testing"

	"craftdesign.group/quarry/internal/artifact"
	"craftdesign.group/quarry/internal/index"
	"craftdesign.group/quarry/internal/ops"
)

// repo.get WAS ANSWERING ONE OF ITS TWO NUMBERS.
//
// It reported contributors: 0 against a repository with 2027 check-ins,
// on every repository, because it filled Checkins from CheckinCount and
// never touched Contributors at all — the field stayed the zero value it
// was born with. repo.list filled BOTH, from index.Summary, so the two
// ops disagreed about the same repository: the fleet listing showed the
// people who put a store together and the store's own page showed none.
//
// A number that is wrong in a direction nobody can act on is worse than
// an absent one, which is why this pins the VALUE rather than the
// field's presence: 0 contributors and 2 contributors are both "a
// number in the field".
//
// authoredStore folds a fresh index holding n check-ins by the given
// authors, so the expectation is arithmetic rather than a fixture.
func authoredStore(t *testing.T, n int, authors ...string) *Repo {
	t.Helper()
	ix, err := index.Open(filepath.Join(t.TempDir(), "i.db"))
	if err != nil {
		t.Fatal(err)
	}
	t.Cleanup(func() { ix.Close() })
	var batch []index.Parsed
	for i := 0; i < n; i++ {
		h := strings.Repeat("cd", 31) + string(rune('0'+i%10)) + string(rune('a'+i/10))
		batch = append(batch, index.Parsed{Hash: h, Art: &artifact.Artifact{
			Type: artifact.Manifest, Date: "2026-09-01T10:00:00", User: authors[i%len(authors)],
			Comment: "check-in",
		}})
	}
	if len(batch) > 0 {
		if err := ix.FoldNow(batch); err != nil {
			t.Fatal(err)
		}
	}
	return &Repo{Index: ix}
}

// The repository's own page says how many people put it together, and it
// says the same thing the fleet row says.
func TestRepoGetReportsTheContributorsItHas(t *testing.T) {
	repo := authoredStore(t, 6, "dan", "jva")
	r := ops.NewRegistry()
	if err := RegisterAll(r, Deps{Version: "v", Repos: NewRepos(map[string]*Repo{"demo": repo})}); err != nil {
		t.Fatal(err)
	}
	out, err := r.Invoke(context.Background(), "repo.get", repoGetIn{Repo: "demo"})
	if err != nil {
		t.Fatal(err)
	}
	got := out.(repoInfo)
	if got.Contributors != 2 {
		t.Errorf("repo.get says contributors = %d for a store two people authored, want 2: "+
			"a repository page showing nobody is the number this whole op exists to avoid",
			got.Contributors)
	}
	// And the neighbour it was already answering is unmoved: Summary's
	// check-in count is the same query CheckinCount ran.
	if got.Checkins != 6 {
		t.Errorf("repo.get says checkins = %d, want 6", got.Checkins)
	}
}

// The two ops that describe a repository must agree about it. They are
// read by different pages — the fleet listing and the repository home —
// and a reader who sees both has no way to tell which one is lying.
func TestRepoGetAndRepoListAgreeAboutAContributorCount(t *testing.T) {
	repo := authoredStore(t, 4, "dan", "jva", "jan")
	d := Deps{Version: "v", Repos: NewRepos(map[string]*Repo{"demo": repo})}
	r := ops.NewRegistry()
	if err := RegisterAll(r, d); err != nil {
		t.Fatal(err)
	}
	one, err := r.Invoke(context.Background(), "repo.get", repoGetIn{Repo: "demo"})
	if err != nil {
		t.Fatal(err)
	}
	list, err := r.Invoke(context.Background(), "repo.list", repoListIn{})
	if err != nil {
		t.Fatal(err)
	}
	rows := list.(repoListOut).Repos
	if len(rows) != 1 {
		t.Fatalf("repo.list returned %d rows, want 1", len(rows))
	}
	single, listed := one.(repoInfo), rows[0]
	if single.Contributors != listed.Contributors {
		t.Errorf("repo.get says %d contributors and repo.list says %d about the same repository",
			single.Contributors, listed.Contributors)
	}
	if single.Checkins != listed.Checkins {
		t.Errorf("repo.get says %d check-ins and repo.list says %d about the same repository",
			single.Checkins, listed.Checkins)
	}
}