github.com/phuslu/fastdns@v0.8.3-0.20240310041952-69506fc67dd1/server_test.go (about) 1 package fastdns 2 3 import ( 4 "context" 5 "fmt" 6 "log" 7 "net" 8 "net/netip" 9 "os" 10 "runtime" 11 "testing" 12 "time" 13 ) 14 15 func allocAddr() string { 16 for i := 20001; i < 50000; i++ { 17 addr := fmt.Sprintf("127.0.0.1:%d", i) 18 conn, err := net.Listen("tcp", addr) 19 if err == nil { 20 conn.Close() 21 return addr 22 } 23 } 24 return "" 25 } 26 27 type mockServerHandler struct{} 28 29 func (h *mockServerHandler) ServeDNS(rw ResponseWriter, req *Message) { 30 log.Printf("%s] %s: TYPE %s", rw.RemoteAddr(), req.Domain, req.Question.Type) 31 HOST(rw, req, 300, []netip.Addr{netip.AddrFrom4([4]byte{1, 1, 1, 1})}) 32 } 33 34 func TestServerHost(t *testing.T) { 35 if runtime.GOOS == "windows" { 36 // On Windows, the resolver always uses C library functions, such as GetAddrInfo and DnsQuery. 37 return 38 } 39 40 s := &Server{ 41 Handler: &mockServerHandler{}, 42 ErrorLog: log.Default(), 43 MaxProcs: 1, 44 } 45 46 addr := allocAddr() 47 if addr == "" { 48 t.Errorf("allocAddr() failed.") 49 } 50 51 go func() { 52 err := s.ListenAndServe(addr) 53 if err != nil { 54 t.Errorf("listen %+v error: %+v", addr, err) 55 } 56 }() 57 58 time.Sleep(100 * time.Millisecond) 59 60 resolver := &net.Resolver{ 61 PreferGo: true, 62 Dial: func(context.Context, string, string) (net.Conn, error) { 63 return net.Dial("udp", addr) 64 }, 65 } 66 67 ips, err := resolver.LookupHost(context.Background(), "example.org") 68 if err != nil { 69 t.Errorf("LookupHost return error: %+v", err) 70 } 71 if ips[0] != "1.1.1.1" { 72 t.Errorf("LookupHost return mismatched reply: %+v", ips) 73 } 74 } 75 76 func TestServerListenError(t *testing.T) { 77 s := &Server{ 78 Handler: &mockServerHandler{}, 79 ErrorLog: log.Default(), 80 MaxProcs: 1, 81 index: 1, 82 } 83 84 const addr = "127.0.1.1:-1" 85 86 err := s.ListenAndServe(addr) 87 if err == nil { 88 t.Errorf("listen %+v shall return error but empty", addr) 89 } 90 } 91 92 func TestServerParseMessageError(t *testing.T) { 93 if runtime.GOOS == "windows" { 94 // On Windows, the resolver always uses C library functions, such as GetAddrInfo and DnsQuery. 95 return 96 } 97 98 s := &Server{ 99 Handler: &mockServerHandler{}, 100 ErrorLog: log.Default(), 101 MaxProcs: 1, 102 } 103 104 addr := allocAddr() 105 if addr == "" { 106 t.Errorf("allocAddr() failed.") 107 } 108 109 go func() { 110 err := s.ListenAndServe(addr) 111 if err != nil { 112 t.Errorf("listen %+v error: %+v", addr, err) 113 } 114 }() 115 116 time.Sleep(100 * time.Millisecond) 117 118 conn, err := net.Dial("udp", addr) 119 if err != nil { 120 t.Errorf("dial to %+v return error: %+v", addr, err) 121 } 122 123 _, _ = conn.Write([]byte{0x00, 0x02, 0x01, 0x00, 0x00, 0x00}) 124 } 125 126 func TestServerForkHost(t *testing.T) { 127 if runtime.GOOS == "windows" { 128 // On Windows, the resolver always uses C library functions, such as GetAddrInfo and DnsQuery. 129 return 130 } 131 132 os.Setenv("FASTDNS_CHILD_INDEX", "1") 133 134 s := &ForkServer{ 135 Handler: &mockServerHandler{}, 136 ErrorLog: log.Default(), 137 MaxProcs: 1, 138 } 139 140 addr := allocAddr() 141 if addr == "" { 142 t.Errorf("allocAddr() failed.") 143 } 144 145 go func() { 146 err := s.ListenAndServe(addr) 147 if err != nil { 148 t.Errorf("listen %+v error: %+v", addr, err) 149 } 150 }() 151 152 time.Sleep(100 * time.Millisecond) 153 154 resolver := &net.Resolver{ 155 PreferGo: true, 156 Dial: func(context.Context, string, string) (net.Conn, error) { 157 return net.Dial("udp", addr) 158 }, 159 } 160 161 ips, err := resolver.LookupHost(context.Background(), "example.org") 162 if err != nil { 163 t.Errorf("LookupHost return error: %+v", err) 164 } 165 if ips[0] != "1.1.1.1" { 166 t.Errorf("LookupHost return mismatched reply: %+v", ips) 167 } 168 } 169 170 func TestServerForkParseMessageError(t *testing.T) { 171 if runtime.GOOS == "windows" { 172 // On Windows, the resolver always uses C library functions, such as GetAddrInfo and DnsQuery. 173 return 174 } 175 176 os.Setenv("FASTDNS_CHILD_INDEX", "1") 177 178 s := &ForkServer{ 179 Handler: &mockServerHandler{}, 180 ErrorLog: log.Default(), 181 MaxProcs: 1, 182 } 183 184 addr := allocAddr() 185 if addr == "" { 186 t.Errorf("allocAddr() failed.") 187 } 188 189 go func() { 190 err := s.ListenAndServe(addr) 191 if err != nil { 192 t.Errorf("listen %+v error: %+v", addr, err) 193 } 194 }() 195 196 time.Sleep(100 * time.Millisecond) 197 198 conn, err := net.Dial("udp", addr) 199 if err != nil { 200 t.Errorf("dial to %+v return error: %+v", addr, err) 201 } 202 203 _, _ = conn.Write([]byte{0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) 204 }