resolver: a query cut short by the caller's context records no reason (closes #298)
check / check (push) Canceled after 0s
check / check (push) Canceled after 0s
When the caller's context ends, the next query returns ErrContextCanceled before anything is sent. querySingleType recorded that as a network error, which outranks a timeout, so a nameserver that had only timed out could be reported as "network error: context canceled". It now records no reason for it. A try the context's deadline cuts short ends as a timeout. When the context has ended before a further try, tryExchange now returns that try's error instead of ErrContextCanceled, so such a nameserver is reported as timed out, not as answering. Model: opus-5-5
This commit was merged in pull request #299.
This commit is contained in:
@@ -1380,10 +1380,10 @@ func TestQueryNameserverIP_Timeout(t *testing.T) {
|
||||
r := newTestResolver(t)
|
||||
|
||||
// Nothing answers at 192.0.2.1, a documentation address. The
|
||||
// resolver tries each query twice, and the first try gives up
|
||||
// after two seconds. A deadline that ends during the first try
|
||||
// makes the status vary from run to run between error and
|
||||
// timeout, so the deadline must outlast the first try.
|
||||
// resolver tries each query twice, and each try gives up after two
|
||||
// seconds. This deadline ends during the second try of the first
|
||||
// record type; TestQueryNameserverIP_DeadlineDuringFirstTry covers
|
||||
// one that ends during the first.
|
||||
ctx, cancel := context.WithTimeout(
|
||||
context.Background(), 3*time.Second,
|
||||
)
|
||||
@@ -1399,6 +1399,62 @@ func TestQueryNameserverIP_Timeout(t *testing.T) {
|
||||
assert.NotEmpty(t, resp.Error)
|
||||
}
|
||||
|
||||
// TestQueryNameserverIP_DeadlineDuringFirstTry gives a query to
|
||||
// 192.0.2.1, where nothing answers, a deadline that ends during its
|
||||
// first try. That try ends at the deadline as a timeout, so the
|
||||
// nameserver is reported as timed out, not as answering.
|
||||
func TestQueryNameserverIP_DeadlineDuringFirstTry(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
r := newTestResolver(t)
|
||||
|
||||
// Well under the two seconds one try waits.
|
||||
ctx, cancel := context.WithTimeout(
|
||||
context.Background(), 500*time.Millisecond,
|
||||
)
|
||||
t.Cleanup(cancel)
|
||||
|
||||
resp, err := r.QueryNameserverIP(
|
||||
ctx, "unreachable.test.", "192.0.2.1",
|
||||
"example.com",
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, resolver.StatusTimeout, resp.Status)
|
||||
assert.NotEmpty(t, resp.Error)
|
||||
}
|
||||
|
||||
// TestQueryNameserverIP_CancelDuringFirstTry cancels the context while
|
||||
// the first try of a query to 192.0.2.1, where nothing answers, waits
|
||||
// for a reply. That try's timeout is all that is learned about the
|
||||
// nameserver, so it is reported as timed out, not as answering.
|
||||
func TestQueryNameserverIP_CancelDuringFirstTry(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
r := newTestResolver(t)
|
||||
|
||||
// The first try starts at once and waits two seconds for a reply;
|
||||
// the cancel comes a second in. The DNS client cuts a try short at
|
||||
// the context's deadline but not at a cancel, so the try still
|
||||
// waits its full two seconds and ends as a timeout a second after
|
||||
// the cancel. By then the context has certainly ended, so no second
|
||||
// try is made. With a deadline instead, the try ends at the moment
|
||||
// the context does, and whether a second try is made depends on
|
||||
// which the resolver sees first.
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
t.Cleanup(cancel)
|
||||
time.AfterFunc(time.Second, cancel)
|
||||
|
||||
resp, err := r.QueryNameserverIP(
|
||||
ctx, "unreachable.test.", "192.0.2.1",
|
||||
"example.com",
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, resolver.StatusTimeout, resp.Status)
|
||||
assert.NotEmpty(t, resp.Error)
|
||||
}
|
||||
|
||||
// TestQueryNameserverIP_CancelledLogsNothing cancels the context while
|
||||
// a query to 192.0.2.1, where nothing answers, is waiting for a reply,
|
||||
// as shutdown does. The query was cut short, not failed, so nothing is
|
||||
|
||||
Reference in New Issue
Block a user