Skip to content

Commit c7964fe

Browse files
author
Per Goncalves da Silva
committed
Refactor slice utils package structure
Signed-off-by: Per Goncalves da Silva <pegoncal@redhat.com>
1 parent 29547aa commit c7964fe

File tree

8 files changed

+282
-271
lines changed

8 files changed

+282
-271
lines changed

internal/catalogmetadata/filter/bundle_predicates.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@ package filter
22

33
import (
44
mmsemver "github.com/Masterminds/semver/v3"
5+
filterutils "github.com/operator-framework/operator-controller/internal/util/filter"
56

67
"github.com/operator-framework/operator-registry/alpha/declcfg"
78

89
"github.com/operator-framework/operator-controller/internal/bundleutil"
9-
slicesutil "github.com/operator-framework/operator-controller/internal/util/slices"
1010
)
1111

12-
func InMastermindsSemverRange(semverRange *mmsemver.Constraints) slicesutil.Predicate[declcfg.Bundle] {
12+
func InMastermindsSemverRange(semverRange *mmsemver.Constraints) filterutils.Predicate[declcfg.Bundle] {
1313
return func(b declcfg.Bundle) bool {
1414
bVersion, err := bundleutil.GetVersion(b)
1515
if err != nil {
@@ -27,7 +27,7 @@ func InMastermindsSemverRange(semverRange *mmsemver.Constraints) slicesutil.Pred
2727
}
2828
}
2929

30-
func InAnyChannel(channels ...declcfg.Channel) slicesutil.Predicate[declcfg.Bundle] {
30+
func InAnyChannel(channels ...declcfg.Channel) filterutils.Predicate[declcfg.Bundle] {
3131
return func(bundle declcfg.Bundle) bool {
3232
for _, ch := range channels {
3333
for _, entry := range ch.Entries {

internal/catalogmetadata/filter/successors.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,17 @@ package filter
22

33
import (
44
"fmt"
5+
filterutils "github.com/operator-framework/operator-controller/internal/util/filter"
56

67
mmsemver "github.com/Masterminds/semver/v3"
78
bsemver "github.com/blang/semver/v4"
89

910
"github.com/operator-framework/operator-registry/alpha/declcfg"
1011

1112
ocv1 "github.com/operator-framework/operator-controller/api/v1"
12-
slicesutil "github.com/operator-framework/operator-controller/internal/util/slices"
1313
)
1414

15-
func SuccessorsOf(installedBundle ocv1.BundleMetadata, channels ...declcfg.Channel) (slicesutil.Predicate[declcfg.Bundle], error) {
15+
func SuccessorsOf(installedBundle ocv1.BundleMetadata, channels ...declcfg.Channel) (filterutils.Predicate[declcfg.Bundle], error) {
1616
installedBundleVersion, err := mmsemver.NewVersion(installedBundle.Version)
1717
if err != nil {
1818
return nil, fmt.Errorf("parsing installed bundle %q version %q: %w", installedBundle.Name, installedBundle.Version, err)
@@ -29,13 +29,13 @@ func SuccessorsOf(installedBundle ocv1.BundleMetadata, channels ...declcfg.Chann
2929
}
3030

3131
// We need either successors or current version (no upgrade)
32-
return slicesutil.Or(
32+
return filterutils.Or(
3333
successorsPredicate,
3434
InMastermindsSemverRange(installedVersionConstraint),
3535
), nil
3636
}
3737

38-
func legacySuccessor(installedBundle ocv1.BundleMetadata, channels ...declcfg.Channel) (slicesutil.Predicate[declcfg.Bundle], error) {
38+
func legacySuccessor(installedBundle ocv1.BundleMetadata, channels ...declcfg.Channel) (filterutils.Predicate[declcfg.Bundle], error) {
3939
installedBundleVersion, err := bsemver.Parse(installedBundle.Version)
4040
if err != nil {
4141
return nil, fmt.Errorf("error parsing installed bundle version: %w", err)

internal/resolve/catalog.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package resolve
33
import (
44
"context"
55
"fmt"
6+
filterutils "github.com/operator-framework/operator-controller/internal/util/filter"
67
"slices"
78
"sort"
89
"strings"
@@ -76,7 +77,7 @@ func (r *CatalogResolver) Resolve(ctx context.Context, ext *ocv1.ClusterExtensio
7677

7778
var catStats []*catStat
7879

79-
resolvedBundles := []foundBundle{}
80+
var resolvedBundles []foundBundle
8081
var priorDeprecation *declcfg.Deprecation
8182

8283
listOptions := []client.ListOption{
@@ -97,7 +98,7 @@ func (r *CatalogResolver) Resolve(ctx context.Context, ext *ocv1.ClusterExtensio
9798
cs.PackageFound = true
9899
cs.TotalBundles = len(packageFBC.Bundles)
99100

100-
var predicates []slicesutil.Predicate[declcfg.Bundle]
101+
var predicates []filterutils.Predicate[declcfg.Bundle]
101102
if len(channels) > 0 {
102103
channelSet := sets.New(channels...)
103104
filteredChannels := slices.DeleteFunc(packageFBC.Channels, func(c declcfg.Channel) bool {
@@ -119,7 +120,7 @@ func (r *CatalogResolver) Resolve(ctx context.Context, ext *ocv1.ClusterExtensio
119120
}
120121

121122
// Apply the predicates to get the candidate bundles
122-
packageFBC.Bundles = slicesutil.RemoveInPlace(packageFBC.Bundles, slicesutil.And(predicates...))
123+
packageFBC.Bundles = slicesutil.RemoveInPlace(packageFBC.Bundles, filterutils.And(predicates...))
123124
cs.MatchedBundles = len(packageFBC.Bundles)
124125
if len(packageFBC.Bundles) == 0 {
125126
return nil

internal/util/slices/filter.go renamed to internal/util/filter/predicates.go

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,8 @@
1-
package slices
2-
3-
import (
4-
"slices"
5-
)
1+
package filter
62

73
// Predicate returns true if the object should be kept when filtering
84
type Predicate[T any] func(entity T) bool
95

10-
// Filter creates a new slice with all elements from s for which the test returns true
11-
func Filter[T any](s []T, test Predicate[T]) []T {
12-
out := make([]T, 0, len(s))
13-
for i := 0; i < len(s); i++ {
14-
if test(s[i]) {
15-
out = append(out, s[i])
16-
}
17-
}
18-
return slices.Clip(out)
19-
}
20-
21-
// RemoveInPlace removes all elements from s for which test returns true.
22-
// Elements between new length and original length are zeroed out.
23-
func RemoveInPlace[T any](s []T, test Predicate[T]) []T {
24-
return slices.DeleteFunc(s, Not(test))
25-
}
26-
276
func And[T any](predicates ...Predicate[T]) Predicate[T] {
287
return func(obj T) bool {
298
for _, predicate := range predicates {
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
package filter_test
2+
3+
import (
4+
"github.com/operator-framework/operator-controller/internal/util/filter"
5+
"github.com/stretchr/testify/require"
6+
"testing"
7+
)
8+
9+
func TestAnd(t *testing.T) {
10+
tests := []struct {
11+
name string
12+
predicates []filter.Predicate[int]
13+
input int
14+
want bool
15+
}{
16+
{
17+
name: "all true",
18+
predicates: []filter.Predicate[int]{
19+
func(i int) bool { return i > 0 },
20+
func(i int) bool { return i < 10 },
21+
},
22+
input: 5,
23+
want: true,
24+
},
25+
{
26+
name: "one false",
27+
predicates: []filter.Predicate[int]{
28+
func(i int) bool { return i > 0 },
29+
func(i int) bool { return i < 5 },
30+
},
31+
input: 5,
32+
want: false,
33+
},
34+
{
35+
name: "all false",
36+
predicates: []filter.Predicate[int]{
37+
func(i int) bool { return i > 10 },
38+
func(i int) bool { return i < 0 },
39+
},
40+
input: 5,
41+
want: false,
42+
},
43+
{
44+
name: "no predicates",
45+
predicates: []filter.Predicate[int]{},
46+
input: 5,
47+
want: true,
48+
},
49+
{
50+
name: "nil predicates",
51+
predicates: nil,
52+
input: 5,
53+
want: true,
54+
},
55+
}
56+
for _, tt := range tests {
57+
t.Run(tt.name, func(t *testing.T) {
58+
got := filter.And(tt.predicates...)(tt.input)
59+
require.Equal(t, tt.want, got, "And() = %v, want %v", got, tt.want)
60+
})
61+
}
62+
}
63+
64+
func TestOr(t *testing.T) {
65+
tests := []struct {
66+
name string
67+
predicates []filter.Predicate[int]
68+
input int
69+
want bool
70+
}{
71+
{
72+
name: "all true",
73+
predicates: []filter.Predicate[int]{
74+
func(i int) bool { return i > 0 },
75+
func(i int) bool { return i < 10 },
76+
},
77+
input: 5,
78+
want: true,
79+
},
80+
{
81+
name: "one false",
82+
predicates: []filter.Predicate[int]{
83+
func(i int) bool { return i > 0 },
84+
func(i int) bool { return i < 5 },
85+
},
86+
input: 5,
87+
want: true,
88+
},
89+
{
90+
name: "all false",
91+
predicates: []filter.Predicate[int]{
92+
func(i int) bool { return i > 10 },
93+
func(i int) bool { return i < 0 },
94+
},
95+
input: 5,
96+
want: false,
97+
},
98+
{
99+
name: "no predicates",
100+
predicates: []filter.Predicate[int]{},
101+
input: 5,
102+
want: false,
103+
},
104+
{
105+
name: "nil predicates",
106+
predicates: nil,
107+
input: 5,
108+
want: false,
109+
},
110+
}
111+
for _, tt := range tests {
112+
t.Run(tt.name, func(t *testing.T) {
113+
got := filter.Or(tt.predicates...)(tt.input)
114+
require.Equal(t, tt.want, got, "Or() = %v, want %v", got, tt.want)
115+
})
116+
}
117+
}
118+
119+
func TestNot(t *testing.T) {
120+
tests := []struct {
121+
name string
122+
predicate filter.Predicate[int]
123+
input int
124+
want bool
125+
}{
126+
{
127+
name: "predicate is true",
128+
predicate: func(i int) bool { return i > 0 },
129+
input: 5,
130+
want: false,
131+
},
132+
{
133+
name: "predicate is false",
134+
predicate: func(i int) bool { return i > 3 },
135+
input: 2,
136+
want: true,
137+
},
138+
}
139+
for _, tt := range tests {
140+
t.Run(tt.name, func(t *testing.T) {
141+
got := filter.Not(tt.predicate)(tt.input)
142+
require.Equal(t, tt.want, got, "Not() = %v, want %v", got, tt.want)
143+
})
144+
}
145+
}

0 commit comments

Comments
 (0)