master
go 213 lines 5.32 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 package discovery
4
5 import (
6 "context"
7 "fmt"
8 "sync"
9 "testing"
10 "time"
11
12 "github.com/netdata/netdata/go/plugins/plugin/agent/discovery/sd"
13 "github.com/netdata/netdata/go/plugins/plugin/framework/confgroup"
14 "github.com/stretchr/testify/assert"
15 "github.com/stretchr/testify/require"
16 )
17
18 func TestNewManager(t *testing.T) {
19 tests := map[string]struct {
20 cfg Config
21 wantErr bool
22 }{
23 "valid config": {
24 cfg: Config{
25 Registry: confgroup.Registry{"module1": confgroup.Default{}},
26 Providers: []ProviderFactory{
27 NewProviderFactory("test", func(BuildContext) (Discoverer, bool, error) {
28 return prepareMockDiscoverer("test", 1, 1), true, nil
29 }),
30 },
31 },
32 },
33 "valid config, sd only": {
34 cfg: Config{
35 Registry: confgroup.Registry{"module1": confgroup.Default{}},
36 Providers: []ProviderFactory{
37 NewProviderFactory("sd", func(BuildContext) (Discoverer, bool, error) {
38 d, err := sd.NewServiceDiscovery(sd.Config{
39 PluginName: "test",
40 ConfDir: []string{"path"},
41 Discoverers: sd.NewRegistry(),
42 })
43 if err != nil {
44 return nil, false, err
45 }
46 return d, true, nil
47 }),
48 },
49 },
50 },
51 "invalid config, registry not set": {
52 cfg: Config{
53 Providers: []ProviderFactory{
54 NewProviderFactory("test", func(BuildContext) (Discoverer, bool, error) {
55 return prepareMockDiscoverer("test", 1, 1), true, nil
56 }),
57 },
58 },
59 wantErr: true,
60 },
61 "invalid config, discoverers not set": {
62 cfg: Config{
63 Registry: confgroup.Registry{"module1": confgroup.Default{}},
64 },
65 wantErr: true,
66 },
67 "invalid config, all providers disabled": {
68 cfg: Config{
69 Registry: confgroup.Registry{"module1": confgroup.Default{}},
70 Providers: []ProviderFactory{
71 NewProviderFactory("disabled", func(BuildContext) (Discoverer, bool, error) {
72 return nil, false, nil
73 }),
74 },
75 },
76 wantErr: true,
77 },
78 }
79
80 for name, test := range tests {
81 t.Run(name, func(t *testing.T) {
82 mgr, err := NewManager(test.cfg)
83
84 if test.wantErr {
85 assert.Error(t, err)
86 } else {
87 require.NoError(t, err)
88 assert.NotNil(t, mgr)
89 }
90 })
91 }
92 }
93
94 func TestManager_Run(t *testing.T) {
95 tests := map[string]func() discoverySim{
96 "several discoverers, unique groups with delayed collect": func() discoverySim {
97 const numGroups, numCfgs = 2, 2
98 d1 := prepareMockDiscoverer("test1", numGroups, numCfgs)
99 d2 := prepareMockDiscoverer("test2", numGroups, numCfgs)
100 mgr := prepareManager(d1, d2)
101 expected := combineGroups(d1.groups, d2.groups)
102
103 sim := discoverySim{
104 mgr: mgr,
105 collectDelay: mgr.sendEvery + time.Second,
106 expectedGroups: expected,
107 }
108 return sim
109 },
110 "several discoverers, unique groups": func() discoverySim {
111 const numGroups, numCfgs = 2, 2
112 d1 := prepareMockDiscoverer("test1", numGroups, numCfgs)
113 d2 := prepareMockDiscoverer("test2", numGroups, numCfgs)
114 mgr := prepareManager(d1, d2)
115 expected := combineGroups(d1.groups, d2.groups)
116 sim := discoverySim{
117 mgr: mgr,
118 expectedGroups: expected,
119 }
120 return sim
121 },
122 "several discoverers, same groups": func() discoverySim {
123 const numGroups, numTargets = 2, 2
124 d1 := prepareMockDiscoverer("test1", numGroups, numTargets)
125 mgr := prepareManager(d1, d1)
126 expected := combineGroups(d1.groups)
127
128 sim := discoverySim{
129 mgr: mgr,
130 expectedGroups: expected,
131 }
132 return sim
133 },
134 "several discoverers, empty groups": func() discoverySim {
135 const numGroups, numCfgs = 1, 0
136 d1 := prepareMockDiscoverer("test1", numGroups, numCfgs)
137 d2 := prepareMockDiscoverer("test2", numGroups, numCfgs)
138 mgr := prepareManager(d1, d2)
139 expected := combineGroups(d1.groups, d2.groups)
140
141 sim := discoverySim{
142 mgr: mgr,
143 expectedGroups: expected,
144 }
145 return sim
146 },
147 "several discoverers, nil groups": func() discoverySim {
148 const numGroups, numCfgs = 0, 0
149 d1 := prepareMockDiscoverer("test1", numGroups, numCfgs)
150 d2 := prepareMockDiscoverer("test2", numGroups, numCfgs)
151 mgr := prepareManager(d1, d2)
152
153 sim := discoverySim{
154 mgr: mgr,
155 expectedGroups: nil,
156 }
157 return sim
158 },
159 }
160
161 for name, sim := range tests {
162 t.Run(name, func(t *testing.T) { sim().run(t) })
163 }
164 }
165
166 func prepareMockDiscoverer(source string, groups, configs int) mockDiscoverer {
167 d := mockDiscoverer{}
168
169 for i := range groups {
170 group := confgroup.Group{
171 Source: fmt.Sprintf("%s_group_%d", source, i+1),
172 }
173 for j := range configs {
174 group.Configs = append(group.Configs,
175 confgroup.Config{"name": fmt.Sprintf("%s_group_%d_target_%d", source, i+1, j+1)})
176 }
177 d.groups = append(d.groups, &group)
178 }
179 return d
180 }
181
182 func prepareManager(discoverers ...Discoverer) *Manager {
183 mgr := &Manager{
184 send: make(chan struct{}, 1),
185 sendEvery: 2 * time.Second,
186 discoverers: discoverers,
187 cache: newCache(),
188 mux: &sync.RWMutex{},
189 }
190 return mgr
191 }
192
193 type mockDiscoverer struct {
194 groups []*confgroup.Group
195 }
196
197 func (md mockDiscoverer) Run(ctx context.Context, out chan<- []*confgroup.Group) {
198 for {
199 select {
200 case <-ctx.Done():
201 return
202 case out <- md.groups:
203 return
204 }
205 }
206 }
207
208 func combineGroups(groups ...[]*confgroup.Group) (combined []*confgroup.Group) {
209 for _, set := range groups {
210 combined = append(combined, set...)
211 }
212 return combined
213 }