diff options
Diffstat (limited to 'src/go/collectors/go.d.plugin/modules/ntpd/ntpd_test.go')
-rw-r--r-- | src/go/collectors/go.d.plugin/modules/ntpd/ntpd_test.go | 372 |
1 files changed, 372 insertions, 0 deletions
diff --git a/src/go/collectors/go.d.plugin/modules/ntpd/ntpd_test.go b/src/go/collectors/go.d.plugin/modules/ntpd/ntpd_test.go new file mode 100644 index 000000000..9435485da --- /dev/null +++ b/src/go/collectors/go.d.plugin/modules/ntpd/ntpd_test.go @@ -0,0 +1,372 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +package ntpd + +import ( + "errors" + "fmt" + "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 TestNTPd_ConfigurationSerialize(t *testing.T) { + module.TestConfigurationSerialize(t, &NTPd{}, dataConfigJSON, dataConfigYAML) +} + +func TestNTPd_Init(t *testing.T) { + tests := map[string]struct { + config Config + wantFail bool + }{ + "default config": { + config: New().Config, + }, + "unset 'address'": { + wantFail: true, + config: Config{ + Address: "", + }, + }, + } + + for name, test := range tests { + t.Run(name, func(t *testing.T) { + n := New() + n.Config = test.config + + if test.wantFail { + assert.Error(t, n.Init()) + } else { + assert.NoError(t, n.Init()) + } + }) + } +} + +func TestNTPd_Charts(t *testing.T) { + assert.Equal(t, len(systemCharts), len(*New().Charts())) +} + +func TestNTPd_Cleanup(t *testing.T) { + tests := map[string]struct { + prepare func(*NTPd) + wantClose bool + }{ + "after New": { + wantClose: false, + prepare: func(*NTPd) {}, + }, + "after Init": { + wantClose: false, + prepare: func(n *NTPd) { _ = n.Init() }, + }, + "after Check": { + wantClose: true, + prepare: func(n *NTPd) { _ = n.Init(); _ = n.Check() }, + }, + "after Collect": { + wantClose: true, + prepare: func(n *NTPd) { _ = n.Init(); n.Collect() }, + }, + } + + for name, test := range tests { + t.Run(name, func(t *testing.T) { + m := &mockClient{} + n := prepareNTPdWithMock(m, true) + test.prepare(n) + + require.NotPanics(t, n.Cleanup) + + if test.wantClose { + assert.True(t, m.closeCalled) + } else { + assert.False(t, m.closeCalled) + } + }) + } +} + +func TestNTPd_Check(t *testing.T) { + tests := map[string]struct { + prepare func() *NTPd + wantFail bool + }{ + "system: success, peers: success": { + wantFail: false, + prepare: func() *NTPd { return prepareNTPdWithMock(&mockClient{}, true) }, + }, + "system: success, list peers: fails": { + wantFail: false, + prepare: func() *NTPd { return prepareNTPdWithMock(&mockClient{errOnPeerIDs: true}, true) }, + }, + "system: success, peers info: fails": { + wantFail: false, + prepare: func() *NTPd { return prepareNTPdWithMock(&mockClient{errOnPeerInfo: true}, true) }, + }, + "system: fails": { + wantFail: true, + prepare: func() *NTPd { return prepareNTPdWithMock(&mockClient{errOnSystemInfo: true}, true) }, + }, + "fail on creating client": { + wantFail: true, + prepare: func() *NTPd { return prepareNTPdWithMock(nil, true) }, + }, + } + + for name, test := range tests { + t.Run(name, func(t *testing.T) { + n := test.prepare() + + require.NoError(t, n.Init()) + + if test.wantFail { + assert.Error(t, n.Check()) + } else { + assert.NoError(t, n.Check()) + } + }) + } + +} + +func TestNTPd_Collect(t *testing.T) { + tests := map[string]struct { + prepare func() *NTPd + expected map[string]int64 + expectedCharts int + }{ + "system: success, peers: success": { + prepare: func() *NTPd { return prepareNTPdWithMock(&mockClient{}, true) }, + expected: map[string]int64{ + "clk_jitter": 626000, + "clk_wander": 81000, + "mintc": 3000000, + "offset": -149638, + "peer_203.0.113.1_delay": 10464000, + "peer_203.0.113.1_dispersion": 5376000, + "peer_203.0.113.1_hmode": 3000000, + "peer_203.0.113.1_hpoll": 7000000, + "peer_203.0.113.1_jitter": 5204000, + "peer_203.0.113.1_offset": 312000, + "peer_203.0.113.1_pmode": 4000000, + "peer_203.0.113.1_ppoll": 7000000, + "peer_203.0.113.1_precision": -21000000, + "peer_203.0.113.1_rootdelay": 198000, + "peer_203.0.113.1_rootdisp": 14465000, + "peer_203.0.113.1_stratum": 2000000, + "peer_203.0.113.1_xleave": 95000, + "peer_203.0.113.2_delay": 10464000, + "peer_203.0.113.2_dispersion": 5376000, + "peer_203.0.113.2_hmode": 3000000, + "peer_203.0.113.2_hpoll": 7000000, + "peer_203.0.113.2_jitter": 5204000, + "peer_203.0.113.2_offset": 312000, + "peer_203.0.113.2_pmode": 4000000, + "peer_203.0.113.2_ppoll": 7000000, + "peer_203.0.113.2_precision": -21000000, + "peer_203.0.113.2_rootdelay": 198000, + "peer_203.0.113.2_rootdisp": 14465000, + "peer_203.0.113.2_stratum": 2000000, + "peer_203.0.113.2_xleave": 95000, + "peer_203.0.113.3_delay": 10464000, + "peer_203.0.113.3_dispersion": 5376000, + "peer_203.0.113.3_hmode": 3000000, + "peer_203.0.113.3_hpoll": 7000000, + "peer_203.0.113.3_jitter": 5204000, + "peer_203.0.113.3_offset": 312000, + "peer_203.0.113.3_pmode": 4000000, + "peer_203.0.113.3_ppoll": 7000000, + "peer_203.0.113.3_precision": -21000000, + "peer_203.0.113.3_rootdelay": 198000, + "peer_203.0.113.3_rootdisp": 14465000, + "peer_203.0.113.3_stratum": 2000000, + "peer_203.0.113.3_xleave": 95000, + "precision": -24000000, + "rootdelay": 10385000, + "rootdisp": 23404000, + "stratum": 2000000, + "sys_jitter": 1648010, + "tc": 7000000, + }, + expectedCharts: len(systemCharts) + len(peerChartsTmpl)*3, + }, + "system: success, list peers: fails": { + prepare: func() *NTPd { return prepareNTPdWithMock(&mockClient{errOnPeerIDs: true}, true) }, + expected: map[string]int64{ + "clk_jitter": 626000, + "clk_wander": 81000, + "mintc": 3000000, + "offset": -149638, + "precision": -24000000, + "rootdelay": 10385000, + "rootdisp": 23404000, + "stratum": 2000000, + "sys_jitter": 1648010, + "tc": 7000000, + }, + expectedCharts: len(systemCharts), + }, + "system: success, peers info: fails": { + prepare: func() *NTPd { return prepareNTPdWithMock(&mockClient{errOnPeerInfo: true}, true) }, + expected: map[string]int64{ + "clk_jitter": 626000, + "clk_wander": 81000, + "mintc": 3000000, + "offset": -149638, + "precision": -24000000, + "rootdelay": 10385000, + "rootdisp": 23404000, + "stratum": 2000000, + "sys_jitter": 1648010, + "tc": 7000000, + }, + expectedCharts: len(systemCharts), + }, + "system: fails": { + prepare: func() *NTPd { return prepareNTPdWithMock(&mockClient{errOnSystemInfo: true}, true) }, + expected: nil, + expectedCharts: len(systemCharts), + }, + "fail on creating client": { + prepare: func() *NTPd { return prepareNTPdWithMock(nil, true) }, + expected: nil, + expectedCharts: len(systemCharts), + }, + } + + for name, test := range tests { + t.Run(name, func(t *testing.T) { + n := test.prepare() + + require.NoError(t, n.Init()) + _ = n.Check() + + mx := n.Collect() + + assert.Equal(t, test.expected, mx) + assert.Equal(t, test.expectedCharts, len(*n.Charts())) + }) + } +} + +func prepareNTPdWithMock(m *mockClient, collectPeers bool) *NTPd { + n := New() + n.CollectPeers = collectPeers + if m == nil { + n.newClient = func(_ Config) (ntpConn, error) { return nil, errors.New("mock.newClient error") } + } else { + n.newClient = func(_ Config) (ntpConn, error) { return m, nil } + } + return n +} + +type mockClient struct { + errOnSystemInfo bool + errOnPeerInfo bool + errOnPeerIDs bool + closeCalled bool +} + +func (m *mockClient) systemInfo() (map[string]string, error) { + if m.errOnSystemInfo { + return nil, errors.New("mockClient.info() error") + } + + info := map[string]string{ + "rootdelay": "10.385", + "tc": "7", + "mintc": "3", + "processor": "x86_64", + "refid": "194.177.210.54", + "reftime": "0xe7504a10.74414244", + "clock": "0xe7504e80.8c46aa3f", + "peer": "14835", + "sys_jitter": "1.648010", + "leapsec": "201701010000", + "expire": "202306280000", + "leap": "0", + "stratum": "2", + "precision": "-24", + "offset": "-0.149638", + "frequency": "- 7.734", + "clk_wander": "0.081", + "tai": "37", + "version": "ntpd 4.2.8p15@1.3728-o Wed Sep 23 11:46:38 UTC 2020 (1)", + "rootdisp": "23.404", + "clk_jitter": "0.626", + "system": "Linux/5.10.0-19-amd64", + } + + return info, nil +} + +func (m *mockClient) peerInfo(id uint16) (map[string]string, error) { + if m.errOnPeerInfo { + return nil, errors.New("mockClient.peerInfo() error") + } + + info := map[string]string{ + "delay": "10.464", + "dispersion": "5.376", + "dstadr": "10.10.10.20", + "dstport": "123", + "filtdelay": "11.34 10.53 10.49 10.46 10.92 10.56 10.69 37.99", + "filtdisp": "0.00 2.01 4.01 5.93 7.89 9.84 11.81 13.73", + "filtoffset": "0.66 0.32 0.18 0.31 0.33 0.10 0.34 14.07", + "flash": "0x0", + "headway": "0", + "hmode": "3", + "hpoll": "7", + "jitter": "5.204", + "keyid": "0", + "leap": "0", + "offset": "0.312", + "pmode": "4", + "ppoll": "7", + "precision": "-21", + "reach": "0xff", + "rec": "0xe7504df8.74802284", + "refid": "193.93.164.193", + "reftime": "0xe7504b8b.0c98a518", + "rootdelay": "0.198", + "rootdisp": "14.465", + "srcadr": fmt.Sprintf("203.0.113.%d", id), + "srcport": "123", + "stratum": "2", + "unreach": "0", + "xleave": "0.095", + } + + return info, nil +} + +func (m *mockClient) peerIDs() ([]uint16, error) { + if m.errOnPeerIDs { + return nil, errors.New("mockClient.peerIDs() error") + } + return []uint16{1, 2, 3}, nil +} + +func (m *mockClient) close() { + m.closeCalled = true +} |