diff --git a/.golangci.yaml b/.golangci.yaml index 9bb9786a8..9d6705bd3 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -19,8 +19,8 @@ linters: - nolintlint - nosprintfhostport - staticcheck - - tenv - unconvert + - usetesting - wastedassign - whitespace disable: diff --git a/api/client_test.go b/api/client_test.go index fe9a15899..2ceeec9cf 100644 --- a/api/client_test.go +++ b/api/client_test.go @@ -1,7 +1,6 @@ package api import ( - "context" "encoding/json" "fmt" "net/http" @@ -137,7 +136,7 @@ func TestClientStream(t *testing.T) { client := NewClient(&url.URL{Scheme: "http", Host: ts.Listener.Addr().String()}, http.DefaultClient) var receivedChunks []ChatResponse - err := client.stream(context.Background(), http.MethodPost, "/v1/chat", nil, func(chunk []byte) error { + err := client.stream(t.Context(), http.MethodPost, "/v1/chat", nil, func(chunk []byte) error { var resp ChatResponse if err := json.Unmarshal(chunk, &resp); err != nil { return fmt.Errorf("failed to unmarshal chunk: %w", err) @@ -223,7 +222,7 @@ func TestClientDo(t *testing.T) { ID string `json:"id"` Success bool `json:"success"` } - err := client.do(context.Background(), http.MethodPost, "/v1/messages", nil, &resp) + err := client.do(t.Context(), http.MethodPost, "/v1/messages", nil, &resp) if tc.wantErr != "" { if err == nil { diff --git a/benchmark/server_benchmark_test.go b/benchmark/server_benchmark_test.go index 672b8b173..4a3c46cda 100644 --- a/benchmark/server_benchmark_test.go +++ b/benchmark/server_benchmark_test.go @@ -78,7 +78,7 @@ func BenchmarkColdStart(b *testing.B) { for _, tt := range tests { b.Run(fmt.Sprintf("%s/cold/%s", m, tt.name), func(b *testing.B) { - ctx := context.Background() + ctx := b.Context() // Set number of tokens as our throughput metric b.SetBytes(int64(tt.maxTokens)) @@ -113,7 +113,7 @@ func BenchmarkWarmStart(b *testing.B) { for _, tt := range tests { b.Run(fmt.Sprintf("%s/warm/%s", m, tt.name), func(b *testing.B) { - ctx := context.Background() + ctx := b.Context() // Pre-warm the model warmup(client, m, tt.prompt, b) @@ -140,7 +140,7 @@ func setup(b *testing.B) *api.Client { if err != nil { b.Fatal(err) } - if _, err := client.Show(context.Background(), &api.ShowRequest{Model: modelName(b)}); err != nil { + if _, err := client.Show(b.Context(), &api.ShowRequest{Model: modelName(b)}); err != nil { b.Fatalf("Model unavailable: %v", err) } diff --git a/cmd/cmd_test.go b/cmd/cmd_test.go index 1cd6ddb40..eb2fb124e 100644 --- a/cmd/cmd_test.go +++ b/cmd/cmd_test.go @@ -2,7 +2,6 @@ package cmd import ( "bytes" - "context" "encoding/json" "io" "net/http" @@ -337,7 +336,7 @@ func TestDeleteHandler(t *testing.T) { t.Cleanup(mockServer.Close) cmd := &cobra.Command{} - cmd.SetContext(context.TODO()) + cmd.SetContext(t.Context()) if err := DeleteHandler(cmd, []string{"test-model"}); err != nil { t.Fatalf("DeleteHandler failed: %v", err) } @@ -399,11 +398,6 @@ func TestGetModelfileName(t *testing.T) { var expectedFilename string if tt.fileExists { - tempDir, err := os.MkdirTemp("", "modelfiledir") - defer os.RemoveAll(tempDir) - if err != nil { - t.Fatalf("temp modelfile dir creation failed: %v", err) - } var fn string if tt.modelfileName != "" { fn = tt.modelfileName @@ -411,7 +405,7 @@ func TestGetModelfileName(t *testing.T) { fn = "Modelfile" } - tempFile, err := os.CreateTemp(tempDir, fn) + tempFile, err := os.CreateTemp(t.TempDir(), fn) if err != nil { t.Fatalf("temp modelfile creation failed: %v", err) } @@ -530,7 +524,7 @@ func TestPushHandler(t *testing.T) { cmd := &cobra.Command{} cmd.Flags().Bool("insecure", false, "") - cmd.SetContext(context.TODO()) + cmd.SetContext(t.Context()) // Redirect stderr to capture progress output oldStderr := os.Stderr @@ -635,7 +629,7 @@ func TestListHandler(t *testing.T) { t.Setenv("OLLAMA_HOST", mockServer.URL) cmd := &cobra.Command{} - cmd.SetContext(context.TODO()) + cmd.SetContext(t.Context()) // Capture stdout oldStdout := os.Stdout @@ -730,7 +724,7 @@ func TestCreateHandler(t *testing.T) { })) t.Setenv("OLLAMA_HOST", mockServer.URL) t.Cleanup(mockServer.Close) - tempFile, err := os.CreateTemp("", "modelfile") + tempFile, err := os.CreateTemp(t.TempDir(), "modelfile") if err != nil { t.Fatal(err) } @@ -750,7 +744,7 @@ func TestCreateHandler(t *testing.T) { } cmd.Flags().Bool("insecure", false, "") - cmd.SetContext(context.TODO()) + cmd.SetContext(t.Context()) // Redirect stderr to capture progress output oldStderr := os.Stderr diff --git a/llm/server_test.go b/llm/server_test.go index 6c8f7590b..b6a8705e5 100644 --- a/llm/server_test.go +++ b/llm/server_test.go @@ -16,7 +16,7 @@ func TestLLMServerCompletionFormat(t *testing.T) { // of a mess, and but it's good enough, until we can refactoring the // Completion method to be more testable. - ctx, cancel := context.WithCancel(context.Background()) + ctx, cancel := context.WithCancel(t.Context()) s := &llmServer{ sem: semaphore.NewWeighted(1), // required to prevent nil panic } diff --git a/server/images_test.go b/server/images_test.go index 22e5b7e6a..363b298e1 100644 --- a/server/images_test.go +++ b/server/images_test.go @@ -3,6 +3,7 @@ package server import ( "bytes" "encoding/binary" + "errors" "os" "path/filepath" "strings" @@ -91,11 +92,7 @@ func createMockGGUFData(architecture string, vision bool) []byte { func TestModelCapabilities(t *testing.T) { // Create a temporary directory for test files - tempDir, err := os.MkdirTemp("", "model_capabilities_test") - if err != nil { - t.Fatalf("Failed to create temp directory: %v", err) - } - defer os.RemoveAll(tempDir) + tempDir := t.TempDir() // Create different types of mock model files completionModelPath := filepath.Join(tempDir, "model.bin") @@ -104,21 +101,13 @@ func TestModelCapabilities(t *testing.T) { // Create a simple model file for tests that don't depend on GGUF content simpleModelPath := filepath.Join(tempDir, "simple_model.bin") - err = os.WriteFile(completionModelPath, createMockGGUFData("llama", false), 0o644) - if err != nil { - t.Fatalf("Failed to create completion model file: %v", err) - } - err = os.WriteFile(visionModelPath, createMockGGUFData("llama", true), 0o644) - if err != nil { - t.Fatalf("Failed to create completion model file: %v", err) - } - err = os.WriteFile(embeddingModelPath, createMockGGUFData("bert", false), 0o644) - if err != nil { - t.Fatalf("Failed to create embedding model file: %v", err) - } - err = os.WriteFile(simpleModelPath, []byte("dummy model data"), 0o644) - if err != nil { - t.Fatalf("Failed to create simple model file: %v", err) + if err := errors.Join( + os.WriteFile(completionModelPath, createMockGGUFData("llama", false), 0o644), + os.WriteFile(visionModelPath, createMockGGUFData("llama", true), 0o644), + os.WriteFile(embeddingModelPath, createMockGGUFData("bert", false), 0o644), + os.WriteFile(simpleModelPath, []byte("dummy model data"), 0o644), + ); err != nil { + t.Fatalf("Failed to create model files: %v", err) } toolsInsertTemplate, err := template.Parse("{{ .prompt }}{{ if .tools }}{{ .tools }}{{ end }}{{ if .suffix }}{{ .suffix }}{{ end }}") @@ -236,27 +225,18 @@ func TestModelCapabilities(t *testing.T) { func TestModelCheckCapabilities(t *testing.T) { // Create a temporary directory for test files - tempDir, err := os.MkdirTemp("", "model_check_capabilities_test") - if err != nil { - t.Fatalf("Failed to create temp directory: %v", err) - } - defer os.RemoveAll(tempDir) + tempDir := t.TempDir() visionModelPath := filepath.Join(tempDir, "vision_model.bin") simpleModelPath := filepath.Join(tempDir, "model.bin") embeddingModelPath := filepath.Join(tempDir, "embedding_model.bin") - err = os.WriteFile(simpleModelPath, []byte("dummy model data"), 0o644) - if err != nil { - t.Fatalf("Failed to create simple model file: %v", err) - } - err = os.WriteFile(visionModelPath, createMockGGUFData("llama", true), 0o644) - if err != nil { - t.Fatalf("Failed to create vision model file: %v", err) - } - err = os.WriteFile(embeddingModelPath, createMockGGUFData("bert", false), 0o644) - if err != nil { - t.Fatalf("Failed to create embedding model file: %v", err) + if err := errors.Join( + os.WriteFile(simpleModelPath, []byte("dummy model data"), 0o644), + os.WriteFile(visionModelPath, createMockGGUFData("llama", true), 0o644), + os.WriteFile(embeddingModelPath, createMockGGUFData("bert", false), 0o644), + ); err != nil { + t.Fatalf("Failed to create model files: %v", err) } toolsInsertTemplate, err := template.Parse("{{ .prompt }}{{ if .tools }}{{ .tools }}{{ end }}{{ if .suffix }}{{ .suffix }}{{ end }}") diff --git a/server/internal/internal/backoff/backoff_test.go b/server/internal/internal/backoff/backoff_test.go index 11ace22a8..f474118f0 100644 --- a/server/internal/internal/backoff/backoff_test.go +++ b/server/internal/internal/backoff/backoff_test.go @@ -3,7 +3,6 @@ package backoff import ( - "context" "testing" "testing/synctest" "time" @@ -29,7 +28,7 @@ func TestLoopAllocs(t *testing.T) { } func BenchmarkLoop(b *testing.B) { - ctx := context.Background() + ctx := b.Context() synctest.Run(func() { for n := range Loop(ctx, 100*time.Millisecond) { if n == b.N { diff --git a/server/modelpath_test.go b/server/modelpath_test.go index 849e0fa73..96429f958 100644 --- a/server/modelpath_test.go +++ b/server/modelpath_test.go @@ -1,7 +1,6 @@ package server import ( - "os" "path/filepath" "testing" @@ -11,9 +10,7 @@ import ( func TestGetBlobsPath(t *testing.T) { // GetBlobsPath expects an actual directory to exist - dir, err := os.MkdirTemp("", "ollama-test") - require.NoError(t, err) - defer os.RemoveAll(dir) + tempDir := t.TempDir() tests := []struct { name string @@ -24,19 +21,19 @@ func TestGetBlobsPath(t *testing.T) { { "empty digest", "", - filepath.Join(dir, "blobs"), + filepath.Join(tempDir, "blobs"), nil, }, { "valid with colon", "sha256:456402914e838a953e0cf80caa6adbe75383d9e63584a964f504a7bbb8f7aad9", - filepath.Join(dir, "blobs", "sha256-456402914e838a953e0cf80caa6adbe75383d9e63584a964f504a7bbb8f7aad9"), + filepath.Join(tempDir, "blobs", "sha256-456402914e838a953e0cf80caa6adbe75383d9e63584a964f504a7bbb8f7aad9"), nil, }, { "valid with dash", "sha256-456402914e838a953e0cf80caa6adbe75383d9e63584a964f504a7bbb8f7aad9", - filepath.Join(dir, "blobs", "sha256-456402914e838a953e0cf80caa6adbe75383d9e63584a964f504a7bbb8f7aad9"), + filepath.Join(tempDir, "blobs", "sha256-456402914e838a953e0cf80caa6adbe75383d9e63584a964f504a7bbb8f7aad9"), nil, }, { @@ -60,7 +57,7 @@ func TestGetBlobsPath(t *testing.T) { } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { - t.Setenv("OLLAMA_MODELS", dir) + t.Setenv("OLLAMA_MODELS", tempDir) got, err := GetBlobsPath(tc.digest) diff --git a/server/prompt_test.go b/server/prompt_test.go index 62aec86a9..b81c01eef 100644 --- a/server/prompt_test.go +++ b/server/prompt_test.go @@ -2,7 +2,6 @@ package server import ( "bytes" - "context" "image" "image/png" "testing" @@ -318,7 +317,7 @@ func TestChatPrompt(t *testing.T) { t.Run(tt.name, func(t *testing.T) { model := tt.model opts := api.Options{Runner: api.Runner{NumCtx: tt.limit}} - prompt, images, err := chatPrompt(context.TODO(), &model, mockRunner{}.Tokenize, &opts, tt.msgs, nil) + prompt, images, err := chatPrompt(t.Context(), &model, mockRunner{}.Tokenize, &opts, tt.msgs, nil) if tt.error == nil && err != nil { t.Fatal(err) } else if tt.error != nil && err != tt.error { diff --git a/server/routes_generate_test.go b/server/routes_generate_test.go index 363d4057a..6bbf5b112 100644 --- a/server/routes_generate_test.go +++ b/server/routes_generate_test.go @@ -87,7 +87,7 @@ func TestGenerateChat(t *testing.T) { }, } - go s.sched.Run(context.TODO()) + go s.sched.Run(t.Context()) _, digest := createBinFile(t, ggml.KV{ "general.architecture": "llama", @@ -631,7 +631,7 @@ func TestGenerate(t *testing.T) { }, } - go s.sched.Run(context.TODO()) + go s.sched.Run(t.Context()) _, digest := createBinFile(t, ggml.KV{ "general.architecture": "llama", diff --git a/server/routes_test.go b/server/routes_test.go index 401e73c84..fd63b78be 100644 --- a/server/routes_test.go +++ b/server/routes_test.go @@ -527,7 +527,7 @@ func TestRoutes(t *testing.T) { for _, tc := range testCases { t.Run(tc.Name, func(t *testing.T) { u := httpSrv.URL + tc.Path - req, err := http.NewRequestWithContext(context.TODO(), tc.Method, u, nil) + req, err := http.NewRequestWithContext(t.Context(), tc.Method, u, nil) if err != nil { t.Fatalf("failed to create request: %v", err) } diff --git a/server/sched_test.go b/server/sched_test.go index 32ff6a8b9..01fb9a703 100644 --- a/server/sched_test.go +++ b/server/sched_test.go @@ -26,7 +26,7 @@ func TestMain(m *testing.M) { } func TestInitScheduler(t *testing.T) { - ctx, done := context.WithCancel(context.Background()) + ctx, done := context.WithCancel(t.Context()) defer done() s := InitScheduler(ctx) s.loadedMu.Lock() @@ -35,7 +35,7 @@ func TestInitScheduler(t *testing.T) { } func TestLoad(t *testing.T) { - ctx, done := context.WithTimeout(context.Background(), 20*time.Millisecond) + ctx, done := context.WithTimeout(t.Context(), 20*time.Millisecond) defer done() s := InitScheduler(ctx) var f *ggml.GGML // value not used in tests @@ -167,7 +167,7 @@ func getCpuFn() discover.GpuInfoList { } func TestRequestsSameModelSameRequest(t *testing.T) { - ctx, done := context.WithTimeout(context.Background(), 500*time.Millisecond) + ctx, done := context.WithTimeout(t.Context(), 500*time.Millisecond) defer done() s := InitScheduler(ctx) s.getGpuFn = getGpuFn @@ -210,7 +210,7 @@ func TestRequestsSameModelSameRequest(t *testing.T) { } func TestRequestsSimpleReloadSameModel(t *testing.T) { - ctx, done := context.WithTimeout(context.Background(), 500*time.Millisecond) + ctx, done := context.WithTimeout(t.Context(), 500*time.Millisecond) defer done() s := InitScheduler(ctx) s.getGpuFn = getGpuFn @@ -258,7 +258,7 @@ func TestRequestsSimpleReloadSameModel(t *testing.T) { } func TestRequestsMultipleLoadedModels(t *testing.T) { - ctx, done := context.WithTimeout(context.Background(), 500*time.Millisecond) + ctx, done := context.WithTimeout(t.Context(), 500*time.Millisecond) defer done() s := InitScheduler(ctx) s.getGpuFn = getGpuFn @@ -355,7 +355,7 @@ func TestRequestsMultipleLoadedModels(t *testing.T) { } func TestGetRunner(t *testing.T) { - ctx, done := context.WithTimeout(context.Background(), 3*time.Second) + ctx, done := context.WithTimeout(t.Context(), 3*time.Second) defer done() a := newScenarioRequest(t, ctx, "ollama-model-1a", 10, &api.Duration{Duration: 2 * time.Millisecond}) @@ -408,7 +408,7 @@ func TestGetRunner(t *testing.T) { } func TestExpireRunner(t *testing.T) { - ctx, done := context.WithTimeout(context.Background(), 20*time.Millisecond) + ctx, done := context.WithTimeout(t.Context(), 20*time.Millisecond) defer done() s := InitScheduler(ctx) req := &LlmRequest{ @@ -455,7 +455,7 @@ func TestExpireRunner(t *testing.T) { // TODO - add one scenario that triggers the bogus finished event with positive ref count func TestPrematureExpired(t *testing.T) { - ctx, done := context.WithTimeout(context.Background(), 500*time.Millisecond) + ctx, done := context.WithTimeout(t.Context(), 500*time.Millisecond) defer done() // Same model, same request @@ -502,7 +502,7 @@ func TestPrematureExpired(t *testing.T) { } func TestUseLoadedRunner(t *testing.T) { - ctx, done := context.WithTimeout(context.Background(), 100*time.Millisecond) + ctx, done := context.WithTimeout(t.Context(), 100*time.Millisecond) req := &LlmRequest{ ctx: ctx, opts: api.DefaultOptions(), @@ -529,7 +529,7 @@ func TestUseLoadedRunner(t *testing.T) { } func TestUpdateFreeSpace(t *testing.T) { - ctx, done := context.WithTimeout(context.Background(), 100*time.Millisecond) + ctx, done := context.WithTimeout(t.Context(), 100*time.Millisecond) defer done() gpus := discover.GpuInfoList{ { @@ -562,7 +562,7 @@ func TestUpdateFreeSpace(t *testing.T) { } func TestFilterGPUsWithoutLoadingModels(t *testing.T) { - ctx, done := context.WithTimeout(context.Background(), 100*time.Millisecond) + ctx, done := context.WithTimeout(t.Context(), 100*time.Millisecond) defer done() gpus := discover.GpuInfoList{ { @@ -596,7 +596,7 @@ func TestFilterGPUsWithoutLoadingModels(t *testing.T) { } func TestFindRunnerToUnload(t *testing.T) { - ctx, done := context.WithTimeout(context.Background(), 100*time.Millisecond) + ctx, done := context.WithTimeout(t.Context(), 100*time.Millisecond) defer done() r1 := &runnerRef{refCount: 1, sessionDuration: 1, numParallel: 1} @@ -616,7 +616,7 @@ func TestFindRunnerToUnload(t *testing.T) { } func TestNeedsReload(t *testing.T) { - ctx, done := context.WithTimeout(context.Background(), 100*time.Millisecond) + ctx, done := context.WithTimeout(t.Context(), 100*time.Millisecond) defer done() llm := &mockLlm{estimatedVRAMByGPU: map[string]uint64{}} @@ -663,7 +663,7 @@ func TestNeedsReload(t *testing.T) { } func TestUnloadAllRunners(t *testing.T) { - ctx, done := context.WithTimeout(context.Background(), 100*time.Millisecond) + ctx, done := context.WithTimeout(t.Context(), 100*time.Millisecond) defer done() llm1 := &mockLlm{estimatedVRAMByGPU: map[string]uint64{}} @@ -695,7 +695,7 @@ func TestUnload(t *testing.T) { } func TestAlreadyCanceled(t *testing.T) { - ctx, done := context.WithTimeout(context.Background(), 500*time.Millisecond) + ctx, done := context.WithTimeout(t.Context(), 500*time.Millisecond) defer done() dctx, done2 := context.WithCancel(ctx) done2() @@ -712,7 +712,7 @@ func TestAlreadyCanceled(t *testing.T) { } func TestHomogeneousGPUs(t *testing.T) { - ctx, done := context.WithTimeout(context.Background(), 100*time.Millisecond) + ctx, done := context.WithTimeout(t.Context(), 100*time.Millisecond) defer done() s := InitScheduler(ctx)