瀏覽代碼

x/model: add LogValue

Also, fix GoString and test
Blake Mizerany 1 年之前
父節點
當前提交
c0d4f55f3e
共有 2 個文件被更改,包括 47 次插入13 次删除
  1. 15 3
      x/model/name.go
  2. 32 10
      x/model/name_test.go

+ 15 - 3
x/model/name.go

@@ -5,6 +5,7 @@ import (
 	"errors"
 	"hash/maphash"
 	"iter"
+	"log/slog"
 	"slices"
 	"strings"
 
@@ -205,10 +206,21 @@ func (r Name) DisplayComplete() string {
 	}).String()
 }
 
-// GoString implements fmt.GoStringer. It is identical to
-// [Name.DisplayComplete], but works with fmt.Printf("%#v", name).
+// GoString implements fmt.GoStringer. It is like DisplayComplete but
+// includes the build or a "?" if the build is missing.
 func (r Name) GoString() string {
-	return r.DisplayComplete()
+	return (Name{
+		host:      cmp.Or(r.host, "?"),
+		namespace: cmp.Or(r.namespace, "?"),
+		model:     cmp.Or(r.model, "?"),
+		tag:       cmp.Or(r.tag, "?"),
+		build:     cmp.Or(r.build, "?"),
+	}).String()
+}
+
+// LogValue implements slog.Valuer.
+func (r Name) LogValue() slog.Value {
+	return slog.StringValue(r.GoString())
 }
 
 // DisplayShort returns a short display string of the Name with only the

+ 32 - 10
x/model/name_test.go

@@ -1,7 +1,10 @@
 package model
 
 import (
+	"bytes"
+	"cmp"
 	"fmt"
+	"log/slog"
 	"slices"
 	"strings"
 	"testing"
@@ -170,6 +173,27 @@ func TestComplete(t *testing.T) {
 	}
 }
 
+func TestNameLogValue(t *testing.T) {
+	cases := []string{
+		"example.com/library/mistral:latest+Q4_0",
+		"mistral:latest",
+		"mistral:7b+Q4_0",
+	}
+	for _, s := range cases {
+		t.Run(s, func(t *testing.T) {
+			var b bytes.Buffer
+			log := slog.New(slog.NewTextHandler(&b, nil))
+			name := ParseName(s)
+			log.Info("", "name", name)
+			want := fmt.Sprintf("name=%s", name.GoString())
+			got := b.String()
+			if !strings.Contains(got, want) {
+				t.Errorf("expected log output to contain %q; got %q", want, got)
+			}
+		})
+	}
+}
+
 func TestNameDisplay(t *testing.T) {
 	cases := []struct {
 		name         string
@@ -179,15 +203,8 @@ func TestNameDisplay(t *testing.T) {
 		wantComplete string
 		wantString   string
 		wantModel    string
+		wantGoString string // default is tt.in
 	}{
-		{
-			name:         "Full Name with Build",
-			in:           "example.com/library/mistral:latest+Q4_0",
-			wantShort:    "mistral:latest",
-			wantLong:     "library/mistral:latest",
-			wantComplete: "example.com/library/mistral:latest",
-			wantModel:    "mistral",
-		},
 		{
 			name:         "Complete Name",
 			in:           "example.com/library/mistral:latest+Q4_0",
@@ -203,6 +220,7 @@ func TestNameDisplay(t *testing.T) {
 			wantLong:     "mistral:latest",
 			wantComplete: "?/?/mistral:latest",
 			wantModel:    "mistral",
+			wantGoString: "?/?/mistral:latest+?",
 		},
 		{
 			name:         "Long Name",
@@ -211,6 +229,7 @@ func TestNameDisplay(t *testing.T) {
 			wantLong:     "library/mistral:latest",
 			wantComplete: "?/library/mistral:latest",
 			wantModel:    "mistral",
+			wantGoString: "?/library/mistral:latest+?",
 		},
 		{
 			name:         "Case Preserved",
@@ -219,6 +238,7 @@ func TestNameDisplay(t *testing.T) {
 			wantLong:     "Library/Mistral:Latest",
 			wantComplete: "?/Library/Mistral:Latest",
 			wantModel:    "Mistral",
+			wantGoString: "?/Library/Mistral:Latest+?",
 		},
 	}
 
@@ -240,8 +260,10 @@ func TestNameDisplay(t *testing.T) {
 			if g := p.DisplayModel(); g != tt.wantModel {
 				t.Errorf("Model = %q; want %q", g, tt.wantModel)
 			}
-			if g, w := fmt.Sprintf("%#v", p), p.DisplayComplete(); g != w {
-				t.Errorf("GoString() = %q; want %q", g, w)
+
+			tt.wantGoString = cmp.Or(tt.wantGoString, tt.in)
+			if g := fmt.Sprintf("%#v", p); g != tt.wantGoString {
+				t.Errorf("GoString() = %q; want %q", g, tt.wantGoString)
 			}
 		})
 	}