diff options
Diffstat (limited to 'src/go/collectors/go.d.plugin/modules/storcli/storcli_test.go')
-rw-r--r-- | src/go/collectors/go.d.plugin/modules/storcli/storcli_test.go | 289 |
1 files changed, 289 insertions, 0 deletions
diff --git a/src/go/collectors/go.d.plugin/modules/storcli/storcli_test.go b/src/go/collectors/go.d.plugin/modules/storcli/storcli_test.go new file mode 100644 index 0000000000..84ea3bb4c3 --- /dev/null +++ b/src/go/collectors/go.d.plugin/modules/storcli/storcli_test.go @@ -0,0 +1,289 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +package storcli + +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") + + dataMegaControllerInfo, _ = os.ReadFile("testdata/megaraid-controllers-info.json") + dataMegaDrivesInfo, _ = os.ReadFile("testdata/megaraid-drives-info.json") +) + +func Test_testDataIsValid(t *testing.T) { + for name, data := range map[string][]byte{ + "dataConfigJSON": dataConfigJSON, + "dataConfigYAML": dataConfigYAML, + + "dataMegaControllerInfo": dataMegaControllerInfo, + "dataMegaDrivesInfo": dataMegaDrivesInfo, + } { + require.NotNil(t, data, name) + } +} + +func TestStorCli_ConfigurationSerialize(t *testing.T) { + module.TestConfigurationSerialize(t, &StorCli{}, dataConfigJSON, dataConfigYAML) +} + +func TestStorCli_Init(t *testing.T) { + tests := map[string]struct { + config Config + wantFail bool + }{ + "fails if 'ndsudo' not found": { + wantFail: true, + config: New().Config, + }, + } + + for name, test := range tests { + t.Run(name, func(t *testing.T) { + stor := New() + + if test.wantFail { + assert.Error(t, stor.Init()) + } else { + assert.NoError(t, stor.Init()) + } + }) + } +} + +func TestStorCli_Cleanup(t *testing.T) { + tests := map[string]struct { + prepare func() *StorCli + }{ + "not initialized exec": { + prepare: func() *StorCli { + return New() + }, + }, + "after check": { + prepare: func() *StorCli { + stor := New() + stor.exec = prepareMockMegaRaidOK() + _ = stor.Check() + return stor + }, + }, + "after collect": { + prepare: func() *StorCli { + stor := New() + stor.exec = prepareMockMegaRaidOK() + _ = stor.Collect() + return stor + }, + }, + } + + for name, test := range tests { + t.Run(name, func(t *testing.T) { + stor := test.prepare() + + assert.NotPanics(t, stor.Cleanup) + }) + } +} + +func TestStorCli_Charts(t *testing.T) { + assert.NotNil(t, New().Charts()) +} + +func TestStorCli_Check(t *testing.T) { + tests := map[string]struct { + prepareMock func() *mockStorCliExec + wantFail bool + }{ + "success MegaRAID controller": { + wantFail: false, + prepareMock: prepareMockMegaRaidOK, + }, + "err on exec": { + wantFail: true, + prepareMock: prepareMockErr, + }, + "unexpected response": { + wantFail: true, + prepareMock: prepareMockUnexpectedResponse, + }, + "empty response": { + wantFail: true, + prepareMock: prepareMockEmptyResponse, + }, + } + + for name, test := range tests { + t.Run(name, func(t *testing.T) { + stor := New() + mock := test.prepareMock() + stor.exec = mock + + if test.wantFail { + assert.Error(t, stor.Check()) + } else { + assert.NoError(t, stor.Check()) + } + }) + } +} + +func TestStorCli_Collect(t *testing.T) { + tests := map[string]struct { + prepareMock func() *mockStorCliExec + wantMetrics map[string]int64 + wantCharts int + }{ + "success MegaRAID controller": { + prepareMock: prepareMockMegaRaidOK, + wantCharts: len(controllerChartsTmpl)*1 + len(physDriveChartsTmpl)*6, + wantMetrics: map[string]int64{ + "cntrl_0_bbu_status_healthy": 1, + "cntrl_0_bbu_status_na": 0, + "cntrl_0_bbu_status_unhealthy": 0, + "cntrl_0_status_degraded": 0, + "cntrl_0_status_failed": 0, + "cntrl_0_status_optimal": 1, + "cntrl_0_status_partially_degraded": 0, + "phys_drive_5000C500C36C8BCD_cntrl_0_media_error_count": 0, + "phys_drive_5000C500C36C8BCD_cntrl_0_other_error_count": 0, + "phys_drive_5000C500C36C8BCD_cntrl_0_predictive_failure_count": 0, + "phys_drive_5000C500C36C8BCD_cntrl_0_smart_alert_status_active": 0, + "phys_drive_5000C500C36C8BCD_cntrl_0_smart_alert_status_inactive": 0, + "phys_drive_5000C500C36C8BCD_cntrl_0_temperature": 28, + "phys_drive_5000C500D59840FE_cntrl_0_media_error_count": 0, + "phys_drive_5000C500D59840FE_cntrl_0_other_error_count": 0, + "phys_drive_5000C500D59840FE_cntrl_0_predictive_failure_count": 0, + "phys_drive_5000C500D59840FE_cntrl_0_smart_alert_status_active": 0, + "phys_drive_5000C500D59840FE_cntrl_0_smart_alert_status_inactive": 0, + "phys_drive_5000C500D59840FE_cntrl_0_temperature": 28, + "phys_drive_5000C500D6061539_cntrl_0_media_error_count": 0, + "phys_drive_5000C500D6061539_cntrl_0_other_error_count": 0, + "phys_drive_5000C500D6061539_cntrl_0_predictive_failure_count": 0, + "phys_drive_5000C500D6061539_cntrl_0_smart_alert_status_active": 0, + "phys_drive_5000C500D6061539_cntrl_0_smart_alert_status_inactive": 0, + "phys_drive_5000C500D6061539_cntrl_0_temperature": 28, + "phys_drive_5000C500DC79B194_cntrl_0_media_error_count": 0, + "phys_drive_5000C500DC79B194_cntrl_0_other_error_count": 0, + "phys_drive_5000C500DC79B194_cntrl_0_predictive_failure_count": 0, + "phys_drive_5000C500DC79B194_cntrl_0_smart_alert_status_active": 0, + "phys_drive_5000C500DC79B194_cntrl_0_smart_alert_status_inactive": 0, + "phys_drive_5000C500DC79B194_cntrl_0_temperature": 28, + "phys_drive_5000C500E54F4EBB_cntrl_0_media_error_count": 0, + "phys_drive_5000C500E54F4EBB_cntrl_0_other_error_count": 0, + "phys_drive_5000C500E54F4EBB_cntrl_0_predictive_failure_count": 0, + "phys_drive_5000C500E54F4EBB_cntrl_0_smart_alert_status_active": 0, + "phys_drive_5000C500E54F4EBB_cntrl_0_smart_alert_status_inactive": 0, + "phys_drive_5000C500E54F4EBB_cntrl_0_temperature": 28, + "phys_drive_5000C500E5659BA7_cntrl_0_media_error_count": 0, + "phys_drive_5000C500E5659BA7_cntrl_0_other_error_count": 0, + "phys_drive_5000C500E5659BA7_cntrl_0_predictive_failure_count": 0, + "phys_drive_5000C500E5659BA7_cntrl_0_smart_alert_status_active": 0, + "phys_drive_5000C500E5659BA7_cntrl_0_smart_alert_status_inactive": 0, + "phys_drive_5000C500E5659BA7_cntrl_0_temperature": 27, + }, + }, + "err on exec": { + prepareMock: prepareMockErr, + wantMetrics: nil, + }, + "unexpected response": { + prepareMock: prepareMockUnexpectedResponse, + wantMetrics: nil, + }, + "empty response": { + prepareMock: prepareMockEmptyResponse, + wantMetrics: nil, + }, + } + + for name, test := range tests { + t.Run(name, func(t *testing.T) { + stor := New() + mock := test.prepareMock() + stor.exec = mock + + mx := stor.Collect() + + assert.Equal(t, test.wantMetrics, mx) + assert.Len(t, *stor.Charts(), test.wantCharts) + testMetricsHasAllChartsDims(t, stor, mx) + }) + } +} + +func prepareMockMegaRaidOK() *mockStorCliExec { + return &mockStorCliExec{ + controllersInfoData: dataMegaControllerInfo, + drivesInfoData: dataMegaDrivesInfo, + } +} + +func prepareMockErr() *mockStorCliExec { + return &mockStorCliExec{ + errOnInfo: true, + } +} + +func prepareMockUnexpectedResponse() *mockStorCliExec { + resp := []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. +`) + return &mockStorCliExec{ + controllersInfoData: resp, + drivesInfoData: resp, + } +} + +func prepareMockEmptyResponse() *mockStorCliExec { + return &mockStorCliExec{} +} + +type mockStorCliExec struct { + errOnInfo bool + controllersInfoData []byte + drivesInfoData []byte +} + +func (m *mockStorCliExec) controllersInfo() ([]byte, error) { + if m.errOnInfo { + return nil, errors.New("mock.controllerInfo() error") + } + return m.controllersInfoData, nil +} + +func (m *mockStorCliExec) drivesInfo() ([]byte, error) { + if m.errOnInfo { + return nil, errors.New("mock.drivesInfo() error") + } + return m.drivesInfoData, nil +} + +func testMetricsHasAllChartsDims(t *testing.T, stor *StorCli, mx map[string]int64) { + for _, chart := range *stor.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) + } + for _, v := range chart.Vars { + _, ok := mx[v.ID] + assert.Truef(t, ok, "collected metrics has no data for var '%s' chart '%s'", v.ID, chart.ID) + } + } +} |