@@ -4,19 +4,196 @@ import (
4
4
"context"
5
5
"encoding/json"
6
6
"errors"
7
+ "testing"
7
8
8
9
. "github.com/onsi/ginkgo/v2"
9
10
. "github.com/onsi/gomega"
10
11
"github.com/operator-framework/deppy/pkg/deppy"
11
12
"github.com/operator-framework/operator-registry/alpha/declcfg"
12
13
"github.com/operator-framework/operator-registry/alpha/property"
14
+ "github.com/stretchr/testify/assert"
15
+ "github.com/stretchr/testify/require"
13
16
14
17
"github.com/operator-framework/operator-controller/internal/catalogmetadata"
15
18
olmvariables "github.com/operator-framework/operator-controller/internal/resolution/variables"
16
19
"github.com/operator-framework/operator-controller/internal/resolution/variablesources"
17
20
testutil "github.com/operator-framework/operator-controller/test/util"
18
21
)
19
22
23
+ func TestMakeBundleVariables (t * testing.T ) {
24
+ t .Run ("valid dependencies" , func (t * testing.T ) {
25
+ const fakeCatalogName = "fake-catalog"
26
+ fakeChannel := catalogmetadata.Channel {Channel : declcfg.Channel {Name : "stable" }}
27
+ bundleSet := map [string ]* catalogmetadata.Bundle {
28
+ // Test package which we will be using as input into
29
+ // the testable function
30
+ "test-package.v1.0.0" : {
31
+ Bundle : declcfg.Bundle {
32
+ Name : "test-package.v1.0.0" ,
33
+ Package : "test-package" ,
34
+ Properties : []property.Property {
35
+ {Type : property .TypePackage , Value : json .RawMessage (`{"packageName": "test-package", "version": "1.0.0"}` )},
36
+ {Type : property .TypePackageRequired , Value : json .RawMessage (`{"packageName": "first-level-dependency", "versionRange": ">=1.0.0 <2.0.0"}` )},
37
+ },
38
+ },
39
+ CatalogName : fakeCatalogName ,
40
+ InChannels : []* catalogmetadata.Channel {& fakeChannel },
41
+ },
42
+
43
+ // First level dependency of test-package. Will be explicitly
44
+ // provided into the testable function as part of variable.
45
+ // This package must have at least one dependency with a version
46
+ // range so we can test that result has correct ordering:
47
+ // the testable function must give priority to newer versions.
48
+ "first-level-dependency.v1.0.0" : {
49
+ Bundle : declcfg.Bundle {
50
+ Name : "first-level-dependency.v1.0.0" ,
51
+ Package : "first-level-dependency" ,
52
+ Properties : []property.Property {
53
+ {Type : property .TypePackage , Value : json .RawMessage (`{"packageName": "first-level-dependency", "version": "1.0.0"}` )},
54
+ {Type : property .TypePackageRequired , Value : json .RawMessage (`{"packageName": "second-level-dependency", "versionRange": ">=1.0.0 <2.0.0"}` )},
55
+ },
56
+ },
57
+ CatalogName : fakeCatalogName ,
58
+ InChannels : []* catalogmetadata.Channel {& fakeChannel },
59
+ },
60
+
61
+ // Second level dependency that matches requirements of the first level dependency.
62
+ "second-level-dependency.v1.0.0" : {
63
+ Bundle : declcfg.Bundle {
64
+ Name : "second-level-dependency.v1.0.0" ,
65
+ Package : "second-level-dependency" ,
66
+ Properties : []property.Property {
67
+ {Type : property .TypePackage , Value : json .RawMessage (`{"packageName": "second-level-dependency", "version": "1.0.0"}` )},
68
+ },
69
+ },
70
+ CatalogName : fakeCatalogName ,
71
+ InChannels : []* catalogmetadata.Channel {& fakeChannel },
72
+ },
73
+
74
+ // Second level dependency that matches requirements of the first level dependency.
75
+ "second-level-dependency.v1.0.1" : {
76
+ Bundle : declcfg.Bundle {
77
+ Name : "second-level-dependency.v1.0.1" ,
78
+ Package : "second-level-dependency" ,
79
+ Properties : []property.Property {
80
+ {Type : property .TypePackage , Value : json .RawMessage (`{"packageName": "second-level-dependency", "version": "1.0.1"}` )},
81
+ },
82
+ },
83
+ CatalogName : fakeCatalogName ,
84
+ InChannels : []* catalogmetadata.Channel {& fakeChannel },
85
+ },
86
+
87
+ // Second level dependency that does not match requirements of the first level dependency.
88
+ "second-level-dependency.v2.0.0" : {
89
+ Bundle : declcfg.Bundle {
90
+ Name : "second-level-dependency.v2.0.0" ,
91
+ Package : "second-level-dependency" ,
92
+ Properties : []property.Property {
93
+ {Type : property .TypePackage , Value : json .RawMessage (`{"packageName": "second-level-dependency", "version": "2.0.0"}` )},
94
+ },
95
+ },
96
+ CatalogName : fakeCatalogName ,
97
+ InChannels : []* catalogmetadata.Channel {& fakeChannel },
98
+ },
99
+
100
+ // Package that is in a our fake catalog, but is not involved
101
+ // in this dependency chain. We need this to make sure that
102
+ // the testable function filters out unrelated bundles.
103
+ "uninvolved-package.v1.0.0" : {
104
+ Bundle : declcfg.Bundle {
105
+ Name : "uninvolved-package.v1.0.0" ,
106
+ Package : "uninvolved-package" ,
107
+ Properties : []property.Property {
108
+ {Type : property .TypePackage , Value : json .RawMessage (`{"packageName": "uninvolved-package", "version": "1.0.0"}` )},
109
+ },
110
+ },
111
+ CatalogName : fakeCatalogName ,
112
+ InChannels : []* catalogmetadata.Channel {& fakeChannel },
113
+ },
114
+ }
115
+
116
+ allBundles := make ([]* catalogmetadata.Bundle , 0 , len (bundleSet ))
117
+ for _ , bundle := range bundleSet {
118
+ allBundles = append (allBundles , bundle )
119
+ }
120
+ requiredPackages := []* olmvariables.RequiredPackageVariable {
121
+ olmvariables .NewRequiredPackageVariable ("test-package" , []* catalogmetadata.Bundle {
122
+ bundleSet ["first-level-dependency.v1.0.0" ],
123
+ }),
124
+ }
125
+ installedPackages := []* olmvariables.InstalledPackageVariable {
126
+ olmvariables .NewInstalledPackageVariable ("test-package" , []* catalogmetadata.Bundle {
127
+ bundleSet ["first-level-dependency.v1.0.0" ],
128
+ }),
129
+ }
130
+
131
+ bundles , err := variablesources .MakeBundleVariables (allBundles , requiredPackages , installedPackages )
132
+ require .NoError (t , err )
133
+ require .Len (t , bundles , 3 )
134
+
135
+ // Each dependency must have a variable.
136
+ // Dependencies from the same package must be sorted by version
137
+ // with higher versions first.
138
+ expectedIDs := []deppy.Identifier {
139
+ "fake-catalog-first-level-dependency-first-level-dependency.v1.0.0" ,
140
+ "fake-catalog-second-level-dependency-second-level-dependency.v1.0.1" ,
141
+ "fake-catalog-second-level-dependency-second-level-dependency.v1.0.0" ,
142
+ }
143
+ actualIDs := collectVariableIDs (bundles )
144
+ assert .Equal (t , expectedIDs , actualIDs )
145
+
146
+ // Bundle variables must have correct dependencies
147
+ bundle := findVariableWithName (bundles , "first-level-dependency.v1.0.0" )
148
+ dependencies := bundle .Dependencies ()
149
+ require .Len (t , dependencies , 2 )
150
+ assert .Equal (t , bundleSet ["second-level-dependency.v1.0.1" ], dependencies [0 ])
151
+ assert .Equal (t , bundleSet ["second-level-dependency.v1.0.0" ], dependencies [1 ])
152
+
153
+ bundle = findVariableWithName (bundles , "second-level-dependency.v1.0.1" )
154
+ dependencies = bundle .Dependencies ()
155
+ require .Len (t , dependencies , 0 )
156
+
157
+ bundle = findVariableWithName (bundles , "second-level-dependency.v1.0.0" )
158
+ dependencies = bundle .Dependencies ()
159
+ require .Len (t , dependencies , 0 )
160
+ })
161
+
162
+ t .Run ("non existent dependencies" , func (t * testing.T ) {
163
+ const fakeCatalogName = "fake-catalog"
164
+ fakeChannel := catalogmetadata.Channel {Channel : declcfg.Channel {Name : "stable" }}
165
+ bundleSet := map [string ]* catalogmetadata.Bundle {
166
+ "test-package.v1.0.0" : {
167
+ Bundle : declcfg.Bundle {
168
+ Name : "test-package.v1.0.0" ,
169
+ Package : "test-package" ,
170
+ Properties : []property.Property {
171
+ {Type : property .TypePackage , Value : json .RawMessage (`{"packageName": "test-package", "version": "1.0.0"}` )},
172
+ {Type : property .TypePackageRequired , Value : json .RawMessage (`{"packageName": "first-level-dependency", "versionRange": ">=1.0.0 <2.0.0"}` )},
173
+ },
174
+ },
175
+ CatalogName : fakeCatalogName ,
176
+ InChannels : []* catalogmetadata.Channel {& fakeChannel },
177
+ },
178
+ }
179
+
180
+ allBundles := make ([]* catalogmetadata.Bundle , 0 , len (bundleSet ))
181
+ for _ , bundle := range bundleSet {
182
+ allBundles = append (allBundles , bundle )
183
+ }
184
+ requiredPackages := []* olmvariables.RequiredPackageVariable {
185
+ olmvariables .NewRequiredPackageVariable ("test-package" , []* catalogmetadata.Bundle {
186
+ bundleSet ["test-package.v1.0.0" ],
187
+ }),
188
+ }
189
+ installedPackages := []* olmvariables.InstalledPackageVariable {}
190
+
191
+ bundles , err := variablesources .MakeBundleVariables (allBundles , requiredPackages , installedPackages )
192
+ assert .ErrorContains (t , err , "could not determine dependencies for bundle with id 'fake-catalog-test-package-test-package.v1.0.0'" )
193
+ assert .Nil (t , bundles )
194
+ })
195
+ }
196
+
20
197
var _ = Describe ("BundlesAndDepsVariableSource" , func () {
21
198
var (
22
199
bdvs * variablesources.BundlesAndDepsVariableSource
@@ -374,7 +551,7 @@ var _ = Describe("BundlesAndDepsVariableSource", func() {
374
551
)
375
552
_ , err := bdvs .GetVariables (context .TODO ())
376
553
Expect (err ).To (HaveOccurred ())
377
- Expect (err .Error ()).To (ContainSubstring ("could not determine dependencies for bundle with id 'fake-catalog-test-package-bundle-2': could not find package dependencies for bundle 'bundle-2' " ))
554
+ Expect (err .Error ()).To (ContainSubstring ("could not determine dependencies for bundle with id 'fake-catalog-test-package-bundle-2': could not find package dependencies for bundle" ))
378
555
})
379
556
380
557
It ("should return error if an inner variable source returns an error" , func () {
0 commit comments