mirror of
https://github.com/ollama/ollama.git
synced 2026-09-21 13:38:14 -05:00
tests: fix metadata deletion test flake (#18493)
Test both publication/deletion orderings directly instead of polling for a short-lived temporary file with a machine-dependent timeout.
This commit is contained in:
@@ -11,9 +11,7 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
"runtime"
|
"runtime"
|
||||||
"slices"
|
"slices"
|
||||||
"strings"
|
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
|
||||||
@@ -590,57 +588,27 @@ func TestGGUFMetadataRemovedForMissingBlob(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestGGUFMetadataNotPublishedAfterDelete(t *testing.T) {
|
func TestGGUFMetadataNotPublishedAfterDelete(t *testing.T) {
|
||||||
gin.SetMode(gin.TestMode)
|
|
||||||
t.Setenv("OLLAMA_MODELS", t.TempDir())
|
t.Setenv("OLLAMA_MODELS", t.TempDir())
|
||||||
|
|
||||||
_, digest := createBinFile(t, gguftest.KV{
|
// Deletion and publication can finish in either order. The deletion tests
|
||||||
"general.architecture": "llama",
|
// above cover metadata that already exists; put deletion first here to
|
||||||
"general.description": strings.Repeat("x", 16<<20),
|
// deterministically cover the writer's post-publication blob check.
|
||||||
}, nil)
|
_, digest := createBinFile(t, gguftest.KV{"general.architecture": "llama"}, nil)
|
||||||
createModelFromBlob(t, "delete-during-load", digest, "")
|
blob, err := manifest.BlobsPath(digest)
|
||||||
|
if err != nil {
|
||||||
loaded := make(chan error, 1)
|
t.Fatal(err)
|
||||||
go func() {
|
|
||||||
_, err := GetModel("delete-during-load")
|
|
||||||
loaded <- err
|
|
||||||
}()
|
|
||||||
|
|
||||||
deadline := time.Now().Add(5 * time.Second)
|
|
||||||
for {
|
|
||||||
entries, err := os.ReadDir(ggufMetadataDir())
|
|
||||||
if err != nil && !errors.Is(err, os.ErrNotExist) {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if slices.ContainsFunc(entries, func(entry os.DirEntry) bool {
|
|
||||||
return strings.HasPrefix(entry.Name(), ".gguf-metadata-")
|
|
||||||
}) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
select {
|
|
||||||
case err := <-loaded:
|
|
||||||
t.Fatalf("GetModel completed before its metadata write could overlap deletion: %v", err)
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
if time.Now().After(deadline) {
|
|
||||||
t.Fatal("timed out waiting for metadata write")
|
|
||||||
}
|
|
||||||
runtime.Gosched()
|
|
||||||
}
|
}
|
||||||
|
if err := os.Remove(blob); err != nil {
|
||||||
deleteModelNamed(t, "delete-during-load")
|
t.Fatal(err)
|
||||||
select {
|
|
||||||
case err := <-loaded:
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("GetModel: %v", err)
|
|
||||||
}
|
|
||||||
case <-time.After(5 * time.Second):
|
|
||||||
t.Fatal("timed out waiting for GetModel")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
path, err := ggufMetadataPath(digest)
|
path, err := ggufMetadataPath(digest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
writeGGUFMetadata(path, blob, ggufMetadata{KV: map[string]any{
|
||||||
|
"general.architecture": "llama",
|
||||||
|
}})
|
||||||
if _, err := os.Stat(path); !errors.Is(err, os.ErrNotExist) {
|
if _, err := os.Stat(path); !errors.Is(err, os.ErrNotExist) {
|
||||||
t.Fatalf("metadata published after model deletion: %v", err)
|
t.Fatalf("metadata published after model deletion: %v", err)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user