package api
import (
"errors"
"strings"
"testing"
"craftdesign.group/quarry/internal/oltp"
"craftdesign.group/quarry/internal/ops"
)
// A ticket on the forge tier is not attachable, and the refusal says so.
//
// The two tiers never meet: a forge-tier ticket lives in the forge's
// database and enters the artifact log only when somebody promotes it,
// while an attachment target is resolved in the STORE. Since the forge
// tier is the DEFAULT, this is most tickets on most repositories.
//
// The old refusal was "no ticket, wiki page, technote or forum post",
// which reads as "that ticket does not exist" about a ticket the forge
// had just created and would happily show. Found by attaching to one by
// accident: zit records the A card against an id the forge can never
// resolve, so the store and the forge disagree in silence.
func TestAForgeTierTicketSaysWhichTierItIsOn(t *testing.T) {
ix, z, _ := attachStore(t)
const id = "46591711a4d778a82c6a63b09be735d0905b4c6c"
d := Deps{Version: "v", Local: &tierLocal{id: id},
Repos: NewRepos(map[string]*Repo{"test": {Index: ix, Zit: z}})}
r := ops.NewRegistry()
if err := RegisterAll(r, d); err != nil {
t.Fatal(err)
}
who := as("dan", "bBl")
_, err := r.Invoke(who, "attachment.remove",
attachmentRemoveIn{Repo: "test", Target: "tkt:" + id, Name: "whatever.txt"})
if !errors.Is(err, ops.ErrNotFound) {
t.Errorf("FAIL: a forge-tier target did not answer not-found: %v", err)
} else if !strings.Contains(err.Error(), "forge tier") || strings.Contains(err.Error(), "wiki page") {
// The generic refusal QUOTES the target, so asserting that the
// id appears would pass against it too — that assertion was
// written first and passed with the fix reverted.
t.Errorf("FAIL: a forge-tier ticket got the generic does-not-exist refusal: %v", err)
}
// A target that really is absent keeps the old answer: the tier is
// named only when there IS a ticket on it.
_, err = r.Invoke(who, "attachment.remove",
attachmentRemoveIn{Repo: "test", Target: "tkt:ffffffffffffffffffffffffffffffffffffffff", Name: "x.txt"})
if !errors.Is(err, ops.ErrNotFound) {
t.Errorf("FAIL: an absent target did not answer not-found: %v", err)
} else if strings.Contains(err.Error(), "forge tier") {
t.Errorf("FAIL: an absent target was reported as a forge-tier ticket: %v", err)
}
}
// tierLocal holds exactly one forge-tier ticket.
type tierLocal struct{ id string }
func (l *tierLocal) LocalTicketNew(_, _, _ string, _ map[string]string) (string, error) {
return l.id, nil
}
func (l *tierLocal) LocalTicketSet(string, string, string, map[string]string) error { return nil }
func (l *tierLocal) LocalTicketByPrefix(_, prefix string) (oltp.LocalTicket, bool, error) {
if prefix != "" && strings.HasPrefix(l.id, prefix) {
return oltp.LocalTicket{ID: l.id}, true, nil
}
return oltp.LocalTicket{}, false, nil
}
func (l *tierLocal) LocalTickets(string) ([]oltp.LocalTicket, error) { return nil, nil }
func (l *tierLocal) LocalTicketDiscard(string, string) error { return nil }
func (l *tierLocal) LocalTicketPromoted(string, string, string) error { return nil }
func (l *tierLocal) LocalTicketRedirect(string, string) (string, bool) { return "", false }