add ut for pkg/repository
Signed-off-by: Lyndon-Li <lyonghui@vmware.com>pull/6432/head
parent
de83980a05
commit
38d5003c6b
|
@ -887,3 +887,467 @@ func TestForget(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestInitRepo(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
funcTable localFuncTable
|
||||||
|
getter *credmock.SecretStore
|
||||||
|
repoService *reposervicenmocks.BackupRepoService
|
||||||
|
retFuncInit interface{}
|
||||||
|
credStoreReturn string
|
||||||
|
credStoreError error
|
||||||
|
expectedErr string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "get repo option fail",
|
||||||
|
expectedErr: "error to get repo options: error to get repo password: invalid credentials interface",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "repo init fail",
|
||||||
|
getter: new(credmock.SecretStore),
|
||||||
|
credStoreReturn: "fake-password",
|
||||||
|
funcTable: localFuncTable{
|
||||||
|
getStorageVariables: func(*velerov1api.BackupStorageLocation, string, string) (map[string]string, error) {
|
||||||
|
return map[string]string{}, nil
|
||||||
|
},
|
||||||
|
getStorageCredentials: func(*velerov1api.BackupStorageLocation, velerocredentials.FileStore) (map[string]string, error) {
|
||||||
|
return map[string]string{}, nil
|
||||||
|
},
|
||||||
|
},
|
||||||
|
repoService: new(reposervicenmocks.BackupRepoService),
|
||||||
|
retFuncInit: func(context.Context, udmrepo.RepoOptions, bool) error {
|
||||||
|
return errors.New("fake-error-1")
|
||||||
|
},
|
||||||
|
expectedErr: "error to init backup repo: fake-error-1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "succeed",
|
||||||
|
getter: new(credmock.SecretStore),
|
||||||
|
credStoreReturn: "fake-password",
|
||||||
|
funcTable: localFuncTable{
|
||||||
|
getStorageVariables: func(*velerov1api.BackupStorageLocation, string, string) (map[string]string, error) {
|
||||||
|
return map[string]string{}, nil
|
||||||
|
},
|
||||||
|
getStorageCredentials: func(*velerov1api.BackupStorageLocation, velerocredentials.FileStore) (map[string]string, error) {
|
||||||
|
return map[string]string{}, nil
|
||||||
|
},
|
||||||
|
},
|
||||||
|
repoService: new(reposervicenmocks.BackupRepoService),
|
||||||
|
retFuncInit: func(context.Context, udmrepo.RepoOptions, bool) error {
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
funcTable = tc.funcTable
|
||||||
|
|
||||||
|
var secretStore velerocredentials.SecretStore
|
||||||
|
if tc.getter != nil {
|
||||||
|
tc.getter.On("Get", mock.Anything, mock.Anything).Return(tc.credStoreReturn, tc.credStoreError)
|
||||||
|
secretStore = tc.getter
|
||||||
|
}
|
||||||
|
|
||||||
|
urp := unifiedRepoProvider{
|
||||||
|
credentialGetter: velerocredentials.CredentialGetter{
|
||||||
|
FromSecret: secretStore,
|
||||||
|
},
|
||||||
|
repoService: tc.repoService,
|
||||||
|
log: velerotest.NewLogger(),
|
||||||
|
}
|
||||||
|
|
||||||
|
if tc.repoService != nil {
|
||||||
|
tc.repoService.On("Init", mock.Anything, mock.Anything, mock.Anything).Return(tc.retFuncInit)
|
||||||
|
}
|
||||||
|
|
||||||
|
err := urp.InitRepo(context.Background(), RepoParam{
|
||||||
|
BackupLocation: &velerov1api.BackupStorageLocation{},
|
||||||
|
BackupRepo: &velerov1api.BackupRepository{},
|
||||||
|
})
|
||||||
|
|
||||||
|
if tc.expectedErr == "" {
|
||||||
|
assert.NoError(t, err)
|
||||||
|
} else {
|
||||||
|
assert.EqualError(t, err, tc.expectedErr)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConnectToRepo(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
funcTable localFuncTable
|
||||||
|
getter *credmock.SecretStore
|
||||||
|
repoService *reposervicenmocks.BackupRepoService
|
||||||
|
retFuncInit interface{}
|
||||||
|
credStoreReturn string
|
||||||
|
credStoreError error
|
||||||
|
expectedErr string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "get repo option fail",
|
||||||
|
expectedErr: "error to get repo options: error to get repo password: invalid credentials interface",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "repo init fail",
|
||||||
|
getter: new(credmock.SecretStore),
|
||||||
|
credStoreReturn: "fake-password",
|
||||||
|
funcTable: localFuncTable{
|
||||||
|
getStorageVariables: func(*velerov1api.BackupStorageLocation, string, string) (map[string]string, error) {
|
||||||
|
return map[string]string{}, nil
|
||||||
|
},
|
||||||
|
getStorageCredentials: func(*velerov1api.BackupStorageLocation, velerocredentials.FileStore) (map[string]string, error) {
|
||||||
|
return map[string]string{}, nil
|
||||||
|
},
|
||||||
|
},
|
||||||
|
repoService: new(reposervicenmocks.BackupRepoService),
|
||||||
|
retFuncInit: func(context.Context, udmrepo.RepoOptions, bool) error {
|
||||||
|
return errors.New("fake-error-1")
|
||||||
|
},
|
||||||
|
expectedErr: "error to connect backup repo: fake-error-1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "succeed",
|
||||||
|
getter: new(credmock.SecretStore),
|
||||||
|
credStoreReturn: "fake-password",
|
||||||
|
funcTable: localFuncTable{
|
||||||
|
getStorageVariables: func(*velerov1api.BackupStorageLocation, string, string) (map[string]string, error) {
|
||||||
|
return map[string]string{}, nil
|
||||||
|
},
|
||||||
|
getStorageCredentials: func(*velerov1api.BackupStorageLocation, velerocredentials.FileStore) (map[string]string, error) {
|
||||||
|
return map[string]string{}, nil
|
||||||
|
},
|
||||||
|
},
|
||||||
|
repoService: new(reposervicenmocks.BackupRepoService),
|
||||||
|
retFuncInit: func(context.Context, udmrepo.RepoOptions, bool) error {
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
funcTable = tc.funcTable
|
||||||
|
|
||||||
|
var secretStore velerocredentials.SecretStore
|
||||||
|
if tc.getter != nil {
|
||||||
|
tc.getter.On("Get", mock.Anything, mock.Anything).Return(tc.credStoreReturn, tc.credStoreError)
|
||||||
|
secretStore = tc.getter
|
||||||
|
}
|
||||||
|
|
||||||
|
urp := unifiedRepoProvider{
|
||||||
|
credentialGetter: velerocredentials.CredentialGetter{
|
||||||
|
FromSecret: secretStore,
|
||||||
|
},
|
||||||
|
repoService: tc.repoService,
|
||||||
|
log: velerotest.NewLogger(),
|
||||||
|
}
|
||||||
|
|
||||||
|
if tc.repoService != nil {
|
||||||
|
tc.repoService.On("Init", mock.Anything, mock.Anything, mock.Anything).Return(tc.retFuncInit)
|
||||||
|
}
|
||||||
|
|
||||||
|
err := urp.ConnectToRepo(context.Background(), RepoParam{
|
||||||
|
BackupLocation: &velerov1api.BackupStorageLocation{},
|
||||||
|
BackupRepo: &velerov1api.BackupRepository{},
|
||||||
|
})
|
||||||
|
|
||||||
|
if tc.expectedErr == "" {
|
||||||
|
assert.NoError(t, err)
|
||||||
|
} else {
|
||||||
|
assert.EqualError(t, err, tc.expectedErr)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBoostRepoConnect(t *testing.T) {
|
||||||
|
var backupRepo *reposervicenmocks.BackupRepo
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
funcTable localFuncTable
|
||||||
|
getter *credmock.SecretStore
|
||||||
|
repoService *reposervicenmocks.BackupRepoService
|
||||||
|
backupRepo *reposervicenmocks.BackupRepo
|
||||||
|
retFuncInit interface{}
|
||||||
|
retFuncOpen []interface{}
|
||||||
|
credStoreReturn string
|
||||||
|
credStoreError error
|
||||||
|
expectedErr string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "get repo option fail",
|
||||||
|
expectedErr: "error to get repo options: error to get repo password: invalid credentials interface",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "repo not opened and connect fail",
|
||||||
|
getter: new(credmock.SecretStore),
|
||||||
|
credStoreReturn: "fake-password",
|
||||||
|
funcTable: localFuncTable{
|
||||||
|
getStorageVariables: func(*velerov1api.BackupStorageLocation, string, string) (map[string]string, error) {
|
||||||
|
return map[string]string{}, nil
|
||||||
|
},
|
||||||
|
getStorageCredentials: func(*velerov1api.BackupStorageLocation, velerocredentials.FileStore) (map[string]string, error) {
|
||||||
|
return map[string]string{}, nil
|
||||||
|
},
|
||||||
|
},
|
||||||
|
repoService: new(reposervicenmocks.BackupRepoService),
|
||||||
|
retFuncOpen: []interface{}{
|
||||||
|
func(context.Context, udmrepo.RepoOptions) udmrepo.BackupRepo {
|
||||||
|
return backupRepo
|
||||||
|
},
|
||||||
|
|
||||||
|
func(context.Context, udmrepo.RepoOptions) error {
|
||||||
|
return errors.New("fake-error-1")
|
||||||
|
},
|
||||||
|
},
|
||||||
|
retFuncInit: func(context.Context, udmrepo.RepoOptions, bool) error {
|
||||||
|
return errors.New("fake-error-2")
|
||||||
|
},
|
||||||
|
expectedErr: "error to connect backup repo: fake-error-2",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "repo not opened and connect succeed",
|
||||||
|
getter: new(credmock.SecretStore),
|
||||||
|
credStoreReturn: "fake-password",
|
||||||
|
funcTable: localFuncTable{
|
||||||
|
getStorageVariables: func(*velerov1api.BackupStorageLocation, string, string) (map[string]string, error) {
|
||||||
|
return map[string]string{}, nil
|
||||||
|
},
|
||||||
|
getStorageCredentials: func(*velerov1api.BackupStorageLocation, velerocredentials.FileStore) (map[string]string, error) {
|
||||||
|
return map[string]string{}, nil
|
||||||
|
},
|
||||||
|
},
|
||||||
|
repoService: new(reposervicenmocks.BackupRepoService),
|
||||||
|
retFuncOpen: []interface{}{
|
||||||
|
func(context.Context, udmrepo.RepoOptions) udmrepo.BackupRepo {
|
||||||
|
return backupRepo
|
||||||
|
},
|
||||||
|
|
||||||
|
func(context.Context, udmrepo.RepoOptions) error {
|
||||||
|
return errors.New("fake-error-1")
|
||||||
|
},
|
||||||
|
},
|
||||||
|
retFuncInit: func(context.Context, udmrepo.RepoOptions, bool) error {
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "repo is opened",
|
||||||
|
getter: new(credmock.SecretStore),
|
||||||
|
credStoreReturn: "fake-password",
|
||||||
|
funcTable: localFuncTable{
|
||||||
|
getStorageVariables: func(*velerov1api.BackupStorageLocation, string, string) (map[string]string, error) {
|
||||||
|
return map[string]string{}, nil
|
||||||
|
},
|
||||||
|
getStorageCredentials: func(*velerov1api.BackupStorageLocation, velerocredentials.FileStore) (map[string]string, error) {
|
||||||
|
return map[string]string{}, nil
|
||||||
|
},
|
||||||
|
},
|
||||||
|
repoService: new(reposervicenmocks.BackupRepoService),
|
||||||
|
backupRepo: new(reposervicenmocks.BackupRepo),
|
||||||
|
retFuncOpen: []interface{}{
|
||||||
|
func(context.Context, udmrepo.RepoOptions) udmrepo.BackupRepo {
|
||||||
|
return backupRepo
|
||||||
|
},
|
||||||
|
|
||||||
|
func(context.Context, udmrepo.RepoOptions) error {
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
},
|
||||||
|
retFuncInit: func(context.Context, udmrepo.RepoOptions, bool) error {
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
funcTable = tc.funcTable
|
||||||
|
|
||||||
|
var secretStore velerocredentials.SecretStore
|
||||||
|
if tc.getter != nil {
|
||||||
|
tc.getter.On("Get", mock.Anything, mock.Anything).Return(tc.credStoreReturn, tc.credStoreError)
|
||||||
|
secretStore = tc.getter
|
||||||
|
}
|
||||||
|
|
||||||
|
urp := unifiedRepoProvider{
|
||||||
|
credentialGetter: velerocredentials.CredentialGetter{
|
||||||
|
FromSecret: secretStore,
|
||||||
|
},
|
||||||
|
repoService: tc.repoService,
|
||||||
|
log: velerotest.NewLogger(),
|
||||||
|
}
|
||||||
|
|
||||||
|
backupRepo = tc.backupRepo
|
||||||
|
|
||||||
|
if tc.repoService != nil {
|
||||||
|
tc.repoService.On("Open", mock.Anything, mock.Anything).Return(tc.retFuncOpen[0], tc.retFuncOpen[1])
|
||||||
|
tc.repoService.On("Init", mock.Anything, mock.Anything, mock.Anything).Return(tc.retFuncInit)
|
||||||
|
}
|
||||||
|
|
||||||
|
if tc.backupRepo != nil {
|
||||||
|
backupRepo.On("Close", mock.Anything).Return(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
err := urp.BoostRepoConnect(context.Background(), RepoParam{
|
||||||
|
BackupLocation: &velerov1api.BackupStorageLocation{},
|
||||||
|
BackupRepo: &velerov1api.BackupRepository{},
|
||||||
|
})
|
||||||
|
|
||||||
|
if tc.expectedErr == "" {
|
||||||
|
assert.NoError(t, err)
|
||||||
|
} else {
|
||||||
|
assert.EqualError(t, err, tc.expectedErr)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPruneRepo(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
funcTable localFuncTable
|
||||||
|
getter *credmock.SecretStore
|
||||||
|
repoService *reposervicenmocks.BackupRepoService
|
||||||
|
retFuncMaintain interface{}
|
||||||
|
credStoreReturn string
|
||||||
|
credStoreError error
|
||||||
|
expectedErr string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "get repo option fail",
|
||||||
|
expectedErr: "error to get repo options: error to get repo password: invalid credentials interface",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "repo maintain fail",
|
||||||
|
getter: new(credmock.SecretStore),
|
||||||
|
credStoreReturn: "fake-password",
|
||||||
|
funcTable: localFuncTable{
|
||||||
|
getStorageVariables: func(*velerov1api.BackupStorageLocation, string, string) (map[string]string, error) {
|
||||||
|
return map[string]string{}, nil
|
||||||
|
},
|
||||||
|
getStorageCredentials: func(*velerov1api.BackupStorageLocation, velerocredentials.FileStore) (map[string]string, error) {
|
||||||
|
return map[string]string{}, nil
|
||||||
|
},
|
||||||
|
},
|
||||||
|
repoService: new(reposervicenmocks.BackupRepoService),
|
||||||
|
retFuncMaintain: func(context.Context, udmrepo.RepoOptions) error {
|
||||||
|
return errors.New("fake-error-1")
|
||||||
|
},
|
||||||
|
expectedErr: "error to prune backup repo: fake-error-1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "succeed",
|
||||||
|
getter: new(credmock.SecretStore),
|
||||||
|
credStoreReturn: "fake-password",
|
||||||
|
funcTable: localFuncTable{
|
||||||
|
getStorageVariables: func(*velerov1api.BackupStorageLocation, string, string) (map[string]string, error) {
|
||||||
|
return map[string]string{}, nil
|
||||||
|
},
|
||||||
|
getStorageCredentials: func(*velerov1api.BackupStorageLocation, velerocredentials.FileStore) (map[string]string, error) {
|
||||||
|
return map[string]string{}, nil
|
||||||
|
},
|
||||||
|
},
|
||||||
|
repoService: new(reposervicenmocks.BackupRepoService),
|
||||||
|
retFuncMaintain: func(context.Context, udmrepo.RepoOptions) error {
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
funcTable = tc.funcTable
|
||||||
|
|
||||||
|
var secretStore velerocredentials.SecretStore
|
||||||
|
if tc.getter != nil {
|
||||||
|
tc.getter.On("Get", mock.Anything, mock.Anything).Return(tc.credStoreReturn, tc.credStoreError)
|
||||||
|
secretStore = tc.getter
|
||||||
|
}
|
||||||
|
|
||||||
|
urp := unifiedRepoProvider{
|
||||||
|
credentialGetter: velerocredentials.CredentialGetter{
|
||||||
|
FromSecret: secretStore,
|
||||||
|
},
|
||||||
|
repoService: tc.repoService,
|
||||||
|
log: velerotest.NewLogger(),
|
||||||
|
}
|
||||||
|
|
||||||
|
if tc.repoService != nil {
|
||||||
|
tc.repoService.On("Maintain", mock.Anything, mock.Anything).Return(tc.retFuncMaintain)
|
||||||
|
}
|
||||||
|
|
||||||
|
err := urp.PruneRepo(context.Background(), RepoParam{
|
||||||
|
BackupLocation: &velerov1api.BackupStorageLocation{},
|
||||||
|
BackupRepo: &velerov1api.BackupRepository{},
|
||||||
|
})
|
||||||
|
|
||||||
|
if tc.expectedErr == "" {
|
||||||
|
assert.NoError(t, err)
|
||||||
|
} else {
|
||||||
|
assert.EqualError(t, err, tc.expectedErr)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetStorageType(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
backupLocation *velerov1api.BackupStorageLocation
|
||||||
|
expectedRet string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "wrong backend type",
|
||||||
|
backupLocation: &velerov1api.BackupStorageLocation{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "aws provider",
|
||||||
|
backupLocation: &velerov1api.BackupStorageLocation{
|
||||||
|
Spec: velerov1api.BackupStorageLocationSpec{
|
||||||
|
Provider: "velero.io/aws",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedRet: "s3",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "azure provider",
|
||||||
|
backupLocation: &velerov1api.BackupStorageLocation{
|
||||||
|
Spec: velerov1api.BackupStorageLocationSpec{
|
||||||
|
Provider: "velero.io/azure",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedRet: "azure",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "gcp provider",
|
||||||
|
backupLocation: &velerov1api.BackupStorageLocation{
|
||||||
|
Spec: velerov1api.BackupStorageLocationSpec{
|
||||||
|
Provider: "velero.io/gcp",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedRet: "gcs",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "fs provider",
|
||||||
|
backupLocation: &velerov1api.BackupStorageLocation{
|
||||||
|
Spec: velerov1api.BackupStorageLocationSpec{
|
||||||
|
Provider: "velero.io/fs",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedRet: "filesystem",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
ret := getStorageType(tc.backupLocation)
|
||||||
|
assert.Equal(t, tc.expectedRet, ret)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,198 @@
|
||||||
|
/*
|
||||||
|
Copyright the Velero contributors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package backend
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/kopia/kopia/repo"
|
||||||
|
"github.com/kopia/kopia/repo/content"
|
||||||
|
"github.com/kopia/kopia/repo/encryption"
|
||||||
|
"github.com/kopia/kopia/repo/format"
|
||||||
|
"github.com/kopia/kopia/repo/hashing"
|
||||||
|
"github.com/kopia/kopia/repo/splitter"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
|
"github.com/vmware-tanzu/velero/pkg/repository/udmrepo"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSetupNewRepositoryOptions(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
flags map[string]string
|
||||||
|
expected repo.NewRepositoryOptions
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "with hash algo",
|
||||||
|
flags: map[string]string{
|
||||||
|
udmrepo.StoreOptionGenHashAlgo: "fake-hash",
|
||||||
|
},
|
||||||
|
expected: repo.NewRepositoryOptions{
|
||||||
|
BlockFormat: format.ContentFormat{
|
||||||
|
Hash: "fake-hash",
|
||||||
|
Encryption: encryption.DefaultAlgorithm,
|
||||||
|
},
|
||||||
|
ObjectFormat: format.ObjectFormat{
|
||||||
|
Splitter: splitter.DefaultAlgorithm,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "with encrypt algo",
|
||||||
|
flags: map[string]string{
|
||||||
|
udmrepo.StoreOptionGenEncryptAlgo: "fake-encrypt",
|
||||||
|
},
|
||||||
|
expected: repo.NewRepositoryOptions{
|
||||||
|
BlockFormat: format.ContentFormat{
|
||||||
|
Hash: hashing.DefaultAlgorithm,
|
||||||
|
Encryption: "fake-encrypt",
|
||||||
|
},
|
||||||
|
ObjectFormat: format.ObjectFormat{
|
||||||
|
Splitter: splitter.DefaultAlgorithm,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "with splitter algo",
|
||||||
|
flags: map[string]string{
|
||||||
|
udmrepo.StoreOptionGenSplitAlgo: "fake-splitter",
|
||||||
|
},
|
||||||
|
expected: repo.NewRepositoryOptions{
|
||||||
|
BlockFormat: format.ContentFormat{
|
||||||
|
Hash: hashing.DefaultAlgorithm,
|
||||||
|
Encryption: encryption.DefaultAlgorithm,
|
||||||
|
},
|
||||||
|
ObjectFormat: format.ObjectFormat{
|
||||||
|
Splitter: "fake-splitter",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "with retention algo",
|
||||||
|
flags: map[string]string{
|
||||||
|
udmrepo.StoreOptionGenRetentionMode: "fake-retention-mode",
|
||||||
|
},
|
||||||
|
expected: repo.NewRepositoryOptions{
|
||||||
|
BlockFormat: format.ContentFormat{
|
||||||
|
Hash: hashing.DefaultAlgorithm,
|
||||||
|
Encryption: encryption.DefaultAlgorithm,
|
||||||
|
},
|
||||||
|
ObjectFormat: format.ObjectFormat{
|
||||||
|
Splitter: splitter.DefaultAlgorithm,
|
||||||
|
},
|
||||||
|
RetentionMode: "fake-retention-mode",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
ret := SetupNewRepositoryOptions(context.Background(), tc.flags)
|
||||||
|
assert.Equal(t, tc.expected, ret)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetupConnectOptions(t *testing.T) {
|
||||||
|
defaultCacheOption := content.CachingOptions{
|
||||||
|
MaxCacheSizeBytes: 2000 << 20,
|
||||||
|
MaxMetadataCacheSizeBytes: 2000 << 20,
|
||||||
|
MaxListCacheDuration: content.DurationSeconds(time.Duration(30) * time.Second),
|
||||||
|
}
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
repoOptions udmrepo.RepoOptions
|
||||||
|
expected repo.ConnectOptions
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "with domain",
|
||||||
|
repoOptions: udmrepo.RepoOptions{
|
||||||
|
GeneralOptions: map[string]string{
|
||||||
|
udmrepo.GenOptionOwnerDomain: "fake-domain",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: repo.ConnectOptions{
|
||||||
|
CachingOptions: defaultCacheOption,
|
||||||
|
ClientOptions: repo.ClientOptions{
|
||||||
|
Hostname: "fake-domain",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "with username",
|
||||||
|
repoOptions: udmrepo.RepoOptions{
|
||||||
|
GeneralOptions: map[string]string{
|
||||||
|
udmrepo.GenOptionOwnerName: "fake-user",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: repo.ConnectOptions{
|
||||||
|
CachingOptions: defaultCacheOption,
|
||||||
|
ClientOptions: repo.ClientOptions{
|
||||||
|
Username: "fake-user",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "with wrong readonly",
|
||||||
|
repoOptions: udmrepo.RepoOptions{
|
||||||
|
GeneralOptions: map[string]string{
|
||||||
|
udmrepo.StoreOptionGenReadOnly: "fake-bool",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: repo.ConnectOptions{
|
||||||
|
CachingOptions: defaultCacheOption,
|
||||||
|
ClientOptions: repo.ClientOptions{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "with correct readonly",
|
||||||
|
repoOptions: udmrepo.RepoOptions{
|
||||||
|
GeneralOptions: map[string]string{
|
||||||
|
udmrepo.StoreOptionGenReadOnly: "true",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: repo.ConnectOptions{
|
||||||
|
CachingOptions: defaultCacheOption,
|
||||||
|
ClientOptions: repo.ClientOptions{
|
||||||
|
ReadOnly: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "with description",
|
||||||
|
repoOptions: udmrepo.RepoOptions{
|
||||||
|
Description: "fake-description",
|
||||||
|
},
|
||||||
|
expected: repo.ConnectOptions{
|
||||||
|
CachingOptions: defaultCacheOption,
|
||||||
|
ClientOptions: repo.ClientOptions{
|
||||||
|
Description: "fake-description",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
ret := SetupConnectOptions(context.Background(), tc.repoOptions)
|
||||||
|
assert.Equal(t, tc.expected, ret)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,80 @@
|
||||||
|
/*
|
||||||
|
Copyright the Velero contributors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package backend
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/kopia/kopia/repo/blob/filesystem"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
|
"github.com/vmware-tanzu/velero/pkg/repository/udmrepo"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestFSSetup(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
flags map[string]string
|
||||||
|
expectedOptions filesystem.Options
|
||||||
|
expectedErr string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "must have fs path",
|
||||||
|
flags: map[string]string{},
|
||||||
|
expectedErr: "key " + udmrepo.StoreOptionFsPath + " not found",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "with fs path only",
|
||||||
|
flags: map[string]string{
|
||||||
|
udmrepo.StoreOptionFsPath: "fake/path",
|
||||||
|
},
|
||||||
|
expectedOptions: filesystem.Options{
|
||||||
|
Path: "fake/path",
|
||||||
|
FileMode: 0o600,
|
||||||
|
DirectoryMode: 0o700,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "with prefix",
|
||||||
|
flags: map[string]string{
|
||||||
|
udmrepo.StoreOptionFsPath: "fake/path",
|
||||||
|
udmrepo.StoreOptionPrefix: "fake-prefix",
|
||||||
|
},
|
||||||
|
expectedOptions: filesystem.Options{
|
||||||
|
Path: "fake/path/fake-prefix",
|
||||||
|
FileMode: 0o600,
|
||||||
|
DirectoryMode: 0o700,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
fsFlags := FsBackend{}
|
||||||
|
|
||||||
|
err := fsFlags.Setup(context.Background(), tc.flags)
|
||||||
|
|
||||||
|
if tc.expectedErr == "" {
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, tc.expectedOptions, fsFlags.options)
|
||||||
|
} else {
|
||||||
|
assert.EqualError(t, err, tc.expectedErr)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -20,6 +20,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/kopia/kopia/repo/blob/gcs"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
"github.com/vmware-tanzu/velero/pkg/repository/udmrepo"
|
"github.com/vmware-tanzu/velero/pkg/repository/udmrepo"
|
||||||
|
@ -27,9 +28,10 @@ import (
|
||||||
|
|
||||||
func TestGcsSetup(t *testing.T) {
|
func TestGcsSetup(t *testing.T) {
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
name string
|
name string
|
||||||
flags map[string]string
|
flags map[string]string
|
||||||
expectedErr string
|
expectedOptions gcs.Options
|
||||||
|
expectedErr string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "must have bucket name",
|
name: "must have bucket name",
|
||||||
|
@ -43,6 +45,44 @@ func TestGcsSetup(t *testing.T) {
|
||||||
},
|
},
|
||||||
expectedErr: "key " + udmrepo.StoreOptionCredentialFile + " not found",
|
expectedErr: "key " + udmrepo.StoreOptionCredentialFile + " not found",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "with prefix",
|
||||||
|
flags: map[string]string{
|
||||||
|
udmrepo.StoreOptionOssBucket: "fake-bucket",
|
||||||
|
udmrepo.StoreOptionCredentialFile: "fake-credential",
|
||||||
|
udmrepo.StoreOptionPrefix: "fake-prefix",
|
||||||
|
},
|
||||||
|
expectedOptions: gcs.Options{
|
||||||
|
BucketName: "fake-bucket",
|
||||||
|
ServiceAccountCredentialsFile: "fake-credential",
|
||||||
|
Prefix: "fake-prefix",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "with wrong readonly",
|
||||||
|
flags: map[string]string{
|
||||||
|
udmrepo.StoreOptionOssBucket: "fake-bucket",
|
||||||
|
udmrepo.StoreOptionCredentialFile: "fake-credential",
|
||||||
|
udmrepo.StoreOptionGcsReadonly: "fake-bool",
|
||||||
|
},
|
||||||
|
expectedOptions: gcs.Options{
|
||||||
|
BucketName: "fake-bucket",
|
||||||
|
ServiceAccountCredentialsFile: "fake-credential",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "with correct readonly",
|
||||||
|
flags: map[string]string{
|
||||||
|
udmrepo.StoreOptionOssBucket: "fake-bucket",
|
||||||
|
udmrepo.StoreOptionCredentialFile: "fake-credential",
|
||||||
|
udmrepo.StoreOptionGcsReadonly: "true",
|
||||||
|
},
|
||||||
|
expectedOptions: gcs.Options{
|
||||||
|
BucketName: "fake-bucket",
|
||||||
|
ServiceAccountCredentialsFile: "fake-credential",
|
||||||
|
ReadOnly: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
|
@ -53,6 +93,7 @@ func TestGcsSetup(t *testing.T) {
|
||||||
|
|
||||||
if tc.expectedErr == "" {
|
if tc.expectedErr == "" {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, tc.expectedOptions, gcsFlags.options)
|
||||||
} else {
|
} else {
|
||||||
assert.EqualError(t, err, tc.expectedErr)
|
assert.EqualError(t, err, tc.expectedErr)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,101 @@
|
||||||
|
// Code generated by mockery v2.22.1. DO NOT EDIT.
|
||||||
|
|
||||||
|
package mocks
|
||||||
|
|
||||||
|
import mock "github.com/stretchr/testify/mock"
|
||||||
|
|
||||||
|
// Reader is an autogenerated mock type for the Reader type
|
||||||
|
type Reader struct {
|
||||||
|
mock.Mock
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close provides a mock function with given fields:
|
||||||
|
func (_m *Reader) Close() error {
|
||||||
|
ret := _m.Called()
|
||||||
|
|
||||||
|
var r0 error
|
||||||
|
if rf, ok := ret.Get(0).(func() error); ok {
|
||||||
|
r0 = rf()
|
||||||
|
} else {
|
||||||
|
r0 = ret.Error(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Length provides a mock function with given fields:
|
||||||
|
func (_m *Reader) Length() int64 {
|
||||||
|
ret := _m.Called()
|
||||||
|
|
||||||
|
var r0 int64
|
||||||
|
if rf, ok := ret.Get(0).(func() int64); ok {
|
||||||
|
r0 = rf()
|
||||||
|
} else {
|
||||||
|
r0 = ret.Get(0).(int64)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read provides a mock function with given fields: p
|
||||||
|
func (_m *Reader) Read(p []byte) (int, error) {
|
||||||
|
ret := _m.Called(p)
|
||||||
|
|
||||||
|
var r0 int
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(0).(func([]byte) (int, error)); ok {
|
||||||
|
return rf(p)
|
||||||
|
}
|
||||||
|
if rf, ok := ret.Get(0).(func([]byte) int); ok {
|
||||||
|
r0 = rf(p)
|
||||||
|
} else {
|
||||||
|
r0 = ret.Get(0).(int)
|
||||||
|
}
|
||||||
|
|
||||||
|
if rf, ok := ret.Get(1).(func([]byte) error); ok {
|
||||||
|
r1 = rf(p)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Seek provides a mock function with given fields: offset, whence
|
||||||
|
func (_m *Reader) Seek(offset int64, whence int) (int64, error) {
|
||||||
|
ret := _m.Called(offset, whence)
|
||||||
|
|
||||||
|
var r0 int64
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(0).(func(int64, int) (int64, error)); ok {
|
||||||
|
return rf(offset, whence)
|
||||||
|
}
|
||||||
|
if rf, ok := ret.Get(0).(func(int64, int) int64); ok {
|
||||||
|
r0 = rf(offset, whence)
|
||||||
|
} else {
|
||||||
|
r0 = ret.Get(0).(int64)
|
||||||
|
}
|
||||||
|
|
||||||
|
if rf, ok := ret.Get(1).(func(int64, int) error); ok {
|
||||||
|
r1 = rf(offset, whence)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
type mockConstructorTestingTNewReader interface {
|
||||||
|
mock.TestingT
|
||||||
|
Cleanup(func())
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewReader creates a new instance of Reader. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||||
|
func NewReader(t mockConstructorTestingTNewReader) *Reader {
|
||||||
|
mock := &Reader{}
|
||||||
|
mock.Mock.Test(t)
|
||||||
|
|
||||||
|
t.Cleanup(func() { mock.AssertExpectations(t) })
|
||||||
|
|
||||||
|
return mock
|
||||||
|
}
|
|
@ -0,0 +1,114 @@
|
||||||
|
// Code generated by mockery v2.22.1. DO NOT EDIT.
|
||||||
|
|
||||||
|
package mocks
|
||||||
|
|
||||||
|
import (
|
||||||
|
object "github.com/kopia/kopia/repo/object"
|
||||||
|
mock "github.com/stretchr/testify/mock"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Writer is an autogenerated mock type for the Writer type
|
||||||
|
type Writer struct {
|
||||||
|
mock.Mock
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checkpoint provides a mock function with given fields:
|
||||||
|
func (_m *Writer) Checkpoint() (object.ID, error) {
|
||||||
|
ret := _m.Called()
|
||||||
|
|
||||||
|
var r0 object.ID
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(0).(func() (object.ID, error)); ok {
|
||||||
|
return rf()
|
||||||
|
}
|
||||||
|
if rf, ok := ret.Get(0).(func() object.ID); ok {
|
||||||
|
r0 = rf()
|
||||||
|
} else {
|
||||||
|
r0 = ret.Get(0).(object.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
if rf, ok := ret.Get(1).(func() error); ok {
|
||||||
|
r1 = rf()
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close provides a mock function with given fields:
|
||||||
|
func (_m *Writer) Close() error {
|
||||||
|
ret := _m.Called()
|
||||||
|
|
||||||
|
var r0 error
|
||||||
|
if rf, ok := ret.Get(0).(func() error); ok {
|
||||||
|
r0 = rf()
|
||||||
|
} else {
|
||||||
|
r0 = ret.Error(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Result provides a mock function with given fields:
|
||||||
|
func (_m *Writer) Result() (object.ID, error) {
|
||||||
|
ret := _m.Called()
|
||||||
|
|
||||||
|
var r0 object.ID
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(0).(func() (object.ID, error)); ok {
|
||||||
|
return rf()
|
||||||
|
}
|
||||||
|
if rf, ok := ret.Get(0).(func() object.ID); ok {
|
||||||
|
r0 = rf()
|
||||||
|
} else {
|
||||||
|
r0 = ret.Get(0).(object.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
if rf, ok := ret.Get(1).(func() error); ok {
|
||||||
|
r1 = rf()
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write provides a mock function with given fields: p
|
||||||
|
func (_m *Writer) Write(p []byte) (int, error) {
|
||||||
|
ret := _m.Called(p)
|
||||||
|
|
||||||
|
var r0 int
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(0).(func([]byte) (int, error)); ok {
|
||||||
|
return rf(p)
|
||||||
|
}
|
||||||
|
if rf, ok := ret.Get(0).(func([]byte) int); ok {
|
||||||
|
r0 = rf(p)
|
||||||
|
} else {
|
||||||
|
r0 = ret.Get(0).(int)
|
||||||
|
}
|
||||||
|
|
||||||
|
if rf, ok := ret.Get(1).(func([]byte) error); ok {
|
||||||
|
r1 = rf(p)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
type mockConstructorTestingTNewWriter interface {
|
||||||
|
mock.TestingT
|
||||||
|
Cleanup(func())
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewWriter creates a new instance of Writer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||||
|
func NewWriter(t mockConstructorTestingTNewWriter) *Writer {
|
||||||
|
mock := &Writer{}
|
||||||
|
mock.Mock.Test(t)
|
||||||
|
|
||||||
|
t.Cleanup(func() { mock.AssertExpectations(t) })
|
||||||
|
|
||||||
|
return mock
|
||||||
|
}
|
|
@ -20,6 +20,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/kopia/kopia/repo/blob/s3"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
"github.com/vmware-tanzu/velero/pkg/repository/udmrepo"
|
"github.com/vmware-tanzu/velero/pkg/repository/udmrepo"
|
||||||
|
@ -27,15 +28,91 @@ import (
|
||||||
|
|
||||||
func TestS3Setup(t *testing.T) {
|
func TestS3Setup(t *testing.T) {
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
name string
|
name string
|
||||||
flags map[string]string
|
flags map[string]string
|
||||||
expectedErr string
|
expectedOptions s3.Options
|
||||||
|
expectedErr string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "must have bucket name",
|
name: "must have bucket name",
|
||||||
flags: map[string]string{},
|
flags: map[string]string{},
|
||||||
expectedErr: "key " + udmrepo.StoreOptionOssBucket + " not found",
|
expectedErr: "key " + udmrepo.StoreOptionOssBucket + " not found",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "with bucket only",
|
||||||
|
flags: map[string]string{
|
||||||
|
udmrepo.StoreOptionOssBucket: "fake-bucket",
|
||||||
|
},
|
||||||
|
expectedOptions: s3.Options{
|
||||||
|
BucketName: "fake-bucket",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "with others",
|
||||||
|
flags: map[string]string{
|
||||||
|
udmrepo.StoreOptionOssBucket: "fake-bucket",
|
||||||
|
udmrepo.StoreOptionS3KeyID: "fake-ak",
|
||||||
|
udmrepo.StoreOptionS3SecretKey: "fake-sk",
|
||||||
|
udmrepo.StoreOptionS3Endpoint: "fake-endpoint",
|
||||||
|
udmrepo.StoreOptionOssRegion: "fake-region",
|
||||||
|
udmrepo.StoreOptionPrefix: "fake-prefix",
|
||||||
|
udmrepo.StoreOptionS3Token: "fake-token",
|
||||||
|
},
|
||||||
|
expectedOptions: s3.Options{
|
||||||
|
BucketName: "fake-bucket",
|
||||||
|
AccessKeyID: "fake-ak",
|
||||||
|
SecretAccessKey: "fake-sk",
|
||||||
|
Endpoint: "fake-endpoint",
|
||||||
|
Region: "fake-region",
|
||||||
|
Prefix: "fake-prefix",
|
||||||
|
SessionToken: "fake-token",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "with wrong tls",
|
||||||
|
flags: map[string]string{
|
||||||
|
udmrepo.StoreOptionOssBucket: "fake-bucket",
|
||||||
|
udmrepo.StoreOptionS3DisableTLS: "fake-bool",
|
||||||
|
udmrepo.StoreOptionS3DisableTLSVerify: "fake-bool",
|
||||||
|
},
|
||||||
|
expectedOptions: s3.Options{
|
||||||
|
BucketName: "fake-bucket",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "with correct tls",
|
||||||
|
flags: map[string]string{
|
||||||
|
udmrepo.StoreOptionOssBucket: "fake-bucket",
|
||||||
|
udmrepo.StoreOptionS3DisableTLS: "true",
|
||||||
|
udmrepo.StoreOptionS3DisableTLSVerify: "false",
|
||||||
|
},
|
||||||
|
expectedOptions: s3.Options{
|
||||||
|
BucketName: "fake-bucket",
|
||||||
|
DoNotUseTLS: true,
|
||||||
|
DoNotVerifyTLS: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "with wrong ca",
|
||||||
|
flags: map[string]string{
|
||||||
|
udmrepo.StoreOptionOssBucket: "fake-bucket",
|
||||||
|
udmrepo.StoreOptionS3CustomCA: "fake-base-64",
|
||||||
|
},
|
||||||
|
expectedOptions: s3.Options{
|
||||||
|
BucketName: "fake-bucket",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "with correct ca",
|
||||||
|
flags: map[string]string{
|
||||||
|
udmrepo.StoreOptionOssBucket: "fake-bucket",
|
||||||
|
udmrepo.StoreOptionS3CustomCA: "ZmFrZS1jYQ==",
|
||||||
|
},
|
||||||
|
expectedOptions: s3.Options{
|
||||||
|
BucketName: "fake-bucket",
|
||||||
|
RootCA: []byte{'f', 'a', 'k', 'e', '-', 'c', 'a'},
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
|
|
|
@ -18,12 +18,14 @@ package kopialib
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"math"
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/kopia/kopia/repo"
|
"github.com/kopia/kopia/repo"
|
||||||
"github.com/kopia/kopia/repo/manifest"
|
"github.com/kopia/kopia/repo/manifest"
|
||||||
|
"github.com/kopia/kopia/repo/object"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/mock"
|
"github.com/stretchr/testify/mock"
|
||||||
|
@ -713,3 +715,486 @@ func TestFlush(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestNewObjectWriter(t *testing.T) {
|
||||||
|
rawObjWriter := repomocks.NewWriter(t)
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
rawWriter *repomocks.DirectRepositoryWriter
|
||||||
|
rawWriterRet object.Writer
|
||||||
|
expectedRet udmrepo.ObjectWriter
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "raw writer is nil",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "new object writer fail",
|
||||||
|
rawWriter: repomocks.NewDirectRepositoryWriter(t),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "succeed",
|
||||||
|
rawWriter: repomocks.NewDirectRepositoryWriter(t),
|
||||||
|
rawWriterRet: rawObjWriter,
|
||||||
|
expectedRet: &kopiaObjectWriter{rawWriter: rawObjWriter},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
kr := &kopiaRepository{}
|
||||||
|
|
||||||
|
if tc.rawWriter != nil {
|
||||||
|
tc.rawWriter.On("NewObjectWriter", mock.Anything, mock.Anything).Return(tc.rawWriterRet)
|
||||||
|
kr.rawWriter = tc.rawWriter
|
||||||
|
}
|
||||||
|
|
||||||
|
ret := kr.NewObjectWriter(context.Background(), udmrepo.ObjectWriteOptions{})
|
||||||
|
|
||||||
|
assert.Equal(t, tc.expectedRet, ret)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUpdateProgress(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
progress int64
|
||||||
|
uploaded int64
|
||||||
|
throttle logThrottle
|
||||||
|
logMessage string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "should not output",
|
||||||
|
throttle: logThrottle{
|
||||||
|
lastTime: math.MaxInt64,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "should output",
|
||||||
|
progress: 100,
|
||||||
|
uploaded: 200,
|
||||||
|
logMessage: "Repo uploaded 300 bytes.",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
logMessage := ""
|
||||||
|
kr := &kopiaRepository{
|
||||||
|
logger: velerotest.NewSingleLogger(&logMessage),
|
||||||
|
throttle: tc.throttle,
|
||||||
|
uploaded: tc.uploaded,
|
||||||
|
}
|
||||||
|
|
||||||
|
kr.updateProgress(tc.progress)
|
||||||
|
|
||||||
|
if len(tc.logMessage) > 0 {
|
||||||
|
assert.Contains(t, logMessage, tc.logMessage)
|
||||||
|
} else {
|
||||||
|
assert.Equal(t, "", logMessage)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestReaderRead(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
rawObjReader *repomocks.Reader
|
||||||
|
rawReaderRetErr error
|
||||||
|
expectedErr string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "raw reader is nil",
|
||||||
|
expectedErr: "object reader is closed or not open",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "raw read fail",
|
||||||
|
rawObjReader: repomocks.NewReader(t),
|
||||||
|
rawReaderRetErr: errors.New("fake-read-error"),
|
||||||
|
expectedErr: "fake-read-error",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "succeed",
|
||||||
|
rawObjReader: repomocks.NewReader(t),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
kr := &kopiaObjectReader{}
|
||||||
|
|
||||||
|
if tc.rawObjReader != nil {
|
||||||
|
tc.rawObjReader.On("Read", mock.Anything).Return(0, tc.rawReaderRetErr)
|
||||||
|
kr.rawReader = tc.rawObjReader
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := kr.Read(nil)
|
||||||
|
|
||||||
|
if tc.expectedErr == "" {
|
||||||
|
assert.NoError(t, err)
|
||||||
|
} else {
|
||||||
|
assert.EqualError(t, err, tc.expectedErr)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestReaderSeek(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
rawObjReader *repomocks.Reader
|
||||||
|
rawReaderRet int64
|
||||||
|
rawReaderRetErr error
|
||||||
|
expectedRet int64
|
||||||
|
expectedErr string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "raw reader is nil",
|
||||||
|
expectedErr: "object reader is closed or not open",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "raw seek fail",
|
||||||
|
rawObjReader: repomocks.NewReader(t),
|
||||||
|
rawReaderRetErr: errors.New("fake-seek-error"),
|
||||||
|
expectedErr: "fake-seek-error",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "succeed",
|
||||||
|
rawObjReader: repomocks.NewReader(t),
|
||||||
|
rawReaderRet: 100,
|
||||||
|
expectedRet: 100,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
kr := &kopiaObjectReader{}
|
||||||
|
|
||||||
|
if tc.rawObjReader != nil {
|
||||||
|
tc.rawObjReader.On("Seek", mock.Anything, mock.Anything).Return(tc.rawReaderRet, tc.rawReaderRetErr)
|
||||||
|
kr.rawReader = tc.rawObjReader
|
||||||
|
}
|
||||||
|
|
||||||
|
ret, err := kr.Seek(0, 0)
|
||||||
|
|
||||||
|
if tc.expectedErr == "" {
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, tc.expectedRet, ret)
|
||||||
|
} else {
|
||||||
|
assert.EqualError(t, err, tc.expectedErr)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestReaderClose(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
rawObjReader *repomocks.Reader
|
||||||
|
rawReaderRetErr error
|
||||||
|
expectedErr string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "raw reader is nil",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "raw close fail",
|
||||||
|
rawObjReader: repomocks.NewReader(t),
|
||||||
|
rawReaderRetErr: errors.New("fake-close-error"),
|
||||||
|
expectedErr: "fake-close-error",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "succeed",
|
||||||
|
rawObjReader: repomocks.NewReader(t),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
kr := &kopiaObjectReader{}
|
||||||
|
|
||||||
|
if tc.rawObjReader != nil {
|
||||||
|
tc.rawObjReader.On("Close").Return(tc.rawReaderRetErr)
|
||||||
|
kr.rawReader = tc.rawObjReader
|
||||||
|
}
|
||||||
|
|
||||||
|
err := kr.Close()
|
||||||
|
|
||||||
|
if tc.expectedErr == "" {
|
||||||
|
assert.NoError(t, err)
|
||||||
|
} else {
|
||||||
|
assert.EqualError(t, err, tc.expectedErr)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestReaderLength(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
rawObjReader *repomocks.Reader
|
||||||
|
rawReaderRet int64
|
||||||
|
expectedRet int64
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "raw reader is nil",
|
||||||
|
expectedRet: -1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "raw length fail",
|
||||||
|
rawObjReader: repomocks.NewReader(t),
|
||||||
|
rawReaderRet: 0,
|
||||||
|
expectedRet: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "succeed",
|
||||||
|
rawObjReader: repomocks.NewReader(t),
|
||||||
|
rawReaderRet: 200,
|
||||||
|
expectedRet: 200,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
kr := &kopiaObjectReader{}
|
||||||
|
|
||||||
|
if tc.rawObjReader != nil {
|
||||||
|
tc.rawObjReader.On("Length").Return(tc.rawReaderRet)
|
||||||
|
kr.rawReader = tc.rawObjReader
|
||||||
|
}
|
||||||
|
|
||||||
|
ret := kr.Length()
|
||||||
|
|
||||||
|
assert.Equal(t, tc.expectedRet, ret)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWriterWrite(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
rawObjWriter *repomocks.Writer
|
||||||
|
rawWrtierRet int
|
||||||
|
rawWriterRetErr error
|
||||||
|
expectedRet int
|
||||||
|
expectedErr string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "raw writer is nil",
|
||||||
|
expectedErr: "object writer is closed or not open",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "raw read fail",
|
||||||
|
rawObjWriter: repomocks.NewWriter(t),
|
||||||
|
rawWriterRetErr: errors.New("fake-write-error"),
|
||||||
|
expectedErr: "fake-write-error",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "succeed",
|
||||||
|
rawObjWriter: repomocks.NewWriter(t),
|
||||||
|
rawWrtierRet: 200,
|
||||||
|
expectedRet: 200,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
kr := &kopiaObjectWriter{}
|
||||||
|
|
||||||
|
if tc.rawObjWriter != nil {
|
||||||
|
tc.rawObjWriter.On("Write", mock.Anything).Return(tc.rawWrtierRet, tc.rawWriterRetErr)
|
||||||
|
kr.rawWriter = tc.rawObjWriter
|
||||||
|
}
|
||||||
|
|
||||||
|
ret, err := kr.Write(nil)
|
||||||
|
|
||||||
|
if tc.expectedErr == "" {
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, tc.expectedRet, ret)
|
||||||
|
} else {
|
||||||
|
assert.EqualError(t, err, tc.expectedErr)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWriterCheckpoint(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
rawObjWriter *repomocks.Writer
|
||||||
|
rawWrtierRet object.ID
|
||||||
|
rawWriterRetErr error
|
||||||
|
expectedRet udmrepo.ID
|
||||||
|
expectedErr string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "raw writer is nil",
|
||||||
|
expectedErr: "object writer is closed or not open",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "raw checkpoint fail",
|
||||||
|
rawObjWriter: repomocks.NewWriter(t),
|
||||||
|
rawWriterRetErr: errors.New("fake-checkpoint-error"),
|
||||||
|
expectedErr: "error to checkpoint object: fake-checkpoint-error",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "succeed",
|
||||||
|
rawObjWriter: repomocks.NewWriter(t),
|
||||||
|
rawWrtierRet: object.ID{},
|
||||||
|
expectedRet: udmrepo.ID(""),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
kr := &kopiaObjectWriter{}
|
||||||
|
|
||||||
|
if tc.rawObjWriter != nil {
|
||||||
|
tc.rawObjWriter.On("Checkpoint").Return(tc.rawWrtierRet, tc.rawWriterRetErr)
|
||||||
|
kr.rawWriter = tc.rawObjWriter
|
||||||
|
}
|
||||||
|
|
||||||
|
ret, err := kr.Checkpoint()
|
||||||
|
|
||||||
|
if tc.expectedErr == "" {
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, tc.expectedRet, ret)
|
||||||
|
} else {
|
||||||
|
assert.EqualError(t, err, tc.expectedErr)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWriterResult(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
rawObjWriter *repomocks.Writer
|
||||||
|
rawWrtierRet object.ID
|
||||||
|
rawWriterRetErr error
|
||||||
|
expectedRet udmrepo.ID
|
||||||
|
expectedErr string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "raw writer is nil",
|
||||||
|
expectedErr: "object writer is closed or not open",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "raw result fail",
|
||||||
|
rawObjWriter: repomocks.NewWriter(t),
|
||||||
|
rawWriterRetErr: errors.New("fake-result-error"),
|
||||||
|
expectedErr: "error to wait object: fake-result-error",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "succeed",
|
||||||
|
rawObjWriter: repomocks.NewWriter(t),
|
||||||
|
rawWrtierRet: object.ID{},
|
||||||
|
expectedRet: udmrepo.ID(""),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
kr := &kopiaObjectWriter{}
|
||||||
|
|
||||||
|
if tc.rawObjWriter != nil {
|
||||||
|
tc.rawObjWriter.On("Result").Return(tc.rawWrtierRet, tc.rawWriterRetErr)
|
||||||
|
kr.rawWriter = tc.rawObjWriter
|
||||||
|
}
|
||||||
|
|
||||||
|
ret, err := kr.Result()
|
||||||
|
|
||||||
|
if tc.expectedErr == "" {
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, tc.expectedRet, ret)
|
||||||
|
} else {
|
||||||
|
assert.EqualError(t, err, tc.expectedErr)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWriterClose(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
rawObjWriter *repomocks.Writer
|
||||||
|
rawWriterRetErr error
|
||||||
|
expectedErr string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "raw writer is nil",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "raw close fail",
|
||||||
|
rawObjWriter: repomocks.NewWriter(t),
|
||||||
|
rawWriterRetErr: errors.New("fake-close-error"),
|
||||||
|
expectedErr: "fake-close-error",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "succeed",
|
||||||
|
rawObjWriter: repomocks.NewWriter(t),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
kr := &kopiaObjectWriter{}
|
||||||
|
|
||||||
|
if tc.rawObjWriter != nil {
|
||||||
|
tc.rawObjWriter.On("Close").Return(tc.rawWriterRetErr)
|
||||||
|
kr.rawWriter = tc.rawObjWriter
|
||||||
|
}
|
||||||
|
|
||||||
|
err := kr.Close()
|
||||||
|
|
||||||
|
if tc.expectedErr == "" {
|
||||||
|
assert.NoError(t, err)
|
||||||
|
} else {
|
||||||
|
assert.EqualError(t, err, tc.expectedErr)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMaintainProgress(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
progress int64
|
||||||
|
uploaded int64
|
||||||
|
throttle logThrottle
|
||||||
|
logMessage string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "should not output",
|
||||||
|
throttle: logThrottle{
|
||||||
|
lastTime: math.MaxInt64,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "should output",
|
||||||
|
progress: 100,
|
||||||
|
uploaded: 200,
|
||||||
|
logMessage: "Repo maintenance uploaded 300 bytes.",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
logMessage := ""
|
||||||
|
km := &kopiaMaintenance{
|
||||||
|
logger: velerotest.NewSingleLogger(&logMessage),
|
||||||
|
throttle: tc.throttle,
|
||||||
|
uploaded: tc.uploaded,
|
||||||
|
}
|
||||||
|
|
||||||
|
km.maintainProgress(tc.progress)
|
||||||
|
|
||||||
|
if len(tc.logMessage) > 0 {
|
||||||
|
assert.Contains(t, logMessage, tc.logMessage)
|
||||||
|
} else {
|
||||||
|
assert.Equal(t, "", logMessage)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue