github.com/braveheart12/just@v0.8.7/ledger/storage/cleaner_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 storage_test
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  	"testing"
    23  
    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/recentstorage"
    28  	"github.com/insolar/insolar/ledger/storage"
    29  	"github.com/insolar/insolar/ledger/storage/storagetest"
    30  	"github.com/insolar/insolar/platformpolicy"
    31  	"github.com/insolar/insolar/testutils"
    32  	"github.com/stretchr/testify/assert"
    33  	"github.com/stretchr/testify/require"
    34  	"github.com/stretchr/testify/suite"
    35  )
    36  
    37  type cleanerSuite struct {
    38  	suite.Suite
    39  
    40  	cm      *component.Manager
    41  	ctx     context.Context
    42  	cleaner func()
    43  
    44  	objectStorage  storage.ObjectStorage
    45  	dropStorage    storage.DropStorage
    46  	storageCleaner storage.Cleaner
    47  }
    48  
    49  func NewCleanerSuite() *cleanerSuite {
    50  	return &cleanerSuite{
    51  		Suite: suite.Suite{},
    52  	}
    53  }
    54  
    55  // Init and run suite
    56  func TestCleaner(t *testing.T) {
    57  	suite.Run(t, NewCleanerSuite())
    58  }
    59  
    60  func (s *cleanerSuite) BeforeTest(suiteName, testName string) {
    61  	s.cm = &component.Manager{}
    62  	s.ctx = inslogger.TestContext(s.T())
    63  
    64  	db, cleaner := storagetest.TmpDB(s.ctx, s.T())
    65  	s.cleaner = cleaner
    66  
    67  	s.objectStorage = storage.NewObjectStorage()
    68  	s.dropStorage = storage.NewDropStorage(0)
    69  	s.storageCleaner = storage.NewCleaner()
    70  
    71  	s.cm.Inject(
    72  		platformpolicy.NewPlatformCryptographyScheme(),
    73  		db,
    74  		s.objectStorage,
    75  		s.storageCleaner,
    76  		s.dropStorage,
    77  	)
    78  
    79  	err := s.cm.Init(s.ctx)
    80  	if err != nil {
    81  		s.T().Error("ComponentManager init failed", err)
    82  	}
    83  	err = s.cm.Start(s.ctx)
    84  	if err != nil {
    85  		s.T().Error("ComponentManager start failed", err)
    86  	}
    87  }
    88  
    89  func (s *cleanerSuite) AfterTest(suiteName, testName string) {
    90  	err := s.cm.Stop(s.ctx)
    91  	if err != nil {
    92  		s.T().Error("ComponentManager stop failed", err)
    93  	}
    94  	s.cleaner()
    95  }
    96  
    97  func (s *cleanerSuite) Test_RemoveRecords() {
    98  	t := s.T()
    99  	ctx := inslogger.TestContext(t)
   100  
   101  	jetID00 := testutils.JetFromString("00")
   102  	jetID01 := testutils.JetFromString("01")
   103  	jetID11 := testutils.JetFromString("11")
   104  	jets := []core.RecordID{jetID00, jetID01, jetID11}
   105  
   106  	// should remove all records in rmJetID on pulses 1, 2, but all in pulse 3 for rmJetID should left
   107  	// and other jets records should not be removed too
   108  	var checks []cleanChecker
   109  	until := 2
   110  	rmUntilPN := core.PulseNumber(core.FirstPulseNumber + until + 1)
   111  	rmJetID := jetID01
   112  
   113  	for _, jetID := range jets {
   114  		for i := 1; i <= 3; i++ {
   115  			pn := core.PulseNumber(core.FirstPulseNumber + i)
   116  
   117  			shouldLeft := true
   118  			if jetID == rmJetID {
   119  				shouldLeft = i > until
   120  			}
   121  
   122  			blobID, err := storagetest.AddRandBlob(ctx, s.objectStorage, jetID, pn)
   123  			require.NoError(t, err)
   124  			blobCC := cleanCase{
   125  				rectype:    "blob",
   126  				id:         blobID,
   127  				jetID:      jetID,
   128  				pulseNum:   pn,
   129  				shouldLeft: shouldLeft,
   130  			}
   131  			checks = append(checks, blobCase{
   132  				cleanCase:     blobCC,
   133  				objectStorage: s.objectStorage,
   134  			})
   135  
   136  			recID, err := storagetest.AddRandRecord(ctx, s.objectStorage, jetID, pn)
   137  			require.NoError(t, err)
   138  			recCC := cleanCase{
   139  				rectype:    "record",
   140  				id:         recID,
   141  				jetID:      jetID,
   142  				pulseNum:   pn,
   143  				shouldLeft: shouldLeft,
   144  			}
   145  			checks = append(checks, recordCase{
   146  				cleanCase:     recCC,
   147  				objectStorage: s.objectStorage,
   148  			})
   149  
   150  			_, err = storagetest.AddRandDrop(ctx, s.dropStorage, jetID, pn)
   151  			require.NoError(t, err)
   152  			dropCC := cleanCase{
   153  				rectype:    "drop",
   154  				id:         recID,
   155  				jetID:      jetID,
   156  				pulseNum:   pn,
   157  				shouldLeft: shouldLeft,
   158  			}
   159  			checks = append(checks, dropCase{
   160  				cleanCase:   dropCC,
   161  				dropStorage: s.dropStorage,
   162  			})
   163  		}
   164  	}
   165  
   166  	s.storageCleaner.CleanJetRecordsUntilPulse(ctx, rmJetID, rmUntilPN)
   167  
   168  	for _, check := range checks {
   169  		check.Check(ctx, t)
   170  	}
   171  }
   172  
   173  func (s *cleanerSuite) Test_RemoveJetIndexes() {
   174  	t := s.T()
   175  	ctx := inslogger.TestContext(t)
   176  
   177  	jetID00 := testutils.JetFromString("00")
   178  	jetID01 := testutils.JetFromString("01")
   179  	jetID11 := testutils.JetFromString("11")
   180  	jets := []core.RecordID{jetID00, jetID01, jetID11}
   181  
   182  	// should remove records in Pulse 1, 2, but left 3
   183  	var checks []cleanChecker
   184  	until := 2
   185  	rmJetID := jetID01
   186  	var removeIndexes []core.RecordID
   187  
   188  	for _, jetID := range jets {
   189  		for i := 1; i <= 3; i++ {
   190  			pn := core.PulseNumber(core.FirstPulseNumber + i)
   191  			idxID, err := storagetest.AddRandIndex(ctx, s.objectStorage, jetID, pn)
   192  			require.NoError(t, err)
   193  
   194  			shouldLeft := true
   195  			if jetID == rmJetID {
   196  				shouldLeft = i > until
   197  				if !shouldLeft {
   198  					removeIndexes = append(removeIndexes, *idxID)
   199  				}
   200  			}
   201  
   202  			cc := cleanCase{
   203  				id:         idxID,
   204  				jetID:      jetID,
   205  				pulseNum:   pn,
   206  				shouldLeft: shouldLeft,
   207  			}
   208  			checks = append(checks, indexCase{
   209  				cleanCase:     cc,
   210  				objectStorage: s.objectStorage,
   211  			})
   212  		}
   213  	}
   214  
   215  	recent := recentstorage.NewRecentIndexStorageMock(s.T())
   216  	recent.FilterNotExistWithLockFunc = func(ctx context.Context, candidates []core.RecordID, fn func(fordelete []core.RecordID)) {
   217  		fn(candidates)
   218  	}
   219  
   220  	s.storageCleaner.CleanJetIndexes(ctx, rmJetID, recent, removeIndexes)
   221  
   222  	for _, check := range checks {
   223  		check.Check(ctx, t)
   224  	}
   225  }
   226  
   227  // check helpers
   228  
   229  type cleanChecker interface {
   230  	Check(ctx context.Context, t *testing.T)
   231  	String() string
   232  }
   233  
   234  type cleanCase struct {
   235  	rectype    string
   236  	id         *core.RecordID
   237  	jetID      core.RecordID
   238  	pulseNum   core.PulseNumber
   239  	shouldLeft bool
   240  }
   241  
   242  func (cc cleanCase) String() string {
   243  	return fmt.Sprintf("%v jetID=%v, pulseNum=%v, shouldLeft=%v",
   244  		cc.rectype, cc.jetID.DebugString(), cc.pulseNum, cc.shouldLeft)
   245  }
   246  
   247  func (cc cleanCase) check(t *testing.T, err error) {
   248  	if cc.shouldLeft {
   249  		if !assert.NoError(t, err) {
   250  			fmt.Printf("%v => err: %T\n", cc, err)
   251  		}
   252  		return
   253  	}
   254  	if !assert.Exactly(t, err, core.ErrNotFound) {
   255  		fmt.Printf("%v => err: %T\n", cc, err)
   256  	}
   257  }
   258  
   259  type indexCase struct {
   260  	cleanCase
   261  	objectStorage storage.ObjectStorage
   262  }
   263  
   264  func (c indexCase) Check(ctx context.Context, t *testing.T) {
   265  	_, err := c.objectStorage.GetObjectIndex(ctx, c.jetID, c.id, false)
   266  	c.check(t, err)
   267  }
   268  
   269  type blobCase struct {
   270  	cleanCase
   271  	objectStorage storage.ObjectStorage
   272  }
   273  
   274  func (c blobCase) Check(ctx context.Context, t *testing.T) {
   275  	_, err := c.objectStorage.GetBlob(ctx, c.jetID, c.id)
   276  	c.check(t, err)
   277  }
   278  
   279  type recordCase struct {
   280  	cleanCase
   281  	objectStorage storage.ObjectStorage
   282  }
   283  
   284  func (c recordCase) Check(ctx context.Context, t *testing.T) {
   285  	_, err := c.objectStorage.GetRecord(ctx, c.jetID, c.id)
   286  	c.check(t, err)
   287  }
   288  
   289  type dropCase struct {
   290  	cleanCase
   291  	dropStorage storage.DropStorage
   292  }
   293  
   294  func (c dropCase) Check(ctx context.Context, t *testing.T) {
   295  	_, err := c.dropStorage.GetDrop(ctx, c.jetID, c.pulseNum)
   296  	c.check(t, err)
   297  }