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  }