github.com/braveheart12/insolar-09-08-19@v0.8.7/ledger/jetcoordinator/jetcoordinator_test.go (about)

     1  /*
     2   *    Copyright 2019 Insolar Technologies
     3   *
     4   *    Licensed under the Apache License, Version 2.0 (the "License");
     5   *    you may not use this file except in compliance with the License.
     6   *    You may obtain a copy of the License at
     7   *
     8   *        http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   *    Unless required by applicable law or agreed to in writing, software
    11   *    distributed under the License is distributed on an "AS IS" BASIS,
    12   *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   *    See the License for the specific language governing permissions and
    14   *    limitations under the License.
    15   */
    16  
    17  package jetcoordinator
    18  
    19  import (
    20  	"context"
    21  	"testing"
    22  
    23  	"github.com/insolar/insolar"
    24  	"github.com/insolar/insolar/component"
    25  	"github.com/insolar/insolar/core"
    26  	"github.com/insolar/insolar/instrumentation/inslogger"
    27  	"github.com/insolar/insolar/ledger/storage"
    28  	"github.com/insolar/insolar/ledger/storage/jet"
    29  	"github.com/insolar/insolar/ledger/storage/nodes"
    30  	"github.com/insolar/insolar/ledger/storage/storagetest"
    31  	"github.com/insolar/insolar/platformpolicy"
    32  	"github.com/insolar/insolar/pulsar/entropygenerator"
    33  	"github.com/insolar/insolar/testutils"
    34  	"github.com/insolar/insolar/testutils/network"
    35  	"github.com/pkg/errors"
    36  	"github.com/stretchr/testify/assert"
    37  	"github.com/stretchr/testify/require"
    38  	"github.com/stretchr/testify/suite"
    39  )
    40  
    41  type jetCoordinatorSuite struct {
    42  	suite.Suite
    43  
    44  	cm      *component.Manager
    45  	ctx     context.Context
    46  	cleaner func()
    47  
    48  	pulseStorage *storage.PulseStorage
    49  	pulseTracker storage.PulseTracker
    50  	jetStorage   storage.JetStorage
    51  	nodeStorage  *nodes.AccessorMock
    52  	coordinator  *JetCoordinator
    53  }
    54  
    55  func NewJetCoordinatorSuite() *jetCoordinatorSuite {
    56  	return &jetCoordinatorSuite{
    57  		Suite: suite.Suite{},
    58  	}
    59  }
    60  
    61  func TestCoordinator(t *testing.T) {
    62  	suite.Run(t, NewJetCoordinatorSuite())
    63  }
    64  
    65  func (s *jetCoordinatorSuite) BeforeTest(suiteName, testName string) {
    66  	s.cm = &component.Manager{}
    67  	s.ctx = inslogger.TestContext(s.T())
    68  
    69  	db, cleaner := storagetest.TmpDB(s.ctx, s.T())
    70  
    71  	s.cleaner = cleaner
    72  	s.pulseTracker = storage.NewPulseTracker()
    73  	s.pulseStorage = storage.NewPulseStorage()
    74  	s.jetStorage = storage.NewJetStorage()
    75  	s.nodeStorage = nodes.NewAccessorMock(s.T())
    76  	s.coordinator = NewJetCoordinator(5)
    77  	s.coordinator.NodeNet = network.NewNodeNetworkMock(s.T())
    78  
    79  	s.cm.Inject(
    80  		testutils.NewPlatformCryptographyScheme(),
    81  		db,
    82  		s.pulseTracker,
    83  		s.pulseStorage,
    84  		s.jetStorage,
    85  		s.nodeStorage,
    86  		s.coordinator,
    87  	)
    88  
    89  	err := s.cm.Init(s.ctx)
    90  	if err != nil {
    91  		s.T().Error("ComponentManager init failed", err)
    92  	}
    93  	err = s.cm.Start(s.ctx)
    94  	if err != nil {
    95  		s.T().Error("ComponentManager start failed", err)
    96  	}
    97  }
    98  
    99  func (s *jetCoordinatorSuite) AfterTest(suiteName, testName string) {
   100  	err := s.cm.Stop(s.ctx)
   101  	if err != nil {
   102  		s.T().Error("ComponentManager stop failed", err)
   103  	}
   104  	s.cleaner()
   105  }
   106  
   107  func (s *jetCoordinatorSuite) TestJetCoordinator_QueryRole() {
   108  	err := s.pulseTracker.AddPulse(s.ctx, core.Pulse{PulseNumber: 0, Entropy: core.Entropy{1, 2, 3}})
   109  	require.NoError(s.T(), err)
   110  	var nds []insolar.Node
   111  	var nodeRefs []core.RecordRef
   112  	for i := 0; i < 100; i++ {
   113  		ref := *core.NewRecordRef(core.DomainID, *core.NewRecordID(0, []byte{byte(i)}))
   114  		nds = append(nds, insolar.Node{ID: ref, Role: core.StaticRoleLightMaterial})
   115  		nodeRefs = append(nodeRefs, ref)
   116  	}
   117  	require.NoError(s.T(), err)
   118  
   119  	s.nodeStorage.InRoleMock.Return(nds, nil)
   120  
   121  	objID := core.NewRecordID(0, []byte{1, 42, 123})
   122  	s.jetStorage.UpdateJetTree(s.ctx, 0, true, *jet.NewID(50, []byte{1, 42, 123}))
   123  
   124  	selected, err := s.coordinator.QueryRole(s.ctx, core.DynamicRoleLightValidator, *objID, 0)
   125  	require.NoError(s.T(), err)
   126  	assert.Equal(s.T(), 3, len(selected))
   127  
   128  	// Indexes are hard-coded from previously calculated values.
   129  	assert.Equal(s.T(), []core.RecordRef{nodeRefs[16], nodeRefs[21], nodeRefs[78]}, selected)
   130  }
   131  
   132  func TestJetCoordinator_Me(t *testing.T) {
   133  	t.Parallel()
   134  	// Arrange
   135  	expectedID := testutils.RandomRef()
   136  	nodeNet := network.NewNodeNetworkMock(t)
   137  	node := network.NewNodeMock(t)
   138  	nodeNet.GetOriginMock.Return(node)
   139  	node.IDMock.Return(expectedID)
   140  	jc := NewJetCoordinator(1)
   141  	jc.NodeNet = nodeNet
   142  
   143  	// Act
   144  	resultID := jc.Me()
   145  
   146  	// Assert
   147  	require.Equal(t, expectedID, resultID)
   148  }
   149  
   150  func TestNewJetCoordinator(t *testing.T) {
   151  	t.Parallel()
   152  	// Act
   153  	calc := NewJetCoordinator(12)
   154  
   155  	// Assert
   156  	require.NotNil(t, calc)
   157  	require.Equal(t, 12, calc.lightChainLimit)
   158  }
   159  
   160  func TestJetCoordinator_IsBeyondLimit_ProblemsWithTracker(t *testing.T) {
   161  	t.Parallel()
   162  	// Arrange
   163  	ctx := inslogger.TestContext(t)
   164  	pulseTrackerMock := storage.NewPulseTrackerMock(t)
   165  	pulseTrackerMock.GetPulseMock.Return(nil, errors.New("it's expected"))
   166  	calc := NewJetCoordinator(12)
   167  	calc.PulseTracker = pulseTrackerMock
   168  
   169  	// Act
   170  	res, err := calc.IsBeyondLimit(ctx, core.FirstPulseNumber, 0)
   171  
   172  	// Assert
   173  	require.NotNil(t, err)
   174  	require.Equal(t, false, res)
   175  }
   176  
   177  func TestJetCoordinator_IsBeyondLimit_ProblemsWithTracker_SecondCall(t *testing.T) {
   178  	t.Parallel()
   179  	// Arrange
   180  	ctx := inslogger.TestContext(t)
   181  	pulseTrackerMock := storage.NewPulseTrackerMock(t)
   182  	pulseTrackerMock.GetPulseFunc = func(p context.Context, p1 core.PulseNumber) (r *storage.Pulse, r1 error) {
   183  		if p1 == core.FirstPulseNumber {
   184  			return &storage.Pulse{}, nil
   185  		}
   186  
   187  		return nil, errors.New("it's expected")
   188  	}
   189  	calc := NewJetCoordinator(12)
   190  	calc.PulseTracker = pulseTrackerMock
   191  
   192  	// Act
   193  	res, err := calc.IsBeyondLimit(ctx, core.FirstPulseNumber, 0)
   194  
   195  	// Assert
   196  	require.NotNil(t, err)
   197  	require.Equal(t, false, res)
   198  }
   199  
   200  func TestJetCoordinator_IsBeyondLimit_OutsideOfLightChainLimit(t *testing.T) {
   201  	t.Parallel()
   202  	// Arrange
   203  	ctx := inslogger.TestContext(t)
   204  	pulseTrackerMock := storage.NewPulseTrackerMock(t)
   205  	pulseTrackerMock.GetPulseFunc = func(p context.Context, p1 core.PulseNumber) (r *storage.Pulse, r1 error) {
   206  		if p1 == core.FirstPulseNumber {
   207  			return &storage.Pulse{SerialNumber: 50}, nil
   208  		}
   209  
   210  		return &storage.Pulse{SerialNumber: 24}, nil
   211  	}
   212  	calc := NewJetCoordinator(25)
   213  	calc.PulseTracker = pulseTrackerMock
   214  
   215  	// Act
   216  	res, err := calc.IsBeyondLimit(ctx, core.FirstPulseNumber, 0)
   217  
   218  	// Assert
   219  	require.Nil(t, err)
   220  	require.Equal(t, true, res)
   221  }
   222  
   223  func TestJetCoordinator_IsBeyondLimit_InsideOfLightChainLimit(t *testing.T) {
   224  	t.Parallel()
   225  	// Arrange
   226  	ctx := inslogger.TestContext(t)
   227  	pulseTrackerMock := storage.NewPulseTrackerMock(t)
   228  	pulseTrackerMock.GetPulseFunc = func(p context.Context, p1 core.PulseNumber) (r *storage.Pulse, r1 error) {
   229  		if p1 == core.FirstPulseNumber {
   230  			return &storage.Pulse{SerialNumber: 50}, nil
   231  		}
   232  
   233  		return &storage.Pulse{SerialNumber: 34}, nil
   234  	}
   235  	calc := NewJetCoordinator(25)
   236  	calc.PulseTracker = pulseTrackerMock
   237  
   238  	// Act
   239  	res, err := calc.IsBeyondLimit(ctx, core.FirstPulseNumber, 0)
   240  
   241  	// Assert
   242  	require.Nil(t, err)
   243  	require.Equal(t, false, res)
   244  }
   245  
   246  func TestJetCoordinator_NodeForJet_CheckLimitFailed(t *testing.T) {
   247  	t.Parallel()
   248  	// Arrange
   249  	ctx := inslogger.TestContext(t)
   250  	pulseTrackerMock := storage.NewPulseTrackerMock(t)
   251  	pulseTrackerMock.GetPulseMock.Return(nil, errors.New("it's expected"))
   252  	calc := NewJetCoordinator(12)
   253  	calc.PulseTracker = pulseTrackerMock
   254  
   255  	// Act
   256  	res, err := calc.NodeForJet(ctx, testutils.RandomJet(), core.FirstPulseNumber, 0)
   257  
   258  	// Assert
   259  	require.NotNil(t, err)
   260  	require.Nil(t, res)
   261  }
   262  
   263  func TestJetCoordinator_NodeForJet_GoToHeavy(t *testing.T) {
   264  	t.Parallel()
   265  	// Arrange
   266  	ctx := inslogger.TestContext(t)
   267  	pulseTrackerMock := storage.NewPulseTrackerMock(t)
   268  	pulseTrackerMock.GetPulseFunc = func(p context.Context, p1 core.PulseNumber) (r *storage.Pulse, r1 error) {
   269  		if p1 == core.FirstPulseNumber {
   270  			return &storage.Pulse{SerialNumber: 50}, nil
   271  		}
   272  
   273  		return &storage.Pulse{SerialNumber: 24}, nil
   274  	}
   275  	expectedID := core.NewRecordRef(testutils.RandomID(), testutils.RandomID())
   276  	activeNodesStorageMock := nodes.NewAccessorMock(t)
   277  	activeNodesStorageMock.InRoleFunc = func(p core.PulseNumber, p1 core.StaticRole) (r []insolar.Node, r1 error) {
   278  		require.Equal(t, core.FirstPulseNumber, int(p))
   279  		require.Equal(t, core.StaticRoleHeavyMaterial, p1)
   280  
   281  		return []insolar.Node{{ID: *expectedID}}, nil
   282  	}
   283  
   284  	pulseStorageMock := testutils.NewPulseStorageMock(t)
   285  	pulseStorageMock.CurrentFunc = func(p context.Context) (r *core.Pulse, r1 error) {
   286  		generator := entropygenerator.StandardEntropyGenerator{}
   287  		return &core.Pulse{PulseNumber: core.FirstPulseNumber, Entropy: generator.GenerateEntropy()}, nil
   288  	}
   289  
   290  	calc := NewJetCoordinator(25)
   291  	calc.PulseTracker = pulseTrackerMock
   292  	calc.Nodes = activeNodesStorageMock
   293  	calc.PulseStorage = pulseStorageMock
   294  	calc.PlatformCryptographyScheme = platformpolicy.NewPlatformCryptographyScheme()
   295  
   296  	// Act
   297  	resNode, err := calc.NodeForJet(ctx, testutils.RandomJet(), core.FirstPulseNumber, 0)
   298  
   299  	// Assert
   300  	require.Nil(t, err)
   301  	require.Equal(t, expectedID, resNode)
   302  }
   303  
   304  func TestJetCoordinator_NodeForJet_GoToLight(t *testing.T) {
   305  	t.Parallel()
   306  	// Arrange
   307  	ctx := inslogger.TestContext(t)
   308  	pulseTrackerMock := storage.NewPulseTrackerMock(t)
   309  	pulseTrackerMock.GetPulseFunc = func(p context.Context, p1 core.PulseNumber) (r *storage.Pulse, r1 error) {
   310  		if p1 == core.FirstPulseNumber {
   311  			return &storage.Pulse{SerialNumber: 50}, nil
   312  		}
   313  
   314  		return &storage.Pulse{SerialNumber: 49}, nil
   315  	}
   316  	expectedID := core.NewRecordRef(testutils.RandomID(), testutils.RandomID())
   317  	activeNodesStorageMock := nodes.NewAccessorMock(t)
   318  	activeNodesStorageMock.InRoleFunc = func(p core.PulseNumber, p1 core.StaticRole) (r []insolar.Node, r1 error) {
   319  		require.Equal(t, 0, int(p))
   320  		require.Equal(t, core.StaticRoleLightMaterial, p1)
   321  
   322  		return []insolar.Node{{ID: *expectedID}}, nil
   323  	}
   324  
   325  	pulseStorageMock := testutils.NewPulseStorageMock(t)
   326  	pulseStorageMock.CurrentFunc = func(p context.Context) (r *core.Pulse, r1 error) {
   327  		generator := entropygenerator.StandardEntropyGenerator{}
   328  		return &core.Pulse{PulseNumber: core.FirstPulseNumber, Entropy: generator.GenerateEntropy()}, nil
   329  	}
   330  
   331  	calc := NewJetCoordinator(25)
   332  	calc.PulseTracker = pulseTrackerMock
   333  	calc.Nodes = activeNodesStorageMock
   334  	calc.PulseStorage = pulseStorageMock
   335  	calc.PlatformCryptographyScheme = platformpolicy.NewPlatformCryptographyScheme()
   336  
   337  	// Act
   338  	resNode, err := calc.NodeForJet(ctx, testutils.RandomJet(), core.FirstPulseNumber, 0)
   339  
   340  	// Assert
   341  	require.Nil(t, err)
   342  	require.Equal(t, expectedID, resNode)
   343  }