github.com/xtls/xray-core@v1.8.12-0.20240518155711-3168d27b0bdb/app/dns/dnscommon_test.go (about)

     1  package dns
     2  
     3  import (
     4  	"math/rand"
     5  	"testing"
     6  	"time"
     7  
     8  	"github.com/google/go-cmp/cmp"
     9  	"github.com/miekg/dns"
    10  	"github.com/xtls/xray-core/common"
    11  	"github.com/xtls/xray-core/common/net"
    12  	dns_feature "github.com/xtls/xray-core/features/dns"
    13  	"golang.org/x/net/dns/dnsmessage"
    14  )
    15  
    16  func Test_parseResponse(t *testing.T) {
    17  	var p [][]byte
    18  
    19  	ans := new(dns.Msg)
    20  	ans.Id = 0
    21  	p = append(p, common.Must2(ans.Pack()).([]byte))
    22  
    23  	p = append(p, []byte{})
    24  
    25  	ans = new(dns.Msg)
    26  	ans.Id = 1
    27  	ans.Answer = append(ans.Answer,
    28  		common.Must2(dns.NewRR("google.com. IN CNAME m.test.google.com")).(dns.RR),
    29  		common.Must2(dns.NewRR("google.com. IN CNAME fake.google.com")).(dns.RR),
    30  		common.Must2(dns.NewRR("google.com. IN A 8.8.8.8")).(dns.RR),
    31  		common.Must2(dns.NewRR("google.com. IN A 8.8.4.4")).(dns.RR),
    32  	)
    33  	p = append(p, common.Must2(ans.Pack()).([]byte))
    34  
    35  	ans = new(dns.Msg)
    36  	ans.Id = 2
    37  	ans.Answer = append(ans.Answer,
    38  		common.Must2(dns.NewRR("google.com. IN CNAME m.test.google.com")).(dns.RR),
    39  		common.Must2(dns.NewRR("google.com. IN CNAME fake.google.com")).(dns.RR),
    40  		common.Must2(dns.NewRR("google.com. IN CNAME m.test.google.com")).(dns.RR),
    41  		common.Must2(dns.NewRR("google.com. IN CNAME test.google.com")).(dns.RR),
    42  		common.Must2(dns.NewRR("google.com. IN AAAA 2001::123:8888")).(dns.RR),
    43  		common.Must2(dns.NewRR("google.com. IN AAAA 2001::123:8844")).(dns.RR),
    44  	)
    45  	p = append(p, common.Must2(ans.Pack()).([]byte))
    46  
    47  	tests := []struct {
    48  		name    string
    49  		want    *IPRecord
    50  		wantErr bool
    51  	}{
    52  		{
    53  			"empty",
    54  			&IPRecord{0, []net.Address(nil), time.Time{}, dnsmessage.RCodeSuccess},
    55  			false,
    56  		},
    57  		{
    58  			"error",
    59  			nil,
    60  			true,
    61  		},
    62  		{
    63  			"a record",
    64  			&IPRecord{
    65  				1,
    66  				[]net.Address{net.ParseAddress("8.8.8.8"), net.ParseAddress("8.8.4.4")},
    67  				time.Time{},
    68  				dnsmessage.RCodeSuccess,
    69  			},
    70  			false,
    71  		},
    72  		{
    73  			"aaaa record",
    74  			&IPRecord{2, []net.Address{net.ParseAddress("2001::123:8888"), net.ParseAddress("2001::123:8844")}, time.Time{}, dnsmessage.RCodeSuccess},
    75  			false,
    76  		},
    77  	}
    78  	for i, tt := range tests {
    79  		t.Run(tt.name, func(t *testing.T) {
    80  			got, err := parseResponse(p[i])
    81  			if (err != nil) != tt.wantErr {
    82  				t.Errorf("handleResponse() error = %v, wantErr %v", err, tt.wantErr)
    83  				return
    84  			}
    85  
    86  			if got != nil {
    87  				// reset the time
    88  				got.Expire = time.Time{}
    89  			}
    90  			if cmp.Diff(got, tt.want) != "" {
    91  				t.Errorf(cmp.Diff(got, tt.want))
    92  				// t.Errorf("handleResponse() = %#v, want %#v", got, tt.want)
    93  			}
    94  		})
    95  	}
    96  }
    97  
    98  func Test_buildReqMsgs(t *testing.T) {
    99  	stubID := func() uint16 {
   100  		return uint16(rand.Uint32())
   101  	}
   102  	type args struct {
   103  		domain  string
   104  		option  dns_feature.IPOption
   105  		reqOpts *dnsmessage.Resource
   106  	}
   107  	tests := []struct {
   108  		name string
   109  		args args
   110  		want int
   111  	}{
   112  		{"dual stack", args{"test.com", dns_feature.IPOption{
   113  			IPv4Enable: true,
   114  			IPv6Enable: true,
   115  			FakeEnable: false,
   116  		}, nil}, 2},
   117  		{"ipv4 only", args{"test.com", dns_feature.IPOption{
   118  			IPv4Enable: true,
   119  			IPv6Enable: false,
   120  			FakeEnable: false,
   121  		}, nil}, 1},
   122  		{"ipv6 only", args{"test.com", dns_feature.IPOption{
   123  			IPv4Enable: false,
   124  			IPv6Enable: true,
   125  			FakeEnable: false,
   126  		}, nil}, 1},
   127  		{"none/error", args{"test.com", dns_feature.IPOption{
   128  			IPv4Enable: false,
   129  			IPv6Enable: false,
   130  			FakeEnable: false,
   131  		}, nil}, 0},
   132  	}
   133  	for _, tt := range tests {
   134  		t.Run(tt.name, func(t *testing.T) {
   135  			if got := buildReqMsgs(tt.args.domain, tt.args.option, stubID, tt.args.reqOpts); !(len(got) == tt.want) {
   136  				t.Errorf("buildReqMsgs() = %v, want %v", got, tt.want)
   137  			}
   138  		})
   139  	}
   140  }
   141  
   142  func Test_genEDNS0Options(t *testing.T) {
   143  	type args struct {
   144  		clientIP net.IP
   145  	}
   146  	tests := []struct {
   147  		name string
   148  		args args
   149  		want *dnsmessage.Resource
   150  	}{
   151  		// TODO: Add test cases.
   152  		{"ipv4", args{net.ParseIP("4.3.2.1")}, nil},
   153  		{"ipv6", args{net.ParseIP("2001::4321")}, nil},
   154  	}
   155  	for _, tt := range tests {
   156  		t.Run(tt.name, func(t *testing.T) {
   157  			if got := genEDNS0Options(tt.args.clientIP); got == nil {
   158  				t.Errorf("genEDNS0Options() = %v, want %v", got, tt.want)
   159  			}
   160  		})
   161  	}
   162  }
   163  
   164  func TestFqdn(t *testing.T) {
   165  	type args struct {
   166  		domain string
   167  	}
   168  	tests := []struct {
   169  		name string
   170  		args args
   171  		want string
   172  	}{
   173  		{"with fqdn", args{"www.example.com."}, "www.example.com."},
   174  		{"without fqdn", args{"www.example.com"}, "www.example.com."},
   175  	}
   176  	for _, tt := range tests {
   177  		t.Run(tt.name, func(t *testing.T) {
   178  			if got := Fqdn(tt.args.domain); got != tt.want {
   179  				t.Errorf("Fqdn() = %v, want %v", got, tt.want)
   180  			}
   181  		})
   182  	}
   183  }