github.com/craicoverflow/tyk@v2.9.6-rc3+incompatible/tcp/tcp_test.go (about) 1 package tcp 2 3 import ( 4 "crypto/tls" 5 "net" 6 "reflect" 7 "testing" 8 9 "github.com/TykTechnologies/tyk/test" 10 ) 11 12 func TestProxyModifier(t *testing.T) { 13 // Echoing 14 upstream := test.TcpMock(false, func(in []byte, err error) (out []byte) { 15 return in 16 }) 17 defer upstream.Close() 18 19 t.Run("Without modifier", func(t *testing.T) { 20 proxy := &Proxy{} 21 proxy.AddDomainHandler("", upstream.Addr().String(), nil) 22 23 testRunner(t, proxy, "", false, []test.TCPTestCase{ 24 {Action: "write", Payload: "ping"}, 25 {Action: "read", Payload: "ping"}, 26 }...) 27 }) 28 29 t.Run("Modify response", func(t *testing.T) { 30 proxy := &Proxy{} 31 proxy.AddDomainHandler("", upstream.Addr().String(), &Modifier{ 32 ModifyResponse: func(src, dst net.Conn, data []byte) ([]byte, error) { 33 return []byte("pong"), nil 34 }, 35 }) 36 37 testRunner(t, proxy, "", false, []test.TCPTestCase{ 38 {Action: "write", Payload: "ping"}, 39 {Action: "read", Payload: "pong"}, 40 }...) 41 }) 42 43 t.Run("Mock request", func(t *testing.T) { 44 proxy := &Proxy{} 45 proxy.AddDomainHandler("", upstream.Addr().String(), &Modifier{ 46 ModifyRequest: func(src, dst net.Conn, data []byte) ([]byte, error) { 47 return []byte("pong"), nil 48 }, 49 }) 50 51 testRunner(t, proxy, "", false, []test.TCPTestCase{ 52 {Action: "write", Payload: "ping"}, 53 {Action: "read", Payload: "pong"}, 54 }...) 55 }) 56 } 57 func TestProxySyncStats(t *testing.T) { 58 t.Skip() 59 // Echoing 60 upstream := test.TcpMock(false, func(in []byte, err error) (out []byte) { 61 return in 62 }) 63 defer upstream.Close() 64 stats := make(chan Stat) 65 proxy := &Proxy{SyncStats: func(s Stat) { 66 stats <- s 67 if s.State == Closed { 68 close(stats) 69 } 70 }} 71 proxy.AddDomainHandler("", upstream.Addr().String(), nil) 72 73 testRunner(t, proxy, "", false, []test.TCPTestCase{ 74 {Action: "write", Payload: "ping"}, 75 {Action: "read", Payload: "ping"}, 76 }...) 77 var c []Stat 78 for s := range stats { 79 c = append(c, s) 80 } 81 expect := []Stat{ 82 {State: Open}, 83 {State: Closed, BytesIn: 4, BytesOut: 4}, 84 } 85 if len(c) != len(expect) { 86 t.Fatalf("expected %d stats got %d stats", len(expect), len(c)) 87 } 88 if !reflect.DeepEqual(c, expect) { 89 t.Errorf("expected %#v got %#v", expect, c) 90 } 91 } 92 93 func TestProxyMultiTarget(t *testing.T) { 94 target1 := test.TcpMock(false, func(in []byte, err error) (out []byte) { 95 return []byte("first") 96 }) 97 defer target1.Close() 98 99 target2 := test.TcpMock(false, func(in []byte, err error) (out []byte) { 100 return []byte("second") 101 }) 102 defer target2.Close() 103 104 t.Run("Single_target, no SNI", func(t *testing.T) { 105 proxy := &Proxy{} 106 proxy.AddDomainHandler("", target1.Addr().String(), nil) 107 108 testRunner(t, proxy, "", true, []test.TCPTestCase{ 109 {Action: "write", Payload: "ping"}, 110 {Action: "read", Payload: "first"}, 111 }...) 112 }) 113 114 t.Run("Single target, SNI, without domain", func(t *testing.T) { 115 proxy := &Proxy{} 116 proxy.AddDomainHandler("", target1.Addr().String(), nil) 117 118 testRunner(t, proxy, "localhost", true, []test.TCPTestCase{ 119 {Action: "write", Payload: "ping"}, 120 {Action: "read", Payload: "first"}, 121 }...) 122 }) 123 124 t.Run("Single target, SNI, domain match", func(t *testing.T) { 125 proxy := &Proxy{} 126 proxy.AddDomainHandler("localhost", target1.Addr().String(), nil) 127 128 testRunner(t, proxy, "localhost", true, []test.TCPTestCase{ 129 {Action: "write", Payload: "ping"}, 130 {Action: "read", Payload: "first"}, 131 }...) 132 }) 133 134 t.Run("Single target, SNI, domain not match", func(t *testing.T) { 135 proxy := &Proxy{} 136 proxy.AddDomainHandler("localhost", target1.Addr().String(), nil) 137 138 // Should cause `Can't detect service based on provided SNI information: example.com` 139 testRunner(t, proxy, "example.com", true, []test.TCPTestCase{ 140 {Action: "write", Payload: "ping"}, 141 {Action: "read", ErrorMatch: "EOF"}, 142 }...) 143 }) 144 145 t.Run("Multiple targets, No SNI", func(t *testing.T) { 146 proxy := &Proxy{} 147 proxy.AddDomainHandler("localhost", target1.Addr().String(), nil) 148 proxy.AddDomainHandler("example.com", target2.Addr().String(), nil) 149 150 // Should cause `Multiple services on different domains running on the same port, but no SNI (domain) information from client 151 testRunner(t, proxy, "", true, []test.TCPTestCase{ 152 {Action: "write", Payload: "ping"}, 153 {Action: "read", ErrorMatch: "EOF"}, 154 }...) 155 }) 156 157 t.Run("Multiple targets, SNI", func(t *testing.T) { 158 proxy := &Proxy{} 159 proxy.AddDomainHandler("localhost", target1.Addr().String(), nil) 160 proxy.AddDomainHandler("example.com", target2.Addr().String(), nil) 161 162 testRunner(t, proxy, "localhost", true, []test.TCPTestCase{ 163 {Action: "write", Payload: "ping"}, 164 {Action: "read", Payload: "first"}, 165 }...) 166 167 testRunner(t, proxy, "example.com", true, []test.TCPTestCase{ 168 {Action: "write", Payload: "ping"}, 169 {Action: "read", Payload: "second"}, 170 }...) 171 172 testRunner(t, proxy, "wrong", true, []test.TCPTestCase{ 173 {Action: "write", Payload: "ping"}, 174 {Action: "read", ErrorMatch: "EOF"}, 175 }...) 176 }) 177 178 t.Run("Multiple targets, SNI with fallback", func(t *testing.T) { 179 proxy := &Proxy{} 180 proxy.AddDomainHandler("", target1.Addr().String(), nil) 181 proxy.AddDomainHandler("example.com", target2.Addr().String(), nil) 182 183 testRunner(t, proxy, "example.com", true, []test.TCPTestCase{ 184 {Action: "write", Payload: "ping"}, 185 {Action: "read", Payload: "second"}, 186 }...) 187 188 // Should fallback to target defined with empty domain 189 testRunner(t, proxy, "wrong", true, []test.TCPTestCase{ 190 {Action: "write", Payload: "ping"}, 191 {Action: "read", Payload: "first"}, 192 }...) 193 }) 194 } 195 196 func testRunner(t *testing.T, proxy *Proxy, hostname string, useSSL bool, testCases ...test.TCPTestCase) { 197 var proxyLn net.Listener 198 var err error 199 200 if useSSL { 201 tlsConfig := &tls.Config{ 202 Certificates: []tls.Certificate{test.Cert("localhost")}, 203 InsecureSkipVerify: true, 204 } 205 tlsConfig.BuildNameToCertificate() 206 proxyLn, err = tls.Listen("tcp", ":0", tlsConfig) 207 208 if err != nil { 209 t.Fatalf(err.Error()) 210 return 211 } 212 } else { 213 proxyLn, _ = net.Listen("tcp", ":0") 214 } 215 defer proxyLn.Close() 216 217 go proxy.Serve(proxyLn) 218 219 runner := test.TCPTestRunner{ 220 Target: proxyLn.Addr().String(), 221 UseSSL: useSSL, 222 Hostname: hostname, 223 } 224 runner.Run(t, testCases...) 225 }