github.com/netdata/go.d.plugin@v0.58.1/agent/discovery/sd/sim_test.go (about) 1 // SPDX-License-Identifier: GPL-3.0-or-later 2 3 package sd 4 5 import ( 6 "context" 7 "errors" 8 "sync" 9 "testing" 10 "time" 11 12 "github.com/netdata/go.d.plugin/agent/confgroup" 13 "github.com/netdata/go.d.plugin/agent/discovery/sd/pipeline" 14 "github.com/netdata/go.d.plugin/logger" 15 16 "github.com/stretchr/testify/assert" 17 ) 18 19 var lock = &sync.Mutex{} 20 21 type discoverySim struct { 22 configs []ConfigFile 23 wantPipelines []*mockPipeline 24 } 25 26 func (sim *discoverySim) run(t *testing.T) { 27 fact := &mockFactory{} 28 mgr := &ServiceDiscovery{ 29 Logger: logger.New(), 30 sdFactory: fact, 31 confProv: &mockConfigProvider{ 32 configs: sim.configs, 33 ch: make(chan ConfigFile), 34 }, 35 confCache: make(map[string]uint64), 36 pipelines: make(map[string]func()), 37 } 38 39 in := make(chan<- []*confgroup.Group) 40 done := make(chan struct{}) 41 ctx, cancel := context.WithCancel(context.Background()) 42 43 go func() { defer close(done); mgr.Run(ctx, in) }() 44 45 time.Sleep(time.Second * 3) 46 47 lock.Lock() 48 assert.Equalf(t, sim.wantPipelines, fact.pipelines, "before stop") 49 lock.Unlock() 50 51 cancel() 52 53 timeout := time.Second * 5 54 55 select { 56 case <-done: 57 lock.Lock() 58 for _, pl := range fact.pipelines { 59 assert.Truef(t, pl.stopped, "pipeline '%s' is not stopped after cancel()", pl.name) 60 } 61 lock.Unlock() 62 case <-time.After(timeout): 63 t.Errorf("sd failed to exit in %s", timeout) 64 } 65 } 66 67 type mockConfigProvider struct { 68 configs []ConfigFile 69 ch chan ConfigFile 70 } 71 72 func (m *mockConfigProvider) Run(ctx context.Context) { 73 for _, conf := range m.configs { 74 select { 75 case <-ctx.Done(): 76 return 77 case m.ch <- conf: 78 } 79 } 80 <-ctx.Done() 81 } 82 83 func (m *mockConfigProvider) Configs() chan ConfigFile { 84 return m.ch 85 } 86 87 type mockFactory struct { 88 pipelines []*mockPipeline 89 } 90 91 func (m *mockFactory) create(cfg pipeline.Config) (sdPipeline, error) { 92 lock.Lock() 93 defer lock.Unlock() 94 95 if cfg.Name == "invalid" { 96 return nil, errors.New("mock sdPipelineFactory.create() error") 97 } 98 99 pl := mockPipeline{name: cfg.Name} 100 m.pipelines = append(m.pipelines, &pl) 101 102 return &pl, nil 103 } 104 105 type mockPipeline struct { 106 name string 107 started bool 108 stopped bool 109 } 110 111 func (m *mockPipeline) Run(ctx context.Context, _ chan<- []*confgroup.Group) { 112 lock.Lock() 113 m.started = true 114 lock.Unlock() 115 defer func() { lock.Lock(); m.stopped = true; lock.Unlock() }() 116 <-ctx.Done() 117 }