github.com/netdata/go.d.plugin@v0.58.1/modules/dnsquery/dnsquery_test.go (about) 1 // SPDX-License-Identifier: GPL-3.0-or-later 2 3 package dnsquery 4 5 import ( 6 "errors" 7 "testing" 8 "time" 9 10 "github.com/netdata/go.d.plugin/agent/module" 11 "github.com/netdata/go.d.plugin/pkg/web" 12 13 "github.com/miekg/dns" 14 "github.com/stretchr/testify/assert" 15 "github.com/stretchr/testify/require" 16 ) 17 18 func TestNew(t *testing.T) { 19 assert.Implements(t, (*module.Module)(nil), New()) 20 } 21 22 func TestDNSQuery_Init(t *testing.T) { 23 tests := map[string]struct { 24 wantFail bool 25 config Config 26 }{ 27 "success when all set": { 28 wantFail: false, 29 config: Config{ 30 Domains: []string{"example.com"}, 31 Servers: []string{"192.0.2.0"}, 32 Network: "udp", 33 RecordTypes: []string{"A"}, 34 Port: 53, 35 Timeout: web.Duration{Duration: time.Second}, 36 }, 37 }, 38 "success when using deprecated record_type": { 39 wantFail: false, 40 config: Config{ 41 Domains: []string{"example.com"}, 42 Servers: []string{"192.0.2.0"}, 43 Network: "udp", 44 RecordType: "A", 45 Port: 53, 46 Timeout: web.Duration{Duration: time.Second}, 47 }, 48 }, 49 "fail with default": { 50 wantFail: true, 51 config: New().Config, 52 }, 53 "fail when domains not set": { 54 wantFail: true, 55 config: Config{ 56 Domains: nil, 57 Servers: []string{"192.0.2.0"}, 58 Network: "udp", 59 RecordTypes: []string{"A"}, 60 Port: 53, 61 Timeout: web.Duration{Duration: time.Second}, 62 }, 63 }, 64 "fail when servers not set": { 65 wantFail: true, 66 config: Config{ 67 Domains: []string{"example.com"}, 68 Servers: nil, 69 Network: "udp", 70 RecordTypes: []string{"A"}, 71 Port: 53, 72 Timeout: web.Duration{Duration: time.Second}, 73 }, 74 }, 75 "fail when network is invalid": { 76 wantFail: true, 77 config: Config{ 78 Domains: []string{"example.com"}, 79 Servers: []string{"192.0.2.0"}, 80 Network: "gcp", 81 RecordTypes: []string{"A"}, 82 Port: 53, 83 Timeout: web.Duration{Duration: time.Second}, 84 }, 85 }, 86 "fail when record_type is invalid": { 87 wantFail: true, 88 config: Config{ 89 Domains: []string{"example.com"}, 90 Servers: []string{"192.0.2.0"}, 91 Network: "udp", 92 RecordTypes: []string{"B"}, 93 Port: 53, 94 Timeout: web.Duration{Duration: time.Second}, 95 }, 96 }, 97 } 98 99 for name, test := range tests { 100 t.Run(name, func(t *testing.T) { 101 dq := New() 102 dq.Config = test.config 103 104 if test.wantFail { 105 assert.False(t, dq.Init()) 106 } else { 107 assert.True(t, dq.Init()) 108 } 109 }) 110 } 111 } 112 113 func TestDNSQuery_Check(t *testing.T) { 114 tests := map[string]struct { 115 wantFail bool 116 prepare func() *DNSQuery 117 }{ 118 "success when DNS query successful": { 119 wantFail: false, 120 prepare: caseDNSClientOK, 121 }, 122 "success when DNS query returns an error": { 123 wantFail: false, 124 prepare: caseDNSClientErr, 125 }, 126 } 127 128 for name, test := range tests { 129 t.Run(name, func(t *testing.T) { 130 dq := test.prepare() 131 132 require.True(t, dq.Init()) 133 134 if test.wantFail { 135 assert.False(t, dq.Check()) 136 } else { 137 assert.True(t, dq.Check()) 138 } 139 }) 140 } 141 } 142 143 func TestDNSQuery_Charts(t *testing.T) { 144 dq := New() 145 146 dq.Domains = []string{"google.com"} 147 dq.Servers = []string{"192.0.2.0", "192.0.2.1"} 148 require.True(t, dq.Init()) 149 150 assert.NotNil(t, dq.Charts()) 151 assert.Len(t, *dq.Charts(), len(dnsChartsTmpl)*len(dq.Servers)) 152 } 153 154 func TestDNSQuery_Collect(t *testing.T) { 155 tests := map[string]struct { 156 prepare func() *DNSQuery 157 wantMetrics map[string]int64 158 }{ 159 "success when DNS query successful": { 160 prepare: caseDNSClientOK, 161 wantMetrics: map[string]int64{ 162 "server_192.0.2.0_record_A_query_status_dns_error": 0, 163 "server_192.0.2.0_record_A_query_status_network_error": 0, 164 "server_192.0.2.0_record_A_query_status_success": 1, 165 "server_192.0.2.0_record_A_query_time": 1000000000, 166 "server_192.0.2.1_record_A_query_status_dns_error": 0, 167 "server_192.0.2.1_record_A_query_status_network_error": 0, 168 "server_192.0.2.1_record_A_query_status_success": 1, 169 "server_192.0.2.1_record_A_query_time": 1000000000, 170 }, 171 }, 172 "fail when DNS query returns an error": { 173 prepare: caseDNSClientErr, 174 wantMetrics: map[string]int64{ 175 "server_192.0.2.0_record_A_query_status_dns_error": 0, 176 "server_192.0.2.0_record_A_query_status_network_error": 1, 177 "server_192.0.2.0_record_A_query_status_success": 0, 178 "server_192.0.2.1_record_A_query_status_dns_error": 0, 179 "server_192.0.2.1_record_A_query_status_network_error": 1, 180 "server_192.0.2.1_record_A_query_status_success": 0, 181 }, 182 }, 183 } 184 185 for name, test := range tests { 186 t.Run(name, func(t *testing.T) { 187 dq := test.prepare() 188 189 require.True(t, dq.Init()) 190 191 mx := dq.Collect() 192 193 require.Equal(t, test.wantMetrics, mx) 194 }) 195 } 196 } 197 198 func caseDNSClientOK() *DNSQuery { 199 dq := New() 200 dq.Domains = []string{"example.com"} 201 dq.Servers = []string{"192.0.2.0", "192.0.2.1"} 202 dq.newDNSClient = func(_ string, _ time.Duration) dnsClient { 203 return mockDNSClient{errOnExchange: false} 204 } 205 return dq 206 } 207 208 func caseDNSClientErr() *DNSQuery { 209 dq := New() 210 dq.Domains = []string{"example.com"} 211 dq.Servers = []string{"192.0.2.0", "192.0.2.1"} 212 dq.newDNSClient = func(_ string, _ time.Duration) dnsClient { 213 return mockDNSClient{errOnExchange: true} 214 } 215 return dq 216 } 217 218 type mockDNSClient struct { 219 errOnExchange bool 220 } 221 222 func (m mockDNSClient) Exchange(_ *dns.Msg, _ string) (response *dns.Msg, rtt time.Duration, err error) { 223 if m.errOnExchange { 224 return nil, time.Second, errors.New("mock.Exchange() error") 225 } 226 return nil, time.Second, nil 227 }