Skip to content
quarry Artifact [7824b22338]
Login

Artifact [7824b22338]

Artifact 7824b2233823fabc4618bf918a43e8affb4c655f0e13f3494f5bd9a7d9385f73:


package xfer

import (
	"strings"
	"testing"
)

// A push refusal has to name the half that is missing AND give the
// remedy for THAT half.
//
// It used to name both halves, say one of them was missing, and then
// prescribe minting a credential. jva measured all four cells with only
// the check-in letter changing between them and found that a person who
// HELD a credential and lacked the letter was told to mint another one
// — advice they can follow, that changes nothing, and that points away
// from the person who could actually help (G-128).
//
// A wrong remedy is worse than a missing one, because it is followable.
func TestAPushRefusalGivesTheRemedyForTheHalfThatFailed(t *testing.T) {
	for _, c := range []struct {
		what              string
		user              string
		mayWrite, hasCred bool
		wants, mustNotSay []string
	}{
		{
			what: "anonymous", user: "", mayWrite: false, hasCred: false,
			wants: []string{"anonymous", "--user"},
		},
		{
			what: "holds a credential, lacks the letter", user: "jan",
			mayWrite: false, hasCred: true,
			wants: []string{"check-in letter", "admin"},
			// The cell jva caught: do not send them to mint a second
			// credential when they already have one.
			mustNotSay: []string{"mint"},
		},
		{
			what: "holds the letter, no credential", user: "jan",
			mayWrite: true, hasCred: false,
			wants: []string{"no push credential", "sync-token"},
		},
		{
			what: "both present, wrong secret signed the card", user: "jan",
			mayWrite: true, hasCred: true,
			wants: []string{"did not verify", "account password"},
			// Nothing is missing here, so the old word was wrong too.
			mustNotSay: []string{"is missing"},
		},
	} {
		got := refusalFor(c.user, c.mayWrite, c.hasCred)
		for _, w := range c.wants {
			if !strings.Contains(got, w) {
				t.Errorf("FAIL [%s]: refusal never says %q: %s", c.what, w, got)
			}
		}
		for _, n := range c.mustNotSay {
			if strings.Contains(got, n) {
				t.Errorf("FAIL [%s]: refusal says %q, which is the wrong cure: %s", c.what, n, got)
			}
		}
		t.Logf("ok [%s]: %s", c.what, got)
	}
}

// The four states must not collapse: two cells sharing a sentence is
// how the wrong remedy survived, since a reader could not tell which
// case they were in.
func TestEachRefusalStateReadsDifferently(t *testing.T) {
	seen := map[string]string{}
	for _, c := range []struct {
		what              string
		user              string
		mayWrite, hasCred bool
	}{
		{"anonymous", "", false, false},
		{"no letter", "jan", false, true},
		{"no credential", "jan", true, false},
		{"bad secret", "jan", true, true},
	} {
		got := refusalFor(c.user, c.mayWrite, c.hasCred)
		if prev, dup := seen[got]; dup {
			t.Errorf("FAIL: %q and %q share one sentence: %s", prev, c.what, got)
			continue
		}
		seen[got] = c.what
	}
	t.Logf("ok: %d states, %d distinct sentences", 4, len(seen))
}