github.com/netdata/go.d.plugin@v0.58.1/modules/ntpd/ntpd_test.go (about) 1 // SPDX-License-Identifier: GPL-3.0-or-later 2 3 package ntpd 4 5 import ( 6 "errors" 7 "fmt" 8 "testing" 9 10 "github.com/stretchr/testify/assert" 11 "github.com/stretchr/testify/require" 12 ) 13 14 func TestNTPd_Init(t *testing.T) { 15 tests := map[string]struct { 16 config Config 17 wantFail bool 18 }{ 19 "default config": { 20 config: New().Config, 21 }, 22 "unset 'address'": { 23 wantFail: true, 24 config: Config{ 25 Address: "", 26 }, 27 }, 28 } 29 30 for name, test := range tests { 31 t.Run(name, func(t *testing.T) { 32 n := New() 33 n.Config = test.config 34 35 if test.wantFail { 36 assert.False(t, n.Init()) 37 } else { 38 assert.True(t, n.Init()) 39 } 40 }) 41 } 42 } 43 44 func TestNTPd_Charts(t *testing.T) { 45 assert.Equal(t, len(systemCharts), len(*New().Charts())) 46 } 47 48 func TestNTPd_Cleanup(t *testing.T) { 49 tests := map[string]struct { 50 prepare func(*NTPd) 51 wantClose bool 52 }{ 53 "after New": { 54 wantClose: false, 55 prepare: func(*NTPd) {}, 56 }, 57 "after Init": { 58 wantClose: false, 59 prepare: func(n *NTPd) { n.Init() }, 60 }, 61 "after Check": { 62 wantClose: true, 63 prepare: func(n *NTPd) { n.Init(); n.Check() }, 64 }, 65 "after Collect": { 66 wantClose: true, 67 prepare: func(n *NTPd) { n.Init(); n.Collect() }, 68 }, 69 } 70 71 for name, test := range tests { 72 t.Run(name, func(t *testing.T) { 73 m := &mockClient{} 74 n := prepareNTPdWithMock(m, true) 75 test.prepare(n) 76 77 require.NotPanics(t, n.Cleanup) 78 79 if test.wantClose { 80 assert.True(t, m.closeCalled) 81 } else { 82 assert.False(t, m.closeCalled) 83 } 84 }) 85 } 86 } 87 88 func TestNTPd_Check(t *testing.T) { 89 tests := map[string]struct { 90 prepare func() *NTPd 91 wantFail bool 92 }{ 93 "system: success, peers: success": { 94 wantFail: false, 95 prepare: func() *NTPd { return prepareNTPdWithMock(&mockClient{}, true) }, 96 }, 97 "system: success, list peers: fails": { 98 wantFail: false, 99 prepare: func() *NTPd { return prepareNTPdWithMock(&mockClient{errOnPeerIDs: true}, true) }, 100 }, 101 "system: success, peers info: fails": { 102 wantFail: false, 103 prepare: func() *NTPd { return prepareNTPdWithMock(&mockClient{errOnPeerInfo: true}, true) }, 104 }, 105 "system: fails": { 106 wantFail: true, 107 prepare: func() *NTPd { return prepareNTPdWithMock(&mockClient{errOnSystemInfo: true}, true) }, 108 }, 109 "fail on creating client": { 110 wantFail: true, 111 prepare: func() *NTPd { return prepareNTPdWithMock(nil, true) }, 112 }, 113 } 114 115 for name, test := range tests { 116 t.Run(name, func(t *testing.T) { 117 n := test.prepare() 118 119 require.True(t, n.Init()) 120 121 if test.wantFail { 122 assert.False(t, n.Check()) 123 } else { 124 assert.True(t, n.Check()) 125 } 126 }) 127 } 128 129 } 130 131 func TestNTPd_Collect(t *testing.T) { 132 tests := map[string]struct { 133 prepare func() *NTPd 134 expected map[string]int64 135 expectedCharts int 136 }{ 137 "system: success, peers: success": { 138 prepare: func() *NTPd { return prepareNTPdWithMock(&mockClient{}, true) }, 139 expected: map[string]int64{ 140 "clk_jitter": 626000, 141 "clk_wander": 81000, 142 "mintc": 3000000, 143 "offset": -149638, 144 "peer_203.0.113.1_delay": 10464000, 145 "peer_203.0.113.1_dispersion": 5376000, 146 "peer_203.0.113.1_hmode": 3000000, 147 "peer_203.0.113.1_hpoll": 7000000, 148 "peer_203.0.113.1_jitter": 5204000, 149 "peer_203.0.113.1_offset": 312000, 150 "peer_203.0.113.1_pmode": 4000000, 151 "peer_203.0.113.1_ppoll": 7000000, 152 "peer_203.0.113.1_precision": -21000000, 153 "peer_203.0.113.1_rootdelay": 198000, 154 "peer_203.0.113.1_rootdisp": 14465000, 155 "peer_203.0.113.1_stratum": 2000000, 156 "peer_203.0.113.1_xleave": 95000, 157 "peer_203.0.113.2_delay": 10464000, 158 "peer_203.0.113.2_dispersion": 5376000, 159 "peer_203.0.113.2_hmode": 3000000, 160 "peer_203.0.113.2_hpoll": 7000000, 161 "peer_203.0.113.2_jitter": 5204000, 162 "peer_203.0.113.2_offset": 312000, 163 "peer_203.0.113.2_pmode": 4000000, 164 "peer_203.0.113.2_ppoll": 7000000, 165 "peer_203.0.113.2_precision": -21000000, 166 "peer_203.0.113.2_rootdelay": 198000, 167 "peer_203.0.113.2_rootdisp": 14465000, 168 "peer_203.0.113.2_stratum": 2000000, 169 "peer_203.0.113.2_xleave": 95000, 170 "peer_203.0.113.3_delay": 10464000, 171 "peer_203.0.113.3_dispersion": 5376000, 172 "peer_203.0.113.3_hmode": 3000000, 173 "peer_203.0.113.3_hpoll": 7000000, 174 "peer_203.0.113.3_jitter": 5204000, 175 "peer_203.0.113.3_offset": 312000, 176 "peer_203.0.113.3_pmode": 4000000, 177 "peer_203.0.113.3_ppoll": 7000000, 178 "peer_203.0.113.3_precision": -21000000, 179 "peer_203.0.113.3_rootdelay": 198000, 180 "peer_203.0.113.3_rootdisp": 14465000, 181 "peer_203.0.113.3_stratum": 2000000, 182 "peer_203.0.113.3_xleave": 95000, 183 "precision": -24000000, 184 "rootdelay": 10385000, 185 "rootdisp": 23404000, 186 "stratum": 2000000, 187 "sys_jitter": 1648010, 188 "tc": 7000000, 189 }, 190 expectedCharts: len(systemCharts) + len(peerChartsTmpl)*3, 191 }, 192 "system: success, list peers: fails": { 193 prepare: func() *NTPd { return prepareNTPdWithMock(&mockClient{errOnPeerIDs: true}, true) }, 194 expected: map[string]int64{ 195 "clk_jitter": 626000, 196 "clk_wander": 81000, 197 "mintc": 3000000, 198 "offset": -149638, 199 "precision": -24000000, 200 "rootdelay": 10385000, 201 "rootdisp": 23404000, 202 "stratum": 2000000, 203 "sys_jitter": 1648010, 204 "tc": 7000000, 205 }, 206 expectedCharts: len(systemCharts), 207 }, 208 "system: success, peers info: fails": { 209 prepare: func() *NTPd { return prepareNTPdWithMock(&mockClient{errOnPeerInfo: true}, true) }, 210 expected: map[string]int64{ 211 "clk_jitter": 626000, 212 "clk_wander": 81000, 213 "mintc": 3000000, 214 "offset": -149638, 215 "precision": -24000000, 216 "rootdelay": 10385000, 217 "rootdisp": 23404000, 218 "stratum": 2000000, 219 "sys_jitter": 1648010, 220 "tc": 7000000, 221 }, 222 expectedCharts: len(systemCharts), 223 }, 224 "system: fails": { 225 prepare: func() *NTPd { return prepareNTPdWithMock(&mockClient{errOnSystemInfo: true}, true) }, 226 expected: nil, 227 expectedCharts: len(systemCharts), 228 }, 229 "fail on creating client": { 230 prepare: func() *NTPd { return prepareNTPdWithMock(nil, true) }, 231 expected: nil, 232 expectedCharts: len(systemCharts), 233 }, 234 } 235 236 for name, test := range tests { 237 t.Run(name, func(t *testing.T) { 238 n := test.prepare() 239 240 require.True(t, n.Init()) 241 _ = n.Check() 242 243 mx := n.Collect() 244 245 assert.Equal(t, test.expected, mx) 246 assert.Equal(t, test.expectedCharts, len(*n.Charts())) 247 }) 248 } 249 } 250 251 func prepareNTPdWithMock(m *mockClient, collectPeers bool) *NTPd { 252 n := New() 253 n.CollectPeers = collectPeers 254 if m == nil { 255 n.newClient = func(_ Config) (ntpConn, error) { return nil, errors.New("mock.newClient error") } 256 } else { 257 n.newClient = func(_ Config) (ntpConn, error) { return m, nil } 258 } 259 return n 260 } 261 262 type mockClient struct { 263 errOnSystemInfo bool 264 errOnPeerInfo bool 265 errOnPeerIDs bool 266 closeCalled bool 267 } 268 269 func (m *mockClient) systemInfo() (map[string]string, error) { 270 if m.errOnSystemInfo { 271 return nil, errors.New("mockClient.info() error") 272 } 273 274 info := map[string]string{ 275 "rootdelay": "10.385", 276 "tc": "7", 277 "mintc": "3", 278 "processor": "x86_64", 279 "refid": "194.177.210.54", 280 "reftime": "0xe7504a10.74414244", 281 "clock": "0xe7504e80.8c46aa3f", 282 "peer": "14835", 283 "sys_jitter": "1.648010", 284 "leapsec": "201701010000", 285 "expire": "202306280000", 286 "leap": "0", 287 "stratum": "2", 288 "precision": "-24", 289 "offset": "-0.149638", 290 "frequency": "- 7.734", 291 "clk_wander": "0.081", 292 "tai": "37", 293 "version": "ntpd 4.2.8p15@1.3728-o Wed Sep 23 11:46:38 UTC 2020 (1)", 294 "rootdisp": "23.404", 295 "clk_jitter": "0.626", 296 "system": "Linux/5.10.0-19-amd64", 297 } 298 299 return info, nil 300 } 301 302 func (m *mockClient) peerInfo(id uint16) (map[string]string, error) { 303 if m.errOnPeerInfo { 304 return nil, errors.New("mockClient.peerInfo() error") 305 } 306 307 info := map[string]string{ 308 "delay": "10.464", 309 "dispersion": "5.376", 310 "dstadr": "10.10.10.20", 311 "dstport": "123", 312 "filtdelay": "11.34 10.53 10.49 10.46 10.92 10.56 10.69 37.99", 313 "filtdisp": "0.00 2.01 4.01 5.93 7.89 9.84 11.81 13.73", 314 "filtoffset": "0.66 0.32 0.18 0.31 0.33 0.10 0.34 14.07", 315 "flash": "0x0", 316 "headway": "0", 317 "hmode": "3", 318 "hpoll": "7", 319 "jitter": "5.204", 320 "keyid": "0", 321 "leap": "0", 322 "offset": "0.312", 323 "pmode": "4", 324 "ppoll": "7", 325 "precision": "-21", 326 "reach": "0xff", 327 "rec": "0xe7504df8.74802284", 328 "refid": "193.93.164.193", 329 "reftime": "0xe7504b8b.0c98a518", 330 "rootdelay": "0.198", 331 "rootdisp": "14.465", 332 "srcadr": fmt.Sprintf("203.0.113.%d", id), 333 "srcport": "123", 334 "stratum": "2", 335 "unreach": "0", 336 "xleave": "0.095", 337 } 338 339 return info, nil 340 } 341 342 func (m *mockClient) peerIDs() ([]uint16, error) { 343 if m.errOnPeerIDs { 344 return nil, errors.New("mockClient.peerIDs() error") 345 } 346 return []uint16{1, 2, 3}, nil 347 } 348 349 func (m *mockClient) close() { 350 m.closeCalled = true 351 }