Skip to content
quarry Artifact [0437d2cbd8]
Login

Artifact [0437d2cbd8]

Artifact 0437d2cbd840a20a5ddae88ff64568f3884e922e2adcabc4c3348d0dd148c067:


package api

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

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

// A forge numbers every ticket of a repository it owns, store and local
// together, oldest first; a ticket filed later takes the next number;
// "#2" opens the same ticket as its hex id; a mirror is never numbered
// (54c5175f option C).
func TestTicketsAreNumberedInCreationOrder(t *testing.T) {
	ix, err := index.Open(filepath.Join(t.TempDir(), "i.db"))
	if err != nil {
		t.Fatal(err)
	}
	t.Cleanup(func() { ix.Close() })
	store := func(id, date, title string) index.Parsed {
		return index.Parsed{Hash: id, Art: &artifact.Artifact{Type: artifact.Ticket, TicketID: id, Date: date, User: "dan",
			Fields: []artifact.Field{{Name: "title", Value: title}, {Name: "status", Value: "Open"}}}}
	}
	older := "aaaa000000000000000000000000000000000000000000000000000000000001"
	newer := "bbbb000000000000000000000000000000000000000000000000000000000002"
	if err := ix.FoldNow([]index.Parsed{store(newer, "2026-09-02T10:00:00", "second"), store(older, "2026-09-01T10:00:00", "first")}); err != nil {
		t.Fatal(err)
	}
	db, err := oltp.Open(filepath.Join(t.TempDir(), "o.db"))
	if err != nil {
		t.Fatal(err)
	}
	t.Cleanup(func() { db.Close() })
	mirrors := memMirrors{}
	_ = mirrors.SetMirror("upstream", "https://upstream.example/x", 3600)
	r := ops.NewRegistry()
	if err := RegisterAll(r, Deps{Version: "v", Repos: NewRepos(map[string]*Repo{"q": {Index: ix}, "upstream": {Index: ix}}),
		Local: db, Idem: db, Numbers: db, Mirrors: mirrors}); err != nil {
		t.Fatal(err)
	}
	ctx := ops.WithUser(context.Background(), "dan")

	filed, err := r.Invoke(ctx, "ticket.intake", ticketIntakeIn{Repo: "q", Title: "third"})
	if err != nil {
		t.Fatal(err)
	}
	third := filed.(ticketIntakeOut)
	if third.Number != 3 {
		t.Fatalf("FAIL: the new ticket is #%d, want 3 after the two older store tickets", third.Number)
	}
	list, err := r.Invoke(ctx, "ticket.list", ticketListIn{Repo: "q", State: "all"})
	if err != nil {
		t.Fatal(err)
	}
	by := map[string]int{}
	for _, row := range list.(ticketListOut).Tickets {
		by[row.ID] = row.Number
	}
	if by[older] != 1 || by[newer] != 2 || by[third.ID] != 3 {
		t.Fatalf("FAIL: list numbers %v", by)
	}
	got, err := r.Invoke(ctx, "ticket.get", ticketGetIn{Repo: "q", ID: "2"})
	if err != nil || got.(ticketGetOut).Ticket.ID != newer || got.(ticketGetOut).Number != 2 {
		t.Fatalf("FAIL: #2 opened %+v (%v)", got, err)
	}
	if loc, err := r.Invoke(ctx, "ticket.get", ticketGetIn{Repo: "q", ID: "3"}); err != nil || loc.(ticketGetOut).Number != 3 {
		t.Fatalf("FAIL: #3 (a local ticket) did not open as itself: %v", err)
	}
	up, err := r.Invoke(ctx, "ticket.list", ticketListIn{Repo: "upstream", State: "all"})
	if err != nil {
		t.Fatal(err)
	}
	for _, row := range up.(ticketListOut).Tickets {
		if row.Number != 0 {
			t.Fatalf("FAIL: a mirror's ticket was numbered #%d", row.Number)
		}
	}
	t.Log("ok: store tickets #1 #2 by creation, the new local ticket #3, #2 and #3 open by number, the mirror unnumbered")
}