master
go 112 lines 2.71 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 package pipeline
4
5 import (
6 "context"
7 "testing"
8 "time"
9
10 "github.com/netdata/netdata/go/plugins/logger"
11 "github.com/netdata/netdata/go/plugins/plugin/agent/discovery/sd/model"
12
13 "github.com/stretchr/testify/assert"
14 "github.com/stretchr/testify/require"
15 )
16
17 type accumulatorDiscoverer func(context.Context, chan<- []model.TargetGroup)
18
19 func (fn accumulatorDiscoverer) Discover(ctx context.Context, ch chan<- []model.TargetGroup) {
20 fn(ctx, ch)
21 }
22
23 func TestAccumulator_Run_FlushesPendingGroupsWhenDiscoverersExit(t *testing.T) {
24 accum := newAccumulator()
25 accum.Logger = logger.New()
26 accum.sendEvery = time.Hour
27 accum.discoverers = []model.Discoverer{
28 accumulatorDiscoverer(func(_ context.Context, ch chan<- []model.TargetGroup) {
29 ch <- []model.TargetGroup{newMockTargetGroup("test", "mock1")}
30 }),
31 }
32
33 ctx := t.Context()
34
35 updates := make(chan []model.TargetGroup)
36 done := make(chan struct{})
37 go func() {
38 defer close(done)
39 accum.run(ctx, updates)
40 }()
41
42 time.Sleep(100 * time.Millisecond)
43
44 select {
45 case got := <-updates:
46 require.Len(t, got, 1)
47 assert.Equal(t, "test", got[0].Source())
48 case <-time.After(time.Second):
49 t.Fatal("timed out waiting for final accumulator flush")
50 }
51
52 select {
53 case <-done:
54 case <-time.After(time.Second):
55 t.Fatal("accumulator did not exit after delivering final flush")
56 }
57 }
58
59 func TestAccumulator_Run_ExitsOnCancelWhenFinalFlushBlocks(t *testing.T) {
60 accum := newAccumulator()
61 accum.Logger = logger.New()
62 accum.sendEvery = time.Hour
63 accum.discoverers = []model.Discoverer{
64 accumulatorDiscoverer(func(_ context.Context, ch chan<- []model.TargetGroup) {
65 ch <- []model.TargetGroup{newMockTargetGroup("test", "mock1")}
66 }),
67 }
68
69 ctx, cancel := context.WithCancel(context.Background())
70 updates := make(chan []model.TargetGroup)
71 done := make(chan struct{})
72 go func() {
73 defer close(done)
74 accum.run(ctx, updates)
75 }()
76
77 time.Sleep(100 * time.Millisecond)
78
79 select {
80 case <-done:
81 t.Fatal("accumulator exited before cancellation instead of waiting for the final flush receiver")
82 default:
83 }
84
85 cancel()
86
87 select {
88 case <-done:
89 case <-time.After(time.Second):
90 t.Fatal("accumulator did not exit after cancellation")
91 }
92 }
93
94 func TestAccumulator_FinalSend_PrefersReadyReceiverAfterCancel(t *testing.T) {
95 accum := newAccumulator()
96 accum.groupsUpdate([]model.TargetGroup{newMockTargetGroup("test", "mock1")})
97
98 ctx, cancel := context.WithCancel(context.Background())
99 cancel()
100
101 updates := make(chan []model.TargetGroup, 1)
102
103 accum.finalSend(ctx, updates)
104
105 select {
106 case got := <-updates:
107 require.Len(t, got, 1)
108 assert.Equal(t, "test", got[0].Source())
109 case <-time.After(time.Second):
110 t.Fatal("timed out waiting for canceled finalSend delivery")
111 }
112 }