From 348378ef568eaaef46aee1b7332b7e941f28dce7 Mon Sep 17 00:00:00 2001 From: Blake Mizerany Date: Sat, 6 Apr 2024 17:58:16 -0700 Subject: [PATCH] x/model: make UnmarshalText illegal for an already valid Name --- x/model/name.go | 5 +++++ x/model/name_test.go | 20 +++++++++++++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/x/model/name.go b/x/model/name.go index fa5f0293a..0319c7ea6 100644 --- a/x/model/name.go +++ b/x/model/name.go @@ -316,7 +316,12 @@ func (r Name) MarshalText() ([]byte, error) { } // UnmarshalText implements [encoding.TextUnmarshaler]. +// +// It is an error to call UnmarshalText on a valid Name. func (r *Name) UnmarshalText(text []byte) error { + if r.Valid() { + return errors.New("model.Name: UnmarshalText on valid Name") + } // unsafeString is safe here because the contract of UnmarshalText // that text belongs to us for the duration of the call. *r = ParseName(unsafeString(text)) diff --git a/x/model/name_test.go b/x/model/name_test.go index 55bdce8dc..e3f2b5911 100644 --- a/x/model/name_test.go +++ b/x/model/name_test.go @@ -25,6 +25,14 @@ func fieldsFromName(p Name) fields { } } +func mustParse(s string) Name { + p := ParseName(s) + if !p.Valid() { + panic(fmt.Sprintf("invalid name: %q", s)) + } + return p +} + var testNames = map[string]fields{ "mistral:latest": {model: "mistral", tag: "latest"}, "mistral": {model: "mistral"}, @@ -374,12 +382,22 @@ func TestNameTextMarshal(t *testing.T) { } }) } +} +func TestNameTextUnmarshalCallOnValidName(t *testing.T) { + // UnmarshalText should not be called on a valid Name. + p := mustParse("x") + if err := p.UnmarshalText([]byte("mistral:latest+Q4_0")); err == nil { + t.Error("UnmarshalText() = nil; want error") + } +} + +func TestNameTextMarshalAllocs(t *testing.T) { var data []byte name := ParseName("example.com/ns/mistral:latest+Q4_0") if !name.Complete() { // sanity check - t.Fatal("name is not complete") + panic("sanity check failed") } allocs := testing.AllocsPerRun(1000, func() {