From 5146992b5b20e4877b0b2de816b6183ecf2df260 Mon Sep 17 00:00:00 2001 From: Lyndon-Li Date: Fri, 4 Sep 2026 15:55:08 +0800 Subject: [PATCH] add UT for progress message Signed-off-by: Lyndon-Li --- .../data_download_controller_test.go | 33 ++++++++++++++----- pkg/controller/data_upload_controller_test.go | 29 ++++++++++++---- .../pod_volume_backup_controller_test.go | 29 ++++++++++++---- .../pod_volume_restore_controller_test.go | 29 ++++++++++++---- pkg/uploader/block/uploader_test.go | 8 +++++ pkg/uploader/kopia/snapshot_test.go | 6 ++-- pkg/uploader/provider/kopia_test.go | 8 ++--- 7 files changed, 109 insertions(+), 33 deletions(-) diff --git a/pkg/controller/data_download_controller_test.go b/pkg/controller/data_download_controller_test.go index 72d51167b..c9026eafa 100644 --- a/pkg/controller/data_download_controller_test.go +++ b/pkg/controller/data_download_controller_test.go @@ -787,6 +787,15 @@ func TestOnDataDownloadProgress(t *testing.T) { BytesDone: bytesDone, }, }, + { + name: "patch in progress phase with negative progress values and message", + dd: dataDownloadBuilder().Result(), + progress: uploader.Progress{ + TotalBytes: -1, + BytesDone: -1, + Message: "some warning message", + }, + }, { name: "failed to get datadownload", dd: dataDownloadBuilder().Result(), @@ -815,20 +824,28 @@ func TestOnDataDownloadProgress(t *testing.T) { require.NoError(t, r.client.Create(t.Context(), dd)) // Create a Progress object - progress := &uploader.Progress{ - TotalBytes: totalBytes, - BytesDone: bytesDone, - } + progress := &test.progress // Call the OnDataDownloadProgress function r.OnDataDownloadProgress(ctx, namespace, duName, progress) if len(test.needErrs) != 0 && !test.needErrs[0] { // Get the updated DataDownload object from the fake client - updatedDu := &velerov2alpha1api.DataDownload{} - require.NoError(t, r.client.Get(ctx, types.NamespacedName{Name: duName, Namespace: namespace}, updatedDu)) + updatedDd := &velerov2alpha1api.DataDownload{} + require.NoError(t, r.client.Get(ctx, types.NamespacedName{Name: duName, Namespace: namespace}, updatedDd)) // Assert that the DataDownload object has been updated with the progress - assert.Equal(t, test.progress.TotalBytes, updatedDu.Status.Progress.TotalBytes) - assert.Equal(t, test.progress.BytesDone, updatedDu.Status.Progress.BytesDone) + if progress.TotalBytes != -1 { + assert.Equal(t, test.progress.TotalBytes, updatedDd.Status.Progress.TotalBytes) + } else { + assert.Equal(t, int64(0), updatedDd.Status.Progress.TotalBytes) // assuming default or original value + } + if progress.BytesDone != -1 { + assert.Equal(t, test.progress.BytesDone, updatedDd.Status.Progress.BytesDone) + } else { + assert.Equal(t, int64(0), updatedDd.Status.Progress.BytesDone) // assuming default or original value + } + if progress.Message != "" { + assert.Contains(t, updatedDd.Status.Message, progress.Message) + } } }) } diff --git a/pkg/controller/data_upload_controller_test.go b/pkg/controller/data_upload_controller_test.go index 30b5926ac..d50ceb749 100644 --- a/pkg/controller/data_upload_controller_test.go +++ b/pkg/controller/data_upload_controller_test.go @@ -809,6 +809,15 @@ func TestOnDataUploadProgress(t *testing.T) { BytesDone: bytesDone, }, }, + { + name: "patch in progress phase with negative progress values and message", + du: dataUploadBuilder().Result(), + progress: uploader.Progress{ + TotalBytes: -1, + BytesDone: -1, + Message: "some warning message", + }, + }, { name: "failed to get dataupload", du: dataUploadBuilder().Result(), @@ -837,10 +846,7 @@ func TestOnDataUploadProgress(t *testing.T) { require.NoError(t, r.client.Create(t.Context(), du)) // Create a Progress object - progress := &uploader.Progress{ - TotalBytes: totalBytes, - BytesDone: bytesDone, - } + progress := &test.progress // Call the OnDataUploadProgress function r.OnDataUploadProgress(ctx, namespace, duName, progress) @@ -849,8 +855,19 @@ func TestOnDataUploadProgress(t *testing.T) { updatedDu := &velerov2alpha1api.DataUpload{} require.NoError(t, r.client.Get(ctx, types.NamespacedName{Name: duName, Namespace: namespace}, updatedDu)) // Assert that the DataUpload object has been updated with the progress - assert.Equal(t, test.progress.TotalBytes, updatedDu.Status.Progress.TotalBytes) - assert.Equal(t, test.progress.BytesDone, updatedDu.Status.Progress.BytesDone) + if progress.TotalBytes != -1 { + assert.Equal(t, test.progress.TotalBytes, updatedDu.Status.Progress.TotalBytes) + } else { + assert.Equal(t, int64(0), updatedDu.Status.Progress.TotalBytes) // assuming default or original value + } + if progress.BytesDone != -1 { + assert.Equal(t, test.progress.BytesDone, updatedDu.Status.Progress.BytesDone) + } else { + assert.Equal(t, int64(0), updatedDu.Status.Progress.BytesDone) // assuming default or original value + } + if progress.Message != "" { + assert.Contains(t, updatedDu.Status.Message, progress.Message) + } } }) } diff --git a/pkg/controller/pod_volume_backup_controller_test.go b/pkg/controller/pod_volume_backup_controller_test.go index 21e30d5db..e74a1c269 100644 --- a/pkg/controller/pod_volume_backup_controller_test.go +++ b/pkg/controller/pod_volume_backup_controller_test.go @@ -625,6 +625,15 @@ func TestOnPVBProgress(t *testing.T) { BytesDone: bytesDone, }, }, + { + name: "patch in progress phase with negative progress values and message", + pvb: pvbBuilder().Result(), + progress: uploader.Progress{ + TotalBytes: -1, + BytesDone: -1, + Message: "some warning message", + }, + }, { name: "failed to get pvb", pvb: pvbBuilder().Result(), @@ -653,17 +662,25 @@ func TestOnPVBProgress(t *testing.T) { require.NoError(t, r.client.Create(t.Context(), pvb)) // Create a Progress object - progress := &uploader.Progress{ - TotalBytes: totalBytes, - BytesDone: bytesDone, - } + progress := &test.progress r.OnDataPathProgress(ctx, namespace, pvbName, progress) if len(test.needErrs) != 0 && !test.needErrs[0] { updatedPvb := &velerov1api.PodVolumeBackup{} require.NoError(t, r.client.Get(ctx, types.NamespacedName{Name: pvbName, Namespace: namespace}, updatedPvb)) - assert.Equal(t, test.progress.TotalBytes, updatedPvb.Status.Progress.TotalBytes) - assert.Equal(t, test.progress.BytesDone, updatedPvb.Status.Progress.BytesDone) + if progress.TotalBytes != -1 { + assert.Equal(t, test.progress.TotalBytes, updatedPvb.Status.Progress.TotalBytes) + } else { + assert.Equal(t, int64(0), updatedPvb.Status.Progress.TotalBytes) // assuming default or original value + } + if progress.BytesDone != -1 { + assert.Equal(t, test.progress.BytesDone, updatedPvb.Status.Progress.BytesDone) + } else { + assert.Equal(t, int64(0), updatedPvb.Status.Progress.BytesDone) // assuming default or original value + } + if progress.Message != "" { + assert.Contains(t, updatedPvb.Status.Message, progress.Message) + } } }) } diff --git a/pkg/controller/pod_volume_restore_controller_test.go b/pkg/controller/pod_volume_restore_controller_test.go index 73167c76f..6bd68e7e1 100644 --- a/pkg/controller/pod_volume_restore_controller_test.go +++ b/pkg/controller/pod_volume_restore_controller_test.go @@ -1470,6 +1470,15 @@ func TestOnPodVolumeRestoreProgress(t *testing.T) { BytesDone: bytesDone, }, }, + { + name: "patch in progress phase with negative progress values and message", + pvr: pvrBuilder().Result(), + progress: uploader.Progress{ + TotalBytes: -1, + BytesDone: -1, + Message: "some warning message", + }, + }, { name: "failed to get pvr", pvr: pvrBuilder().Result(), @@ -1498,17 +1507,25 @@ func TestOnPodVolumeRestoreProgress(t *testing.T) { require.NoError(t, r.client.Create(t.Context(), pvr)) // Create a Progress object - progress := &uploader.Progress{ - TotalBytes: totalBytes, - BytesDone: bytesDone, - } + progress := &test.progress r.OnDataPathProgress(ctx, namespace, pvrName, progress) if len(test.needErrs) != 0 && !test.needErrs[0] { updatedPVR := &velerov1api.PodVolumeRestore{} require.NoError(t, r.client.Get(ctx, types.NamespacedName{Name: pvrName, Namespace: namespace}, updatedPVR)) - assert.Equal(t, test.progress.TotalBytes, updatedPVR.Status.Progress.TotalBytes) - assert.Equal(t, test.progress.BytesDone, updatedPVR.Status.Progress.BytesDone) + if progress.TotalBytes != -1 { + assert.Equal(t, test.progress.TotalBytes, updatedPVR.Status.Progress.TotalBytes) + } else { + assert.Equal(t, int64(0), updatedPVR.Status.Progress.TotalBytes) // assuming default or original value + } + if progress.BytesDone != -1 { + assert.Equal(t, test.progress.BytesDone, updatedPVR.Status.Progress.BytesDone) + } else { + assert.Equal(t, int64(0), updatedPVR.Status.Progress.BytesDone) // assuming default or original value + } + if progress.Message != "" { + assert.Contains(t, updatedPVR.Status.Message, progress.Message) + } } }) } diff --git a/pkg/uploader/block/uploader_test.go b/pkg/uploader/block/uploader_test.go index bb94eb3de..f011219e4 100644 --- a/pkg/uploader/block/uploader_test.go +++ b/pkg/uploader/block/uploader_test.go @@ -295,6 +295,8 @@ func TestBlockUploaderBackup(t *testing.T) { var iterator cbt.Iterator if !tc.nilBitmap { iterMock := cbtmocks.NewIterator(t) + iterMock.On("Error").Return(nil).Maybe() + iterMock.On("Error").Return(nil).Maybe() iterator = iterMock backupMode := udmrepo.ObjectDataBackupModeInc @@ -573,6 +575,7 @@ func TestRestoreData(t *testing.T) { reader := bytes.NewReader(data) iterMock := cbtmocks.NewIterator(t) + iterMock.On("Error").Return(nil).Maybe() iterMock.On("Count").Return(uint64(1)) iterMock.On("Next").Return(uint64(0), true).Once() iterMock.On("Next").Return(uint64(0), false) @@ -603,6 +606,7 @@ func TestRestoreData(t *testing.T) { reader := &errReader{err: errors.New("read error")} iterMock := cbtmocks.NewIterator(t) + iterMock.On("Error").Return(nil).Maybe() iterMock.On("Count").Return(uint64(1)) iterMock.On("Next").Return(uint64(0), true).Once() iterMock.On("Next").Return(uint64(0), false) @@ -623,6 +627,7 @@ func TestBlockUploaderRestore(t *testing.T) { repoWriter.On("ReadMetadata", mock.Anything, udmrepo.ID("root-id")).Return(nil, errors.New("meta not found")) iterMock := cbtmocks.NewIterator(t) + iterMock.On("Error").Return(nil).Maybe() _, _, err := blkup.Restore(udmrepo.Snapshot{RootObject: udmrepo.ObjectMetadata{ID: "root-id"}}, destInfo{}, iterMock, nil) require.Error(t, err) assert.Contains(t, err.Error(), "meta not found") @@ -680,6 +685,7 @@ func TestBlockUploaderRestore(t *testing.T) { } iterMock := cbtmocks.NewIterator(t) + iterMock.On("Error").Return(nil).Maybe() iterMock.On("Count").Return(uint64(1)) iterMock.On("Next").Return(uint64(0), true).Once() iterMock.On("Next").Return(uint64(0), false) @@ -708,6 +714,7 @@ func TestBlockUploaderRestore(t *testing.T) { } dest := destInfo{size: 4194304, path: "/dev/target"} iterMock := cbtmocks.NewIterator(t) + iterMock.On("Error").Return(nil).Maybe() _, _, err := blkup.Restore(snap, dest, iterMock, nil) require.Error(t, err) @@ -732,6 +739,7 @@ func TestBlockUploaderRestore(t *testing.T) { } dest := destInfo{size: 512, path: "/dev/small"} iterMock := cbtmocks.NewIterator(t) + iterMock.On("Error").Return(nil).Maybe() _, _, err := blkup.Restore(snap, dest, iterMock, nil) require.Error(t, err) diff --git a/pkg/uploader/kopia/snapshot_test.go b/pkg/uploader/kopia/snapshot_test.go index e58c2bb88..08c34befd 100644 --- a/pkg/uploader/kopia/snapshot_test.go +++ b/pkg/uploader/kopia/snapshot_test.go @@ -200,7 +200,7 @@ func TestSnapshotSource(t *testing.T) { t.Run(tc.name, func(t *testing.T) { s := injectSnapshotFuncs() MockFuncs(s, tc.args) - _, _, err = SnapshotSource(ctx, s.repoWriterMock, s.uploderMock, sourceInfo, rootDir, false, "/", nil, tc.uploaderCfg, log, "TestSnapshotSource") + _, _, err = SnapshotSource(ctx, s.repoWriterMock, s.uploderMock, sourceInfo, rootDir, false, "/", nil, tc.uploaderCfg, &fakeProgressUpdater{}, log, "TestSnapshotSource") if tc.notError { assert.NoError(t, err) } else { @@ -648,9 +648,9 @@ func TestBackup(t *testing.T) { var snapshotInfo *uploader.SnapshotInfo var err error if tc.isEmptyUploader { - snapshotInfo, isSnapshotEmpty, err = Backup(t.Context(), nil, s.repoWriterMock, tc.sourcePath, "", tc.forceFull, tc.parentSnapshot, tc.volMode, map[string]string{}, tc.tags, &logrus.Logger{}) + snapshotInfo, isSnapshotEmpty, err = Backup(t.Context(), nil, s.repoWriterMock, tc.sourcePath, "", tc.forceFull, tc.parentSnapshot, tc.volMode, map[string]string{}, tc.tags, &fakeProgressUpdater{}, &logrus.Logger{}) } else { - snapshotInfo, isSnapshotEmpty, err = Backup(t.Context(), s.uploderMock, s.repoWriterMock, tc.sourcePath, "", tc.forceFull, tc.parentSnapshot, tc.volMode, map[string]string{}, tc.tags, &logrus.Logger{}) + snapshotInfo, isSnapshotEmpty, err = Backup(t.Context(), s.uploderMock, s.repoWriterMock, tc.sourcePath, "", tc.forceFull, tc.parentSnapshot, tc.volMode, map[string]string{}, tc.tags, &fakeProgressUpdater{}, &logrus.Logger{}) } // Check if the returned error matches the expected error if tc.expectedError != nil { diff --git a/pkg/uploader/provider/kopia_test.go b/pkg/uploader/provider/kopia_test.go index ca1cf8f5a..fd5629151 100644 --- a/pkg/uploader/provider/kopia_test.go +++ b/pkg/uploader/provider/kopia_test.go @@ -65,27 +65,27 @@ func (f *FakeRestoreProgressUpdater) UpdateProgress(p *uploader.Progress) {} func TestRunBackup(t *testing.T) { testCases := []struct { name string - hookBackupFunc func(ctx context.Context, fsUploader kopia.SnapshotUploader, repoWriter repo.RepositoryWriter, sourcePath string, realSource string, forceFull bool, parentSnapshot string, volMode uploader.PersistentVolumeMode, uploaderCfg map[string]string, tags map[string]string, log logrus.FieldLogger) (*uploader.SnapshotInfo, bool, error) + hookBackupFunc func(ctx context.Context, fsUploader kopia.SnapshotUploader, repoWriter repo.RepositoryWriter, sourcePath string, realSource string, forceFull bool, parentSnapshot string, volMode uploader.PersistentVolumeMode, uploaderCfg map[string]string, tags map[string]string, updater uploader.ProgressUpdater, log logrus.FieldLogger) (*uploader.SnapshotInfo, bool, error) volMode uploader.PersistentVolumeMode notError bool }{ { name: "success to backup", - hookBackupFunc: func(ctx context.Context, fsUploader kopia.SnapshotUploader, repoWriter repo.RepositoryWriter, sourcePath string, realSource string, forceFull bool, parentSnapshot string, volMode uploader.PersistentVolumeMode, uploaderCfg map[string]string, tags map[string]string, log logrus.FieldLogger) (*uploader.SnapshotInfo, bool, error) { + hookBackupFunc: func(ctx context.Context, fsUploader kopia.SnapshotUploader, repoWriter repo.RepositoryWriter, sourcePath string, realSource string, forceFull bool, parentSnapshot string, volMode uploader.PersistentVolumeMode, uploaderCfg map[string]string, tags map[string]string, updater uploader.ProgressUpdater, log logrus.FieldLogger) (*uploader.SnapshotInfo, bool, error) { return &uploader.SnapshotInfo{}, false, nil }, notError: true, }, { name: "get error to backup", - hookBackupFunc: func(ctx context.Context, fsUploader kopia.SnapshotUploader, repoWriter repo.RepositoryWriter, sourcePath string, realSource string, forceFull bool, parentSnapshot string, volMode uploader.PersistentVolumeMode, uploaderCfg map[string]string, tags map[string]string, log logrus.FieldLogger) (*uploader.SnapshotInfo, bool, error) { + hookBackupFunc: func(ctx context.Context, fsUploader kopia.SnapshotUploader, repoWriter repo.RepositoryWriter, sourcePath string, realSource string, forceFull bool, parentSnapshot string, volMode uploader.PersistentVolumeMode, uploaderCfg map[string]string, tags map[string]string, updater uploader.ProgressUpdater, log logrus.FieldLogger) (*uploader.SnapshotInfo, bool, error) { return &uploader.SnapshotInfo{}, false, errors.New("failed to backup") }, notError: false, }, { name: "success to backup block mode volume", - hookBackupFunc: func(ctx context.Context, fsUploader kopia.SnapshotUploader, repoWriter repo.RepositoryWriter, sourcePath string, realSource string, forceFull bool, parentSnapshot string, volMode uploader.PersistentVolumeMode, uploaderCfg map[string]string, tags map[string]string, log logrus.FieldLogger) (*uploader.SnapshotInfo, bool, error) { + hookBackupFunc: func(ctx context.Context, fsUploader kopia.SnapshotUploader, repoWriter repo.RepositoryWriter, sourcePath string, realSource string, forceFull bool, parentSnapshot string, volMode uploader.PersistentVolumeMode, uploaderCfg map[string]string, tags map[string]string, updater uploader.ProgressUpdater, log logrus.FieldLogger) (*uploader.SnapshotInfo, bool, error) { return &uploader.SnapshotInfo{}, false, nil }, volMode: uploader.PersistentVolumeBlock,