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