github.com/jfrog/jfrog-cli-core/v2@v2.51.0/artifactory/commands/transferfiles/state/state_test.go (about)

     1  package state
     2  
     3  import (
     4  	"testing"
     5  	"time"
     6  
     7  	"github.com/jfrog/jfrog-cli-core/v2/utils/reposnapshot"
     8  	"github.com/jfrog/jfrog-client-go/utils/io/fileutils"
     9  	"github.com/stretchr/testify/assert"
    10  )
    11  
    12  func TestGetRepositoryState(t *testing.T) {
    13  	stateManager, cleanUp := InitStateTest(t)
    14  	defer cleanUp()
    15  
    16  	// Assert repo does not exist before it was created.
    17  	loadAndAssertRepo(t, repo1Key, false)
    18  
    19  	// Create new repos.
    20  	createAndAssertRepoState(t, stateManager, repo1Key)
    21  	createAndAssertRepoState(t, stateManager, repo2Key)
    22  
    23  	// Add data to current repo.
    24  	stateManager.CurrentRepo.FullTransfer.Started = "start"
    25  	stateManager.CurrentRepo.FullTransfer.Ended = "end"
    26  	assert.NoError(t, stateManager.persistTransferState(false))
    27  
    28  	// Create new repo, and assert data on previous repo is loaded correctly.
    29  	createAndAssertRepoState(t, stateManager, repo3Key)
    30  	transferState := loadAndAssertRepo(t, repo2Key, true)
    31  	assert.Equal(t, "start", transferState.CurrentRepo.FullTransfer.Started)
    32  	assert.Equal(t, "end", transferState.CurrentRepo.FullTransfer.Ended)
    33  }
    34  
    35  func loadAndAssertRepo(t *testing.T, repoKey string, expectedToExist bool) *TransferState {
    36  	transferState, exists, err := LoadTransferState(repoKey, false)
    37  	assert.NoError(t, err)
    38  	assert.Equal(t, expectedToExist, exists)
    39  	if expectedToExist {
    40  		assert.Equal(t, repoKey, transferState.CurrentRepo.Name)
    41  	}
    42  	return &transferState
    43  }
    44  
    45  func createAndAssertRepoState(t *testing.T, stateManager *TransferStateManager, repoKey string) {
    46  	assert.NoError(t, stateManager.SetRepoState(repoKey, 0, 0, false, false))
    47  	transferState := loadAndAssertRepo(t, repoKey, true)
    48  	assert.Empty(t, transferState.CurrentRepo.FullTransfer)
    49  	assert.Empty(t, transferState.CurrentRepo.Diffs)
    50  }
    51  
    52  func TestSaveAndLoadState(t *testing.T) {
    53  	stateManager, cleanUp := InitStateTest(t)
    54  	defer cleanUp()
    55  	stateManager.CurrentRepo = newRepositoryTransferState(repo4Key).CurrentRepo
    56  
    57  	assert.NoError(t, stateManager.persistTransferState(false))
    58  	actualState, exists, err := LoadTransferState(repo4Key, false)
    59  	assert.NoError(t, err)
    60  	assert.True(t, exists)
    61  	assert.Equal(t, stateManager.TransferState, actualState)
    62  
    63  	// Persist the transfer state with a high version and assert loading yields an error.
    64  	stateManager.TransferState.Version = 1000
    65  	assert.NoError(t, stateManager.persistTransferState(false))
    66  	_, _, err = LoadTransferState(repo4Key, false)
    67  	assert.ErrorContains(t, err, transferStateFileInvalidVersionErrorMsg)
    68  }
    69  
    70  func TestGetTransferStateAndSnapshotClean(t *testing.T) {
    71  	stateManager, cleanUp := InitStateTest(t)
    72  	defer cleanUp()
    73  
    74  	// Make the snapshot not auto save.
    75  	snapshotCleanUp := setAutoSaveSnapshot(1000)
    76  	defer snapshotCleanUp()
    77  
    78  	// Assert getting state before it was created returns clean state.
    79  	cleanTransferState, cleanRepoTransferSnapshot, err := getCleanStateAndSnapshot(repo1Key)
    80  	assert.NoError(t, err)
    81  	assertGetTransferStateAndSnapshot(t, false, cleanTransferState, cleanRepoTransferSnapshot, false)
    82  
    83  	// Create repo-state.
    84  	createAndAssertRepoState(t, stateManager, repo1Key)
    85  	// Assert getting clean state on reset.
    86  	assertGetTransferStateAndSnapshot(t, true, cleanTransferState, cleanRepoTransferSnapshot, false)
    87  
    88  	// Mark phase 1 as started.
    89  	assert.NoError(t, stateManager.SetRepoFullTransferStarted(time.Now()))
    90  	getRootAndAddSnapshotData(t, stateManager)
    91  	// Create only the snapshot file in snapshot dir (without repo state). Since the state file is missing in the snapshots dir the load should start clean.
    92  	assert.NoError(t, stateManager.repoTransferSnapshot.snapshotManager.PersistRepoSnapshot())
    93  	snapshotPath, err := GetRepoSnapshotFilePath(repo1Key)
    94  	assert.NoError(t, err)
    95  	exists, err := fileutils.IsFileExists(snapshotPath, false)
    96  	assert.NoError(t, err)
    97  	assert.True(t, exists)
    98  	assertGetTransferStateAndSnapshot(t, false, cleanTransferState, cleanRepoTransferSnapshot, false)
    99  }
   100  
   101  // Set the snapshot's save-interval and return a cleanup function.
   102  func setAutoSaveSnapshot(interval int) (cleanUp func()) {
   103  	previousSaveInterval := snapshotSaveIntervalMin
   104  	snapshotSaveIntervalMin = interval
   105  	return func() {
   106  		snapshotSaveIntervalMin = previousSaveInterval
   107  	}
   108  }
   109  
   110  // Testing two scenarios here:
   111  // 1. loading (snapshot file and state) from existing snapshot
   112  // 2. loading state of fully transferred repository (phase 1 completed)
   113  func TestGetTransferStateAndSnapshotLoading(t *testing.T) {
   114  	stateManager, cleanUp := InitStateTest(t)
   115  	defer cleanUp()
   116  
   117  	// Create repo-state.
   118  	createAndAssertRepoState(t, stateManager, repo1Key)
   119  
   120  	// Add content to state and snapshot.
   121  	assert.NoError(t, stateManager.SetRepoFullTransferStarted(time.Now()))
   122  	assert.NoError(t, stateManager.IncTransferredSizeAndFilesPhase1(2, 3))
   123  	_ = getRootAndAddSnapshotData(t, stateManager)
   124  	// Get state before saving.
   125  	originalState := stateManager.TransferState
   126  	assert.NoError(t, stateManager.SaveStateAndSnapshots())
   127  	// Modify state again, and assert that the loaded state from snapshot was not modified and remained as saved.
   128  	assert.NoError(t, stateManager.IncTransferredSizeAndFilesPhase1(2, 3))
   129  	assert.NotEqual(t, stateManager.TransferState.CurrentRepo, originalState.CurrentRepo)
   130  	assertGetTransferStateAndSnapshot(t, false, originalState, stateManager.repoTransferSnapshot, true)
   131  
   132  	// After repo fully transferred, expected to load state without snapshots.
   133  	assert.NoError(t, stateManager.SetRepoFullTransferCompleted())
   134  	assertGetTransferStateAndSnapshot(t, false, stateManager.TransferState, nil, false)
   135  }
   136  
   137  func assertGetTransferStateAndSnapshot(t *testing.T, reset bool, expectedTransferState TransferState,
   138  	expectedRepoTransferSnapshot *RepoTransferSnapshot, expectedSnapshotLoaded bool) {
   139  	transferState, repoTransferSnapshot, err := getTransferStateAndSnapshot(repo1Key, reset)
   140  	assert.NoError(t, err)
   141  	assert.Equal(t, expectedTransferState.Version, transferState.Version)
   142  	assert.Equal(t, expectedTransferState.CurrentRepo, transferState.CurrentRepo)
   143  
   144  	// If one or both snapshots are nil, don't assert by field.
   145  	if expectedRepoTransferSnapshot == nil || repoTransferSnapshot == nil {
   146  		assert.Equal(t, expectedRepoTransferSnapshot, repoTransferSnapshot)
   147  		return
   148  	}
   149  	assert.Equal(t, expectedSnapshotLoaded, repoTransferSnapshot.loadedFromSnapshot)
   150  }
   151  
   152  func getRootAndAddSnapshotData(t *testing.T, stateManager *TransferStateManager) (root *reposnapshot.Node) {
   153  	root, err := stateManager.LookUpNode(".")
   154  	assert.NoError(t, err)
   155  	assert.NoError(t, root.IncrementFilesCount(10))
   156  	assert.NoError(t, root.AddChildNode("child", nil))
   157  	return
   158  }