Skip to content

Commit cb3c16e

Browse files
committed
chore: refactor validation function
Signed-off-by: Alessio Pragliola <seth.pro@gmail.com>
1 parent cd6a614 commit cb3c16e

3 files changed

Lines changed: 34 additions & 80 deletions

File tree

catalog/internal/catalog/loader.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ func (l *Loader) updateSources(path string, config *sourceConfig) error {
195195
}
196196

197197
// Validate includedModels/excludedModels patterns early
198-
if err := ValidateSourceFilters(&source); err != nil {
198+
if err := ValidateSourceFilters(source.IncludedModels, source.ExcludedModels); err != nil {
199199
return fmt.Errorf("invalid source %s: %w", id, err)
200200
}
201201

catalog/internal/catalog/model_filter.go

Lines changed: 20 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,28 @@ func compilePatterns(field string, patterns []string) ([]*compiledPattern, error
6262
return compiled, nil
6363
}
6464

65+
// ValidateSourceFilters validates that the includedModels and excludedModels patterns
66+
// are valid (non-empty, compilable, non-conflicting). This is useful for early validation
67+
// at configuration load time without constructing the full ModelFilter.
68+
func ValidateSourceFilters(included, excluded []string) error {
69+
if err := detectConflictingPatterns(included, excluded); err != nil {
70+
return err
71+
}
72+
73+
if _, err := compilePatterns("includedModels", included); err != nil {
74+
return err
75+
}
76+
77+
if _, err := compilePatterns("excludedModels", excluded); err != nil {
78+
return err
79+
}
80+
81+
return nil
82+
}
83+
6584
// NewModelFilter builds a ModelFilter from the provided include/exclude pattern lists.
6685
func NewModelFilter(included, excluded []string) (*ModelFilter, error) {
67-
if err := detectConflictingPatterns(included, excluded); err != nil {
86+
if err := ValidateSourceFilters(included, excluded); err != nil {
6887
return nil, err
6988
}
7089

@@ -136,31 +155,6 @@ func (f *ModelFilter) Allows(name string) bool {
136155
return true
137156
}
138157

139-
// ValidateSourceFilters checks that the includedModels and excludedModels patterns
140-
// in a source are valid (non-empty, compilable, non-conflicting) without constructing
141-
// the full ModelFilter. This is useful for early validation at configuration load time.
142-
func ValidateSourceFilters(source *Source) error {
143-
if source == nil {
144-
return fmt.Errorf("source cannot be nil")
145-
}
146-
147-
// Check for conflicting patterns
148-
if err := detectConflictingPatterns(source.IncludedModels, source.ExcludedModels); err != nil {
149-
return fmt.Errorf("source %s: %w", source.Id, err)
150-
}
151-
152-
// Validate that all patterns compile successfully
153-
if _, err := compilePatterns("includedModels", source.IncludedModels); err != nil {
154-
return fmt.Errorf("source %s: %w", source.Id, err)
155-
}
156-
157-
if _, err := compilePatterns("excludedModels", source.ExcludedModels); err != nil {
158-
return fmt.Errorf("source %s: %w", source.Id, err)
159-
}
160-
161-
return nil
162-
}
163-
164158
// NewModelFilterFromSource composes a ModelFilter using the source-level configuration and any legacy additions.
165159
func NewModelFilterFromSource(source *Source, extraIncluded, extraExcluded []string) (*ModelFilter, error) {
166160
if source == nil {

catalog/internal/catalog/model_filter_test.go

Lines changed: 13 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -69,76 +69,36 @@ func TestModelFilterWithWildcardInMiddle(t *testing.T) {
6969
}
7070

7171
func TestValidateSourceFilters(t *testing.T) {
72-
t.Run("valid source with no filters", func(t *testing.T) {
73-
source := &Source{
74-
CatalogSource: apimodels.CatalogSource{
75-
Id: "test",
76-
Name: "Test source",
77-
},
78-
}
79-
err := ValidateSourceFilters(source)
72+
t.Run("no filters", func(t *testing.T) {
73+
err := ValidateSourceFilters(nil, nil)
8074
assert.NoError(t, err)
8175
})
8276

83-
t.Run("valid source with patterns", func(t *testing.T) {
84-
source := &Source{
85-
CatalogSource: apimodels.CatalogSource{
86-
Id: "test",
87-
Name: "Test source",
88-
IncludedModels: []string{"Granite/*", "Meta/*"},
89-
ExcludedModels: []string{"*-beta"},
90-
},
91-
}
92-
err := ValidateSourceFilters(source)
77+
t.Run("valid patterns", func(t *testing.T) {
78+
err := ValidateSourceFilters([]string{"Granite/*", "Meta/*"}, []string{"*-beta"})
9379
assert.NoError(t, err)
9480
})
9581

9682
t.Run("conflicting patterns", func(t *testing.T) {
97-
source := &Source{
98-
CatalogSource: apimodels.CatalogSource{
99-
Id: "test",
100-
Name: "Test source",
101-
IncludedModels: []string{"Granite/*"},
102-
ExcludedModels: []string{"Granite/*"},
103-
},
104-
}
105-
err := ValidateSourceFilters(source)
83+
err := ValidateSourceFilters([]string{"Granite/*"}, []string{"Granite/*"})
10684
require.Error(t, err)
107-
assert.Contains(t, err.Error(), "source test")
10885
assert.Contains(t, err.Error(), "Granite/*")
10986
})
11087

11188
t.Run("empty pattern in includedModels", func(t *testing.T) {
112-
source := &Source{
113-
CatalogSource: apimodels.CatalogSource{
114-
Id: "test",
115-
Name: "Test source",
116-
IncludedModels: []string{"Granite/*", ""},
117-
},
118-
}
119-
err := ValidateSourceFilters(source)
89+
err := ValidateSourceFilters([]string{"Granite/*", ""}, nil)
12090
require.Error(t, err)
121-
assert.Contains(t, err.Error(), "source test")
12291
assert.Contains(t, err.Error(), "pattern cannot be empty")
12392
})
12493

125-
t.Run("invalid regex pattern", func(t *testing.T) {
126-
// This shouldn't happen with our glob-to-regex conversion,
127-
// but validates the error path exists
128-
source := &Source{
129-
CatalogSource: apimodels.CatalogSource{
130-
Id: "test",
131-
Name: "Test source",
132-
IncludedModels: []string{"valid/*"},
133-
},
134-
}
135-
err := ValidateSourceFilters(source)
136-
assert.NoError(t, err) // Our conversion always produces valid regex
94+
t.Run("whitespace-only pattern", func(t *testing.T) {
95+
err := ValidateSourceFilters([]string{" "}, nil)
96+
require.Error(t, err)
97+
assert.Contains(t, err.Error(), "pattern cannot be empty")
13798
})
13899

139-
t.Run("nil source", func(t *testing.T) {
140-
err := ValidateSourceFilters(nil)
141-
require.Error(t, err)
142-
assert.Contains(t, err.Error(), "source cannot be nil")
100+
t.Run("valid glob patterns", func(t *testing.T) {
101+
err := ValidateSourceFilters([]string{"valid/*"}, nil)
102+
assert.NoError(t, err) // Our conversion always produces valid regex
143103
})
144104
}

0 commit comments

Comments
 (0)