github.com/braveheart12/just@v0.8.7/network/hostnetwork/transport_test.go (about) 1 /* 2 * The Clear BSD License 3 * 4 * Copyright (c) 2019 Insolar Technologies 5 * 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without modification, are permitted (subject to the limitations in the disclaimer below) provided that the following conditions are met: 9 * 10 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 11 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 12 * Neither the name of Insolar Technologies nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 13 * 14 * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 15 * 16 */ 17 18 package hostnetwork 19 20 import ( 21 "context" 22 "encoding/gob" 23 "sync" 24 "testing" 25 "time" 26 27 "github.com/insolar/insolar/configuration" 28 "github.com/insolar/insolar/core" 29 "github.com/insolar/insolar/log" 30 "github.com/insolar/insolar/network" 31 "github.com/insolar/insolar/network/transport/host" 32 "github.com/insolar/insolar/network/transport/packet/types" 33 "github.com/insolar/insolar/network/utils" 34 "github.com/pkg/errors" 35 "github.com/stretchr/testify/require" 36 ) 37 38 const ( 39 InvalidPacket types.PacketType = 1024 40 41 ID1 = "4K2V1kpVycZ6qSFsNdz2FtpNxnJs17eBNzf9rdCMcKoe" 42 ID2 = "4NwnA4HWZurKyXWNowJwYmb9CwX4gBKzwQKov1ExMf8M" 43 ID3 = "4Ss5JMkXAD9Z7cktFEdrqeMuT6jGMF1pVozTyPHZ6zT4" 44 IDUNKNOWN = "4K3Mi2hyZ6QKgynGv33sR5n3zWmSzdo8zv5Em7X26r1w" 45 DOMAIN = ".4F7BsTMVPKFshM1MwLf6y23cid6fL3xMpazVoF9krzUw" 46 ) 47 48 type MockResolver struct { 49 mapping map[core.RecordRef]*host.Host 50 smapping map[core.ShortNodeID]*host.Host 51 } 52 53 func (m *MockResolver) ResolveConsensus(id core.ShortNodeID) (*host.Host, error) { 54 result, exist := m.smapping[id] 55 if !exist { 56 return nil, errors.New("failed to resolve") 57 } 58 return result, nil 59 } 60 61 func (m *MockResolver) ResolveConsensusRef(nodeID core.RecordRef) (*host.Host, error) { 62 return m.Resolve(nodeID) 63 } 64 65 func (m *MockResolver) Resolve(nodeID core.RecordRef) (*host.Host, error) { 66 result, exist := m.mapping[nodeID] 67 if !exist { 68 return nil, errors.New("failed to resolve") 69 } 70 return result, nil 71 } 72 73 func (m *MockResolver) Inject(nodeKeeper network.NodeKeeper) {} 74 func (m *MockResolver) AddToKnownHosts(h *host.Host) {} 75 func (m *MockResolver) Rebalance(network.PartitionPolicy) {} 76 func (m *MockResolver) GetRandomNodes(int) []host.Host { return nil } 77 78 func (m *MockResolver) addMapping(key, value string) error { 79 k, err := core.NewRefFromBase58(key) 80 if err != nil { 81 return err 82 } 83 h, err := host.NewHostN(value, *k) 84 if err != nil { 85 return err 86 } 87 m.mapping[*k] = h 88 return nil 89 } 90 91 func (m *MockResolver) addMappingHost(h *host.Host) { 92 m.mapping[h.NodeID] = h 93 m.smapping[h.ShortID] = h 94 } 95 96 func newMockResolver() *MockResolver { 97 return &MockResolver{ 98 mapping: make(map[core.RecordRef]*host.Host), 99 smapping: make(map[core.ShortNodeID]*host.Host), 100 } 101 } 102 103 func mockConfiguration(address string) configuration.Configuration { 104 result := configuration.Configuration{} 105 result.Host.Transport = configuration.Transport{Protocol: "TCP", Address: address, BehindNAT: false} 106 return result 107 } 108 109 func TestNewInternalTransport(t *testing.T) { 110 // broken address 111 _, err := NewInternalTransport(mockConfiguration("abirvalg"), ID1+DOMAIN) 112 require.Error(t, err) 113 address := "127.0.0.1:0" 114 tp, err := NewInternalTransport(mockConfiguration(address), ID1+DOMAIN) 115 require.NoError(t, err) 116 defer tp.Stop() 117 // require that new address with correct port has been assigned 118 require.NotEqual(t, address, tp.PublicAddress()) 119 ref, err := core.NewRefFromBase58(ID1 + DOMAIN) 120 require.NoError(t, err) 121 require.Equal(t, *ref, tp.GetNodeID()) 122 } 123 124 func TestNewInternalTransport2(t *testing.T) { 125 ctx := context.Background() 126 tp, err := NewInternalTransport(mockConfiguration("127.0.0.1:0"), ID1+DOMAIN) 127 require.NoError(t, err) 128 go tp.Start(ctx) 129 time.Sleep(time.Millisecond) 130 // no assertion, check that Stop does not block 131 defer func(t *testing.T) { 132 tp.Stop() 133 require.True(t, true) 134 }(t) 135 } 136 137 func createTwoHostNetworks(id1, id2 string) (t1, t2 network.HostNetwork, err error) { 138 m := newMockResolver() 139 140 i1, err := NewInternalTransport(mockConfiguration("127.0.0.1:0"), ID1+DOMAIN) 141 if err != nil { 142 return nil, nil, err 143 } 144 tr1 := NewHostTransport(i1, m) 145 i2, err := NewInternalTransport(mockConfiguration("127.0.0.1:0"), ID2+DOMAIN) 146 if err != nil { 147 return nil, nil, err 148 } 149 tr2 := NewHostTransport(i2, m) 150 151 err = m.addMapping(id1, tr1.PublicAddress()) 152 if err != nil { 153 return nil, nil, errors.Wrapf(err, "failed to add mapping %s -> %s", id1, tr1.PublicAddress()) 154 } 155 err = m.addMapping(id2, tr2.PublicAddress()) 156 if err != nil { 157 return nil, nil, errors.Wrapf(err, "failed to add mapping %s -> %s", id2, tr2.PublicAddress()) 158 } 159 160 return tr1, tr2, nil 161 } 162 163 func TestNewInternalTransport3(t *testing.T) { 164 _, err := NewInternalTransport(mockConfiguration("127.0.0.1:0"), "") 165 require.Error(t, err) 166 } 167 168 func TestNewHostTransport(t *testing.T) { 169 ctx := context.Background() 170 ctx2 := context.Background() 171 t1, t2, err := createTwoHostNetworks(ID1+DOMAIN, ID2+DOMAIN) 172 ref1, err := core.NewRefFromBase58(ID1 + DOMAIN) 173 require.NoError(t, err) 174 require.Equal(t, *ref1, t1.GetNodeID()) 175 ref2, err := core.NewRefFromBase58(ID2 + DOMAIN) 176 require.Equal(t, *ref2, t2.GetNodeID()) 177 require.NoError(t, err) 178 179 count := 10 180 wg := sync.WaitGroup{} 181 wg.Add(count) 182 183 handler := func(ctx context.Context, request network.Request) (network.Response, error) { 184 log.Info("handler triggered") 185 wg.Done() 186 return t2.BuildResponse(ctx, request, nil), nil 187 } 188 t2.RegisterRequestHandler(types.Ping, handler) 189 190 t2.Start(ctx) 191 t1.Start(ctx2) 192 193 defer func() { 194 t1.Stop() 195 t2.Stop() 196 }() 197 198 for i := 0; i < count; i++ { 199 request := t1.NewRequestBuilder().Type(types.Ping).Data(nil).Build() 200 ref, err := core.NewRefFromBase58(ID2 + DOMAIN) 201 require.NoError(t, err) 202 _, err = t1.SendRequest(ctx, request, *ref) 203 require.NoError(t, err) 204 } 205 wg.Wait() 206 } 207 208 func TestHostTransport_SendRequestPacket(t *testing.T) { 209 m := newMockResolver() 210 ctx := context.Background() 211 212 i1, err := NewInternalTransport(mockConfiguration("127.0.0.1:0"), ID1+DOMAIN) 213 require.NoError(t, err) 214 t1 := NewHostTransport(i1, m) 215 t1.Start(ctx) 216 defer t1.Stop() 217 218 unknownID, err := core.NewRefFromBase58(IDUNKNOWN + DOMAIN) 219 require.NoError(t, err) 220 221 // should return error because cannot resolve NodeID -> Address 222 request := t1.NewRequestBuilder().Type(types.Ping).Data(nil).Build() 223 _, err = t1.SendRequest(ctx, request, *unknownID) 224 require.Error(t, err) 225 226 err = m.addMapping(ID2+DOMAIN, "abirvalg") 227 require.Error(t, err) 228 err = m.addMapping(ID3+DOMAIN, "127.0.0.1:7654") 229 require.NoError(t, err) 230 231 ref, err := core.NewRefFromBase58(ID2 + DOMAIN) 232 require.NoError(t, err) 233 // should return error because resolved address is invalid 234 _, err = t1.SendRequest(ctx, request, *ref) 235 require.Error(t, err) 236 } 237 238 func TestHostTransport_SendRequestPacket2(t *testing.T) { 239 t1, t2, err := createTwoHostNetworks(ID1+DOMAIN, ID2+DOMAIN) 240 require.NoError(t, err) 241 ctx := context.Background() 242 ctx2 := context.Background() 243 244 wg := sync.WaitGroup{} 245 wg.Add(1) 246 247 handler := func(ctx context.Context, r network.Request) (network.Response, error) { 248 log.Info("handler triggered") 249 ref, err := core.NewRefFromBase58(ID1 + DOMAIN) 250 require.NoError(t, err) 251 require.Equal(t, *ref, r.GetSender()) 252 require.Equal(t, t1.PublicAddress(), r.GetSenderHost().Address.String()) 253 wg.Done() 254 return t2.BuildResponse(ctx, r, nil), nil 255 } 256 257 t2.RegisterRequestHandler(types.Ping, handler) 258 259 t2.Start(ctx) 260 t1.Start(ctx2) 261 defer func() { 262 t1.Stop() 263 t2.Stop() 264 }() 265 266 request := t1.NewRequestBuilder().Type(types.Ping).Data(nil).Build() 267 ref, err := core.NewRefFromBase58(ID1 + DOMAIN) 268 require.NoError(t, err) 269 require.Equal(t, *ref, request.GetSender()) 270 require.Equal(t, t1.PublicAddress(), request.GetSenderHost().Address.String()) 271 272 ref, err = core.NewRefFromBase58(ID2 + DOMAIN) 273 require.NoError(t, err) 274 _, err = t1.SendRequest(ctx, request, *ref) 275 require.NoError(t, err) 276 wg.Wait() 277 } 278 279 func TestHostTransport_SendRequestPacket3(t *testing.T) { 280 t1, t2, err := createTwoHostNetworks(ID1+DOMAIN, ID2+DOMAIN) 281 require.NoError(t, err) 282 ctx := context.Background() 283 ctx2 := context.Background() 284 285 type Data struct { 286 Number int 287 } 288 gob.Register(&Data{}) 289 290 handler := func(ctx context.Context, r network.Request) (network.Response, error) { 291 log.Info("handler triggered") 292 d := r.GetData().(*Data) 293 return t2.BuildResponse(ctx, r, &Data{Number: d.Number + 1}), nil 294 } 295 t2.RegisterRequestHandler(types.Ping, handler) 296 297 t2.Start(ctx) 298 t1.Start(ctx2) 299 defer func() { 300 t1.Stop() 301 t2.Stop() 302 }() 303 304 magicNumber := 42 305 request := t1.NewRequestBuilder().Type(types.Ping).Data(&Data{Number: magicNumber}).Build() 306 ref, err := core.NewRefFromBase58(ID2 + DOMAIN) 307 require.NoError(t, err) 308 f, err := t1.SendRequest(ctx, request, *ref) 309 require.NoError(t, err) 310 require.Equal(t, f.GetRequest().GetSender(), request.GetSender()) 311 312 r, err := f.GetResponse(time.Second) 313 require.NoError(t, err) 314 315 d := r.GetData().(*Data) 316 require.Equal(t, magicNumber+1, d.Number) 317 318 magicNumber = 666 319 request = t1.NewRequestBuilder().Type(types.Ping).Data(&Data{Number: magicNumber}).Build() 320 f, err = t1.SendRequest(ctx, request, *ref) 321 require.NoError(t, err) 322 323 r = <-f.Response() 324 d = r.GetData().(*Data) 325 require.Equal(t, magicNumber+1, d.Number) 326 } 327 328 func TestHostTransport_SendRequestPacket_errors(t *testing.T) { 329 t1, t2, err := createTwoHostNetworks(ID1+DOMAIN, ID2+DOMAIN) 330 require.NoError(t, err) 331 ctx := context.Background() 332 ctx2 := context.Background() 333 334 handler := func(ctx context.Context, r network.Request) (network.Response, error) { 335 log.Info("handler triggered") 336 time.Sleep(time.Second) 337 return t2.BuildResponse(ctx, r, nil), nil 338 } 339 t2.RegisterRequestHandler(types.Ping, handler) 340 341 t2.Start(ctx) 342 defer t2.Stop() 343 t1.Start(ctx2) 344 345 request := t1.NewRequestBuilder().Type(types.Ping).Data(nil).Build() 346 ref, err := core.NewRefFromBase58(ID2 + DOMAIN) 347 require.NoError(t, err) 348 f, err := t1.SendRequest(ctx, request, *ref) 349 require.NoError(t, err) 350 351 _, err = f.GetResponse(time.Millisecond) 352 require.Error(t, err) 353 354 f, err = t1.SendRequest(ctx, request, *ref) 355 require.NoError(t, err) 356 t1.Stop() 357 358 _, err = f.GetResponse(time.Second) 359 require.Error(t, err) 360 } 361 362 func TestHostTransport_WrongHandler(t *testing.T) { 363 t1, t2, err := createTwoHostNetworks(ID1+DOMAIN, ID2+DOMAIN) 364 require.NoError(t, err) 365 ctx := context.Background() 366 ctx2 := context.Background() 367 368 wg := sync.WaitGroup{} 369 wg.Add(1) 370 371 handler := func(ctx context.Context, r network.Request) (network.Response, error) { 372 log.Info("handler triggered") 373 wg.Done() 374 return t2.BuildResponse(ctx, r, nil), nil 375 } 376 t2.RegisterRequestHandler(InvalidPacket, handler) 377 378 t2.Start(ctx) 379 t1.Start(ctx2) 380 defer func() { 381 t1.Stop() 382 t2.Stop() 383 }() 384 385 request := t1.NewRequestBuilder().Type(types.Ping).Build() 386 ref, err := core.NewRefFromBase58(ID2 + DOMAIN) 387 require.NoError(t, err) 388 _, err = t1.SendRequest(ctx, request, *ref) 389 require.NoError(t, err) 390 391 // should timeout because there is no handler set for Ping packet 392 result := utils.WaitTimeout(&wg, time.Millisecond*100) 393 require.False(t, result) 394 } 395 396 func TestDoubleStart(t *testing.T) { 397 ctx := context.Background() 398 tp, err := NewInternalTransport(mockConfiguration("127.0.0.1:0"), ID1+DOMAIN) 399 require.NoError(t, err) 400 wg := sync.WaitGroup{} 401 wg.Add(2) 402 403 f := func(group *sync.WaitGroup, t network.InternalTransport) { 404 t.Start(ctx) 405 wg.Done() 406 } 407 go f(&wg, tp) 408 go f(&wg, tp) 409 wg.Wait() 410 411 tp.Stop() 412 }