diff options
Diffstat (limited to 'src/go/collectors/go.d.plugin/modules/dmcache/dmcache_test.go')
-rw-r--r-- | src/go/collectors/go.d.plugin/modules/dmcache/dmcache_test.go | 253 |
1 files changed, 253 insertions, 0 deletions
diff --git a/src/go/collectors/go.d.plugin/modules/dmcache/dmcache_test.go b/src/go/collectors/go.d.plugin/modules/dmcache/dmcache_test.go new file mode 100644 index 000000000..ef2de991a --- /dev/null +++ b/src/go/collectors/go.d.plugin/modules/dmcache/dmcache_test.go @@ -0,0 +1,253 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +package dmcache + +import ( + "errors" + "os" + "testing" + + "github.com/netdata/netdata/go/go.d.plugin/agent/module" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +var ( + dataConfigJSON, _ = os.ReadFile("testdata/config.json") + dataConfigYAML, _ = os.ReadFile("testdata/config.yaml") +) + +func Test_testDataIsValid(t *testing.T) { + for name, data := range map[string][]byte{ + "dataConfigJSON": dataConfigJSON, + "dataConfigYAML": dataConfigYAML, + } { + require.NotNil(t, data, name) + + } +} + +func TestDmCace_Configuration(t *testing.T) { + module.TestConfigurationSerialize(t, &DmCache{}, dataConfigJSON, dataConfigYAML) +} + +func TestDmCache_Init(t *testing.T) { + tests := map[string]struct { + config Config + wantFail bool + }{ + "fails if failed to locate ndsudo": { + wantFail: true, + config: New().Config, + }, + } + + for name, test := range tests { + t.Run(name, func(t *testing.T) { + lvm := New() + lvm.Config = test.config + + if test.wantFail { + assert.Error(t, lvm.Init()) + } else { + assert.NoError(t, lvm.Init()) + } + }) + } +} + +func TestDmCache_Cleanup(t *testing.T) { + tests := map[string]struct { + prepare func() *DmCache + }{ + "not initialized exec": { + prepare: func() *DmCache { + return New() + }, + }, + "after check": { + prepare: func() *DmCache { + lvm := New() + lvm.exec = prepareMockOK() + _ = lvm.Check() + return lvm + }, + }, + "after collect": { + prepare: func() *DmCache { + lvm := New() + lvm.exec = prepareMockOK() + _ = lvm.Collect() + return lvm + }, + }, + } + + for name, test := range tests { + t.Run(name, func(t *testing.T) { + lvm := test.prepare() + + assert.NotPanics(t, lvm.Cleanup) + }) + } +} + +func TestDmCache_Charts(t *testing.T) { + assert.NotNil(t, New().Charts()) +} + +func TestDmCache_Check(t *testing.T) { + tests := map[string]struct { + prepareMock func() *mockDmsetupExec + wantFail bool + }{ + "success case": { + prepareMock: prepareMockOK, + wantFail: false, + }, + "error on cache status": { + prepareMock: prepareMockErr, + wantFail: true, + }, + "empty response": { + prepareMock: prepareMockEmptyResponse, + wantFail: true, + }, + "unexpected response": { + prepareMock: prepareMockUnexpectedResponse, + wantFail: true, + }, + } + + for name, test := range tests { + t.Run(name, func(t *testing.T) { + dmcache := New() + mock := test.prepareMock() + dmcache.exec = mock + + if test.wantFail { + assert.Error(t, dmcache.Check()) + } else { + assert.NoError(t, dmcache.Check()) + } + }) + } +} + +func TestLVM_Collect(t *testing.T) { + tests := map[string]struct { + prepareMock func() *mockDmsetupExec + wantCharts int + wantMetrics map[string]int64 + }{ + "success case": { + prepareMock: prepareMockOK, + wantCharts: len(deviceChartsTmpl) * 2, + wantMetrics: map[string]int64{ + "dmcache_device_vg_raid1_md21-media_cache_free_bytes": 1252402397184, + "dmcache_device_vg_raid1_md21-media_cache_used_bytes": 396412059648, + "dmcache_device_vg_raid1_md21-media_demotions_bytes": 0, + "dmcache_device_vg_raid1_md21-media_dirty_bytes": 0, + "dmcache_device_vg_raid1_md21-media_metadata_free_bytes": 32243712, + "dmcache_device_vg_raid1_md21-media_metadata_used_bytes": 9699328, + "dmcache_device_vg_raid1_md21-media_promotions_bytes": 48035266560, + "dmcache_device_vg_raid1_md21-media_read_hits": 82870357, + "dmcache_device_vg_raid1_md21-media_read_misses": 5499462, + "dmcache_device_vg_raid1_md21-media_write_hits": 26280342, + "dmcache_device_vg_raid1_md21-media_write_misses": 8017854, + "dmcache_device_vg_raid2_md22-media_cache_free_bytes": 1252402397184, + "dmcache_device_vg_raid2_md22-media_cache_used_bytes": 396412059648, + "dmcache_device_vg_raid2_md22-media_demotions_bytes": 0, + "dmcache_device_vg_raid2_md22-media_dirty_bytes": 0, + "dmcache_device_vg_raid2_md22-media_metadata_free_bytes": 32243712, + "dmcache_device_vg_raid2_md22-media_metadata_used_bytes": 9699328, + "dmcache_device_vg_raid2_md22-media_promotions_bytes": 48035266560, + "dmcache_device_vg_raid2_md22-media_read_hits": 82870357, + "dmcache_device_vg_raid2_md22-media_read_misses": 5499462, + "dmcache_device_vg_raid2_md22-media_write_hits": 26280342, + "dmcache_device_vg_raid2_md22-media_write_misses": 8017854, + }, + }, + "error on cache status": { + prepareMock: prepareMockErr, + wantMetrics: nil, + }, + "empty response": { + prepareMock: prepareMockEmptyResponse, + wantMetrics: nil, + }, + "unexpected response": { + prepareMock: prepareMockUnexpectedResponse, + wantMetrics: nil, + }, + } + + for name, test := range tests { + t.Run(name, func(t *testing.T) { + dmcache := New() + mock := test.prepareMock() + dmcache.exec = mock + + mx := dmcache.Collect() + + assert.Equal(t, test.wantMetrics, mx) + assert.Len(t, *dmcache.Charts(), test.wantCharts) + testMetricsHasAllChartsDims(t, dmcache, mx) + }) + } +} + +func testMetricsHasAllChartsDims(t *testing.T, dmcache *DmCache, mx map[string]int64) { + for _, chart := range *dmcache.Charts() { + if chart.Obsolete { + continue + } + for _, dim := range chart.Dims { + _, ok := mx[dim.ID] + assert.Truef(t, ok, "collected metrics has no data for dim '%s' chart '%s'", dim.ID, chart.ID) + } + } +} + +func prepareMockOK() *mockDmsetupExec { + return &mockDmsetupExec{ + cacheStatusData: []byte(` +vg_raid1_md21-media: 0 2404139008 cache 8 2368/10240 4096 189024/786216 82870357 5499462 26280342 8017854 0 22905 0 3 metadata2 writethrough no_discard_passdown 2 migration_threshold 32768 mq 10 random_threshold 0 sequential_threshold 0 discard_promote_adjustment 0 read_promote_adjustment 0 write_promote_adjustment 0 rw - +vg_raid2_md22-media: 0 2404139008 cache 8 2368/10240 4096 189024/786216 82870357 5499462 26280342 8017854 0 22905 0 3 metadata2 writethrough no_discard_passdown 2 migration_threshold 32768 mq 10 random_threshold 0 sequential_threshold 0 discard_promote_adjustment 0 read_promote_adjustment 0 write_promote_adjustment 0 rw - +`), + } +} + +func prepareMockErr() *mockDmsetupExec { + return &mockDmsetupExec{ + errOnCacheStatus: true, + } +} + +func prepareMockEmptyResponse() *mockDmsetupExec { + return &mockDmsetupExec{} +} + +func prepareMockUnexpectedResponse() *mockDmsetupExec { + return &mockDmsetupExec{ + cacheStatusData: []byte(` +Lorem ipsum dolor sit amet, consectetur adipiscing elit. +Nulla malesuada erat id magna mattis, eu viverra tellus rhoncus. +Fusce et felis pulvinar, posuere sem non, porttitor eros. +`), + } +} + +type mockDmsetupExec struct { + errOnCacheStatus bool + cacheStatusData []byte +} + +func (m *mockDmsetupExec) cacheStatus() ([]byte, error) { + if m.errOnCacheStatus { + return nil, errors.New("mock.cacheStatus() error") + } + + return m.cacheStatusData, nil +} |