package release import ( "context" "crypto/ed25519" "testing" "time" ) func markerOn(t *testing.T, s Store, priv ed25519.PrivateKey, acct string) { t.Helper() if err := WriteDigestMarker(context.Background(), s, RootSigner(priv), acct, "test"); err != nil { t.Fatalf("WriteDigestMarker: %v", err) } } func TestDigestMarkerLifecycle(t *testing.T) { s := NewDirStore(t.TempDir()) ctx := context.Background() priv, pub := testKeys(t) if m, err := ReadDigestMarker(ctx, s, pub, "bab"); m != nil || err != nil { t.Fatalf("absent marker = %+v, %v; want nil, nil", m, err) } markerOn(t, s, priv, "bab") m, err := ReadDigestMarker(ctx, s, pub, "bab") if err != nil || m == nil || m.Account != "bab" || m.At.IsZero() { t.Fatalf("marker = %+v, %v", m, err) } // Writing it again keeps the first time: moving it later would hide a // straggler written in between. time.Sleep(1100 * time.Millisecond) markerOn(t, s, priv, "bab") again, _ := ReadDigestMarker(ctx, s, pub, "bab") if !again.At.Equal(m.At) { t.Fatalf("a second write moved the marker from %s to %s", m.At, again.At) } if other, err := ReadDigestMarker(ctx, s, pub, "cdf"); other != nil || err != nil { t.Fatalf("the marker is per account: %+v, %v", other, err) } if err := RemoveDigestMarker(ctx, s, "bab"); err != nil { t.Fatal(err) } if m, err := ReadDigestMarker(ctx, s, pub, "bab"); m != nil || err != nil { t.Fatalf("after removal = %+v, %v", m, err) } if err := RemoveDigestMarker(ctx, s, "bab"); err != nil { t.Fatalf("removing an absent marker: %v", err) } } func TestDigestMarkerIsRootOnly(t *testing.T) { s := NewDirStore(t.TempDir()) ctx := context.Background() root, pub := testKeys(t) seed, grant, err := MintKeyGrant(root, "ci", []string{"canary"}, time.Hour) if err != nil { t.Fatal(err) } key, err := ParseSigningKey(seed, "test") if err != nil { t.Fatal(err) } sg, err := ScopedSigner(key, grant, pub) if err != nil { t.Fatal(err) } if err := WriteDigestMarker(ctx, s, sg, "bab", "ci"); err == nil { t.Fatal("a scoped key wrote the marker") } // A marker signed by some other key is present but unverifiable: an // error, never "absent". other, _ := testKeys(t) markerOn(t, s, other, "bab") if m, err := ReadDigestMarker(ctx, s, pub, "bab"); m != nil || err == nil { t.Fatalf("a foreign marker = %+v, %v; want an error", m, err) } }