Fix TestDNS_ServiceLookup_ARecordLimits so that it only creates test agents the minimal amount of time (#21608)

* get rid of unused column

* get rid of duplicate section now that deletion of unused column makes the section duplicate..

* explicit set protocol rathern than infer it in checkDNSService

* explicit have attribute for whether to set EDNS0 in the test cases  rathern than infer it in checkDNSService

* now modify so that test agents are only created for each unique configuration which is based on the a_record_limit.

* Fix TestDNS_ServiceLookup_AnswerLimits  so that it only creates test agents the minimal amount of time. (#21609)

Fix TestDNS_ServiceLookup_AnswerLimits  so that it only creates test agents the minimal amount of time
pull/21614/head
John Murret 3 months ago committed by GitHub
parent e2bb1b76cc
commit f76da16000
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -2919,62 +2919,8 @@ func TestDNS_ServiceLookup_LargeResponses(t *testing.T) {
} }
} }
func testDNSServiceLookupResponseLimits(t *testing.T, answerLimit int, qType uint16, func testDNSServiceLookupResponseLimits(questions []string, answerLimit int, qType uint16,
expectedService, expectedQuery, expectedQueryID int, additionalHCL string) (bool, error) { expectedService, expectedQuery, expectedQueryID int, a *TestAgent) (bool, error) {
a := NewTestAgent(t, `
node_name = "test-node"
dns_config {
udp_answer_limit = `+fmt.Sprintf("%d", answerLimit)+`
}
`+additionalHCL)
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 choices[i] {
nodeAddress = fmt.Sprintf("fe80::%d", i+1)
}
args := &structs.RegisterRequest{
Datacenter: "dc1",
Node: fmt.Sprintf("foo%d", i),
Address: nodeAddress,
Service: &structs.NodeService{
Service: "api-tier",
Port: 8080,
},
}
var out struct{}
if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil {
return false, fmt.Errorf("err: %v", err)
}
}
var id string
{
args := &structs.PreparedQueryRequest{
Datacenter: "dc1",
Op: structs.PreparedQueryCreate,
Query: &structs.PreparedQuery{
Name: "api-tier",
Service: structs.ServiceQuery{
Service: "api-tier",
},
},
}
if err := a.RPC(context.Background(), "PreparedQuery.Apply", args, &id); err != nil {
return false, fmt.Errorf("err: %v", err)
}
}
// Look up the service directly and via prepared query.
questions := []string{
"api-tier.service.consul.",
"api-tier.query.consul.",
id + ".query.consul.",
}
for idx, question := range questions { for idx, question := range questions {
m := new(dns.Msg) m := new(dns.Msg)
m.SetQuestion(question, qType) m.SetQuestion(question, qType)
@ -3011,23 +2957,38 @@ func testDNSServiceLookupResponseLimits(t *testing.T, answerLimit int, qType uin
func checkDNSService( func checkDNSService(
t *testing.T, t *testing.T,
generateNumNodes int, protocol string,
aRecordLimit int, questions []string,
a *TestAgent,
qType uint16, qType uint16,
expectedResultsCount int, expectedResultsCount int,
udpSize uint16, udpSize uint16,
setEDNS0 bool,
) { ) {
a := NewTestAgent(t, ` for _, question := range questions {
node_name = "test-node" t.Run("question: "+question, func(t *testing.T) {
dns_config {
a_record_limit = `+fmt.Sprintf("%d", aRecordLimit)+` m := new(dns.Msg)
udp_answer_limit = `+fmt.Sprintf("%d", aRecordLimit)+`
m.SetQuestion(question, qType)
if setEDNS0 {
m.SetEdns0(udpSize, true)
} }
`) c := &dns.Client{Net: protocol, UDPSize: udpSize}
defer a.Shutdown() in, _, err := c.Exchange(m, a.DNSAddr())
testrpc.WaitForTestAgent(t, a.RPC, "dc1") 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 registerServicesAndPreparedQuery(t *testing.T, generateNumNodes int, a *TestAgent, serviceUniquenessKey string) []string {
choices := perfectlyRandomChoices(generateNumNodes, pctNodesWithIPv6) choices := perfectlyRandomChoices(generateNumNodes, pctNodesWithIPv6)
serviceName := fmt.Sprintf("api-tier-%s", serviceUniquenessKey)
for i := 0; i < generateNumNodes; i++ { for i := 0; i < generateNumNodes; i++ {
nodeAddress := fmt.Sprintf("127.0.0.%d", i+1) nodeAddress := fmt.Sprintf("127.0.0.%d", i+1)
if choices[i] { if choices[i] {
@ -3038,7 +2999,7 @@ func checkDNSService(
Node: fmt.Sprintf("foo%d", i), Node: fmt.Sprintf("foo%d", i),
Address: nodeAddress, Address: nodeAddress,
Service: &structs.NodeService{ Service: &structs.NodeService{
Service: "api-tier", Service: serviceName,
Port: 8080, Port: 8080,
}, },
} }
@ -3046,61 +3007,42 @@ func checkDNSService(
var out struct{} var out struct{}
require.NoError(t, a.RPC(context.Background(), "Catalog.Register", args, &out)) require.NoError(t, a.RPC(context.Background(), "Catalog.Register", args, &out))
} }
var id string var preparedQueryID string
{ {
args := &structs.PreparedQueryRequest{ args := &structs.PreparedQueryRequest{
Datacenter: "dc1", Datacenter: "dc1",
Op: structs.PreparedQueryCreate, Op: structs.PreparedQueryCreate,
Query: &structs.PreparedQuery{ Query: &structs.PreparedQuery{
Name: "api-tier", Name: serviceName,
Service: structs.ServiceQuery{ Service: structs.ServiceQuery{
Service: "api-tier", Service: serviceName,
}, },
}, },
} }
require.NoError(t, a.RPC(context.Background(), "PreparedQuery.Apply", args, &id)) require.NoError(t, a.RPC(context.Background(), "PreparedQuery.Apply", args, &preparedQueryID))
} }
// Look up the service directly and via prepared query. // Look up the service directly and via prepared query.
questions := []string{ questions := []string{
"api-tier.service.consul.", fmt.Sprintf("%s.service.consul.", serviceName),
"api-tier.query.consul.", fmt.Sprintf("%s.query.consul.", serviceName),
id + ".query.consul.", preparedQueryID + ".query.consul.",
}
for _, question := range questions {
question := question
t.Run("question: "+question, func(t *testing.T) {
m := new(dns.Msg)
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)
})
} }
return questions
} }
func TestDNS_ServiceLookup_ARecordLimits(t *testing.T) { func TestDNS_ServiceLookup_ARecordLimits(t *testing.T) {
if testing.Short() { if testing.Short() {
t.Skip("too slow for testing.Short") t.Skip("too slow for testing.Short")
} }
const (
UDP = "udp"
TCP = "tcp"
)
tests := []struct { type testCase struct {
name string protocol string
aRecordLimit int aRecordLimit int
expectedAResults int expectedAResults int
expectedAAAAResults int expectedAAAAResults int
@ -3108,68 +3050,90 @@ func TestDNS_ServiceLookup_ARecordLimits(t *testing.T) {
expectedSRVResults int expectedSRVResults int
numNodesTotal int numNodesTotal int
udpSize uint16 udpSize uint16
_unused_udpAnswerLimit int // NOTE: this field is not used setEDNS0 bool
}{ }
type aRecordLimit struct {
name string
limit int
}
tests := map[string]testCase{
// UDP + EDNS // UDP + EDNS
{"udp-edns-1", 1, 1, 1, 1, 30, 30, 8192, 3}, "udp-edns-1": {UDP, 1, 1, 1, 1, 30, 30, 8192, true},
{"udp-edns-2", 2, 2, 2, 2, 30, 30, 8192, 3}, "udp-edns-2": {UDP, 2, 2, 2, 2, 30, 30, 8192, true},
{"udp-edns-3", 3, 3, 3, 3, 30, 30, 8192, 3}, "udp-edns-3": {UDP, 3, 3, 3, 3, 30, 30, 8192, true},
{"udp-edns-4", 4, 4, 4, 4, 30, 30, 8192, 3}, "udp-edns-4": {UDP, 4, 4, 4, 4, 30, 30, 8192, true},
{"udp-edns-5", 5, 5, 5, 5, 30, 30, 8192, 3}, "udp-edns-5": {UDP, 5, 5, 5, 5, 30, 30, 8192, true},
{"udp-edns-6", 6, 6, 6, 6, 30, 30, 8192, 3}, "udp-edns-6": {UDP, 6, 6, 6, 6, 30, 30, 8192, true},
{"udp-edns-max", 6, 2, 1, 3, 3, 3, 8192, 3}, "udp-edns-max": {UDP, 6, 2, 1, 3, 3, 3, 8192, true},
// 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, 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, 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 // All UDP without EDNS and no udpAnswerLimit
// Size of records is limited by UDP payload // Size of records is limited by UDP payload
{"udp-1", 1, 1, 0, 1, 1, 1, 512, 0}, "udp-1": {UDP, 1, 1, 0, 1, 1, 1, 512, false},
{"udp-2", 2, 1, 1, 2, 2, 2, 512, 0}, "udp-2": {UDP, 2, 1, 1, 2, 2, 2, 512, false},
{"udp-3", 3, 1, 1, 2, 2, 2, 512, 0}, "udp-3": {UDP, 3, 1, 1, 2, 2, 2, 512, false},
{"udp-4", 4, 1, 1, 2, 2, 2, 512, 0}, "udp-4": {UDP, 4, 1, 1, 2, 2, 2, 512, false},
{"udp-5", 5, 1, 1, 2, 2, 2, 512, 0}, "udp-5": {UDP, 5, 1, 1, 2, 2, 2, 512, false},
{"udp-6", 6, 1, 1, 2, 2, 2, 512, 0}, "udp-6": {UDP, 6, 1, 1, 2, 2, 2, 512, false},
// Only 3 A and 3 SRV records on 512 bytes // Only 3 A and 3 SRV records on 512 bytes
{"udp-max", 6, 1, 1, 2, 2, 2, 512, 0}, "udp-max": {UDP, 6, 1, 1, 2, 2, 2, 512, false},
{"tcp-1", 1, 1, 1, 1, 30, 30, 0, 0}, "tcp-1": {TCP, 1, 1, 1, 1, 30, 30, 0, false},
{"tcp-2", 2, 2, 2, 2, 30, 30, 0, 0}, "tcp-2": {TCP, 2, 2, 2, 2, 30, 30, 0, false},
{"tcp-3", 3, 3, 3, 3, 30, 30, 0, 0}, "tcp-3": {TCP, 3, 3, 3, 3, 30, 30, 0, false},
{"tcp-4", 4, 4, 4, 4, 30, 30, 0, 0}, "tcp-4": {TCP, 4, 4, 4, 4, 30, 30, 0, false},
{"tcp-5", 5, 5, 5, 5, 30, 30, 0, 0}, "tcp-5": {TCP, 5, 5, 5, 5, 30, 30, 0, false},
{"tcp-6", 6, 6, 6, 6, 30, 30, 0, 0}, "tcp-6": {TCP, 6, 6, 6, 6, 30, 30, 0, false},
{"tcp-max", 6, 1, 1, 2, 2, 2, 0, 0}, "tcp-max": {TCP, 6, 1, 1, 2, 2, 2, 0, false},
}
for _, recordLimit := range []aRecordLimit{
{"1", 1},
{"2", 2},
{"3", 3},
{"4", 4},
{"5", 5},
{"6", 6},
{"max", 6},
} {
t.Run("record-limit-"+recordLimit.name, func(t *testing.T) {
a := NewTestAgent(t, `
node_name = "test-node"
dns_config {
a_record_limit = `+fmt.Sprintf("%d", recordLimit.limit)+`
udp_answer_limit = `+fmt.Sprintf("%d", recordLimit.limit)+`
} }
for _, test := range tests { `)
test := test // capture loop var
t.Run(test.name, func(t *testing.T) { defer a.Shutdown()
testrpc.WaitForTestAgent(t, a.RPC, "dc1")
// All those queries should have at max queriesLimited elements for _, testName := range []string{
fmt.Sprintf("udp-edns-%s", recordLimit.name),
fmt.Sprintf("udp-%s", recordLimit.name),
fmt.Sprintf("tcp-%s", recordLimit.name),
} {
t.Run(testName, func(t *testing.T) {
test := tests[testName]
questions := registerServicesAndPreparedQuery(t, test.numNodesTotal, a, testName)
t.Run("A", func(t *testing.T) { t.Run("A", func(t *testing.T) {
checkDNSService(t, test.numNodesTotal, test.aRecordLimit, dns.TypeA, test.expectedAResults, test.udpSize) checkDNSService(t, test.protocol, questions, a, dns.TypeA, test.expectedAResults, test.udpSize, test.setEDNS0)
}) })
t.Run("AAAA", func(t *testing.T) { t.Run("AAAA", func(t *testing.T) {
checkDNSService(t, test.numNodesTotal, test.aRecordLimit, dns.TypeAAAA, test.expectedAAAAResults, test.udpSize) checkDNSService(t, test.protocol, questions, a, dns.TypeAAAA, test.expectedAAAAResults, test.udpSize, test.setEDNS0)
}) })
t.Run("ANY", func(t *testing.T) { t.Run("ANY", func(t *testing.T) {
checkDNSService(t, test.numNodesTotal, test.aRecordLimit, dns.TypeANY, test.expectedANYResults, test.udpSize) checkDNSService(t, test.protocol, questions, a, dns.TypeANY, test.expectedANYResults, test.udpSize, test.setEDNS0)
}) })
// No limits but the size of records for SRV records, since not subject to randomization issues // No limits but the size of records for SRV records, since not subject to randomization issues
t.Run("SRV", func(t *testing.T) { t.Run("SRV", func(t *testing.T) {
checkDNSService(t, test.expectedSRVResults, test.aRecordLimit, dns.TypeSRV, test.numNodesTotal, test.udpSize) checkDNSService(t, test.protocol, questions, a, dns.TypeSRV, test.numNodesTotal, test.udpSize, test.setEDNS0)
})
}) })
}
}) })
} }
} }
@ -3217,26 +3181,37 @@ func TestDNS_ServiceLookup_AnswerLimits(t *testing.T) {
} }
for _, test := range tests { for _, test := range tests {
test := test // capture loop var test := test // capture loop var
t.Run(fmt.Sprintf("answer-limit-%s", test.name), func(t *testing.T) {
a := NewTestAgent(t, fmt.Sprintf(`
node_name = "test-node"
dns_config {
udp_answer_limit = %d
}`, test.udpAnswerLimit))
defer a.Shutdown()
testrpc.WaitForTestAgent(t, a.RPC, "dc1")
questions := registerServicesAndPreparedQuery(t, generateNumNodes, a, test.name)
t.Run(fmt.Sprintf("A lookup %v", test), func(t *testing.T) { t.Run(fmt.Sprintf("A lookup %v", test), func(t *testing.T) {
ok, err := testDNSServiceLookupResponseLimits(t, test.udpAnswerLimit, dns.TypeA, test.expectedAService, test.expectedAQuery, test.expectedAQueryID, "") ok, err := testDNSServiceLookupResponseLimits(questions, test.udpAnswerLimit, dns.TypeA, test.expectedAService, test.expectedAQuery, test.expectedAQueryID, a)
if !ok { if !ok {
t.Fatalf("Expected service A lookup %s to pass: %v", test.name, err) t.Fatalf("Expected service A lookup %s to pass: %v", test.name, err)
} }
}) })
t.Run(fmt.Sprintf("AAAA lookup %v", test), func(t *testing.T) { t.Run(fmt.Sprintf("AAAA lookup %v", test), func(t *testing.T) {
ok, err := testDNSServiceLookupResponseLimits(t, test.udpAnswerLimit, dns.TypeAAAA, test.expectedAAAAService, test.expectedAAAAQuery, test.expectedAAAAQueryID, "") ok, err := testDNSServiceLookupResponseLimits(questions, test.udpAnswerLimit, dns.TypeAAAA, test.expectedAAAAService, test.expectedAAAAQuery, test.expectedAAAAQueryID, a)
if !ok { if !ok {
t.Fatalf("Expected service AAAA lookup %s to pass: %v", test.name, err) t.Fatalf("Expected service AAAA lookup %s to pass: %v", test.name, err)
} }
}) })
t.Run(fmt.Sprintf("ANY lookup %v", test), func(t *testing.T) { t.Run(fmt.Sprintf("ANY lookup %v", test), func(t *testing.T) {
ok, err := testDNSServiceLookupResponseLimits(t, test.udpAnswerLimit, dns.TypeANY, test.expectedANYService, test.expectedANYQuery, test.expectedANYQueryID, "") ok, err := testDNSServiceLookupResponseLimits(questions, test.udpAnswerLimit, dns.TypeANY, test.expectedANYService, test.expectedANYQuery, test.expectedANYQueryID, a)
if !ok { if !ok {
t.Fatalf("Expected service ANY lookup %s to pass: %v", test.name, err) t.Fatalf("Expected service ANY lookup %s to pass: %v", test.name, err)
} }
}) })
})
} }
} }

Loading…
Cancel
Save