diff --git a/core/ai.go b/core/ai.go index a0785c2ba..bf56f4960 100644 --- a/core/ai.go +++ b/core/ai.go @@ -106,7 +106,7 @@ func ParseAIModelConfigs(config string) ([]AIModelConfig, error) { pipeline := parts[0] modelID := parts[1] - warm, err := strconv.ParseBool(parts[3]) + warm, err := strconv.ParseBool(parts[2]) if err != nil { return nil, err } diff --git a/core/ai_test.go b/core/ai_test.go index bbdbb6a25..8a053e281 100644 --- a/core/ai_test.go +++ b/core/ai_test.go @@ -3,6 +3,8 @@ package core import ( "context" "fmt" + "os" + "path/filepath" "strconv" "sync" "testing" @@ -697,3 +699,85 @@ func (s *StubAIWorkerServer) Send(n *net.NotifyAIJob) error { return nil } + +// Utility function to create a temporary file for file-based configurations +func mockFile(t *testing.T, content string) string { + tmpDir := t.TempDir() + filePath := filepath.Join(tmpDir, "config.json") + err := os.WriteFile(filePath, []byte(content), 0644) + if err != nil { + t.Fatalf("Failed to write mock file: %v", err) + } + return filePath +} + +func TestParseAIModelConfigs(t *testing.T) { + tests := []struct { + name string + input string + fileData string + expected []AIModelConfig + expectedErr string + }{{ + name: "Valid Inline String Config", + input: "pipeline1:model1:true,pipeline2:model2:false", + expected: []AIModelConfig{ + {Pipeline: "pipeline1", ModelID: "model1", Warm: true}, + {Pipeline: "pipeline2", ModelID: "model2", Warm: false}, + }, + }, + { + name: "Invalid Inline String Config Missing Parts", + input: "pipeline1:model1", + expectedErr: "invalid AI model config expected ::", + }, + { + name: "Valid File-Based Config", + fileData: `[{"pipeline": "pipeline1", "model_id": "model1", "warm": true}, {"pipeline": "pipeline2", "model_id": "model2", "warm": false}]`, + expected: []AIModelConfig{ + {Pipeline: "pipeline1", ModelID: "model1", Warm: true}, + {Pipeline: "pipeline2", ModelID: "model2", Warm: false}, + }, + }, + { + name: "Invalid File Config Corrupted JSON", + fileData: `[{"pipeline": "pipeline1", "model_id": "model1", "warm": true`, + expectedErr: "unexpected end of JSON input", + }, + { + name: "File Not Found", + input: "nonexistent.json", + expectedErr: "invalid AI model config expected ::", + }, + { + name: "Invalid Boolean Value in Inline String Config", + input: "pipeline1:model1:invalid_bool", + expectedErr: "strconv.ParseBool: parsing \"invalid_bool\": invalid syntax", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + var result []AIModelConfig + var err error + + // Mock file handling if fileData is provided + if tt.fileData != "" { + mockFilePath := mockFile(t, tt.fileData) + result, err = ParseAIModelConfigs(mockFilePath) + } else { + result, err = ParseAIModelConfigs(tt.input) + } + + // Verify error messages match + assert := assert.New(t) + if tt.expectedErr != "" { + assert.Equal(err.Error(), tt.expectedErr) + assert.Empty(result, err) + } else { + assert.Empty(err) + assert.Equal(tt.expected, result) + } + }) + } +}