inspektor-gadget
195 строк · 4.5 Кб
1// Copyright 2023 The Inspektor Gadget 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
15package operators
16
17import (
18"testing"
19
20"github.com/stretchr/testify/assert"
21
22"github.com/inspektor-gadget/inspektor-gadget/pkg/gadgets"
23"github.com/inspektor-gadget/inspektor-gadget/pkg/params"
24)
25
26type testOp struct {
27name string
28dependencies []string
29}
30
31func (op testOp) Name() string {
32return op.name
33}
34
35func (op testOp) Dependencies() []string {
36return op.dependencies
37}
38
39func (op testOp) GlobalParamDescs() params.ParamDescs {
40return nil
41}
42
43func (op testOp) ParamDescs() params.ParamDescs {
44return nil
45}
46
47func (op testOp) Description() string {
48return ""
49}
50
51func (op testOp) CanOperateOn(gadgets.GadgetDesc) bool {
52return true
53}
54
55func (op testOp) Init(*params.Params) error {
56return nil
57}
58
59func (op testOp) Close() error {
60return nil
61}
62
63func (op testOp) Instantiate(gadgetContext GadgetContext, gadgetInstance any, perGadgetParams *params.Params) (OperatorInstance, error) {
64return nil, nil
65}
66
67func checkDependencies(t *testing.T, ops, sortedOps Operators) {
68assert.Equal(t, len(ops), len(sortedOps), "Length of sorted ops has to be the same as the original ops")
69
70outerLoop:
71for _, op := range ops {
72deps := op.Dependencies()
73for _, sortedOp := range sortedOps {
74if len(deps) == 0 {
75continue outerLoop
76}
77if sortedOp.Name() == op.Name() {
78assert.Failf(t, "Dependencies of %q were not met", op.Name())
79}
80for i, dep := range deps {
81if sortedOp.Name() == dep {
82deps = append(deps[0:i], deps[i+1:]...)
83}
84}
85}
86}
87}
88
89func createOp(name string, deps []string) testOp {
90return testOp{name, deps}
91}
92
93func Test_SortOperatorsSimple(t *testing.T) {
94ops := Operators{
95createOp("b", []string{"a"}),
96createOp("a", []string{}),
97}
98
99sortedOps, err := SortOperators(ops)
100if assert.NoError(t, err) {
101checkDependencies(t, ops, sortedOps)
102}
103}
104
105func Test_SortOperatorsTwoIncomingDeps(t *testing.T) {
106ops := Operators{
107createOp("b", []string{"a"}),
108createOp("c", []string{"a"}),
109createOp("a", []string{}),
110}
111
112sortedOps, err := SortOperators(ops)
113if assert.NoError(t, err) {
114checkDependencies(t, ops, sortedOps)
115}
116}
117
118func Test_SortOperatorsTwoOutgoingDeps(t *testing.T) {
119ops := Operators{
120createOp("b", []string{"a"}),
121createOp("c", []string{"a", "b"}),
122createOp("a", []string{}),
123}
124
125sortedOps, err := SortOperators(ops)
126if assert.NoError(t, err) {
127checkDependencies(t, ops, sortedOps)
128}
129}
130
131func Test_SortOperatorsTwoOutgoingDepsReversed(t *testing.T) {
132ops := Operators{
133createOp("c", []string{"a", "b"}),
134createOp("b", []string{"a"}),
135createOp("a", []string{}),
136}
137
138sortedOps, err := SortOperators(ops)
139if assert.NoError(t, err) {
140checkDependencies(t, ops, sortedOps)
141}
142}
143
144func Test_SortOperatorsLargeGraph(t *testing.T) {
145ops := Operators{
146createOp("a", []string{}),
147createOp("b", []string{"a"}),
148createOp("c", []string{"a", "h"}),
149createOp("d", []string{"a"}),
150createOp("e", []string{"d", "b"}),
151createOp("f", []string{"h"}),
152createOp("g", []string{"e"}),
153createOp("h", []string{"d"}),
154createOp("i", []string{"g", "f"}),
155}
156
157sortedOps, err := SortOperators(ops)
158if assert.NoError(t, err) {
159checkDependencies(t, ops, sortedOps)
160}
161}
162
163func Test_SortOperatorsMissingDep(t *testing.T) {
164ops := Operators{
165createOp("a", []string{"b"}),
166}
167
168_, err := SortOperators(ops)
169assert.ErrorContains(t, err, "dependency \""+ops[0].Dependencies()[0]+"\" is not available in operators")
170}
171
172func Test_SortOperatorsCyclicDep(t *testing.T) {
173ops := Operators{
174createOp("a", []string{"b"}),
175createOp("b", []string{"a"}),
176createOp("c", []string{"a"}),
177}
178
179_, err := SortOperators(ops)
180assert.ErrorContains(t, err, "dependency cycle detected")
181}
182
183func Test_SortOperatorsLargeCyclicDep(t *testing.T) {
184ops := Operators{
185createOp("a", []string{"b"}),
186createOp("b", []string{"c"}),
187createOp("c", []string{"d"}),
188createOp("d", []string{"e"}),
189createOp("e", []string{"f"}),
190createOp("f", []string{"a"}),
191}
192
193_, err := SortOperators(ops)
194assert.ErrorContains(t, err, "dependency cycle detected")
195}
196