Compare commits
4 Commits
main
...
2361-kopia
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
42d0e5d196 | ||
|
|
070622fd08 | ||
|
|
0928e53a8b | ||
|
|
41d5550b4b |
@ -2,6 +2,8 @@ module github.com/alcionai/corso/src
|
||||
|
||||
go 1.19
|
||||
|
||||
replace github.com/kopia/kopia => github.com/alcionai/kopia v0.12.2-0.20230202002134-2a25d14bb364
|
||||
|
||||
require (
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.0
|
||||
github.com/alcionai/clues v0.0.0-20230131232239-cee86233b005
|
||||
@ -80,13 +82,13 @@ require (
|
||||
github.com/klauspost/reedsolomon v1.11.3 // indirect
|
||||
github.com/kylelemons/godebug v1.1.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.16 // indirect
|
||||
github.com/mattn/go-isatty v0.0.17 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.14 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.2 // indirect
|
||||
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect
|
||||
github.com/microsoft/kiota-serialization-text-go v0.6.0
|
||||
github.com/minio/md5-simd v1.1.2 // indirect
|
||||
github.com/minio/minio-go/v7 v7.0.45 // indirect
|
||||
github.com/minio/minio-go/v7 v7.0.47 // indirect
|
||||
github.com/minio/sha256-simd v1.0.0 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
@ -117,7 +119,7 @@ require (
|
||||
golang.org/x/sync v0.1.0 // indirect
|
||||
golang.org/x/sys v0.4.0 // indirect
|
||||
golang.org/x/text v0.6.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef // indirect
|
||||
google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect
|
||||
google.golang.org/grpc v1.52.0 // indirect
|
||||
google.golang.org/protobuf v1.28.1 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
|
||||
15
src/go.sum
15
src/go.sum
@ -54,6 +54,8 @@ github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpH
|
||||
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo=
|
||||
github.com/alcionai/clues v0.0.0-20230131232239-cee86233b005 h1:eTgICcmcydEWG8J+hgnidf0pzujV3Gd2XqmknykZkzA=
|
||||
github.com/alcionai/clues v0.0.0-20230131232239-cee86233b005/go.mod h1:UlAs8jkWIpsOMakiC8NxPgQQVQRdvyf1hYMszlYYLb4=
|
||||
github.com/alcionai/kopia v0.12.2-0.20230202002134-2a25d14bb364 h1:mJ3zLxz88hrbALYff9D4/SI/97hVRiRFeMLUz7gcy8Q=
|
||||
github.com/alcionai/kopia v0.12.2-0.20230202002134-2a25d14bb364/go.mod h1:f5sHcTthFWc16s0maScUqaK6JPLVxCqF8Pwz4iIZaOE=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
@ -241,8 +243,6 @@ github.com/klauspost/reedsolomon v1.11.3/go.mod h1:FXLZzlJIdfqEnQLdUKWNRuMZg747h
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kopia/htmluibuild v0.0.0-20220928042710-9fdd02afb1e7 h1:WP5VfIQL7AaYkO4zTNSCsVOawTzudbc4tvLojvg0RKc=
|
||||
github.com/kopia/kopia v0.12.2-0.20230123092305-e5387cec0acb h1:0jLaKLiloYvRNbuHHpnQkJ7STAgzQ4z6n+KPa6Kyg7I=
|
||||
github.com/kopia/kopia v0.12.2-0.20230123092305-e5387cec0acb/go.mod h1:dtCyMCsWulG82o9bDopvnny9DpOQe0PnSDczJLuhnWA=
|
||||
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
@ -259,8 +259,9 @@ github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
|
||||
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU=
|
||||
github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
@ -287,8 +288,8 @@ github.com/microsoftgraph/msgraph-sdk-go-core v0.33.0 h1:cDL3ov/IZ2ZarUJdGGPsdR+
|
||||
github.com/microsoftgraph/msgraph-sdk-go-core v0.33.0/go.mod h1:d0mU3PQAWnN/C4CwPJEZz2QhesrnR5UDnqRu2ODWPkI=
|
||||
github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34=
|
||||
github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM=
|
||||
github.com/minio/minio-go/v7 v7.0.45 h1:g4IeM9M9pW/Lo8AGGNOjBZYlvmtlE1N5TQEYWXRWzIs=
|
||||
github.com/minio/minio-go/v7 v7.0.45/go.mod h1:nCrRzjoSUQh8hgKKtu3Y708OLvRLtuASMg2/nvmbarw=
|
||||
github.com/minio/minio-go/v7 v7.0.47 h1:sLiuCKGSIcn/MI6lREmTzX91DX/oRau4ia0j6e6eOSs=
|
||||
github.com/minio/minio-go/v7 v7.0.47/go.mod h1:nCrRzjoSUQh8hgKKtu3Y708OLvRLtuASMg2/nvmbarw=
|
||||
github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g=
|
||||
github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM=
|
||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||
@ -747,8 +748,8 @@ google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6D
|
||||
google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef h1:uQ2vjV/sHTsWSqdKeLqmwitzgvjMl7o4IdtHwUDXSJY=
|
||||
google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM=
|
||||
google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f h1:BWUVssLB0HVOSY78gIdvk1dTVYtT1y8SBWtPYuTJ/6w=
|
||||
google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
|
||||
@ -20,6 +20,7 @@ type MockExchangeDataCollection struct {
|
||||
Data [][]byte
|
||||
Names []string
|
||||
ModTimes []time.Time
|
||||
Versions []uint32
|
||||
ColState data.CollectionState
|
||||
PrevPath path.Path
|
||||
DeletedItems []bool
|
||||
@ -31,6 +32,7 @@ var (
|
||||
_ data.Stream = &MockExchangeData{}
|
||||
_ data.StreamInfo = &MockExchangeData{}
|
||||
_ data.StreamSize = &MockExchangeData{}
|
||||
_ data.Versioner = &MockExchangeData{}
|
||||
)
|
||||
|
||||
// NewMockExchangeDataCollection creates an data collection that will return the specified number of
|
||||
@ -54,6 +56,8 @@ func NewMockExchangeCollection(pathRepresentation path.Path, numMessagesToReturn
|
||||
c.DeletedItems = append(c.DeletedItems, false)
|
||||
}
|
||||
|
||||
c.Versions = make([]uint32, c.messageCount)
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
@ -124,6 +128,7 @@ func (medc *MockExchangeDataCollection) Items() <-chan data.Stream {
|
||||
size: int64(len(medc.Data[i])),
|
||||
modifiedTime: medc.ModTimes[i],
|
||||
deleted: medc.DeletedItems[i],
|
||||
version: medc.Versions[i],
|
||||
}
|
||||
}
|
||||
}()
|
||||
@ -139,6 +144,7 @@ type MockExchangeData struct {
|
||||
size int64
|
||||
modifiedTime time.Time
|
||||
deleted bool
|
||||
version uint32
|
||||
}
|
||||
|
||||
func (med *MockExchangeData) UUID() string {
|
||||
@ -175,6 +181,10 @@ func (med *MockExchangeData) ModTime() time.Time {
|
||||
return med.modifiedTime
|
||||
}
|
||||
|
||||
func (med *MockExchangeData) Version() uint32 {
|
||||
return med.version
|
||||
}
|
||||
|
||||
type errReader struct {
|
||||
readErr error
|
||||
}
|
||||
|
||||
@ -87,6 +87,10 @@ type StreamModTime interface {
|
||||
ModTime() time.Time
|
||||
}
|
||||
|
||||
type Versioner interface {
|
||||
Version() uint32
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// functionality
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
@ -339,9 +339,15 @@ func collectionEntries(
|
||||
modTime = smt.ModTime()
|
||||
}
|
||||
|
||||
o := fs.OwnerInfo{}
|
||||
if sv, ok := e.(data.Versioner); ok {
|
||||
o.UserID = sv.Version()
|
||||
}
|
||||
|
||||
entry := virtualfs.StreamingFileWithModTimeFromReader(
|
||||
encodedName,
|
||||
modTime,
|
||||
o,
|
||||
newBackupStreamReader(serializationVersion, e.ToReader()),
|
||||
)
|
||||
if err := cb(ctx, entry); err != nil {
|
||||
|
||||
@ -1027,6 +1027,7 @@ func (suite *HierarchyBuilderUnitSuite) TestBuildDirectoryTreeSingleSubtree() {
|
||||
virtualfs.StreamingFileWithModTimeFromReader(
|
||||
encodeElements(testFileName)[0],
|
||||
time.Time{},
|
||||
fs.OwnerInfo{},
|
||||
io.NopCloser(bytes.NewReader(testFileData)),
|
||||
),
|
||||
},
|
||||
@ -1334,6 +1335,7 @@ func (suite *HierarchyBuilderUnitSuite) TestBuildDirectoryTreeMultipleSubdirecto
|
||||
virtualfs.StreamingFileWithModTimeFromReader(
|
||||
encodeElements(inboxFileName1)[0],
|
||||
time.Time{},
|
||||
fs.OwnerInfo{},
|
||||
io.NopCloser(bytes.NewReader(inboxFileData1)),
|
||||
),
|
||||
virtualfs.NewStaticDirectory(
|
||||
@ -1342,11 +1344,13 @@ func (suite *HierarchyBuilderUnitSuite) TestBuildDirectoryTreeMultipleSubdirecto
|
||||
virtualfs.StreamingFileWithModTimeFromReader(
|
||||
encodeElements(personalFileName1)[0],
|
||||
time.Time{},
|
||||
fs.OwnerInfo{},
|
||||
io.NopCloser(bytes.NewReader(testFileData)),
|
||||
),
|
||||
virtualfs.StreamingFileWithModTimeFromReader(
|
||||
encodeElements(personalFileName2)[0],
|
||||
time.Time{},
|
||||
fs.OwnerInfo{},
|
||||
io.NopCloser(bytes.NewReader(testFileData2)),
|
||||
),
|
||||
},
|
||||
@ -1357,6 +1361,7 @@ func (suite *HierarchyBuilderUnitSuite) TestBuildDirectoryTreeMultipleSubdirecto
|
||||
virtualfs.StreamingFileWithModTimeFromReader(
|
||||
encodeElements(workFileName1)[0],
|
||||
time.Time{},
|
||||
fs.OwnerInfo{},
|
||||
io.NopCloser(bytes.NewReader(testFileData3)),
|
||||
),
|
||||
},
|
||||
@ -2018,6 +2023,7 @@ func (suite *HierarchyBuilderUnitSuite) TestBuildDirectoryTreeSkipsDeletedSubtre
|
||||
virtualfs.StreamingFileWithModTimeFromReader(
|
||||
encodeElements(testFileName)[0],
|
||||
time.Time{},
|
||||
fs.OwnerInfo{},
|
||||
io.NopCloser(bytes.NewReader(testFileData)),
|
||||
),
|
||||
},
|
||||
@ -2028,6 +2034,7 @@ func (suite *HierarchyBuilderUnitSuite) TestBuildDirectoryTreeSkipsDeletedSubtre
|
||||
virtualfs.StreamingFileWithModTimeFromReader(
|
||||
encodeElements(testFileName2)[0],
|
||||
time.Time{},
|
||||
fs.OwnerInfo{},
|
||||
io.NopCloser(bytes.NewReader(testFileData2)),
|
||||
),
|
||||
},
|
||||
@ -2043,6 +2050,7 @@ func (suite *HierarchyBuilderUnitSuite) TestBuildDirectoryTreeSkipsDeletedSubtre
|
||||
virtualfs.StreamingFileWithModTimeFromReader(
|
||||
encodeElements(testFileName3)[0],
|
||||
time.Time{},
|
||||
fs.OwnerInfo{},
|
||||
io.NopCloser(bytes.NewReader(testFileData3)),
|
||||
),
|
||||
},
|
||||
@ -2053,6 +2061,7 @@ func (suite *HierarchyBuilderUnitSuite) TestBuildDirectoryTreeSkipsDeletedSubtre
|
||||
virtualfs.StreamingFileWithModTimeFromReader(
|
||||
encodeElements(testFileName4)[0],
|
||||
time.Time{},
|
||||
fs.OwnerInfo{},
|
||||
io.NopCloser(bytes.NewReader(testFileData4)),
|
||||
),
|
||||
},
|
||||
@ -2201,6 +2210,7 @@ func (suite *HierarchyBuilderUnitSuite) TestBuildDirectoryTreeSelectsCorrectSubt
|
||||
virtualfs.StreamingFileWithModTimeFromReader(
|
||||
encodeElements(inboxFileName1)[0],
|
||||
time.Time{},
|
||||
fs.OwnerInfo{},
|
||||
io.NopCloser(bytes.NewReader(inboxFileData1)),
|
||||
),
|
||||
},
|
||||
@ -2216,6 +2226,7 @@ func (suite *HierarchyBuilderUnitSuite) TestBuildDirectoryTreeSelectsCorrectSubt
|
||||
virtualfs.StreamingFileWithModTimeFromReader(
|
||||
encodeElements(contactsFileName1)[0],
|
||||
time.Time{},
|
||||
fs.OwnerInfo{},
|
||||
io.NopCloser(bytes.NewReader(contactsFileData1)),
|
||||
),
|
||||
},
|
||||
@ -2255,6 +2266,7 @@ func (suite *HierarchyBuilderUnitSuite) TestBuildDirectoryTreeSelectsCorrectSubt
|
||||
virtualfs.StreamingFileWithModTimeFromReader(
|
||||
encodeElements(inboxFileName1)[0],
|
||||
time.Time{},
|
||||
fs.OwnerInfo{},
|
||||
// Wrap with a backup reader so it gets the version injected.
|
||||
newBackupStreamReader(
|
||||
serializationVersion,
|
||||
@ -2274,6 +2286,7 @@ func (suite *HierarchyBuilderUnitSuite) TestBuildDirectoryTreeSelectsCorrectSubt
|
||||
virtualfs.StreamingFileWithModTimeFromReader(
|
||||
encodeElements(eventsFileName1)[0],
|
||||
time.Time{},
|
||||
fs.OwnerInfo{},
|
||||
io.NopCloser(bytes.NewReader(eventsFileData1)),
|
||||
),
|
||||
},
|
||||
|
||||
@ -6,6 +6,7 @@ import (
|
||||
"io"
|
||||
stdpath "path"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/kopia/kopia/repo"
|
||||
@ -510,6 +511,251 @@ func (suite *KopiaIntegrationSuite) TestBackupCollectionsHandlesNoCollections()
|
||||
}
|
||||
}
|
||||
|
||||
type KopiaCachedBackupSuite struct {
|
||||
suite.Suite
|
||||
w *Wrapper
|
||||
ctx context.Context
|
||||
snapshotBase IncrementalBase
|
||||
|
||||
testPath path.Path
|
||||
baseFileName string
|
||||
baseModTime time.Time
|
||||
baseVersion uint32
|
||||
|
||||
tags map[string]string
|
||||
expectedTags map[string]string
|
||||
}
|
||||
|
||||
func TestKopiaCachedBackupSuite(t *testing.T) {
|
||||
tester.RunOnAny(
|
||||
t,
|
||||
tester.CorsoCITests,
|
||||
tester.CorsoKopiaWrapperTests)
|
||||
|
||||
suite.Run(t, new(KopiaCachedBackupSuite))
|
||||
}
|
||||
|
||||
func (suite *KopiaCachedBackupSuite) SetupSuite() {
|
||||
tester.MustGetEnvSets(suite.T(), tester.AWSStorageCredEnvs)
|
||||
|
||||
tmp, err := path.Builder{}.Append(testInboxDir).ToDataLayerExchangePathForCategory(
|
||||
testTenant,
|
||||
testUser,
|
||||
path.EmailCategory,
|
||||
false,
|
||||
)
|
||||
require.NoError(suite.T(), err)
|
||||
|
||||
suite.testPath = tmp
|
||||
|
||||
// tags that are supplied by the caller. This includes basic tags to support
|
||||
// lookups and extra tags the caller may want to apply.
|
||||
suite.tags = map[string]string{
|
||||
"fnords": "smarf",
|
||||
"brunhilda": "",
|
||||
}
|
||||
|
||||
reasons := []Reason{
|
||||
{
|
||||
ResourceOwner: suite.testPath.ResourceOwner(),
|
||||
Service: suite.testPath.Service(),
|
||||
Category: suite.testPath.Category(),
|
||||
},
|
||||
}
|
||||
|
||||
for _, r := range reasons {
|
||||
for _, k := range r.TagKeys() {
|
||||
suite.tags[k] = ""
|
||||
}
|
||||
}
|
||||
|
||||
suite.expectedTags = map[string]string{}
|
||||
|
||||
maps.Copy(suite.expectedTags, normalizeTagKVs(suite.tags))
|
||||
}
|
||||
|
||||
func (suite *KopiaCachedBackupSuite) SetupTest() {
|
||||
t := suite.T()
|
||||
|
||||
//nolint:forbidigo
|
||||
suite.ctx, _ = logger.SeedLevel(context.Background(), logger.Development)
|
||||
c, err := openKopiaRepo(t, suite.ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
suite.w = &Wrapper{c}
|
||||
|
||||
baseCollection := mockconnector.NewMockExchangeCollection(suite.testPath, 1)
|
||||
|
||||
suite.baseFileName = baseCollection.Names[0]
|
||||
suite.baseModTime = baseCollection.ModTimes[0]
|
||||
suite.baseVersion = baseCollection.Versions[0]
|
||||
|
||||
// Make a backup to start with as the base.
|
||||
stats, deets, _, err := suite.w.BackupCollections(
|
||||
suite.ctx,
|
||||
nil,
|
||||
[]data.Collection{baseCollection},
|
||||
nil,
|
||||
suite.tags,
|
||||
false,
|
||||
)
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.Equal(suite.T(), 1, stats.TotalFileCount, "total files")
|
||||
assert.Equal(suite.T(), 1, stats.UncachedFileCount, "uncached files")
|
||||
assert.Equal(suite.T(), 0, stats.CachedFileCount, "cached files")
|
||||
assert.Equal(suite.T(), 5, stats.TotalDirectoryCount)
|
||||
assert.Equal(suite.T(), 0, stats.IgnoredErrorCount)
|
||||
assert.Equal(suite.T(), 0, stats.ErrorCount)
|
||||
assert.False(suite.T(), stats.Incomplete)
|
||||
|
||||
// 1 file and 5 folder entries.
|
||||
details := deets.Details().Entries
|
||||
assert.Len(
|
||||
suite.T(),
|
||||
details,
|
||||
6,
|
||||
)
|
||||
|
||||
for _, entry := range details {
|
||||
assert.True(suite.T(), entry.Updated)
|
||||
}
|
||||
|
||||
checkSnapshotTags(
|
||||
t,
|
||||
suite.ctx,
|
||||
suite.w.c,
|
||||
suite.expectedTags,
|
||||
stats.SnapshotID,
|
||||
)
|
||||
|
||||
snap, err := snapshot.LoadSnapshot(
|
||||
suite.ctx,
|
||||
suite.w.c,
|
||||
manifest.ID(stats.SnapshotID),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
suite.snapshotBase = IncrementalBase{
|
||||
Manifest: snap,
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *KopiaCachedBackupSuite) TearDownTest() {
|
||||
assert.NoError(suite.T(), suite.w.Close(suite.ctx))
|
||||
logger.Flush(suite.ctx)
|
||||
}
|
||||
|
||||
func (suite *KopiaCachedBackupSuite) TestBackupCollections_WithModTimeAndVersion() {
|
||||
table := []struct {
|
||||
name string
|
||||
col func() data.Collection
|
||||
expectedUploadedFiles int
|
||||
expectedCachedFiles int
|
||||
// Whether entries in the resulting details should be marked as updated.
|
||||
deetsUpdated bool
|
||||
}{
|
||||
{
|
||||
name: "NoUpdates",
|
||||
col: func() data.Collection {
|
||||
res := mockconnector.NewMockExchangeCollection(suite.testPath, 1)
|
||||
res.Names[0] = suite.baseFileName
|
||||
res.ModTimes[0] = suite.baseModTime
|
||||
res.Versions[0] = suite.baseVersion
|
||||
|
||||
return res
|
||||
},
|
||||
expectedUploadedFiles: 0,
|
||||
expectedCachedFiles: 1,
|
||||
deetsUpdated: false,
|
||||
},
|
||||
{
|
||||
name: "UpdatedModTime",
|
||||
col: func() data.Collection {
|
||||
res := mockconnector.NewMockExchangeCollection(suite.testPath, 1)
|
||||
res.Names[0] = suite.baseFileName
|
||||
res.ModTimes[0] = suite.baseModTime.Add(1 * time.Minute)
|
||||
res.Versions[0] = suite.baseVersion
|
||||
|
||||
return res
|
||||
},
|
||||
expectedUploadedFiles: 1,
|
||||
expectedCachedFiles: 0,
|
||||
deetsUpdated: true,
|
||||
},
|
||||
{
|
||||
name: "UpdatedVersion",
|
||||
col: func() data.Collection {
|
||||
res := mockconnector.NewMockExchangeCollection(suite.testPath, 1)
|
||||
res.Names[0] = suite.baseFileName
|
||||
res.ModTimes[0] = suite.baseModTime
|
||||
res.Versions[0] = suite.baseVersion + 1
|
||||
|
||||
return res
|
||||
},
|
||||
expectedUploadedFiles: 1,
|
||||
expectedCachedFiles: 0,
|
||||
deetsUpdated: true,
|
||||
},
|
||||
{
|
||||
name: "UpdatedModTimeAndVersion",
|
||||
col: func() data.Collection {
|
||||
res := mockconnector.NewMockExchangeCollection(suite.testPath, 1)
|
||||
res.Names[0] = suite.baseFileName
|
||||
res.ModTimes[0] = suite.baseModTime.Add(1 * time.Minute)
|
||||
res.Versions[0] = suite.baseVersion + 1
|
||||
|
||||
return res
|
||||
},
|
||||
expectedUploadedFiles: 1,
|
||||
expectedCachedFiles: 0,
|
||||
deetsUpdated: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range table {
|
||||
suite.T().Run(test.name, func(t *testing.T) {
|
||||
stats, deets, _, err := suite.w.BackupCollections(
|
||||
suite.ctx,
|
||||
[]IncrementalBase{suite.snapshotBase},
|
||||
[]data.Collection{test.col()},
|
||||
nil,
|
||||
suite.tags,
|
||||
false,
|
||||
)
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.Equal(t, test.expectedUploadedFiles, stats.TotalFileCount, "total files")
|
||||
assert.Equal(t, test.expectedUploadedFiles, stats.UncachedFileCount, "uncached files")
|
||||
assert.Equal(t, test.expectedCachedFiles, stats.CachedFileCount, "cached files")
|
||||
assert.Equal(t, 5, stats.TotalDirectoryCount)
|
||||
assert.Equal(t, 0, stats.IgnoredErrorCount)
|
||||
assert.Equal(t, 0, stats.ErrorCount)
|
||||
assert.False(t, stats.Incomplete)
|
||||
|
||||
// 1 file and 5 folder entries.
|
||||
details := deets.Details().Entries
|
||||
assert.Len(
|
||||
t,
|
||||
details,
|
||||
test.expectedUploadedFiles+test.expectedCachedFiles+5,
|
||||
)
|
||||
|
||||
for _, entry := range details {
|
||||
assert.Equal(t, test.deetsUpdated, entry.Updated)
|
||||
}
|
||||
|
||||
checkSnapshotTags(
|
||||
t,
|
||||
suite.ctx,
|
||||
suite.w.c,
|
||||
suite.expectedTags,
|
||||
stats.SnapshotID,
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
type KopiaSimpleRepoIntegrationSuite struct {
|
||||
suite.Suite
|
||||
w *Wrapper
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user