test: remove variable shadowing in TestDNS_ServiceLookup_ARecordLimits

pull/15740/head
R.B. Boyer 2 years ago
parent eb3ff8cf73
commit ee0ba0ef63

@ -12,12 +12,12 @@ import (
"testing"
"time"
"github.com/hashicorp/consul/agent/consul"
"github.com/hashicorp/serf/coordinate"
"github.com/miekg/dns"
"github.com/stretchr/testify/require"
"github.com/hashicorp/consul/agent/config"
"github.com/hashicorp/consul/agent/consul"
agentdns "github.com/hashicorp/consul/agent/dns"
"github.com/hashicorp/consul/agent/structs"
"github.com/hashicorp/consul/api"
@ -5168,9 +5168,10 @@ func testDNSServiceLookupResponseLimits(t *testing.T, answerLimit int, qType uin
defer a.Shutdown()
testrpc.WaitForTestAgent(t, a.RPC, "dc1")
choices := perfectlyRandomChoices(generateNumNodes, pctNodesWithIPv6)
for i := 0; i < generateNumNodes; i++ {
nodeAddress := fmt.Sprintf("127.0.0.%d", i+1)
if rand.Float64() < pctNodesWithIPv6 {
if choices[i] {
nodeAddress = fmt.Sprintf("fe80::%d", i+1)
}
args := &structs.RegisterRequest{
@ -5246,8 +5247,14 @@ func testDNSServiceLookupResponseLimits(t *testing.T, answerLimit int, qType uin
return true, nil
}
func checkDNSService(t *testing.T, generateNumNodes int, aRecordLimit int, qType uint16,
expectedResultsCount int, udpSize uint16) error {
func checkDNSService(
t *testing.T,
generateNumNodes int,
aRecordLimit int,
qType uint16,
expectedResultsCount int,
udpSize uint16,
) {
a := NewTestAgent(t, `
node_name = "test-node"
dns_config {
@ -5255,12 +5262,12 @@ func checkDNSService(t *testing.T, generateNumNodes int, aRecordLimit int, qType
udp_answer_limit = `+fmt.Sprintf("%d", aRecordLimit)+`
}
`)
defer a.Shutdown()
testrpc.WaitForTestAgent(t, a.RPC, "dc1")
choices := perfectlyRandomChoices(generateNumNodes, pctNodesWithIPv6)
for i := 0; i < generateNumNodes; i++ {
nodeAddress := fmt.Sprintf("127.0.0.%d", i+1)
if rand.Float64() < pctNodesWithIPv6 {
if choices[i] {
nodeAddress = fmt.Sprintf("fe80::%d", i+1)
}
args := &structs.RegisterRequest{
@ -5274,9 +5281,7 @@ func checkDNSService(t *testing.T, generateNumNodes int, aRecordLimit int, qType
}
var out struct{}
if err := a.RPC("Catalog.Register", args, &out); err != nil {
return fmt.Errorf("err: %v", err)
}
require.NoError(t, a.RPC("Catalog.Register", args, &out))
}
var id string
{
@ -5291,9 +5296,7 @@ func checkDNSService(t *testing.T, generateNumNodes int, aRecordLimit int, qType
},
}
if err := a.RPC("PreparedQuery.Apply", args, &id); err != nil {
return fmt.Errorf("err: %v", err)
}
require.NoError(t, a.RPC("PreparedQuery.Apply", args, &id))
}
// Look up the service directly and via prepared query.
@ -5303,28 +5306,29 @@ func checkDNSService(t *testing.T, generateNumNodes int, aRecordLimit int, qType
id + ".query.consul.",
}
for _, question := range questions {
m := new(dns.Msg)
question := question
t.Run("question: "+question, func(t *testing.T) {
m.SetQuestion(question, qType)
protocol := "tcp"
if udpSize > 0 {
protocol = "udp"
}
if udpSize > 512 {
m.SetEdns0(udpSize, true)
}
c := &dns.Client{Net: protocol, UDPSize: 8192}
in, _, err := c.Exchange(m, a.DNSAddr())
t.Logf("DNS Response for %+v - %+v", m, in)
if err != nil {
return fmt.Errorf("err: %v", err)
}
if len(in.Answer) != expectedResultsCount {
return fmt.Errorf("%d/%d answers received for type %v for %s (%s)", len(in.Answer), expectedResultsCount, qType, question, protocol)
}
}
m := new(dns.Msg)
return nil
m.SetQuestion(question, qType)
protocol := "tcp"
if udpSize > 0 {
protocol = "udp"
}
if udpSize > 512 {
m.SetEdns0(udpSize, true)
}
c := &dns.Client{Net: protocol, UDPSize: 8192}
in, _, err := c.Exchange(m, a.DNSAddr())
require.NoError(t, err)
t.Logf("DNS Response for %+v - %+v", m, in)
require.Equal(t, expectedResultsCount, len(in.Answer),
"%d/%d answers received for type %v for %s (%s)", len(in.Answer), expectedResultsCount, qType, question, protocol)
})
}
}
func TestDNS_ServiceLookup_ARecordLimits(t *testing.T) {
@ -5334,77 +5338,81 @@ func TestDNS_ServiceLookup_ARecordLimits(t *testing.T) {
t.Parallel()
tests := []struct {
name string
aRecordLimit int
expectedAResults int
expectedAAAAResults int
expectedSRVResults int
numNodesTotal int
udpSize uint16
udpAnswerLimit int
name string
aRecordLimit int
expectedAResults int
expectedAAAAResults int
expectedANYResults int
expectedSRVResults int
numNodesTotal int
udpSize uint16
_unused_udpAnswerLimit int // NOTE: this field is not used
}{
// UDP + EDNS
{"udp-edns-1", 1, 1, 1, 30, 30, 8192, 3},
{"udp-edns-2", 2, 2, 1, 30, 30, 8192, 3},
{"udp-edns-3", 3, 3, 1, 30, 30, 8192, 3},
{"udp-edns-4", 4, 4, 1, 30, 30, 8192, 3},
{"udp-edns-5", 5, 5, 1, 30, 30, 8192, 3},
{"udp-edns-6", 6, 6, 1, 30, 30, 8192, 3},
{"udp-edns-max", 6, 3, 3, 3, 3, 8192, 3},
{"udp-edns-1", 1, 1, 1, 1, 30, 30, 8192, 3},
{"udp-edns-2", 2, 2, 2, 2, 30, 30, 8192, 3},
{"udp-edns-3", 3, 3, 3, 3, 30, 30, 8192, 3},
{"udp-edns-4", 4, 4, 4, 4, 30, 30, 8192, 3},
{"udp-edns-5", 5, 5, 5, 5, 30, 30, 8192, 3},
{"udp-edns-6", 6, 6, 6, 6, 30, 30, 8192, 3},
{"udp-edns-max", 6, 2, 1, 3, 3, 3, 8192, 3},
// All UDP without EDNS have a limit of 2 answers due to udpAnswerLimit
// Even SRV records are limit to 2 records
{"udp-limit-1", 1, 1, 1, 1, 1, 512, 2},
{"udp-limit-2", 2, 2, 2, 2, 2, 512, 2},
{"udp-limit-1", 1, 1, 0, 1, 1, 1, 512, 2},
{"udp-limit-2", 2, 1, 1, 2, 2, 2, 512, 2},
// AAAA results limited by size of payload
{"udp-limit-3", 3, 2, 2, 2, 2, 512, 2},
{"udp-limit-4", 4, 2, 2, 2, 2, 512, 2},
{"udp-limit-5", 5, 2, 2, 2, 2, 512, 2},
{"udp-limit-6", 6, 2, 2, 2, 2, 512, 2},
{"udp-limit-max", 6, 2, 2, 2, 2, 512, 2},
{"udp-limit-3", 3, 1, 1, 2, 2, 2, 512, 2},
{"udp-limit-4", 4, 1, 1, 2, 2, 2, 512, 2},
{"udp-limit-5", 5, 1, 1, 2, 2, 2, 512, 2},
{"udp-limit-6", 6, 1, 1, 2, 2, 2, 512, 2},
{"udp-limit-max", 6, 1, 1, 2, 2, 2, 512, 2},
// All UDP without EDNS and no udpAnswerLimit
// Size of records is limited by UDP payload
{"udp-1", 1, 1, 1, 1, 1, 512, 0},
{"udp-2", 2, 2, 2, 2, 2, 512, 0},
{"udp-3", 3, 2, 2, 2, 2, 512, 0},
{"udp-4", 4, 2, 2, 2, 2, 512, 0},
{"udp-5", 5, 2, 2, 2, 2, 512, 0},
{"udp-6", 6, 2, 2, 2, 2, 512, 0},
{"udp-1", 1, 1, 0, 1, 1, 1, 512, 0},
{"udp-2", 2, 1, 1, 2, 2, 2, 512, 0},
{"udp-3", 3, 1, 1, 2, 2, 2, 512, 0},
{"udp-4", 4, 1, 1, 2, 2, 2, 512, 0},
{"udp-5", 5, 1, 1, 2, 2, 2, 512, 0},
{"udp-6", 6, 1, 1, 2, 2, 2, 512, 0},
// Only 3 A and 3 SRV records on 512 bytes
{"udp-max", 6, 2, 2, 2, 2, 512, 0},
{"udp-max", 6, 1, 1, 2, 2, 2, 512, 0},
{"tcp-1", 1, 1, 1, 30, 30, 0, 0},
{"tcp-2", 2, 2, 2, 30, 30, 0, 0},
{"tcp-3", 3, 3, 3, 30, 30, 0, 0},
{"tcp-4", 4, 4, 4, 30, 30, 0, 0},
{"tcp-5", 5, 5, 5, 30, 30, 0, 0},
{"tcp-6", 6, 6, 5, 30, 30, 0, 0},
{"tcp-max", 6, 2, 2, 2, 2, 0, 0},
{"tcp-1", 1, 1, 1, 1, 30, 30, 0, 0},
{"tcp-2", 2, 2, 2, 2, 30, 30, 0, 0},
{"tcp-3", 3, 3, 3, 3, 30, 30, 0, 0},
{"tcp-4", 4, 4, 4, 4, 30, 30, 0, 0},
{"tcp-5", 5, 5, 5, 5, 30, 30, 0, 0},
{"tcp-6", 6, 6, 6, 6, 30, 30, 0, 0},
{"tcp-max", 6, 1, 1, 2, 2, 2, 0, 0},
}
for _, test := range tests {
test := test // capture loop var
queriesLimited := []uint16{
dns.TypeA,
dns.TypeAAAA,
dns.TypeANY,
}
// All those queries should have at max queriesLimited elements
for idx, qType := range queriesLimited {
t.Run(fmt.Sprintf("ARecordLimit %d qType: %d", idx, qType), func(t *testing.T) {
t.Run(test.name, func(t *testing.T) {
t.Parallel()
// All those queries should have at max queriesLimited elements
t.Run("A", func(t *testing.T) {
t.Parallel()
err := checkDNSService(t, test.numNodesTotal, test.aRecordLimit, qType, test.expectedAResults, test.udpSize)
if err != nil {
t.Fatalf("Expected lookup %s to pass: %v", test.name, err)
}
checkDNSService(t, test.numNodesTotal, test.aRecordLimit, dns.TypeA, test.expectedAResults, test.udpSize)
})
t.Run("AAAA", func(t *testing.T) {
t.Parallel()
checkDNSService(t, test.numNodesTotal, test.aRecordLimit, dns.TypeAAAA, test.expectedAAAAResults, test.udpSize)
})
t.Run("ANY", func(t *testing.T) {
t.Parallel()
checkDNSService(t, test.numNodesTotal, test.aRecordLimit, dns.TypeANY, test.expectedANYResults, test.udpSize)
})
// No limits but the size of records for SRV records, since not subject to randomization issues
t.Run("SRV", func(t *testing.T) {
t.Parallel()
checkDNSService(t, test.expectedSRVResults, test.aRecordLimit, dns.TypeSRV, test.numNodesTotal, test.udpSize)
})
}
// No limits but the size of records for SRV records, since not subject to randomization issues
t.Run("SRV lookup limitARecord", func(t *testing.T) {
t.Parallel()
err := checkDNSService(t, test.expectedSRVResults, test.aRecordLimit, dns.TypeSRV, test.numNodesTotal, test.udpSize)
if err != nil {
t.Fatalf("Expected service SRV lookup %s to pass: %v", test.name, err)
}
})
}
}
@ -8277,3 +8285,72 @@ func TestECSNotGlobalError(t *testing.T) {
require.Equal(t, errNameNotFound, errors.Unwrap(e))
})
}
// perfectlyRandomChoices assigns exactly the provided fraction of size items a
// true value, and then presents a random permutation of those boolean values.
func perfectlyRandomChoices(size int, frac float64) []bool {
out := make([]bool, size)
max := int(float64(size) * frac)
for i := 0; i < max; i++ {
out[i] = true
}
rand.Shuffle(size, func(i, j int) {
out[i], out[j] = out[j], out[i]
})
return out
}
func TestPerfectlyRandomChoices(t *testing.T) {
count := func(got []bool) int {
var x int
for _, v := range got {
if v {
x++
}
}
return x
}
type testcase struct {
size int
frac float64
expect int
}
run := func(t *testing.T, tc testcase) {
got := perfectlyRandomChoices(tc.size, tc.frac)
require.Equal(t, tc.expect, count(got))
}
cases := []testcase{
// 100%
{0, 1, 0},
{1, 1, 1},
{2, 1, 2},
{3, 1, 3},
{5, 1, 5},
// 50%
{0, 0.5, 0},
{1, 0.5, 0},
{2, 0.5, 1},
{3, 0.5, 1},
{5, 0.5, 2},
// 10%
{0, 0.1, 0},
{1, 0.1, 0},
{2, 0.1, 0},
{3, 0.1, 0},
{5, 0.1, 0},
{10, 0.1, 1},
{11, 0.1, 1},
{15, 0.1, 1},
}
for _, tc := range cases {
t.Run(fmt.Sprintf("size=%d frac=%g", tc.size, tc.frac), func(t *testing.T) {
run(t, tc)
})
}
}

Loading…
Cancel
Save