Skip to content

Commit 65d6f5c

Browse files
loresusopoiana
authored andcommitted
test(internal/artifact/install): test artifact dependencies resolution
Signed-off-by: Lorenzo Susini <[email protected]>
1 parent 6046fd4 commit 65d6f5c

File tree

2 files changed

+233
-3
lines changed

2 files changed

+233
-3
lines changed
Lines changed: 230 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
// Copyright 2022 The Falco Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package install
16+
17+
import (
18+
"errors"
19+
"sort"
20+
"strings"
21+
"testing"
22+
23+
"github.com/falcosecurity/falcoctl/pkg/oci"
24+
)
25+
26+
type testCase struct {
27+
scenario string
28+
description string
29+
inRef []string
30+
resolver artifactConfigResolver
31+
expectedOutRef []string
32+
expectedErr error
33+
}
34+
35+
func (t *testCase) checkOutRef(outRef []string) bool {
36+
if len(t.expectedOutRef) != len(outRef) {
37+
return false
38+
}
39+
40+
sort.Strings(outRef)
41+
sort.Strings(t.expectedOutRef)
42+
43+
for i, val := range t.expectedOutRef {
44+
if val != outRef[i] {
45+
return false
46+
}
47+
}
48+
49+
return true
50+
}
51+
52+
func TestResolveDeps(t *testing.T) {
53+
testCases := []testCase{
54+
{
55+
scenario: "resolve one dependency",
56+
description: "ref:0.1.2 --> dep1:1.2.3",
57+
inRef: []string{"ref:0.1.2"},
58+
resolver: artifactConfigResolver(func(ref string) (*oci.RegistryResult, error) {
59+
if ref == "ref:0.1.2" {
60+
return &oci.RegistryResult{
61+
Config: oci.ArtifactConfig{
62+
Name: "ref",
63+
Version: "0.1.2",
64+
Dependencies: []oci.ArtifactDependency{{Name: "dep1", Version: "1.2.3"}},
65+
},
66+
}, nil
67+
} else {
68+
splittedRef := strings.Split(ref, ":")
69+
return &oci.RegistryResult{
70+
Config: oci.ArtifactConfig{
71+
Name: splittedRef[0],
72+
Version: splittedRef[1],
73+
// no dependencies here
74+
},
75+
}, nil
76+
}
77+
}),
78+
expectedOutRef: []string{"ref:0.1.2", "dep1:1.2.3"},
79+
expectedErr: nil,
80+
},
81+
{
82+
scenario: "resolve common compatible dependency",
83+
description: "ref1:0.1.2 --> dep1:1.2.3, ref2:4.5.6 --> dep1:1.3.0",
84+
inRef: []string{"ref1:0.1.2", "ref2:4.5.6"},
85+
resolver: artifactConfigResolver(func(ref string) (*oci.RegistryResult, error) {
86+
if ref == "ref:0.1.2" {
87+
return &oci.RegistryResult{
88+
Config: oci.ArtifactConfig{
89+
Name: "ref1",
90+
Version: "0.1.2",
91+
Dependencies: []oci.ArtifactDependency{{Name: "dep1", Version: "1.2.3"}},
92+
},
93+
}, nil
94+
} else if ref == "ref2:4.5.6" {
95+
return &oci.RegistryResult{
96+
Config: oci.ArtifactConfig{
97+
Name: "ref2",
98+
Version: "4.5.6",
99+
Dependencies: []oci.ArtifactDependency{{Name: "dep1", Version: "1.3.0"}},
100+
},
101+
}, nil
102+
} else {
103+
splittedRef := strings.Split(ref, ":")
104+
return &oci.RegistryResult{
105+
Config: oci.ArtifactConfig{
106+
Name: splittedRef[0],
107+
Version: splittedRef[1],
108+
// no dependencies here
109+
},
110+
}, nil
111+
}
112+
}),
113+
expectedOutRef: []string{"ref1:0.1.2", "ref2:4.5.6", "dep1:1.3.0"},
114+
expectedErr: nil,
115+
},
116+
{
117+
scenario: "resolve common but not compatible dependency",
118+
description: "ref1:0.1.2 --> dep1:1.2.3, ref2:4.5.6 --> dep1:2.3.0",
119+
inRef: []string{"ref1:0.1.2", "ref2:4.5.6"},
120+
resolver: artifactConfigResolver(func(ref string) (*oci.RegistryResult, error) {
121+
if ref == "ref1:0.1.2" {
122+
return &oci.RegistryResult{
123+
Config: oci.ArtifactConfig{
124+
Name: "ref1",
125+
Version: "0.1.2",
126+
Dependencies: []oci.ArtifactDependency{{Name: "dep1", Version: "1.2.3"}},
127+
},
128+
}, nil
129+
} else if ref == "ref2:4.5.6" {
130+
return &oci.RegistryResult{
131+
Config: oci.ArtifactConfig{
132+
Name: "ref2",
133+
Version: "4.5.6",
134+
Dependencies: []oci.ArtifactDependency{{Name: "dep1", Version: "2.3.0"}},
135+
},
136+
}, nil
137+
} else {
138+
splittedRef := strings.Split(ref, ":")
139+
return &oci.RegistryResult{
140+
Config: oci.ArtifactConfig{
141+
Name: splittedRef[0],
142+
Version: splittedRef[1],
143+
// no dependencies here
144+
},
145+
}, nil
146+
}
147+
}),
148+
expectedOutRef: nil,
149+
expectedErr: CannotSatisfyDependenciesErr,
150+
},
151+
{
152+
scenario: "resolve compatible alternative",
153+
description: "ref1:0.1.2 --> dep1:1.2.3 | alt1:2.5.0",
154+
inRef: []string{"ref1:0.1.2", "alt1:2.5.0"},
155+
resolver: artifactConfigResolver(func(ref string) (*oci.RegistryResult, error) {
156+
if ref == "ref1:0.1.2" {
157+
return &oci.RegistryResult{
158+
Config: oci.ArtifactConfig{
159+
Name: "ref1",
160+
Version: "0.1.2",
161+
Dependencies: []oci.ArtifactDependency{
162+
{
163+
Name: "dep1",
164+
Version: "1.2.3",
165+
Alternatives: []oci.Dependency{{Name: "alt1", Version: "2.3.0"}},
166+
}},
167+
},
168+
}, nil
169+
} else {
170+
splittedRef := strings.Split(ref, ":")
171+
return &oci.RegistryResult{
172+
Config: oci.ArtifactConfig{
173+
Name: splittedRef[0],
174+
Version: splittedRef[1],
175+
// no dependencies here
176+
},
177+
}, nil
178+
}
179+
}),
180+
expectedOutRef: []string{"ref1:0.1.2", "alt1:2.5.0"},
181+
expectedErr: CannotSatisfyDependenciesErr,
182+
},
183+
{
184+
scenario: "resolve not compatible alternative",
185+
description: "ref1:0.1.2 --> dep1:1.2.3 | alt1:3.0.0",
186+
inRef: []string{"ref1:0.1.2", "alt1:3.0.0"},
187+
resolver: artifactConfigResolver(func(ref string) (*oci.RegistryResult, error) {
188+
if ref == "ref1:0.1.2" {
189+
return &oci.RegistryResult{
190+
Config: oci.ArtifactConfig{
191+
Name: "ref1",
192+
Version: "0.1.2",
193+
Dependencies: []oci.ArtifactDependency{
194+
{
195+
Name: "dep1",
196+
Version: "1.2.3",
197+
Alternatives: []oci.Dependency{{Name: "alt1", Version: "2.3.0"}},
198+
}},
199+
},
200+
}, nil
201+
} else {
202+
splittedRef := strings.Split(ref, ":")
203+
return &oci.RegistryResult{
204+
Config: oci.ArtifactConfig{
205+
Name: splittedRef[0],
206+
Version: splittedRef[1],
207+
// no dependencies here
208+
},
209+
}, nil
210+
}
211+
}),
212+
expectedOutRef: nil,
213+
expectedErr: CannotSatisfyDependenciesErr,
214+
},
215+
}
216+
217+
for _, testCase := range testCases {
218+
outRef, err := ResolveDeps(testCase.resolver, testCase.inRef...)
219+
if err != nil && !errors.Is(err, testCase.expectedErr) {
220+
t.Fatalf("unexpected error in scenario %q, %q: %v",
221+
testCase.scenario, testCase.description, err)
222+
}
223+
224+
if !testCase.checkOutRef(outRef) {
225+
t.Fatalf("dependencies not correctly resolved in scenario %q, %q:\n got %v, expected %v",
226+
testCase.scenario, testCase.description, outRef, testCase.expectedOutRef)
227+
}
228+
}
229+
230+
}

pkg/oci/types.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ func (rc *ArtifactConfig) ParseRequirements(requirements ...string) error {
119119
return nil
120120
}
121121

122-
type dependency struct {
122+
type Dependency struct {
123123
Name string `json:"name"`
124124
Version string `json:"version"`
125125
}
@@ -128,7 +128,7 @@ type dependency struct {
128128
type ArtifactDependency struct {
129129
Name string `json:"name"`
130130
Version string `json:"version"`
131-
Alternatives []dependency `json:"alternatives,omitempty"`
131+
Alternatives []Dependency `json:"alternatives,omitempty"`
132132
}
133133

134134
// SetAlternative sets an alternative dependency for an artifact dependency.
@@ -142,7 +142,7 @@ func (a *ArtifactDependency) SetAlternative(name, version string) {
142142

143143
// we could insert in the middle while looking for a dup...
144144
// ...but we are lazy.
145-
a.Alternatives = append(a.Alternatives, dependency{name, version})
145+
a.Alternatives = append(a.Alternatives, Dependency{name, version})
146146
sort.Slice(a.Alternatives, func(i, j int) bool {
147147
return a.Alternatives[i].Name < a.Alternatives[j].Name
148148
})

0 commit comments

Comments
 (0)