From 89beb44c2871479f3bd7004015b62ae8aa63c1da Mon Sep 17 00:00:00 2001 From: Chun-Hung Tseng Date: Mon, 26 Jun 2023 23:37:40 +0200 Subject: [PATCH] All large file download and upload testing --- README.md | 8 ++-- drive_test.go | 107 ++++++++++++++++++++++--------------------- drive_test_helper.go | 50 ++++++++++++++++---- file.go | 6 +-- go.mod | 6 +-- go.sum | 12 ++--- 6 files changed, 112 insertions(+), 77 deletions(-) diff --git a/README.md b/README.md index ae68d62..ce2ec38 100644 --- a/README.md +++ b/README.md @@ -55,8 +55,9 @@ Currently, the development are split into 2 versions. V1 supports the features [ - [ ] File actions - [x] Download - [x] Download empty file - - [ ] Properly handle large files and empty files (check iOS codebase) + - [x] Properly handle large files and empty files (check iOS codebase) - esp. large files, where buffering in-memory will screw up the runtime + - [ ] Improve large file handling - [ ] Check signature and hash - [x] Delete - [x] Upload @@ -64,8 +65,7 @@ Currently, the development are split into 2 versions. V1 supports the features [ - [x] Parse mime type - [x] Add revision - [x] Modified time - - [ ] Improve to handle large files - - [ ] Upload verification + - [ ] Improve large file handling - [ ] Handle failed / interrupted upload - [ ] List file metadata - [x] Duplicated file name handling: 422: A file or folder with that name already exists (Code=2500, Status=422) @@ -107,7 +107,6 @@ Currently, the development are split into 2 versions. V1 supports the features [ - [x] Remove delete all's hardcoded string - [ ] Address TODO and FIXME - [ ] Use CI to run integration tests -- [ ] Figure out the bottleneck by doing some profiling - [ ] Some error handling from [here](https://github.com/ProtonMail/WebClients/blob/main/packages/shared/lib/drive/constants.ts) MAX_NAME_LENGTH, TIMEOUT - [x] Point to the right proton-go-api branch - [x] Run `go get github.com/henrybear327/go-proton-api@dev` to update go mod @@ -125,6 +124,7 @@ Currently, the development are split into 2 versions. V1 supports the features [ Moving files and folders are [features](https://github.com/rclone/rclone/blob/51a468b2bae4ca8e21760435211623a8199a9167/fs/features.go#L25) +- [ ] Figure out the bottleneck by doing some profiling - [ ] Folder - [ ] (Feature) Update (force overwrite) - [ ] (Feature) Move diff --git a/drive_test.go b/drive_test.go index c111176..6e1f67b 100644 --- a/drive_test.go +++ b/drive_test.go @@ -3,6 +3,7 @@ package proton_api_bridge import ( "context" "log" + "strings" "testing" "github.com/henrybear327/Proton-API-Bridge/common" @@ -78,15 +79,15 @@ func TestUploadAndDownloadAndDeleteAFile(t *testing.T) { }) log.Println("Upload integrationTestImage.png") - uploadFile(t, ctx, protonDrive, "", "integrationTestImage.png", "testcase/integrationTestImage.png") + uploadFileByFilepath(t, ctx, protonDrive, "", "integrationTestImage.png", "testcase/integrationTestImage.png") checkRevisions(protonDrive, ctx, t, "integrationTestImage.png", 1) checkFileListing(t, ctx, protonDrive, []string{"/integrationTestImage.png"}) - downloadFile(t, ctx, protonDrive, "", "integrationTestImage.png", "testcase/integrationTestImage.png") + downloadFile(t, ctx, protonDrive, "", "integrationTestImage.png", "testcase/integrationTestImage.png", "") log.Println("Upload a new revision to replace integrationTestImage.png") - uploadFile(t, ctx, protonDrive, "", "integrationTestImage.png", "testcase/integrationTestImage2.png") /* Add a revision */ + uploadFileByFilepath(t, ctx, protonDrive, "", "integrationTestImage.png", "testcase/integrationTestImage2.png") /* Add a revision */ checkRevisions(protonDrive, ctx, t, "integrationTestImage.png", 2) - downloadFile(t, ctx, protonDrive, "", "integrationTestImage.png", "testcase/integrationTestImage2.png") + downloadFile(t, ctx, protonDrive, "", "integrationTestImage.png", "testcase/integrationTestImage2.png", "") checkFileListing(t, ctx, protonDrive, []string{"/integrationTestImage.png"}) log.Println("Delete file integrationTestImage.png") @@ -102,15 +103,15 @@ func TestUploadAndDeleteAnEmptyFileAtRoot(t *testing.T) { }) log.Println("Upload empty.txt") - uploadFile(t, ctx, protonDrive, "", "empty.txt", "testcase/empty.txt") + uploadFileByFilepath(t, ctx, protonDrive, "", "empty.txt", "testcase/empty.txt") checkRevisions(protonDrive, ctx, t, "empty.txt", 1) checkFileListing(t, ctx, protonDrive, []string{"/empty.txt"}) - downloadFile(t, ctx, protonDrive, "", "empty.txt", "testcase/empty.txt") + downloadFile(t, ctx, protonDrive, "", "empty.txt", "testcase/empty.txt", "") log.Println("Upload a new revision to replace empty.txt") - uploadFile(t, ctx, protonDrive, "", "empty.txt", "testcase/empty.txt") /* Add a revision */ + uploadFileByFilepath(t, ctx, protonDrive, "", "empty.txt", "testcase/empty.txt") /* Add a revision */ checkRevisions(protonDrive, ctx, t, "empty.txt", 2) - downloadFile(t, ctx, protonDrive, "", "empty.txt", "testcase/empty.txt") + downloadFile(t, ctx, protonDrive, "", "empty.txt", "testcase/empty.txt", "") checkFileListing(t, ctx, protonDrive, []string{"/empty.txt"}) log.Println("Delete file empty.txt") @@ -130,15 +131,15 @@ func TestUploadAndDownloadAndDeleteAFileAtAFolderOneLevelFromRoot(t *testing.T) checkFileListing(t, ctx, protonDrive, []string{"/level1"}) log.Println("Upload integrationTestImage.png to level1") - uploadFile(t, ctx, protonDrive, "level1", "integrationTestImage.png", "testcase/integrationTestImage.png") + uploadFileByFilepath(t, ctx, protonDrive, "level1", "integrationTestImage.png", "testcase/integrationTestImage.png") checkRevisions(protonDrive, ctx, t, "integrationTestImage.png", 1) checkFileListing(t, ctx, protonDrive, []string{"/level1", "/level1/integrationTestImage.png"}) - downloadFile(t, ctx, protonDrive, "level1", "integrationTestImage.png", "testcase/integrationTestImage.png") + downloadFile(t, ctx, protonDrive, "level1", "integrationTestImage.png", "testcase/integrationTestImage.png", "") log.Println("Upload a new revision to replace integrationTestImage.png in level1") - uploadFile(t, ctx, protonDrive, "level1", "integrationTestImage.png", "testcase/integrationTestImage2.png") /* Add a revision */ + uploadFileByFilepath(t, ctx, protonDrive, "level1", "integrationTestImage.png", "testcase/integrationTestImage2.png") /* Add a revision */ checkRevisions(protonDrive, ctx, t, "integrationTestImage.png", 2) - downloadFile(t, ctx, protonDrive, "level1", "integrationTestImage.png", "testcase/integrationTestImage2.png") + downloadFile(t, ctx, protonDrive, "level1", "integrationTestImage.png", "testcase/integrationTestImage2.png", "") log.Println("Delete folder level1") deleteBySearchingFromRoot(t, ctx, protonDrive, "level1", true) @@ -181,19 +182,19 @@ func TestCreateAndMoveAndDeleteFolderWithAFile(t *testing.T) { checkFileListing(t, ctx, protonDrive, []string{"/src"}) log.Println("Upload integrationTestImage.png to src") - uploadFile(t, ctx, protonDrive, "src", "integrationTestImage.png", "testcase/integrationTestImage.png") + uploadFileByFilepath(t, ctx, protonDrive, "src", "integrationTestImage.png", "testcase/integrationTestImage.png") checkRevisions(protonDrive, ctx, t, "integrationTestImage.png", 1) checkFileListing(t, ctx, protonDrive, []string{"/src", "/src/integrationTestImage.png"}) - downloadFile(t, ctx, protonDrive, "src", "integrationTestImage.png", "testcase/integrationTestImage.png") + downloadFile(t, ctx, protonDrive, "src", "integrationTestImage.png", "testcase/integrationTestImage.png", "") log.Println("Create a folder dst at root") createFolder(t, ctx, protonDrive, "", "dst") checkFileListing(t, ctx, protonDrive, []string{"/src", "/src/integrationTestImage.png", "/dst"}) log.Println("Upload a new revision to replace integrationTestImage.png in src") - uploadFile(t, ctx, protonDrive, "src", "integrationTestImage.png", "testcase/integrationTestImage2.png") /* Add a revision */ + uploadFileByFilepath(t, ctx, protonDrive, "src", "integrationTestImage.png", "testcase/integrationTestImage2.png") /* Add a revision */ checkRevisions(protonDrive, ctx, t, "integrationTestImage.png", 2) - downloadFile(t, ctx, protonDrive, "src", "integrationTestImage.png", "testcase/integrationTestImage2.png") + downloadFile(t, ctx, protonDrive, "src", "integrationTestImage.png", "testcase/integrationTestImage2.png", "") checkFileListing(t, ctx, protonDrive, []string{"/src", "/src/integrationTestImage.png", "/dst"}) log.Println("Move folder src to under folder dst") @@ -217,19 +218,19 @@ func TestCreateAndMoveAndDeleteAFileOneLevelFromRoot(t *testing.T) { checkFileListing(t, ctx, protonDrive, []string{"/src"}) log.Println("Upload integrationTestImage.png to src") - uploadFile(t, ctx, protonDrive, "src", "integrationTestImage.png", "testcase/integrationTestImage.png") + uploadFileByFilepath(t, ctx, protonDrive, "src", "integrationTestImage.png", "testcase/integrationTestImage.png") checkRevisions(protonDrive, ctx, t, "integrationTestImage.png", 1) checkFileListing(t, ctx, protonDrive, []string{"/src", "/src/integrationTestImage.png"}) - downloadFile(t, ctx, protonDrive, "src", "integrationTestImage.png", "testcase/integrationTestImage.png") + downloadFile(t, ctx, protonDrive, "src", "integrationTestImage.png", "testcase/integrationTestImage.png", "") log.Println("Create a folder dst at root") createFolder(t, ctx, protonDrive, "", "dst") checkFileListing(t, ctx, protonDrive, []string{"/src", "/src/integrationTestImage.png", "/dst"}) log.Println("Upload a new revision to replace integrationTestImage.png in src") - uploadFile(t, ctx, protonDrive, "src", "integrationTestImage.png", "testcase/integrationTestImage2.png") /* Add a revision */ + uploadFileByFilepath(t, ctx, protonDrive, "src", "integrationTestImage.png", "testcase/integrationTestImage2.png") /* Add a revision */ checkRevisions(protonDrive, ctx, t, "integrationTestImage.png", 2) - downloadFile(t, ctx, protonDrive, "src", "integrationTestImage.png", "testcase/integrationTestImage2.png") + downloadFile(t, ctx, protonDrive, "src", "integrationTestImage.png", "testcase/integrationTestImage2.png", "") checkFileListing(t, ctx, protonDrive, []string{"/src", "/src/integrationTestImage.png", "/dst"}) log.Println("Move folder src to under folder dst") @@ -241,39 +242,43 @@ func TestCreateAndMoveAndDeleteAFileOneLevelFromRoot(t *testing.T) { checkFileListing(t, ctx, protonDrive, []string{"/src"}) } -// func TestUploadLargeNumberOfBlocks(t *testing.T) { -// ctx, cancel, protonDrive := setup(t) -// t.Cleanup(func() { -// defer cancel() -// defer tearDown(t, ctx, protonDrive) -// }) +func TestUploadLargeNumberOfBlocks(t *testing.T) { + ctx, cancel, protonDrive := setup(t) + t.Cleanup(func() { + defer cancel() + defer tearDown(t, ctx, protonDrive) + }) -// // in order to simulate uploading large files -// // we use 1KB for the UPLOAD_BLOCK_SIZE -// // so a 1000KB file will generate 1000 blocks to test the uploading mechanism -// // and also testing the downloading mechanism -// ORIGINAL_UPLOAD_BLOCK_SIZE := UPLOAD_BLOCK_SIZE -// defer func() { -// UPLOAD_BLOCK_SIZE = ORIGINAL_UPLOAD_BLOCK_SIZE -// }() -// blocks := 500 -// UPLOAD_BLOCK_SIZE = 1000 + // in order to simulate uploading large files + // we use 1KB for the UPLOAD_BLOCK_SIZE + // so a 1000KB file will generate 1000 blocks to test the uploading mechanism + // and also testing the downloading mechanism + ORIGINAL_UPLOAD_BLOCK_SIZE := UPLOAD_BLOCK_SIZE + defer func() { + UPLOAD_BLOCK_SIZE = ORIGINAL_UPLOAD_BLOCK_SIZE + }() + blocks := 100 + UPLOAD_BLOCK_SIZE = 10 -// file1Content := RandomString(UPLOAD_BLOCK_SIZE * blocks) + filename := "fileContent.txt" + file1Content := RandomString(UPLOAD_BLOCK_SIZE * blocks) + file1ContentReader := strings.NewReader(file1Content) + file2Content := RandomString(UPLOAD_BLOCK_SIZE * blocks) + file2ContentReader := strings.NewReader(file2Content) -// log.Println("Upload file1Content") -// uploadFile(t, ctx, protonDrive, "", "integrationTestImage.png", "testcase/integrationTestImage.png") -// checkRevisions(protonDrive, ctx, t, "integrationTestImage.png", 1) -// checkFileListing(t, ctx, protonDrive, []string{"/integrationTestImage.png"}) -// downloadFile(t, ctx, protonDrive, "", "integrationTestImage.png", "testcase/integrationTestImage.png") + log.Println("Upload fileContent.txt") + uploadFileByReader(t, ctx, protonDrive, "", filename, file1ContentReader) + checkRevisions(protonDrive, ctx, t, filename, 1) + checkFileListing(t, ctx, protonDrive, []string{"/" + filename}) + downloadFile(t, ctx, protonDrive, "", filename, "", file1Content) -// log.Println("Upload a new revision to replace integrationTestImage.png") -// uploadFile(t, ctx, protonDrive, "", "integrationTestImage.png", "testcase/integrationTestImage2.png") /* Add a revision */ -// checkRevisions(protonDrive, ctx, t, "integrationTestImage.png", 2) -// downloadFile(t, ctx, protonDrive, "", "integrationTestImage.png", "testcase/integrationTestImage2.png") -// checkFileListing(t, ctx, protonDrive, []string{"/integrationTestImage.png"}) + log.Println("Upload a new revision to replace fileContent.txt") + uploadFileByReader(t, ctx, protonDrive, "", filename, file2ContentReader) + checkRevisions(protonDrive, ctx, t, filename, 2) + checkFileListing(t, ctx, protonDrive, []string{"/" + filename}) + downloadFile(t, ctx, protonDrive, "", filename, "", file2Content) -// log.Println("Delete file integrationTestImage.png") -// deleteBySearchingFromRoot(t, ctx, protonDrive, "integrationTestImage.png", false) -// checkFileListing(t, ctx, protonDrive, []string{}) -// } + log.Println("Delete file fileContent.txt") + deleteBySearchingFromRoot(t, ctx, protonDrive, filename, false) + checkFileListing(t, ctx, protonDrive, []string{}) +} diff --git a/drive_test_helper.go b/drive_test_helper.go index c7272db..0495fba 100644 --- a/drive_test_helper.go +++ b/drive_test_helper.go @@ -4,8 +4,10 @@ import ( "bufio" "bytes" "context" + "io" "os" "testing" + "time" "github.com/henrybear327/go-proton-api" @@ -66,7 +68,29 @@ func createFolder(t *testing.T, ctx context.Context, protonDrive *ProtonDrive, p } } -func uploadFile(t *testing.T, ctx context.Context, protonDrive *ProtonDrive, parent, name string, filepath string) { +func uploadFileByReader(t *testing.T, ctx context.Context, protonDrive *ProtonDrive, parent, name string, in io.Reader) { + parentLink := protonDrive.RootLink + if parent != "" { + targetFolderLink, err := protonDrive.SearchByNameRecursivelyFromRoot(ctx, parent, true) + if err != nil { + t.Fatal(err) + } + if targetFolderLink == nil { + t.Fatalf("Folder %v not found", parent) + } + parentLink = targetFolderLink + } + if parentLink.Type != proton.LinkTypeFolder { + t.Fatalf("parentLink is not of folder type") + } + + _, _, err := protonDrive.UploadFileByReader(ctx, parentLink.LinkID, name, time.Now(), in) + if err != nil { + t.Fatal(err) + } +} + +func uploadFileByFilepath(t *testing.T, ctx context.Context, protonDrive *ProtonDrive, parent, name string, filepath string) { parentLink := protonDrive.RootLink if parent != "" { targetFolderLink, err := protonDrive.SearchByNameRecursivelyFromRoot(ctx, parent, true) @@ -101,7 +125,7 @@ func uploadFile(t *testing.T, ctx context.Context, protonDrive *ProtonDrive, par } } -func downloadFile(t *testing.T, ctx context.Context, protonDrive *ProtonDrive, parent, name string, filepath string) { +func downloadFile(t *testing.T, ctx context.Context, protonDrive *ProtonDrive, parent, name string, filepath string, data string) { parentLink := protonDrive.RootLink if parent != "" { targetFolderLink, err := protonDrive.SearchByNameRecursivelyFromRoot(ctx, parent, true) @@ -135,17 +159,25 @@ func downloadFile(t *testing.T, ctx context.Context, protonDrive *ProtonDrive, p t.Fatalf("FileSystemAttr should not be nil") } else { if len(downloadedData) != int(fileSystemAttr.Size) { - t.Fatalf("Downloaded file size != uploaded file size: %#v", fileSystemAttr) + t.Fatalf("Downloaded file size != uploaded file size: %#v vs %#v", len(downloadedData), int(fileSystemAttr.Size)) } } - originalData, err := os.ReadFile(filepath) - if err != nil { - t.Fatal(err) - } + if filepath != "" { + originalData, err := os.ReadFile(filepath) + if err != nil { + t.Fatal(err) + } - if !bytes.Equal(downloadedData, originalData) { - t.Fatalf("Downloaded content is different from the original content") + if !bytes.Equal(downloadedData, originalData) { + t.Fatalf("Downloaded content is different from the original content") + } + } else if data != "" { + if !bytes.Equal(downloadedData, []byte(data)) { + t.Fatalf("Downloaded content is different from the original content") + } + } else { + t.Fatalf("Nothing to verify against") } } } diff --git a/file.go b/file.go index 847df57..97cd2ca 100644 --- a/file.go +++ b/file.go @@ -47,13 +47,11 @@ func (protonDrive *ProtonDrive) GetActiveRevision(ctx context.Context, link *pro } } - // FIXME: compute total blocks required - // TODO: handle large file downloading - // FIXME: total block calculation: how? - revision, err := protonDrive.c.GetRevision(ctx, protonDrive.MainShare.ShareID, link.LinkID, revisions[activeRevision].ID, 1, 50) + revision, err := protonDrive.c.GetRevisionAllBlocks(ctx, protonDrive.MainShare.ShareID, link.LinkID, revisions[activeRevision].ID) if err != nil { return nil, err } + // log.Println("Total blocks", len(revision.Blocks)) return &revision, nil } diff --git a/go.mod b/go.mod index dd87bd9..fc84466 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.18 require ( github.com/ProtonMail/gopenpgp/v2 v2.7.1 github.com/gabriel-vasile/mimetype v1.4.2 - github.com/henrybear327/go-proton-api v0.0.0-20230626095836-c05921e07e64 + github.com/henrybear327/go-proton-api v0.0.0-20230626213659-c3c0905ee910 github.com/relvacode/iso8601 v1.3.0 ) @@ -22,13 +22,13 @@ require ( github.com/cronokirby/saferith v0.33.0 // indirect github.com/emersion/go-message v0.16.0 // indirect github.com/emersion/go-textwrapper v0.0.0-20200911093747-65d896831594 // indirect - github.com/emersion/go-vcard v0.0.0-20230331202150-f3d26859ccd3 // indirect + github.com/emersion/go-vcard v0.0.0-20230626131229-38c18b295bbd // indirect github.com/go-resty/resty/v2 v2.7.0 // indirect github.com/google/uuid v1.3.0 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/sirupsen/logrus v1.9.3 // indirect golang.org/x/crypto v0.10.0 // indirect - golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 // indirect + golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df // indirect golang.org/x/net v0.11.0 // indirect golang.org/x/sync v0.3.0 // indirect golang.org/x/sys v0.9.0 // indirect diff --git a/go.sum b/go.sum index c4f9ee0..0657142 100644 --- a/go.sum +++ b/go.sum @@ -36,8 +36,8 @@ github.com/emersion/go-message v0.16.0 h1:uZLz8ClLv3V5fSFF/fFdW9jXjrZkXIpE1Fn8fK github.com/emersion/go-message v0.16.0/go.mod h1:pDJDgf/xeUIF+eicT6B/hPX/ZbEorKkUMPOxrPVG2eQ= github.com/emersion/go-textwrapper v0.0.0-20200911093747-65d896831594 h1:IbFBtwoTQyw0fIM5xv1HF+Y+3ZijDR839WMulgxCcUY= github.com/emersion/go-textwrapper v0.0.0-20200911093747-65d896831594/go.mod h1:aqO8z8wPrjkscevZJFVE1wXJrLpC5LtJG7fqLOsPb2U= -github.com/emersion/go-vcard v0.0.0-20230331202150-f3d26859ccd3 h1:hQ1wTMaKcGfobYRT88RM8NFNyX+IQHvagkm/tqViU98= -github.com/emersion/go-vcard v0.0.0-20230331202150-f3d26859ccd3/go.mod h1:HMJKR5wlh/ziNp+sHEDV2ltblO4JD2+IdDOWtGcQBTM= +github.com/emersion/go-vcard v0.0.0-20230626131229-38c18b295bbd h1:n1kH4lDJLDgO8sqkt0QgeQXKims1L8khdgilk9G5lm8= +github.com/emersion/go-vcard v0.0.0-20230626131229-38c18b295bbd/go.mod h1:HMJKR5wlh/ziNp+sHEDV2ltblO4JD2+IdDOWtGcQBTM= github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU= github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= @@ -50,8 +50,8 @@ github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSM github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/henrybear327/go-proton-api v0.0.0-20230626095836-c05921e07e64 h1:23dMmB9tttnzpli/aswiujO+/uj8Uuxh9jRSenOnQnE= -github.com/henrybear327/go-proton-api v0.0.0-20230626095836-c05921e07e64/go.mod h1:l42xBSOrCmkAxzWUHcoUsG/cP8m1hMhV72GoChOX3bg= +github.com/henrybear327/go-proton-api v0.0.0-20230626213659-c3c0905ee910 h1:FZIVc2R3G2dY+c1u2KYiXaBx1IiLfmp6ir5cm9ityPs= +github.com/henrybear327/go-proton-api v0.0.0-20230626213659-c3c0905ee910/go.mod h1:l42xBSOrCmkAxzWUHcoUsG/cP8m1hMhV72GoChOX3bg= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk= github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= @@ -81,8 +81,8 @@ golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2Uz golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/crypto v0.10.0 h1:LKqV2xt9+kDzSTfOhx4FrkEBcMrAgHSYgzywV9zcGmM= golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I= -golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 h1:k/i9J1pBpvlfR+9QsetwPyERsqu1GIbi967PQMq3Ivc= -golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= +golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df h1:UA2aFVmmsIlefxMk29Dp2juaUSth8Pyn3Tq5Y5mJGME= +golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=