Skip to content
quarry Artifact [16d393ab5d]
Login

Artifact [16d393ab5d]

Artifact 16d393ab5d0977b09719b1756710bfa5b43853a51bc34b70b3fb81a5b77dae25:


package api

import (
	"errors"
	"strings"
	"testing"

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

// A PROMOTED local id names the artifact its files belong on; an absent
// target gets the plain refusal.
//
// A forge-tier ticket now takes attachments and holds them until
// promotion (localattach_test.go), so the one local case that still
// refuses is the id a promoted ticket left behind: it is a redirect,
// and "no ticket" would read as if the ticket never existed. The
// refusal says where it went instead — the same not-found, with the
// artifact named — while an id nothing ever answered to stays the
// generic does-not-exist, so the two are not confused.
func TestAPromotedLocalIdSaysWhereItsFilesBelong(t *testing.T) {
	ix, z, _ := attachStore(t)
	const id = "46591711a4d778a82c6a63b09be735d0905b4c6c"
	const to = "9a7d3a8fd2c8a6b3e4b5c6d7e8f90a1b2c3d4e5f"
	d := Deps{Version: "v", Local: &tierLocal{id: id, promotedTo: to},
		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 promoted local id did not answer not-found: %v", err)
	} else if !strings.Contains(err.Error(), "was promoted to "+to[:12]) || strings.Contains(err.Error(), "wiki page") {
		t.Errorf("FAIL: a promoted local id got the generic does-not-exist refusal: %v", err)
	}

	_, 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(), "promoted") {
		t.Errorf("FAIL: an absent target was reported as a promoted ticket: %v", err)
	}
}

// tierLocal is a LocalTicketStore holding one ticket, already promoted
// when promotedTo is set: then it answers only as a redirect, as the
// real store does once a ticket's changes are gone.
type tierLocal struct {
	noLocalAttachments
	id, promotedTo 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 l.promotedTo == "" && 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, string) error { return nil }
func (l *tierLocal) LocalTicketClaim(string, string) (string, bool, error)    { return "t", true, nil }
func (l *tierLocal) LocalTicketRelease(string, string, string) error          { return nil }
func (l *tierLocal) LocalTicketRedirect(_, prefix string) (string, bool) {
	if l.promotedTo != "" && prefix != "" && strings.HasPrefix(l.id, prefix) {
		return l.promotedTo, true
	}
	return "", false
}