github.com/netdata/go.d.plugin@v0.58.1/agent/discovery/sd/pipeline/sim_test.go (about)

     1  // SPDX-License-Identifier: GPL-3.0-or-later
     2  
     3  package pipeline
     4  
     5  import (
     6  	"context"
     7  	"sort"
     8  	"testing"
     9  	"time"
    10  
    11  	"github.com/netdata/go.d.plugin/agent/confgroup"
    12  	"github.com/netdata/go.d.plugin/agent/discovery/sd/model"
    13  	"github.com/netdata/go.d.plugin/logger"
    14  
    15  	"github.com/stretchr/testify/assert"
    16  	"github.com/stretchr/testify/require"
    17  	"gopkg.in/yaml.v2"
    18  )
    19  
    20  type discoverySim struct {
    21  	config            string
    22  	discoverers       []model.Discoverer
    23  	wantClassifyCalls int
    24  	wantComposeCalls  int
    25  	wantConfGroups    []*confgroup.Group
    26  }
    27  
    28  func (sim discoverySim) run(t *testing.T) {
    29  	t.Helper()
    30  
    31  	var cfg Config
    32  	err := yaml.Unmarshal([]byte(sim.config), &cfg)
    33  	require.Nilf(t, err, "cfg unmarshal")
    34  
    35  	clr, err := newTargetClassificator(cfg.Classify)
    36  	require.Nilf(t, err, "classify %v", err)
    37  
    38  	cmr, err := newConfigComposer(cfg.Compose)
    39  	require.Nilf(t, err, "compose")
    40  
    41  	mockClr := &mockClassificator{clr: clr}
    42  	mockCmr := &mockComposer{cmr: cmr}
    43  
    44  	accum := newAccumulator()
    45  	accum.sendEvery = time.Second * 2
    46  
    47  	pl := &Pipeline{
    48  		Logger:      logger.New(),
    49  		accum:       accum,
    50  		discoverers: sim.discoverers,
    51  		clr:         mockClr,
    52  		cmr:         mockCmr,
    53  		items:       make(map[string]map[uint64][]confgroup.Config),
    54  	}
    55  
    56  	pl.accum.Logger = pl.Logger
    57  	clr.Logger = pl.Logger
    58  	cmr.Logger = pl.Logger
    59  
    60  	groups := sim.collectGroups(t, pl)
    61  
    62  	sortConfigGroups(groups)
    63  	sortConfigGroups(sim.wantConfGroups)
    64  
    65  	assert.Equal(t, sim.wantConfGroups, groups)
    66  	assert.Equalf(t, sim.wantClassifyCalls, mockClr.calls, "classify calls")
    67  	assert.Equalf(t, sim.wantComposeCalls, mockCmr.calls, "compose calls")
    68  }
    69  
    70  func (sim discoverySim) collectGroups(t *testing.T, pl *Pipeline) []*confgroup.Group {
    71  	ctx, cancel := context.WithCancel(context.Background())
    72  	defer cancel()
    73  
    74  	in := make(chan []*confgroup.Group)
    75  	done := make(chan struct{})
    76  
    77  	go func() { defer close(done); pl.Run(ctx, in) }()
    78  
    79  	timeout := time.Second * 10
    80  	var groups []*confgroup.Group
    81  
    82  	func() {
    83  		for {
    84  			select {
    85  			case inGroups := <-in:
    86  				groups = append(groups, inGroups...)
    87  			case <-done:
    88  				return
    89  			case <-time.After(timeout):
    90  				t.Logf("discovery timed out after %s, got %d groups, expected %d, some events are skipped",
    91  					timeout, len(groups), len(sim.wantConfGroups))
    92  				return
    93  			}
    94  		}
    95  	}()
    96  
    97  	return groups
    98  }
    99  
   100  type mockClassificator struct {
   101  	calls int
   102  	clr   *targetClassificator
   103  }
   104  
   105  func (m *mockClassificator) classify(tgt model.Target) model.Tags {
   106  	m.calls++
   107  	return m.clr.classify(tgt)
   108  }
   109  
   110  type mockComposer struct {
   111  	calls int
   112  	cmr   *configComposer
   113  }
   114  
   115  func (m *mockComposer) compose(tgt model.Target) []confgroup.Config {
   116  	m.calls++
   117  	return m.cmr.compose(tgt)
   118  }
   119  
   120  func sortConfigGroups(groups []*confgroup.Group) {
   121  	sort.Slice(groups, func(i, j int) bool {
   122  		return groups[i].Source < groups[j].Source
   123  	})
   124  
   125  	for _, g := range groups {
   126  		sort.Slice(g.Configs, func(i, j int) bool {
   127  			return g.Configs[i].Name() < g.Configs[j].Name()
   128  		})
   129  	}
   130  }