master
go 205 lines 5.26 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 package agent
4
5 import (
6 "bytes"
7 "context"
8 "io"
9 "sync"
10 "testing"
11 "time"
12
13 "github.com/netdata/netdata/go/plugins/pkg/safewriter"
14 "github.com/netdata/netdata/go/plugins/plugin/agent/discovery"
15 "github.com/netdata/netdata/go/plugins/plugin/agent/discovery/dummy"
16 "github.com/netdata/netdata/go/plugins/plugin/agent/policy"
17 "github.com/netdata/netdata/go/plugins/plugin/framework/collectorapi"
18
19 "github.com/stretchr/testify/assert"
20 "github.com/stretchr/testify/require"
21 )
22
23 func TestNew(t *testing.T) {
24 t.Run("uses injected module registry", func(t *testing.T) {
25 reg := prepareRegistry(&sync.Mutex{}, map[string]int{}, "module1")
26 a := New(Config{Name: "test", ModuleRegistry: reg})
27 assert.Equal(t, reg, a.ModuleRegistry)
28 })
29
30 t.Run("keeps nil module registry when not provided", func(t *testing.T) {
31 a := New(Config{Name: "test"})
32 assert.Nil(t, a.ModuleRegistry)
33 })
34 }
35
36 func TestAgent_serviceDiscoveryEnabled(t *testing.T) {
37 tests := map[string]struct {
38 agent *Agent
39 want bool
40 }{
41 "non-terminal policy enables service discovery": {
42 agent: &Agent{runModePolicy: policy.Agent(false)},
43 want: true,
44 },
45 "terminal policy disables service discovery": {
46 agent: &Agent{runModePolicy: policy.Agent(true)},
47 want: false,
48 },
49 "plugin-level disable wins over policy": {
50 agent: &Agent{
51 runModePolicy: policy.Agent(false),
52 DisableServiceDiscovery: true,
53 },
54 want: false,
55 },
56 }
57
58 for name, test := range tests {
59 t.Run(name, func(t *testing.T) {
60 require.NotNil(t, test.agent)
61 assert.Equal(t, test.want, test.agent.serviceDiscoveryEnabled())
62 })
63 }
64 }
65
66 func TestAgent_setupRuntimeService(t *testing.T) {
67 tests := map[string]struct {
68 policy policy.RunModePolicy
69 wantEnabled bool
70 }{
71 "terminal mode disables runtime service": {
72 policy: policy.Agent(true),
73 wantEnabled: false,
74 },
75 "non-terminal mode enables runtime service": {
76 policy: policy.Agent(false),
77 wantEnabled: true,
78 },
79 }
80
81 for name, test := range tests {
82 t.Run(name, func(t *testing.T) {
83 a := New(Config{
84 Name: "test",
85 RunModePolicy: test.policy,
86 })
87 require.NotNil(t, a)
88 a.Out = io.Discard
89
90 svc, stop := a.setupRuntimeService()
91 if !test.wantEnabled {
92 assert.Nil(t, svc)
93 assert.Nil(t, stop)
94 return
95 }
96
97 require.NotNil(t, svc)
98 require.NotNil(t, stop)
99 stop()
100 })
101 }
102 }
103
104 func TestAgent_Run(t *testing.T) {
105 a := New(Config{
106 Name: "test",
107 RunModePolicy: policy.RunModePolicy{
108 IsTerminal: false,
109 AutoEnableDiscovered: true,
110 UseFileStatusPersistence: true,
111 EnableRuntimeCharts: true,
112 },
113 DiscoveryProviders: []discovery.ProviderFactory{
114 discovery.NewProviderFactory("dummy", func(ctx discovery.BuildContext) (discovery.Discoverer, bool, error) {
115 if len(ctx.DummyNames) == 0 {
116 return nil, false, nil
117 }
118 d, err := dummy.NewDiscovery(dummy.Config{
119 Registry: ctx.Registry,
120 Names: ctx.DummyNames,
121 })
122 if err != nil {
123 return nil, false, err
124 }
125 return d, true, nil
126 }),
127 },
128 })
129
130 var buf bytes.Buffer
131 a.Out = safewriter.New(&buf)
132
133 var mux sync.Mutex
134 stats := make(map[string]int)
135 a.ModuleRegistry = prepareRegistry(&mux, stats, "module1", "module2")
136
137 ctx, cancel := context.WithCancel(context.Background())
138 var wg sync.WaitGroup
139
140 wg.Go(func() { a.run(ctx) })
141
142 time.Sleep(time.Second * 2)
143 cancel()
144 wg.Wait()
145
146 assert.Equalf(t, 1, stats["module1_init"], "module1 init")
147 assert.Equalf(t, 1, stats["module2_init"], "module2 init")
148 assert.Equalf(t, 1, stats["module1_check"], "module1 check")
149 assert.Equalf(t, 1, stats["module2_check"], "module2 check")
150 assert.Equalf(t, 1, stats["module1_charts"], "module1 charts")
151 assert.Equalf(t, 1, stats["module2_charts"], "module2 charts")
152 assert.Truef(t, stats["module1_collect"] > 0, "module1 collect")
153 assert.Truef(t, stats["module2_collect"] > 0, "module2 collect")
154 assert.Equalf(t, 1, stats["module1_cleanup"], "module1 cleanup")
155 assert.Equalf(t, 1, stats["module2_cleanup"], "module2 cleanup")
156 assert.True(t, buf.String() != "")
157 }
158
159 func prepareRegistry(mux *sync.Mutex, stats map[string]int, names ...string) collectorapi.Registry {
160 reg := collectorapi.Registry{}
161 for _, name := range names {
162 reg.Register(name, collectorapi.Creator{
163 Create: func() collectorapi.CollectorV1 {
164 return prepareMockModule(name, mux, stats)
165 },
166 })
167 }
168 return reg
169 }
170
171 func prepareMockModule(name string, mux *sync.Mutex, stats map[string]int) collectorapi.CollectorV1 {
172 return &collectorapi.MockCollectorV1{
173 InitFunc: func(context.Context) error {
174 mux.Lock()
175 defer mux.Unlock()
176 stats[name+"_init"]++
177 return nil
178 },
179 CheckFunc: func(context.Context) error {
180 mux.Lock()
181 defer mux.Unlock()
182 stats[name+"_check"]++
183 return nil
184 },
185 ChartsFunc: func() *collectorapi.Charts {
186 mux.Lock()
187 defer mux.Unlock()
188 stats[name+"_charts"]++
189 return &collectorapi.Charts{
190 &collectorapi.Chart{ID: "id", Title: "title", Units: "units", Dims: collectorapi.Dims{{ID: "id1"}}},
191 }
192 },
193 CollectFunc: func(context.Context) map[string]int64 {
194 mux.Lock()
195 defer mux.Unlock()
196 stats[name+"_collect"]++
197 return map[string]int64{"id1": 1}
198 },
199 CleanupFunc: func(context.Context) {
200 mux.Lock()
201 defer mux.Unlock()
202 stats[name+"_cleanup"]++
203 },
204 }
205 }