@@ -0,0 +1,210 @@
6+ "github.com/charmbracelet/catwalk/pkg/catwalk"
7+ "github.com/charmbracelet/crush/internal/config"
8+ "github.com/stretchr/testify/require"
11+func TestParseModelStr(t *testing.T) {
15+ expectedFilter string
16+ expectedModelID string
17+ setupProviders func() map[string]config.ProviderConfig
20+ name: "simple model with no slashes",
23+ expectedModelID: "gpt-4o",
24+ setupProviders: setupMockProviders,
27+ name: "valid provider and model",
28+ modelStr: "openai/gpt-4o",
29+ expectedFilter: "openai",
30+ expectedModelID: "gpt-4o",
31+ setupProviders: setupMockProviders,
34+ name: "model with multiple slashes and first part is invalid provider",
35+ modelStr: "moonshot/kimi-k2",
37+ expectedModelID: "moonshot/kimi-k2",
38+ setupProviders: setupMockProviders,
41+ name: "full path with valid provider and model with slashes",
42+ modelStr: "synthetic/moonshot/kimi-k2",
43+ expectedFilter: "synthetic",
44+ expectedModelID: "moonshot/kimi-k2",
45+ setupProviders: setupMockProvidersWithSlashes,
48+ name: "empty model string",
52+ setupProviders: setupMockProviders,
55+ name: "model with trailing slash but valid provider",
57+ expectedFilter: "openai",
59+ setupProviders: setupMockProviders,
63+ for _, tt := range tests {
64+ t.Run(tt.name, func(t *testing.T) {
65+ providers := tt.setupProviders()
66+ filter, modelID := parseModelStr(providers, tt.modelStr)
68+ require.Equal(t, tt.expectedFilter, filter, "provider filter mismatch")
69+ require.Equal(t, tt.expectedModelID, modelID, "model ID mismatch")
74+func setupMockProviders() map[string]config.ProviderConfig {
75+ return map[string]config.ProviderConfig{
79+ Models: []catwalk.Model{{ID: "gpt-4o"}, {ID: "gpt-4o-mini"}},
84+ Models: []catwalk.Model{{ID: "claude-3-sonnet"}, {ID: "claude-3-opus"}},
89+func setupMockProvidersWithSlashes() map[string]config.ProviderConfig {
90+ return map[string]config.ProviderConfig{
94+ Models: []catwalk.Model{
95+ {ID: "moonshot/kimi-k2"},
96+ {ID: "deepseek/deepseek-chat"},
102+ Models: []catwalk.Model{{ID: "gpt-4o"}},
107+func TestFindModels(t *testing.T) {
111+ expectedProvider string
112+ expectedModelID string
114+ errorContains string
115+ setupProviders func() map[string]config.ProviderConfig
118+ name: "simple model found in one provider",
120+ expectedProvider: "openai",
121+ expectedModelID: "gpt-4o",
123+ setupProviders: setupMockProviders,
126+ name: "model with slashes in ID",
127+ modelStr: "moonshot/kimi-k2",
128+ expectedProvider: "synthetic",
129+ expectedModelID: "moonshot/kimi-k2",
131+ setupProviders: setupMockProvidersWithSlashes,
134+ name: "provider and model with slashes in ID",
135+ modelStr: "synthetic/moonshot/kimi-k2",
136+ expectedProvider: "synthetic",
137+ expectedModelID: "moonshot/kimi-k2",
139+ setupProviders: setupMockProvidersWithSlashes,
142+ name: "model not found",
143+ modelStr: "nonexistent-model",
145+ errorContains: "not found",
146+ setupProviders: setupMockProviders,
149+ name: "invalid provider specified",
150+ modelStr: "nonexistent-provider/gpt-4o",
152+ errorContains: "provider",
153+ setupProviders: setupMockProviders,
156+ name: "model found in multiple providers without provider filter",
157+ modelStr: "shared-model",
159+ errorContains: "multiple providers",
160+ setupProviders: func() map[string]config.ProviderConfig {
161+ return map[string]config.ProviderConfig{
164+ Models: []catwalk.Model{{ID: "shared-model"}},
168+ Models: []catwalk.Model{{ID: "shared-model"}},
174+ name: "empty model string",
177+ errorContains: "not found",
178+ setupProviders: setupMockProviders,
182+ for _, tt := range tests {
183+ t.Run(tt.name, func(t *testing.T) {
184+ providers := tt.setupProviders()
186+ // Use findModels with the model as "large" and empty "small".
187+ matches, _, err := findModels(providers, tt.modelStr, "")
190+ require.Contains(t, err.Error(), tt.errorContains)
192+ require.NoError(t, err)
197+ // Validate the matches.
198+ match, err := validateMatches(matches, tt.modelStr, "large")
201+ require.Error(t, err)
202+ require.Contains(t, err.Error(), tt.errorContains)
204+ require.NoError(t, err)
205+ require.Equal(t, tt.expectedProvider, match.provider)
206+ require.Equal(t, tt.expectedModelID, match.modelID)