ref_test.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. package blob
  2. import (
  3. "strings"
  4. "testing"
  5. )
  6. // test refs
  7. const (
  8. refTooLong = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
  9. )
  10. var testRefs = map[string]Ref{
  11. "mistral:latest": {name: "mistral", tag: "latest"},
  12. "mistral": {name: "mistral"},
  13. "mistral:30B": {name: "mistral", tag: "30B"},
  14. "mistral:7b": {name: "mistral", tag: "7b"},
  15. "mistral:7b+Q4_0": {name: "mistral", tag: "7b", build: "Q4_0"},
  16. "mistral+KQED": {name: "mistral", build: "KQED"},
  17. "mistral.x-3:7b+Q4_0": {name: "mistral.x-3", tag: "7b", build: "Q4_0"},
  18. "mistral:7b+q4_0": {name: "mistral", tag: "7b", build: "Q4_0"},
  19. "llama2": {name: "llama2"},
  20. // invalid
  21. "mistral:7b+Q4_0:latest": {},
  22. "mi tral": {},
  23. "x/y/z/foo": {},
  24. "/0": {},
  25. "0/": {},
  26. }
  27. func TestRefParts(t *testing.T) {
  28. const wantNumParts = 5
  29. var ref Ref
  30. if len(ref.Parts()) != wantNumParts {
  31. t.Errorf("Parts() = %d; want %d", len(ref.Parts()), wantNumParts)
  32. }
  33. }
  34. func TestParseRef(t *testing.T) {
  35. for s, want := range testRefs {
  36. t.Run(s, func(t *testing.T) {
  37. got := ParseRef(s)
  38. if got != want {
  39. t.Errorf("ParseRef(%q) = %q; want %q", s, got, want)
  40. }
  41. // test round-trip
  42. if ParseRef(got.String()) != got {
  43. t.Errorf("String() = %q; want %q", got.String(), s)
  44. }
  45. })
  46. }
  47. }
  48. func TestRefFull(t *testing.T) {
  49. const empty = "!(MISSING DOMAIN)/!(MISSING NAMESPACE)/!(MISSING NAME):!(MISSING TAG)+!(MISSING BUILD)"
  50. cases := []struct {
  51. in string
  52. wantFull string
  53. }{
  54. {"", empty},
  55. {"example.com/mistral:7b+x", "!(MISSING DOMAIN)/example.com/mistral:7b+X"},
  56. {"example.com/mistral:7b+Q4_0", "!(MISSING DOMAIN)/example.com/mistral:7b+Q4_0"},
  57. {"example.com/x/mistral:latest", "example.com/x/mistral:latest+!(MISSING BUILD)"},
  58. {"example.com/x/mistral:latest+Q4_0", "example.com/x/mistral:latest+Q4_0"},
  59. {"mistral:7b+x", "!(MISSING DOMAIN)/!(MISSING NAMESPACE)/mistral:7b+X"},
  60. {"mistral:7b+q4_0", "!(MISSING DOMAIN)/!(MISSING NAMESPACE)/mistral:7b+Q4_0"},
  61. {"mistral:7b+Q4_0", "!(MISSING DOMAIN)/!(MISSING NAMESPACE)/mistral:7b+Q4_0"},
  62. {"mistral:latest", "!(MISSING DOMAIN)/!(MISSING NAMESPACE)/mistral:latest+!(MISSING BUILD)"},
  63. {"mistral", "!(MISSING DOMAIN)/!(MISSING NAMESPACE)/mistral:!(MISSING TAG)+!(MISSING BUILD)"},
  64. {"mistral:30b", "!(MISSING DOMAIN)/!(MISSING NAMESPACE)/mistral:30b+!(MISSING BUILD)"},
  65. }
  66. for _, tt := range cases {
  67. t.Run(tt.in, func(t *testing.T) {
  68. ref := ParseRef(tt.in)
  69. t.Logf("ParseRef(%q) = %#v", tt.in, ref)
  70. if g := ref.Full(); g != tt.wantFull {
  71. t.Errorf("Full(%q) = %q; want %q", tt.in, g, tt.wantFull)
  72. }
  73. })
  74. }
  75. }
  76. func TestParseRefAllocs(t *testing.T) {
  77. // test allocations
  78. allocs := testing.AllocsPerRun(1000, func() {
  79. ParseRef("example.com/mistral:7b+Q4_0")
  80. })
  81. if allocs > 0 {
  82. t.Errorf("ParseRef allocs = %v; want 0", allocs)
  83. }
  84. }
  85. func BenchmarkParseRef(b *testing.B) {
  86. b.ReportAllocs()
  87. var r Ref
  88. for i := 0; i < b.N; i++ {
  89. r = ParseRef("example.com/mistral:7b+Q4_0")
  90. }
  91. _ = r
  92. }
  93. func FuzzParseRef(f *testing.F) {
  94. f.Add("example.com/mistral:7b+Q4_0")
  95. f.Add("example.com/mistral:7b+q4_0")
  96. f.Add("example.com/mistral:7b+x")
  97. f.Add("x/y/z:8n+I")
  98. f.Fuzz(func(t *testing.T, s string) {
  99. r0 := ParseRef(s)
  100. if !r0.Valid() {
  101. if r0 != (Ref{}) {
  102. t.Errorf("expected invalid ref to be zero value; got %#v", r0)
  103. }
  104. t.Skipf("invalid ref: %q", s)
  105. }
  106. if !strings.EqualFold(r0.String(), s) {
  107. t.Errorf("String() did not round-trip with case insensitivity: %q\ngot = %q\nwant = %q", s, r0.String(), s)
  108. }
  109. r1 := ParseRef(r0.String())
  110. if r0 != r1 {
  111. t.Errorf("round-trip mismatch: %q != %q", r0, r1)
  112. }
  113. })
  114. }