diff options
Diffstat (limited to 'src/go/plugin/go.d/modules/gearman/gearman_test.go')
-rw-r--r-- | src/go/plugin/go.d/modules/gearman/gearman_test.go | 326 |
1 files changed, 326 insertions, 0 deletions
diff --git a/src/go/plugin/go.d/modules/gearman/gearman_test.go b/src/go/plugin/go.d/modules/gearman/gearman_test.go new file mode 100644 index 000000000..43069abce --- /dev/null +++ b/src/go/plugin/go.d/modules/gearman/gearman_test.go @@ -0,0 +1,326 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +package gearman + +import ( + "errors" + "os" + "testing" + + "github.com/netdata/netdata/go/plugins/plugin/go.d/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") + + dataStatus, _ = os.ReadFile("testdata/status.txt") + dataPriorityStatus, _ = os.ReadFile("testdata/priority-status.txt") +) + +func Test_testDataIsValid(t *testing.T) { + for name, data := range map[string][]byte{ + "dataConfigJSON": dataConfigJSON, + "dataConfigYAML": dataConfigYAML, + + "dataStatus": dataStatus, + "dataPriorityStatus": dataPriorityStatus, + } { + require.NotNil(t, data, name) + } +} + +func TestGearman_ConfigurationSerialize(t *testing.T) { + module.TestConfigurationSerialize(t, &Gearman{}, dataConfigJSON, dataConfigYAML) +} + +func TestGearman_Init(t *testing.T) { + tests := map[string]struct { + config Config + wantFail bool + }{ + "success with default config": { + wantFail: false, + config: New().Config, + }, + "fails if address not set": { + wantFail: true, + config: func() Config { + conf := New().Config + conf.Address = "" + return conf + }(), + }, + } + + for name, test := range tests { + t.Run(name, func(t *testing.T) { + gear := New() + gear.Config = test.config + + if test.wantFail { + assert.Error(t, gear.Init()) + } else { + assert.NoError(t, gear.Init()) + } + }) + } +} + +func TestGearman_Cleanup(t *testing.T) { + tests := map[string]struct { + prepare func() *Gearman + }{ + "not initialized": { + prepare: func() *Gearman { + return New() + }, + }, + "after check": { + prepare: func() *Gearman { + gear := New() + gear.newConn = func(config Config) gearmanConn { return prepareMockOk() } + _ = gear.Check() + return gear + }, + }, + "after collect": { + prepare: func() *Gearman { + gear := New() + gear.newConn = func(config Config) gearmanConn { return prepareMockOk() } + _ = gear.Collect() + return gear + }, + }, + } + + for name, test := range tests { + t.Run(name, func(t *testing.T) { + gear := test.prepare() + + assert.NotPanics(t, gear.Cleanup) + }) + } +} + +func TestGearman_Charts(t *testing.T) { + assert.NotNil(t, New().Charts()) +} + +func TestGearman_Check(t *testing.T) { + tests := map[string]struct { + prepareMock func() *mockGearmanConn + wantFail bool + }{ + "success case": { + wantFail: false, + prepareMock: prepareMockOk, + }, + "err on connect": { + wantFail: true, + prepareMock: prepareMockErrOnConnect, + }, + "unexpected response": { + wantFail: true, + prepareMock: prepareMockUnexpectedResponse, + }, + "empty response": { + wantFail: false, + prepareMock: prepareMockEmptyResponse, + }, + } + + for name, test := range tests { + t.Run(name, func(t *testing.T) { + gear := New() + mock := test.prepareMock() + gear.newConn = func(config Config) gearmanConn { return mock } + + if test.wantFail { + assert.Error(t, gear.Check()) + } else { + assert.NoError(t, gear.Check()) + } + }) + } +} + +func TestGearman_Collect(t *testing.T) { + tests := map[string]struct { + prepareMock func() *mockGearmanConn + wantMetrics map[string]int64 + wantCharts int + disconnectBeforeCleanup bool + disconnectAfterCleanup bool + }{ + "success case": { + prepareMock: prepareMockOk, + disconnectBeforeCleanup: false, + disconnectAfterCleanup: true, + wantCharts: len(summaryCharts) + len(functionStatusChartsTmpl)*4 + len(functionPriorityStatusChartsTmpl)*4, + wantMetrics: map[string]int64{ + "function_generic_worker1_high_priority_jobs": 10, + "function_generic_worker1_jobs_queued": 4, + "function_generic_worker1_jobs_running": 3, + "function_generic_worker1_jobs_waiting": 1, + "function_generic_worker1_low_priority_jobs": 12, + "function_generic_worker1_normal_priority_jobs": 11, + "function_generic_worker1_workers_available": 500, + "function_generic_worker2_high_priority_jobs": 4, + "function_generic_worker2_jobs_queued": 78, + "function_generic_worker2_jobs_running": 78, + "function_generic_worker2_jobs_waiting": 0, + "function_generic_worker2_low_priority_jobs": 6, + "function_generic_worker2_normal_priority_jobs": 5, + "function_generic_worker2_workers_available": 500, + "function_generic_worker3_high_priority_jobs": 7, + "function_generic_worker3_jobs_queued": 2, + "function_generic_worker3_jobs_running": 1, + "function_generic_worker3_jobs_waiting": 1, + "function_generic_worker3_low_priority_jobs": 9, + "function_generic_worker3_normal_priority_jobs": 8, + "function_generic_worker3_workers_available": 760, + "function_prefix_generic_worker4_high_priority_jobs": 1, + "function_prefix_generic_worker4_jobs_queued": 78, + "function_prefix_generic_worker4_jobs_running": 78, + "function_prefix_generic_worker4_jobs_waiting": 0, + "function_prefix_generic_worker4_low_priority_jobs": 3, + "function_prefix_generic_worker4_normal_priority_jobs": 2, + "function_prefix_generic_worker4_workers_available": 500, + "total_high_priority_jobs": 22, + "total_jobs_queued": 162, + "total_jobs_running": 160, + "total_jobs_waiting": 2, + "total_low_priority_jobs": 30, + "total_normal_priority_jobs": 26, + "total_workers_avail": 0, + "total_workers_available": 2260, + }, + }, + "unexpected response": { + prepareMock: prepareMockUnexpectedResponse, + disconnectBeforeCleanup: false, + disconnectAfterCleanup: true, + }, + "empty response": { + prepareMock: prepareMockEmptyResponse, + disconnectBeforeCleanup: false, + disconnectAfterCleanup: true, + wantCharts: len(summaryCharts), + wantMetrics: map[string]int64{ + "total_high_priority_jobs": 0, + "total_jobs_queued": 0, + "total_jobs_running": 0, + "total_jobs_waiting": 0, + "total_low_priority_jobs": 0, + "total_normal_priority_jobs": 0, + "total_workers_avail": 0, + }, + }, + "err on connect": { + prepareMock: prepareMockErrOnConnect, + disconnectBeforeCleanup: false, + disconnectAfterCleanup: false, + }, + "err on query status": { + prepareMock: prepareMockErrOnQueryStatus, + disconnectBeforeCleanup: true, + disconnectAfterCleanup: true, + }, + } + + for name, test := range tests { + t.Run(name, func(t *testing.T) { + gear := New() + mock := test.prepareMock() + gear.newConn = func(config Config) gearmanConn { return mock } + + mx := gear.Collect() + + require.Equal(t, test.wantMetrics, mx, "want metrics") + + if len(test.wantMetrics) > 0 { + module.TestMetricsHasAllChartsDims(t, gear.Charts(), mx) + assert.Equal(t, test.wantCharts, len(*gear.Charts()), "want charts") + } + + assert.Equal(t, test.disconnectBeforeCleanup, mock.disconnectCalled, "disconnect before cleanup") + gear.Cleanup() + assert.Equal(t, test.disconnectAfterCleanup, mock.disconnectCalled, "disconnect after cleanup") + }) + } +} + +func prepareMockOk() *mockGearmanConn { + return &mockGearmanConn{ + responseStatus: dataStatus, + responsePriorityStatus: dataPriorityStatus, + } +} + +func prepareMockErrOnConnect() *mockGearmanConn { + return &mockGearmanConn{ + errOnConnect: true, + } +} + +func prepareMockErrOnQueryStatus() *mockGearmanConn { + return &mockGearmanConn{ + errOnQueryStatus: true, + } +} + +func prepareMockUnexpectedResponse() *mockGearmanConn { + resp := []byte("Lorem ipsum dolor sit amet, consectetur adipiscing elit.") + return &mockGearmanConn{ + responseStatus: resp, + responsePriorityStatus: resp, + } +} + +func prepareMockEmptyResponse() *mockGearmanConn { + return &mockGearmanConn{ + responseStatus: []byte("."), + responsePriorityStatus: []byte("."), + } +} + +type mockGearmanConn struct { + errOnConnect bool + + responseStatus []byte + errOnQueryStatus bool + + responsePriorityStatus []byte + errOnQueryPriorityStatus bool + + disconnectCalled bool +} + +func (m *mockGearmanConn) connect() error { + if m.errOnConnect { + return errors.New("mock.connect() error") + } + return nil +} + +func (m *mockGearmanConn) disconnect() { + m.disconnectCalled = true +} + +func (m *mockGearmanConn) queryStatus() ([]byte, error) { + if m.errOnQueryStatus { + return nil, errors.New("mock.queryStatus() error") + } + return m.responseStatus, nil +} + +func (m *mockGearmanConn) queryPriorityStatus() ([]byte, error) { + if m.errOnQueryPriorityStatus { + return nil, errors.New("mock.queryPriorityStatus() error") + } + return m.responsePriorityStatus, nil +} |