github.com/braveheart12/just@v0.8.7/ledger/recentstorage/recentstorage_concrete_test.go (about)

     1  /*
     2   *    Copyright 2019 Insolar
     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 recentstorage
    18  
    19  import (
    20  	"bytes"
    21  	"sync"
    22  	"testing"
    23  
    24  	"github.com/insolar/insolar/core"
    25  	"github.com/insolar/insolar/instrumentation/inslogger"
    26  	"github.com/insolar/insolar/testutils"
    27  	"github.com/stretchr/testify/require"
    28  )
    29  
    30  func TestNewRecentIndexStorage(t *testing.T) {
    31  	t.Parallel()
    32  	jetID := testutils.RandomID()
    33  	index := NewRecentIndexStorage(jetID, 123)
    34  	require.NotNil(t, index)
    35  	require.NotNil(t, index.indexes)
    36  	require.Equal(t, 123, index.DefaultTTL)
    37  }
    38  
    39  func TestNewRecentIndexStorage_AddId(t *testing.T) {
    40  	t.Parallel()
    41  	ctx := inslogger.TestContext(t)
    42  	jetID := testutils.RandomID()
    43  	s := NewRecentIndexStorage(jetID, 123)
    44  
    45  	wg := sync.WaitGroup{}
    46  	wg.Add(3)
    47  
    48  	go func() {
    49  		s.AddObject(ctx, *core.NewRecordID(123, []byte{1}))
    50  		wg.Done()
    51  	}()
    52  	go func() {
    53  		s.AddObject(ctx, *core.NewRecordID(123, []byte{2}))
    54  		wg.Done()
    55  	}()
    56  	go func() {
    57  		s.AddObject(ctx, *core.NewRecordID(123, []byte{3}))
    58  		wg.Done()
    59  	}()
    60  
    61  	wg.Wait()
    62  	require.Equal(t, 3, len(s.GetObjects()))
    63  }
    64  
    65  func TestPendingStorage_AddPendingRequest(t *testing.T) {
    66  	t.Parallel()
    67  	ctx := inslogger.TestContext(t)
    68  	jetID := testutils.RandomID()
    69  
    70  	s := NewPendingStorage(jetID)
    71  
    72  	obj1 := *core.NewRecordID(0, nil)
    73  	obj2 := *core.NewRecordID(1, nil)
    74  
    75  	wg := sync.WaitGroup{}
    76  	wg.Add(3)
    77  
    78  	expectedIDs := []core.RecordID{
    79  		*core.NewRecordID(123, []byte{1}),
    80  		*core.NewRecordID(123, []byte{2}),
    81  		*core.NewRecordID(123, []byte{3}),
    82  	}
    83  	go func() {
    84  		s.AddPendingRequest(ctx, obj1, expectedIDs[0])
    85  		wg.Done()
    86  	}()
    87  	go func() {
    88  		s.AddPendingRequest(ctx, obj1, expectedIDs[1])
    89  		wg.Done()
    90  	}()
    91  	go func() {
    92  		s.AddPendingRequest(ctx, obj2, expectedIDs[2])
    93  		wg.Done()
    94  	}()
    95  	wg.Wait()
    96  
    97  	contains := func(slice []core.RecordID, x core.RecordID) bool {
    98  		for _, n := range slice {
    99  			if x == n {
   100  				return true
   101  			}
   102  		}
   103  		return false
   104  	}
   105  	requests := s.GetRequests()
   106  	require.Equal(t, 2, len(requests))
   107  	for key, objContext := range requests {
   108  		if bytes.Equal(key.Bytes(), obj1.Bytes()) {
   109  			require.Equal(t, 2, len(objContext.Requests))
   110  			require.Equal(t, true, contains(objContext.Requests, expectedIDs[0]))
   111  			require.Equal(t, true, contains(objContext.Requests, expectedIDs[1]))
   112  		} else {
   113  			require.Equal(t, 1, len(objContext.Requests))
   114  			require.Equal(t, expectedIDs[2], objContext.Requests[0])
   115  		}
   116  	}
   117  }
   118  
   119  func TestPendingStorage_RemovePendingRequest(t *testing.T) {
   120  	t.Parallel()
   121  	ctx := inslogger.TestContext(t)
   122  	jetID := testutils.RandomID()
   123  
   124  	s := NewPendingStorage(jetID)
   125  
   126  	obj := *core.NewRecordID(0, nil)
   127  
   128  	expectedIDs := []core.RecordID{
   129  		*core.NewRecordID(123, []byte{1}),
   130  	}
   131  	extraIDs := []core.RecordID{
   132  		*core.NewRecordID(123, []byte{2}),
   133  		*core.NewRecordID(123, []byte{3}),
   134  		*core.NewRecordID(123, []byte{4}),
   135  	}
   136  	s.requests = map[core.RecordID]*lockedPendingObjectContext{
   137  		obj: {
   138  			Context: &PendingObjectContext{
   139  				Requests: []core.RecordID{expectedIDs[0], extraIDs[0], extraIDs[1], extraIDs[2]},
   140  			},
   141  		},
   142  	}
   143  
   144  	wg := sync.WaitGroup{}
   145  	wg.Add(3)
   146  	go func() {
   147  		s.RemovePendingRequest(ctx, obj, extraIDs[0])
   148  		wg.Done()
   149  	}()
   150  	go func() {
   151  		s.RemovePendingRequest(ctx, obj, extraIDs[1])
   152  		wg.Done()
   153  	}()
   154  	go func() {
   155  		s.RemovePendingRequest(ctx, obj, extraIDs[2])
   156  		wg.Done()
   157  	}()
   158  	wg.Wait()
   159  
   160  	require.Equal(
   161  		t,
   162  		map[core.RecordID]PendingObjectContext{
   163  			obj: {
   164  				Active:   true,
   165  				Requests: []core.RecordID{expectedIDs[0]},
   166  			},
   167  		},
   168  		s.GetRequests(),
   169  	)
   170  }
   171  
   172  func TestPendingStorage_RemovePendingRequest_RemoveNothingIfThereIsNothing(t *testing.T) {
   173  	t.Parallel()
   174  	ctx := inslogger.TestContext(t)
   175  	jetID := testutils.RandomID()
   176  	objID := testutils.RandomID()
   177  	anotherObj := *core.NewRecordID(123, nil)
   178  	s := NewPendingStorage(jetID)
   179  
   180  	s.requests = map[core.RecordID]*lockedPendingObjectContext{
   181  		objID: {
   182  			Context: &PendingObjectContext{
   183  				Requests: []core.RecordID{},
   184  			},
   185  		},
   186  	}
   187  
   188  	s.RemovePendingRequest(ctx, anotherObj, testutils.RandomID())
   189  
   190  	require.Equal(
   191  		t,
   192  		map[core.RecordID]PendingObjectContext{
   193  			objID: {
   194  				Requests: []core.RecordID{},
   195  			},
   196  		},
   197  		s.GetRequests(),
   198  	)
   199  }
   200  
   201  func TestNewRecentStorageProvider(t *testing.T) {
   202  	t.Parallel()
   203  	// Act
   204  	provider := NewRecentStorageProvider(888)
   205  
   206  	// Assert
   207  	require.Equal(t, 888, provider.DefaultTTL)
   208  	require.NotNil(t, provider.pendingStorages)
   209  	require.NotNil(t, provider.indexStorages)
   210  }
   211  
   212  func TestRecentStorageProvider_GetStorage(t *testing.T) {
   213  	t.Parallel()
   214  	// Arrange
   215  	provider := NewRecentStorageProvider(8)
   216  
   217  	// Act
   218  	wg := sync.WaitGroup{}
   219  	wg.Add(8)
   220  
   221  	for i := 0; i < 8; i++ {
   222  		go func() {
   223  			id := testutils.RandomJet()
   224  			storage := provider.GetIndexStorage(inslogger.TestContext(t), id)
   225  			require.NotNil(t, storage)
   226  			pendingStorage := provider.GetPendingStorage(inslogger.TestContext(t), id)
   227  			require.NotNil(t, pendingStorage)
   228  			wg.Done()
   229  		}()
   230  	}
   231  
   232  	wg.Wait()
   233  
   234  	// Assert
   235  	require.Equal(t, 8, len(provider.indexStorages))
   236  	require.Equal(t, 8, len(provider.pendingStorages))
   237  }
   238  
   239  func TestRecentStorage_markForDelete(t *testing.T) {
   240  	t.Parallel()
   241  	candidates := make([]core.RecordID, 0, 100)
   242  	expect := make([]core.RecordID, 0, 50)
   243  	recentStorageMap := make(map[core.RecordID]recentObjectMeta)
   244  
   245  	for i := 0; i < 100; i++ {
   246  		rID := testutils.RandomID()
   247  		candidates = append(candidates, rID)
   248  		if i%2 == 0 {
   249  			expect = append(expect, rID)
   250  		} else {
   251  			recentStorageMap[rID] = recentObjectMeta{i}
   252  		}
   253  	}
   254  
   255  	recentStorage := NewRecentIndexStorage(testutils.RandomJet(), 888)
   256  	recentStorage.indexes = recentStorageMap
   257  
   258  	markedCandidates := recentStorage.markForDelete(candidates)
   259  
   260  	require.Equal(t, expect, markedCandidates)
   261  }
   262  
   263  func TestRecentStorageProvider_DecreaseIndexesTTL(t *testing.T) {
   264  	t.Parallel()
   265  	// Arrange
   266  	ctx := inslogger.TestContext(t)
   267  
   268  	firstJet := testutils.RandomJet()
   269  	secondJet := testutils.RandomJet()
   270  
   271  	provider := NewRecentStorageProvider(8)
   272  	provider.GetIndexStorage(ctx, firstJet).AddObject(ctx, testutils.RandomID())
   273  	provider.GetIndexStorage(ctx, firstJet).AddObject(ctx, testutils.RandomID())
   274  
   275  	removedFirst := testutils.RandomID()
   276  	removedSecond := testutils.RandomID()
   277  	provider.GetIndexStorage(ctx, secondJet).AddObjectWithTLL(ctx, removedFirst, 1)
   278  	provider.GetIndexStorage(ctx, secondJet).AddObjectWithTLL(ctx, removedSecond, 1)
   279  
   280  	// Act
   281  	result := provider.DecreaseIndexesTTL(ctx)
   282  
   283  	// Assert
   284  	provider.indexLock.Lock()
   285  	defer provider.indexLock.Unlock()
   286  	require.NotNil(t, result)
   287  	require.Equal(t, 1, len(provider.indexStorages))
   288  	require.Equal(t, 1, len(result))
   289  	require.Equal(t, 2, len(result[secondJet]))
   290  	if removedFirst != result[secondJet][0] && removedFirst != result[secondJet][1] {
   291  		require.Fail(t, "return result is broken")
   292  	}
   293  	if removedSecond != result[secondJet][1] && removedSecond != result[secondJet][0] {
   294  		require.Fail(t, "return result is broken")
   295  	}
   296  	for _, index := range provider.indexStorages[firstJet].indexes {
   297  		require.Equal(t, 7, index.ttl)
   298  	}
   299  }
   300  
   301  func TestRecentStorageProvider_DecreaseIndexesTTL_WorksOnEmptyStorage(t *testing.T) {
   302  	t.Parallel()
   303  	// Arrange
   304  	ctx := inslogger.TestContext(t)
   305  	provider := NewRecentStorageProvider(8)
   306  
   307  	// Act
   308  	result := provider.DecreaseIndexesTTL(ctx)
   309  
   310  	// Assert
   311  	require.Equal(t, map[core.RecordID][]core.RecordID{}, result)
   312  }
   313  
   314  func TestPendingStorageConcrete_GetRequestsForObject(t *testing.T) {
   315  	t.Parallel()
   316  
   317  	objID := testutils.RandomID()
   318  	requestID := testutils.RandomID()
   319  
   320  	unexpectedID := testutils.RandomID()
   321  	unexpectedReqID := testutils.RandomID()
   322  
   323  	pendingStorage := &PendingStorageConcrete{
   324  		requests: map[core.RecordID]*lockedPendingObjectContext{
   325  			objID: {
   326  				Context: &PendingObjectContext{
   327  					Requests: []core.RecordID{requestID},
   328  				},
   329  			},
   330  			unexpectedID: {
   331  				Context: &PendingObjectContext{
   332  					Requests: []core.RecordID{unexpectedReqID},
   333  				},
   334  			},
   335  		},
   336  	}
   337  
   338  	requests := pendingStorage.GetRequestsForObject(objID)
   339  
   340  	require.Equal(t, 1, len(requests))
   341  	require.Equal(t, requestID, requests[0])
   342  }
   343  
   344  func TestPendingStorageConcrete_GetRequestsForObject_NoObject(t *testing.T) {
   345  	t.Parallel()
   346  
   347  	unexpectedReqID := testutils.RandomID()
   348  
   349  	pendingStorage := &PendingStorageConcrete{
   350  		requests: map[core.RecordID]*lockedPendingObjectContext{},
   351  	}
   352  
   353  	requests := pendingStorage.GetRequestsForObject(unexpectedReqID)
   354  
   355  	require.Nil(t, requests)
   356  }
   357  
   358  func TestPendingStorageConcrete_SetContextToObject(t *testing.T) {
   359  	t.Parallel()
   360  
   361  	pendingStorage := &PendingStorageConcrete{
   362  		requests: map[core.RecordID]*lockedPendingObjectContext{},
   363  	}
   364  	expectedObj := testutils.RandomID()
   365  	expectedContext := PendingObjectContext{
   366  		Active:   true,
   367  		Requests: []core.RecordID{testutils.RandomID(), testutils.RandomID()},
   368  	}
   369  
   370  	pendingStorage.SetContextToObject(inslogger.TestContext(t), expectedObj, expectedContext)
   371  
   372  	require.Equal(t, 1, len(pendingStorage.requests))
   373  	require.Equal(t, expectedContext, *pendingStorage.requests[expectedObj].Context)
   374  }
   375  
   376  func TestPendingStorageConcrete_RemovePendingRequest_RemoveFromStart(t *testing.T) {
   377  	t.Parallel()
   378  
   379  	objID := testutils.RandomID()
   380  	first := testutils.RandomID()
   381  	second := testutils.RandomID()
   382  	pendingStorage := &PendingStorageConcrete{
   383  		requests: map[core.RecordID]*lockedPendingObjectContext{
   384  
   385  			objID: {
   386  				Context: &PendingObjectContext{
   387  					Requests: []core.RecordID{first, second},
   388  				},
   389  			},
   390  		},
   391  	}
   392  
   393  	pendingStorage.RemovePendingRequest(inslogger.TestContext(t), objID, first)
   394  
   395  	require.Equal(t, 1, len(pendingStorage.requests[objID].Context.Requests))
   396  	require.Equal(t, second, pendingStorage.requests[objID].Context.Requests[0])
   397  }
   398  
   399  func TestPendingStorageConcrete_RemovePendingRequest_RemoveFromEnd(t *testing.T) {
   400  	t.Parallel()
   401  
   402  	objID := testutils.RandomID()
   403  	first := testutils.RandomID()
   404  	second := testutils.RandomID()
   405  	pendingStorage := &PendingStorageConcrete{
   406  		requests: map[core.RecordID]*lockedPendingObjectContext{
   407  
   408  			objID: {
   409  				Context: &PendingObjectContext{
   410  					Requests: []core.RecordID{first, second},
   411  				},
   412  			},
   413  		},
   414  	}
   415  
   416  	pendingStorage.RemovePendingRequest(inslogger.TestContext(t), objID, second)
   417  
   418  	require.Equal(t, 1, len(pendingStorage.requests[objID].Context.Requests))
   419  	require.Equal(t, first, pendingStorage.requests[objID].Context.Requests[0])
   420  }
   421  
   422  func TestPendingStorageConcrete_RemovePendingRequest_RemoveFromMiddle(t *testing.T) {
   423  	t.Parallel()
   424  
   425  	objID := testutils.RandomID()
   426  	first := testutils.RandomID()
   427  	second := testutils.RandomID()
   428  	third := testutils.RandomID()
   429  	pendingStorage := &PendingStorageConcrete{
   430  		requests: map[core.RecordID]*lockedPendingObjectContext{
   431  
   432  			objID: {
   433  				Context: &PendingObjectContext{
   434  					Requests: []core.RecordID{first, second, third},
   435  				},
   436  			},
   437  		},
   438  	}
   439  
   440  	pendingStorage.RemovePendingRequest(inslogger.TestContext(t), objID, second)
   441  
   442  	require.Equal(t, 2, len(pendingStorage.requests[objID].Context.Requests))
   443  	require.Equal(t, first, pendingStorage.requests[objID].Context.Requests[0])
   444  	require.Equal(t, third, pendingStorage.requests[objID].Context.Requests[1])
   445  }
   446  
   447  func TestPendingStorageConcrete_RemovePendingRequest_NothingHappensIfNoRequests(t *testing.T) {
   448  	t.Parallel()
   449  
   450  	objID := testutils.RandomID()
   451  	pendingStorage := &PendingStorageConcrete{
   452  		requests: map[core.RecordID]*lockedPendingObjectContext{
   453  
   454  			objID: {
   455  				Context: &PendingObjectContext{},
   456  			},
   457  		},
   458  	}
   459  
   460  	pendingStorage.RemovePendingRequest(inslogger.TestContext(t), objID, testutils.RandomID())
   461  
   462  	require.Equal(t, 1, len(pendingStorage.requests))
   463  	_, ok := pendingStorage.requests[objID]
   464  	require.Equal(t, true, ok)
   465  }
   466  
   467  func TestPendingStorageConcrete_RemovePendingRequest_RemoveOnlyOne(t *testing.T) {
   468  	t.Parallel()
   469  
   470  	first := testutils.RandomID()
   471  	objID := testutils.RandomID()
   472  
   473  	pendingStorage := &PendingStorageConcrete{
   474  		requests: map[core.RecordID]*lockedPendingObjectContext{
   475  			objID: {
   476  				Context: &PendingObjectContext{
   477  					Requests: []core.RecordID{first},
   478  				},
   479  			},
   480  		},
   481  	}
   482  
   483  	pendingStorage.RemovePendingRequest(inslogger.TestContext(t), objID, first)
   484  
   485  	require.Equal(t, 0, len(pendingStorage.requests[objID].Context.Requests))
   486  }
   487  
   488  func TestPendingStorageConcrete_RemovePendingRequest_RemoveNotExisting(t *testing.T) {
   489  	t.Parallel()
   490  
   491  	objID := testutils.RandomID()
   492  	first := testutils.RandomID()
   493  	second := testutils.RandomID()
   494  	third := testutils.RandomID()
   495  	pendingStorage := &PendingStorageConcrete{
   496  		requests: map[core.RecordID]*lockedPendingObjectContext{
   497  
   498  			objID: {
   499  				Context: &PendingObjectContext{
   500  					Requests: []core.RecordID{first, second},
   501  				},
   502  			},
   503  		},
   504  	}
   505  
   506  	pendingStorage.RemovePendingRequest(inslogger.TestContext(t), objID, third)
   507  
   508  	require.Equal(t, 2, len(pendingStorage.requests[objID].Context.Requests))
   509  	require.Equal(t, first, pendingStorage.requests[objID].Context.Requests[0])
   510  	require.Equal(t, second, pendingStorage.requests[objID].Context.Requests[1])
   511  }