Files
v2rayA/core/dns/cache_response_test.go
Zakk 9cdc300d0e fix(core/dns): query_type decoding, ECS scope, cache TTLs, bind errors, and SO_MARK for native outbounds
RuleConfig.QueryType had no string decoder while the service writes
query_type as "A"/"AAAA", so any DNS rule with a query type made the core
exit at startup; accept names and numbers. ECS was gated on
IsGlobalUnicast, which is true for RFC 1918 and ULA, so LAN clients'
private prefixes were still sent upstream; also require a non-private,
non-loopback, non-link-local address. Cache hits returned the stored
message with its original TTLs; subtract the elapsed time, floored at
min_ttl, on a copy. The listener logged bind failures inside the serve
goroutines and Start returned nil; bind synchronously so the error is
reported. DNS-over-TCP read the length prefix with a single Read; use
io.ReadFull. CacheConfig.NegativeCache was never read; negative answers
are no longer cached when it is off.

The native anytls, juicity and tuic outbounds were rebuilt with an empty
SenderConfig and dialed with their own dialers, so streamSettings.sockopt
(the 0x80 loop-protection mark) never reached their server connections
and transparent-proxy mode re-captured them. Carry the original
streamSettings into the rebuilt sender settings and dial through the
xray dialer that applies them.
2026-09-18 02:49:39 +10:00

54 lines
1.5 KiB
Go

package dns
import (
"testing"
"time"
"github.com/miekg/dns"
)
func TestCacheHitDecreasesRecordTTLs(t *testing.T) {
config := newTestCacheConfig()
config.MinTTL = 100
cache := NewDnsCache(config)
key := newTestCacheKey("example.com", TypeA)
response := newTestDNSResponse("example.com", TypeA, dns.RcodeSuccess, 150)
cache.Set(key, response, 150)
entry := cache.entries[key].Value.(*CacheEntry)
entry.StoredAt = time.Now().Add(-75 * time.Second)
entry.ExpiresAt = time.Now().Add(time.Minute)
cached, ok := cache.Get(key)
if !ok {
t.Fatal("expected cache hit")
}
if got := cached.Answer[0].Header().Ttl; got != 100 {
t.Errorf("cached answer TTL = %d, want 100", got)
}
if got := cached.RawMsg.Answer[0].Header().Ttl; got != 100 {
t.Errorf("cached raw message TTL = %d, want 100", got)
}
if got := cached.TTL; got != 100 {
t.Errorf("cached response TTL = %d, want 100", got)
}
if got := response.Answer[0].Header().Ttl; got != 150 {
t.Errorf("stored answer TTL = %d, want 150", got)
}
}
func TestNegativeResponsesAreNotCachedWhenDisabled(t *testing.T) {
for _, rcode := range []int{dns.RcodeNameError, dns.RcodeServerFailure, dns.RcodeRefused} {
config := newTestCacheConfig()
config.NegativeCache = false
cache := NewDnsCache(config)
key := newTestCacheKey("negative.example.com", TypeA)
response := newTestDNSResponse("negative.example.com", TypeA, rcode, 0)
cache.Set(key, response, 0)
if _, ok := cache.Get(key); ok {
t.Errorf("rcode %d was cached with negative caching disabled", rcode)
}
}
}