From 05469feace47bd0311a55389be63185f4dad9b39 Mon Sep 17 00:00:00 2001 From: Sourav Gupta Date: Thu, 27 Apr 2023 23:12:30 +0530 Subject: [PATCH 1/8] Adding README --- sdk/storage/azfile/README.md | 266 +++++++++++++++++++++++++++++++++++ 1 file changed, 266 insertions(+) create mode 100644 sdk/storage/azfile/README.md diff --git a/sdk/storage/azfile/README.md b/sdk/storage/azfile/README.md new file mode 100644 index 000000000000..2b6ba2b9a02e --- /dev/null +++ b/sdk/storage/azfile/README.md @@ -0,0 +1,266 @@ +# Azure File Storage SDK for Go + +> Service Version: 2020-10-02 + +Azure File Shares offers fully managed file shares in the cloud that are accessible via the industry standard +[Server Message Block (SMB) protocol](https://docs.microsoft.com/windows/desktop/FileIO/microsoft-smb-protocol-and-cifs-protocol-overview). +Azure file shares can be mounted concurrently by cloud or on-premises deployments of Windows, Linux, and macOS. +Additionally, Azure file shares can be cached on Windows Servers with Azure File Sync for fast access near where the data is being used. + +[Source code][source] | [API reference documentation][docs] | [REST API documentation][rest_docs] | [Product documentation][product_docs] + +## Getting started + +### Install the package + +Install the Azure File Storage SDK for Go with [go get][goget]: + +```Powershell +go get github.com/Azure/azure-sdk-for-go/sdk/storage/azfile +``` + +### Prerequisites + +A supported [Go][godevdl] version (the Azure SDK supports the two most recent Go releases). + +You need an [Azure subscription][azure_sub] and a +[Storage Account][storage_account_docs] to use this package. + +To create a new Storage Account, you can use the [Azure Portal][storage_account_create_portal], +[Azure PowerShell][storage_account_create_ps], or the [Azure CLI][storage_account_create_cli]. +Here's an example using the Azure CLI: + +```Powershell +az storage account create --name MyStorageAccount --resource-group MyResourceGroup --location westus --sku Standard_LRS +``` + +### Authenticate the client + +The Azure File Storage SDK for Go allows you to interact with four types of resources: the storage +account itself, file shares, directories, and files. Interaction with these resources starts with an instance of a +client. To create a client object, you will need the storage account's file service URL and a +credential that allows you to access the storage account: + +```go +// create a credential for authenticating using shared key +cred, err := service.NewSharedKeyCredential("", "") +// TODO: handle err + +// create service.Client for the specified storage account that uses the above credential +client, err := service.NewClientWithSharedKeyCredential("https://.file.core.windows.net/", cred, nil) +// TODO: handle err +``` + +## Key concepts + +Azure file shares can be used to: + +- Completely replace or supplement traditional on-premises file servers or NAS devices. +- "Lift and shift" applications to the cloud that expect a file share to store file application or user data. +- Simplify new cloud development projects with shared application settings, diagnostic shares, and Dev/Test/Debug tool file shares. + +### Goroutine safety +We guarantee that all client instance methods are goroutine-safe and independent of each other ([guideline](https://azure.github.io/azure-sdk/golang_introduction.html#thread-safety)). This ensures that the recommendation of reusing client instances is always safe, even across goroutines. + +### Additional concepts + +[Client options](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azcore/policy#ClientOptions) | +[Accessing the response](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime#WithCaptureResponse) | +[Handling failures](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azcore#ResponseError) | +[Logging](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azcore/log) + + +## Examples + +### Create a share and upload a file + +```go +const ( +shareName = "sample-share" +dirName = "sample-dir" +fileName = "sample-file" +) + +// Get a connection string to our Azure Storage account. You can +// obtain your connection string from the Azure Portal (click +// Access Keys under Settings in the Portal Storage account blade) +// or using the Azure CLI with: +// +// az storage account show-connection-string --name --resource-group +// +// And you can provide the connection string to your application +// using an environment variable. +connectionString := "" + +// Path to the local file to upload +localFilePath := "" + +// Get reference to a share and create it +shareClient, err := share.NewClientFromConnectionString(connectionString, shareName, nil) +// TODO: handle error +_, err = shareClient.Create(context.TODO(), nil) +// TODO: handle error + +// Get reference to a directory and create it +dirClient := shareClient.NewDirectoryClient(dirName) +_, err = dirClient.Create(context.TODO(), nil) +// TODO: handle error + +// open the file for reading +file, err := os.OpenFile(localFilePath, os.O_RDONLY, 0) +// TODO: handle error +defer file.Close() + +// get the size of file +fInfo, err := file.Stat() +// TODO: handle error +fSize := fInfo.Size() + +// create the file +fClient := dirClient.NewFileClient(fileName) +_, err = fClient.Create(context.TODO(), fSize, nil) +// TODO: handle error + +// upload the file +err = fClient.UploadFile(context.TODO(), file, nil) +// TODO: handle error +``` + +### Download a file + +```go +const ( +shareName = "sample-share" +dirName = "sample-dir" +fileName = "sample-file" +) + +connectionString := "" + +// Path to the save the downloaded file +localFilePath := "" + +// Get reference to the share +shareClient, err := share.NewClientFromConnectionString(connectionString, shareName, nil) +// TODO: handle error + +// Get reference to the directory +dirClient := shareClient.NewDirectoryClient(dirName) + +// Get reference to the file +fClient := dirClient.NewFileClient(fileName) + +// create or open a local file where we can download the Azure File +file, err := os.Create(localFilePath) +// TODO: handle error +defer file.Close() + +// Download the file +_, err = fClient.DownloadFile(context.TODO(), file, nil) +// TODO: handle error +``` + +### Traverse a share + +```go +const shareName = "sample-share" + +connectionString := "" + +// Get reference to the share +shareClient, err := share.NewClientFromConnectionString(connectionString, shareName, nil) +// TODO: handle error + +// Track the remaining directories to walk, starting from the root +var dirs []*directory.Client +dirs = append(dirs, shareClient.NewRootDirectoryClient()) +for len(dirs) > 0 { + dirClient := dirs[0] + dirs = dirs[1:] + + // Get all the next directory's files and subdirectories + pager := dirClient.NewListFilesAndDirectoriesPager(nil) + for pager.More() { + resp, err := pager.NextPage(context.TODO()) + // TODO: handle error + + for _, d := range resp.Segment.Directories { + fmt.Println(*d.Name) + // Keep walking down directories + dirs = append(dirs, dirClient.NewSubdirectoryClient(*d.Name)) + } + + for _, f := range resp.Segment.Files { + fmt.Println(*f.Name) + } + } +} +``` + +## Troubleshooting + +All File service operations will return an +[*azcore.ResponseError][azcore_response_error] on failure with a +populated `ErrorCode` field. Many of these errors are recoverable. +The [fileerror][file_error] package provides the possible Storage error codes +along with various helper facilities for error handling. + +```go +const ( + connectionString = "" + shareName = "sample-share" +) + +// create a client with the provided connection string +client, err := service.NewClientFromConnectionString(connectionString, nil) +// TODO: handle error + +// try to delete the share, avoiding any potential race conditions with an in-progress or completed deletion +_, err = client.DeleteShare(context.TODO(), shareName, nil) + +if fileerror.HasCode(err, fileerror.ShareBeingDeleted, fileerror.ShareNotFound) { + // ignore any errors if the share is being deleted or already has been deleted +} else if err != nil { + // TODO: some other error +} +``` + +## Next steps + +Get started with our [File samples][samples]. They contain complete examples of the above snippets and more. + +## Contributing + +See the [Storage CONTRIBUTING.md][storage_contrib] for details on building, +testing, and contributing to this library. + +This project welcomes contributions and suggestions. Most contributions require +you to agree to a Contributor License Agreement (CLA) declaring that you have +the right to, and actually do, grant us the rights to use your contribution. For +details, visit [cla.microsoft.com][cla]. + +This project has adopted the [Microsoft Open Source Code of Conduct][coc]. +For more information see the [Code of Conduct FAQ][coc_faq] +or contact [opencode@microsoft.com][coc_contact] with any +additional questions or comments. + + +[source]: https://github.com/Azure/azure-sdk-for-go/tree/main/sdk/storage/azfile +[docs]: https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/storage/azfile +[rest_docs]: https://docs.microsoft.com/rest/api/storageservices/file-service-rest-api +[product_docs]: https://docs.microsoft.com/azure/storage/files/storage-files-introduction +[godevdl]: https://go.dev/dl/ +[goget]: https://pkg.go.dev/cmd/go#hdr-Add_dependencies_to_current_module_and_install_them +[storage_account_docs]: https://docs.microsoft.com/azure/storage/common/storage-account-overview +[storage_account_create_ps]: https://docs.microsoft.com/azure/storage/common/storage-quickstart-create-account?tabs=azure-powershell +[storage_account_create_cli]: https://docs.microsoft.com/azure/storage/common/storage-quickstart-create-account?tabs=azure-cli +[storage_account_create_portal]: https://docs.microsoft.com/azure/storage/common/storage-quickstart-create-account?tabs=azure-portal +[azure_sub]: https://azure.microsoft.com/free/ +[azcore_response_error]: https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azcore#ResponseError +[file_error]: https://github.com/Azure/azure-sdk-for-go/tree/main/sdk/storage/azfile/fileerror/error_codes.go +[samples]: https://github.com/Azure/azure-sdk-for-go/blob/main/sdk/storage/azfile/file/examples_test.go +[storage_contrib]: https://github.com/Azure/azure-sdk-for-go/blob/main/CONTRIBUTING.md +[cla]: https://cla.microsoft.com +[coc]: https://opensource.microsoft.com/codeofconduct/ +[coc_faq]: https://opensource.microsoft.com/codeofconduct/faq/ +[coc_contact]: mailto:opencode@microsoft.com From c73dcbf90125a3e715cbc536b551d28e184c60f1 Mon Sep 17 00:00:00 2001 From: Sourav Gupta Date: Fri, 28 Apr 2023 13:17:34 +0530 Subject: [PATCH 2/8] Adding doc.go --- sdk/storage/azfile/doc.go | 224 +++++++++++++++++++++++++++++++++++++- 1 file changed, 222 insertions(+), 2 deletions(-) diff --git a/sdk/storage/azfile/doc.go b/sdk/storage/azfile/doc.go index 31fb97f1f287..51d645839165 100644 --- a/sdk/storage/azfile/doc.go +++ b/sdk/storage/azfile/doc.go @@ -4,6 +4,226 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. -// Package azfile provides access to Azure File storage. -// For more information please see https://learn.microsoft.com/rest/api/storageservices/file-service-rest-api +/* +Package azfile provides access to Azure File Storage. +For more information please see https://learn.microsoft.com/rest/api/storageservices/file-service-rest-api + +The azfile package is capable of :- + - Creating, deleting, and querying shares in an account + - Creating, deleting, and querying directories in a share + - Creating, deleting, and querying files in a share or directory + - Creating Shared Access Signature for authentication + +Types of Resources + +The azfile package allows you to interact with four types of resources :- + +* Azure storage accounts. +* Shares within those storage accounts. +* Directories within those shares. +* Files within those shares or directories. + +The Azure File Storage (azfile) client library for Go allows you to interact with each of these components through the use of a dedicated client object. +To create a client object, you will need the account's file service endpoint URL and a credential that allows you to access the account. + +Types of Credentials + +The clients support different forms of authentication. +The azfile library supports authorization via a shared key, Connection String, +or with a Shared Access Signature token. + +Using a Shared Key + +To use an account shared key (aka account key or access key), provide the key as a string. +This can be found in your storage account in the Azure Portal under the "Access Keys" section. + +Use the key as the credential parameter to authenticate the client: + + accountName, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_NAME") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_NAME could not be found") + } + accountKey, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_KEY") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_KEY could not be found") + } + + serviceURL := fmt.Sprintf("https://%s.file.core.windows.net/", accountName) + + cred, err := service.NewSharedKeyCredential(accountName, accountKey) + handle(err) + + serviceClient, err := service.NewClientWithSharedKeyCredential(serviceURL, cred, nil) + handle(err) + + fmt.Println(serviceClient.URL()) + +Using a Connection String + +Depending on your use case and authorization method, you may prefer to initialize a client instance with a connection string instead of providing the account URL and credential separately. +To do this, pass the connection string to the service client's `NewClientFromConnectionString` method. +The connection string can be found in your storage account in the Azure Portal under the "Access Keys" section. + + connStr := "DefaultEndpointsProtocol=https;AccountName=;AccountKey=;EndpointSuffix=core.windows.net" + serviceClient, err := azfile.NewServiceClientFromConnectionString(connStr, nil) + handle(err) + +Using a Shared Access Signature (SAS) Token + +To use a shared access signature (SAS) token, provide the token at the end of your service URL. +You can generate a SAS token from the Azure Portal under Shared Access Signature or use the service.Client.GetSASURL() functions. + + accountName, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_NAME") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_NAME could not be found") + } + accountKey, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_KEY") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_KEY could not be found") + } + serviceURL := fmt.Sprintf("https://%s.file.core.windows.net/", accountName) + + cred, err := service.NewSharedKeyCredential(accountName, accountKey) + handle(err) + serviceClient, err := service.NewClientWithSharedKeyCredential(serviceURL, cred, nil) + handle(err) + fmt.Println(serviceClient.URL()) + + // Alternatively, you can create SAS on the fly + + resources := sas.AccountResourceTypes{Service: true} + permission := sas.AccountPermissions{Read: true} + start := time.Now() + expiry := start.AddDate(0, 0, 1) + serviceURLWithSAS, err := serviceClient.GetSASURL(resources, permission, expiry, &service.GetSASURLOptions{StartTime: &start}) + handle(err) + + serviceClientWithSAS, err := service.NewClientWithNoCredential(serviceURLWithSAS, nil) + handle(err) + + fmt.Println(serviceClientWithSAS.URL()) + +Types of Clients + +There are four different clients provided to interact with the various components of the File Service: + +1. **`ServiceClient`** + * Get and set account settings. + * Query, create, delete and restore shares within the account. + +2. **`ShareClient`** + * Get and set share access settings, properties, and metadata. + * Create, delete, and query directories and files within the share. + * `lease.ShareClient` to support share lease management. + +3. **`DirectoryClient`** + * Create or delete operations on a given directory. + * Get and set directory properties. + * List sub-directories and files within the given directory. + +3. **`FileClient`** + * Get and set file properties. + * Perform CRUD operations on a given file. + * `FileLeaseClient` to support file lease management. + +Examples + + // Your account name and key can be obtained from the Azure Portal. + accountName, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_NAME") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_NAME could not be found") + } + + accountKey, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_KEY") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_KEY could not be found") + } + + cred, err := service.NewSharedKeyCredential(accountName, accountKey) + handle(err) + + // The service URL for file endpoints is usually in the form: http(s)://.file.core.windows.net/ + serviceClient, err := service.NewClientWithSharedKeyCredential(fmt.Sprintf("https://%s.file.core.windows.net/", accountName), cred, nil) + handle(err) + + // ===== 1. Create a share ===== + + // First, create a share client, and use the Create method to create a new share in your account + shareClient := serviceClient.NewShareClient("testshare") + handle(err) + + // All APIs have an options' bag struct as a parameter. + // The options' bag struct allows you to specify optional parameters such as metadata, quota, etc. + // If you want to use the default options, pass in nil. + _, err = shareClient.Create(context.TODO(), nil) + handle(err) + + // ===== 2. Create a directory ===== + + // First, create a directory client, and use the Create method to create a new directory in the share + dirClient := shareClient.NewDirectoryClient("testdir") + _, err = dirClient.Create(context.TODO(), nil) + + // ===== 3. Upload and Download a file ===== + uploadData := "Hello world!" + + // First, create a file client, and use the Create method to create a new file in the directory + fileClient := dirClient.NewFileClient("HelloWorld.txt") + _, err = fileClient.Create(context.TODO(), int64(len(uploadData)), nil) + handle(err) + + // Upload data to the file + _, err = fileClient.UploadRange(context.TODO(), 0, streaming.NopCloser(strings.NewReader(uploadData)), nil) + handle(err) + + // Download the file's contents and ensure that the download worked properly + fileDownloadResponse, err := fileClient.DownloadStream(context.TODO(), nil) + handle(err) + + // Use io.readAll to read the downloaded data. + // RetryReaderOptions has a lot of in-depth tuning abilities, but for the sake of simplicity, we'll omit those here. + reader := fileDownloadResponse.Body + downloadData, err := io.ReadAll(reader) + handle(err) + if string(downloadData) != uploadData { + handle(errors.New("uploaded data should be same as downloaded data")) + } + + if err = reader.Close(); err != nil { + handle(err) + return + } + + // ===== 3. List directories and files in a share ===== + // List methods returns a pager object which can be used to iterate over the results of a paging operation. + // To iterate over a page use the NextPage(context.Context) to fetch the next page of results. + // PageResponse() can be used to iterate over the results of the specific page. + // Always check the Err() method after paging to see if an error was returned by the pager. A pager will return either an error or the page of results. + // The below code lists the contents only for a single level of the directory hierarchy. + rootDirClient := shareClient.NewRootDirectoryClient() + pager := rootDirClient.NewListFilesAndDirectoriesPager(nil) + for pager.More() { + resp, err := pager.NextPage(context.TODO()) + handle(err) + for _, d := range resp.Segment.Directories { + fmt.Println(*d.Name) + } + for _, f := range resp.Segment.Files { + fmt.Println(*f.Name) + } + } + + // Delete the file. + _, err = fileClient.Delete(context.TODO(), nil) + handle(err) + + // Delete the directory. + _, err = dirClient.Delete(context.TODO(), nil) + handle(err) + + // Delete the share. + _, err = shareClient.Delete(context.TODO(), nil) + handle(err) +*/ + package azfile From ec79091436fb139540accb45f0b2c916bff5eabb Mon Sep 17 00:00:00 2001 From: Sourav Gupta Date: Fri, 28 Apr 2023 14:53:53 +0530 Subject: [PATCH 3/8] Adding log.go --- sdk/storage/azfile/file/client.go | 8 ++++++++ sdk/storage/azfile/file/client_test.go | 15 ++++++++++++++- .../azfile/internal/exported/log_events.go | 17 +++++++++++++++++ sdk/storage/azfile/log.go | 16 ++++++++++++++++ 4 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 sdk/storage/azfile/internal/exported/log_events.go create mode 100644 sdk/storage/azfile/log.go diff --git a/sdk/storage/azfile/file/client.go b/sdk/storage/azfile/file/client.go index cb2175ea00f1..f2d5e57289a8 100644 --- a/sdk/storage/azfile/file/client.go +++ b/sdk/storage/azfile/file/client.go @@ -12,6 +12,7 @@ import ( "errors" "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" "github.com/Azure/azure-sdk-for-go/sdk/azcore/streaming" + "github.com/Azure/azure-sdk-for-go/sdk/internal/log" "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/fileerror" "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/base" "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/exported" @@ -281,6 +282,13 @@ func (f *Client) uploadFromReader(ctx context.Context, reader io.ReaderAt, actua } // TODO: Add logs + if log.Should(exported.EventUpload) { + urlParts, err := sas.ParseURL(f.URL()) + if err == nil { + log.Writef(exported.EventUpload, "file name %s actual size %v chunk-size %v chunk-count %v", + urlParts.DirectoryOrFilePath, actualSize, o.ChunkSize, ((actualSize-1)/o.ChunkSize)+1) + } + } progress := int64(0) progressLock := &sync.Mutex{} diff --git a/sdk/storage/azfile/file/client_test.go b/sdk/storage/azfile/file/client_test.go index fea7ab8e19f6..7056bb611e14 100644 --- a/sdk/storage/azfile/file/client_test.go +++ b/sdk/storage/azfile/file/client_test.go @@ -13,9 +13,11 @@ import ( "crypto/rand" "encoding/binary" "fmt" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/log" "github.com/Azure/azure-sdk-for-go/sdk/azcore/streaming" "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" "github.com/Azure/azure-sdk-for-go/sdk/internal/recording" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile" "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/file" "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/fileerror" "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/shared" @@ -2822,13 +2824,22 @@ func (f *FileRecordedTestsSuite) TestFileUploadDownloadSmallBuffer() { _require := require.New(f.T()) testName := f.T().Name() + var fileSize int64 = 10 * 1024 + listenerCalled := false + log.SetEvents(azfile.EventUpload, log.EventRequest, log.EventResponse) + log.SetListener(func(cls log.Event, msg string) { + if cls == azfile.EventUpload { + listenerCalled = true + _require.Equal(msg, fmt.Sprintf("file name %v actual size %v chunk-size 2048 chunk-count 5", testcommon.GenerateFileName(testName), fileSize)) + } + }) + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) _require.NoError(err) shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) defer testcommon.DeleteShare(context.Background(), _require, shareClient) - var fileSize int64 = 10 * 1024 fClient := shareClient.NewRootDirectoryClient().NewFileClient(testcommon.GenerateFileName(testName)) _, err = fClient.Create(context.Background(), fileSize, nil) _require.NoError(err) @@ -2869,6 +2880,8 @@ func (f *FileRecordedTestsSuite) TestFileUploadDownloadSmallBuffer() { _require.Len(rangeList.Ranges, 1) _require.Equal(*rangeList.Ranges[0].Start, int64(0)) _require.Equal(*rangeList.Ranges[0].End, fileSize-1) + + _require.True(listenerCalled) } func (f *FileRecordedTestsSuite) TestFileUploadDownloadSmallFile() { diff --git a/sdk/storage/azfile/internal/exported/log_events.go b/sdk/storage/azfile/internal/exported/log_events.go new file mode 100644 index 000000000000..f38793f683ba --- /dev/null +++ b/sdk/storage/azfile/internal/exported/log_events.go @@ -0,0 +1,17 @@ +//go:build go1.18 +// +build go1.18 + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. + +package exported + +import ( + "github.com/Azure/azure-sdk-for-go/sdk/internal/log" +) + +// NOTE: these are publicly exported via type-aliasing in azfile/log.go +const ( + // EventUpload is used when we compute number of blocks to upload and size of each block. + EventUpload log.Event = "azfile.Upload" +) diff --git a/sdk/storage/azfile/log.go b/sdk/storage/azfile/log.go new file mode 100644 index 000000000000..f59215653531 --- /dev/null +++ b/sdk/storage/azfile/log.go @@ -0,0 +1,16 @@ +//go:build go1.18 +// +build go1.18 + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package azfile + +import ( + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/exported" +) + +const ( + // EventUpload is used for logging events related to upload operation. + EventUpload = exported.EventUpload +) From a74c25b7ff3e1cedd8f7f5cc5978b3cefd28f345 Mon Sep 17 00:00:00 2001 From: Sourav Gupta Date: Fri, 28 Apr 2023 14:58:14 +0530 Subject: [PATCH 4/8] Adding changelog --- sdk/storage/azfile/CHANGELOG.md | 6 +----- sdk/storage/azfile/internal/exported/log_events.go | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/sdk/storage/azfile/CHANGELOG.md b/sdk/storage/azfile/CHANGELOG.md index bb825f2e6ba7..04f97b45434f 100644 --- a/sdk/storage/azfile/CHANGELOG.md +++ b/sdk/storage/azfile/CHANGELOG.md @@ -4,8 +4,4 @@ ### Features Added -### Breaking Changes - -### Bugs Fixed - -### Other Changes \ No newline at end of file +* This is the initial preview release of the `azfile` library diff --git a/sdk/storage/azfile/internal/exported/log_events.go b/sdk/storage/azfile/internal/exported/log_events.go index f38793f683ba..d33528ea8eb2 100644 --- a/sdk/storage/azfile/internal/exported/log_events.go +++ b/sdk/storage/azfile/internal/exported/log_events.go @@ -12,6 +12,6 @@ import ( // NOTE: these are publicly exported via type-aliasing in azfile/log.go const ( - // EventUpload is used when we compute number of blocks to upload and size of each block. + // EventUpload is used when we compute number of chunks to upload and size of each chunk. EventUpload log.Event = "azfile.Upload" ) From 0c49fd3f9be4efddffbcc6c98100df9cccc584c1 Mon Sep 17 00:00:00 2001 From: Sourav Gupta Date: Fri, 28 Apr 2023 17:57:43 +0530 Subject: [PATCH 5/8] upload range from url test addition --- sdk/storage/azfile/directory/client_test.go | 4 - sdk/storage/azfile/file/client.go | 2 - sdk/storage/azfile/file/client_test.go | 75 ++++++++++--------- sdk/storage/azfile/file/models.go | 1 - sdk/storage/azfile/go.mod | 3 +- sdk/storage/azfile/go.sum | 6 +- .../internal/testcommon/clients_auth.go | 18 +++++ .../azfile/internal/testcommon/common.go | 3 + sdk/storage/azfile/lease/models.go | 1 - sdk/storage/azfile/share/models.go | 2 - 10 files changed, 68 insertions(+), 47 deletions(-) diff --git a/sdk/storage/azfile/directory/client_test.go b/sdk/storage/azfile/directory/client_test.go index 96fe27da6399..4e91138e9aad 100644 --- a/sdk/storage/azfile/directory/client_test.go +++ b/sdk/storage/azfile/directory/client_test.go @@ -1115,7 +1115,3 @@ func (d *DirectoryRecordedTestsSuite) TestDirectoryCreateNegativeWithoutSAS() { _, err = dirClient.Create(context.Background(), nil) _require.Error(err) } - -// TODO: add tests for listing files and directories after file client is completed - -// TODO: add tests for ListHandles and ForceCloseHandles diff --git a/sdk/storage/azfile/file/client.go b/sdk/storage/azfile/file/client.go index cb2175ea00f1..708cb1b492f6 100644 --- a/sdk/storage/azfile/file/client.go +++ b/sdk/storage/azfile/file/client.go @@ -280,8 +280,6 @@ func (f *Client) uploadFromReader(ctx context.Context, reader io.ReaderAt, actua o.ChunkSize = MaxUpdateRangeBytes } - // TODO: Add logs - progress := int64(0) progressLock := &sync.Mutex{} diff --git a/sdk/storage/azfile/file/client_test.go b/sdk/storage/azfile/file/client_test.go index fea7ab8e19f6..29abb53c65dd 100644 --- a/sdk/storage/azfile/file/client_test.go +++ b/sdk/storage/azfile/file/client_test.go @@ -13,9 +13,11 @@ import ( "crypto/rand" "encoding/binary" "fmt" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" "github.com/Azure/azure-sdk-for-go/sdk/azcore/streaming" "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" "github.com/Azure/azure-sdk-for-go/sdk/internal/recording" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob" "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/file" "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/fileerror" "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/shared" @@ -1792,11 +1794,20 @@ func (f *FileRecordedTestsSuite) TestFileUploadRangeFromURLOffsetNegative() { _require.Equal(err.Error(), "invalid argument: source and destination offsets must be >= 0") } -// TODO: check why this is failing -/*func (f *FileRecordedTestsSuite) TestFileUploadRangeFromURLCopySourceAuth() { +func (f *FileRecordedTestsSuite) TestFileUploadRangeFromURLCopySourceAuthBlob() { _require := require.New(f.T()) testName := f.T().Name() + accountName, _ := testcommon.GetGenericAccountInfo(testcommon.TestAccountDefault) + _require.Greater(len(accountName), 0) + + cred, err := testcommon.GetGenericTokenCredential() + _require.NoError(err) + + // Getting token + accessToken, err := cred.GetToken(context.Background(), policy.TokenRequestOptions{Scopes: []string{"https://storage.azure.com/.default"}}) + _require.NoError(err) + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) _require.NoError(err) @@ -1804,56 +1815,54 @@ func (f *FileRecordedTestsSuite) TestFileUploadRangeFromURLOffsetNegative() { shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) defer testcommon.DeleteShare(context.Background(), _require, shareClient) - var fileSize int64 = 1024 * 20 - srcFileName := "src" + testcommon.GenerateFileName(testName) - srcFClient := shareClient.NewRootDirectoryClient().NewFileClient(srcFileName) - _, err = srcFClient.Create(context.Background(), fileSize, nil) - _require.NoError(err) - - gResp, err := srcFClient.GetProperties(context.Background(), nil) - _require.NoError(err) - _require.Equal(*gResp.ContentLength, fileSize) - + var fileSize int64 = 1024 * 10 contentSize := 1024 * 8 // 8KB - content := make([]byte, contentSize) - body := bytes.NewReader(content) - rsc := streaming.NopCloser(body) + _, content := testcommon.GenerateData(contentSize) contentCRC64 := crc64.Checksum(content, shared.CRC64Table) - _, err = srcFClient.UploadRange(context.Background(), 0, rsc, nil) + // create source block blob + blobClient, err := azblob.NewClient("https://"+accountName+".blob.core.windows.net/", cred, nil) _require.NoError(err) - destFClient := shareClient.NewRootDirectoryClient().NewFileClient("dest" + testcommon.GenerateFileName(testName)) - _, err = destFClient.Create(context.Background(), fileSize, nil) + containerName := "goc" + testcommon.GenerateEntityName(testName) + blobName := "blob" + testcommon.GenerateEntityName(testName) + _, err = blobClient.CreateContainer(context.Background(), containerName, nil) _require.NoError(err) + defer func() { + _, err := blobClient.DeleteContainer(context.Background(), containerName, nil) + _require.NoError(err) + }() - cred, err := azidentity.NewDefaultAzureCredential(nil) + _, err = blobClient.UploadBuffer(context.Background(), containerName, blobName, content, nil) _require.NoError(err) - // Getting token - token, err := cred.GetToken(context.Background(), policy.TokenRequestOptions{Scopes: []string{"https://storage.azure.com/.default"}}) + destFClient := shareClient.NewRootDirectoryClient().NewFileClient("dest" + testcommon.GenerateFileName(testName)) + _, err = destFClient.Create(context.Background(), fileSize, nil) _require.NoError(err) - uResp, err := destFClient.UploadRangeFromURL(context.Background(), srcFClient.URL(), 0, 0, int64(contentSize), &file.UploadRangeFromURLOptions{ + blobURL := blobClient.ServiceClient().NewContainerClient(containerName).NewBlockBlobClient(blobName).URL() + uResp, err := destFClient.UploadRangeFromURL(context.Background(), blobURL, 0, 0, int64(contentSize), &file.UploadRangeFromURLOptions{ SourceContentCRC64: contentCRC64, - CopySourceAuthorization: to.Ptr("Bearer " + token.Token), + CopySourceAuthorization: to.Ptr("Bearer " + accessToken.Token), }) _require.NoError(err) _require.NotNil(uResp.XMSContentCRC64) _require.EqualValues(binary.LittleEndian.Uint64(uResp.XMSContentCRC64), contentCRC64) - rangeList, err := destFClient.GetRangeList(context.Background(), nil) + // validate the content uploaded + dResp, err := destFClient.DownloadStream(context.Background(), &file.DownloadStreamOptions{ + Range: file.HTTPRange{Offset: 0, Count: int64(contentSize)}, + }) _require.NoError(err) - _require.NotNil(rangeList.RequestID) - cResp, err := destFClient.ClearRange(context.Background(), file.HTTPRange{Offset: 0, Count: int64(contentSize)}, nil) - _require.NoError(err) - _require.Nil(cResp.ContentMD5) + data, err := ioutil.ReadAll(dResp.Body) + defer func() { + err = dResp.Body.Close() + _require.NoError(err) + }() - rangeList2, err := destFClient.GetRangeList(context.Background(), nil) - _require.NoError(err) - _require.NotNil(rangeList2.RequestID) -}*/ + _require.EqualValues(data, content) +} func (f *FileUnrecordedTestsSuite) TestFileUploadBuffer() { _require := require.New(f.T()) @@ -3108,6 +3117,4 @@ func (f *FileRecordedTestsSuite) TestFileForceCloseHandlesDefault() { _require.Nil(resp.Marker) } -// TODO: Add tests for GetRangeList, ListHandles and ForceCloseHandles - // TODO: Add tests for retry header options diff --git a/sdk/storage/azfile/file/models.go b/sdk/storage/azfile/file/models.go index ea5b7e20c333..4b8c528971ef 100644 --- a/sdk/storage/azfile/file/models.go +++ b/sdk/storage/azfile/file/models.go @@ -199,7 +199,6 @@ type StartCopyFromURLOptions struct { LeaseAccessConditions *LeaseAccessConditions } -// TODO: discuss on the types of FileAttributes, FileCreationTime and FileLastWriteTime in CopyFileSMBInfo. func (o *StartCopyFromURLOptions) format() (*generated.FileClientStartCopyOptions, *generated.CopyFileSMBInfo, *generated.LeaseAccessConditions) { if o == nil { return nil, nil, nil diff --git a/sdk/storage/azfile/go.mod b/sdk/storage/azfile/go.mod index 943df24d78fc..cbd96fa64efc 100644 --- a/sdk/storage/azfile/go.mod +++ b/sdk/storage/azfile/go.mod @@ -6,7 +6,8 @@ require ( github.com/Azure/azure-sdk-for-go/sdk/azcore v1.4.0 github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.2 github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 - github.com/stretchr/testify v1.7.0 + github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.0.0 + github.com/stretchr/testify v1.7.1 ) require ( diff --git a/sdk/storage/azfile/go.sum b/sdk/storage/azfile/go.sum index 33b86c891fa5..8f03fb9639d6 100644 --- a/sdk/storage/azfile/go.sum +++ b/sdk/storage/azfile/go.sum @@ -4,6 +4,8 @@ github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.2 h1:uqM+VoHjVH6zdlkLF2b6O github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.2/go.mod h1:twTKAa1E6hLmSDjLhaCkbTMQKc7p/rNLU40rLxGEOCI= github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 h1:sXr+ck84g/ZlZUOZiNELInmMgOsuGwdjjVkEIde0OtY= github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0/go.mod h1:okt5dMMTOFjX/aovMlrjvvXoPMBVSPzk9185BT0+eZM= +github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.0.0 h1:u/LLAOFgsMv7HmNL4Qufg58y+qElGOt5qv0z1mURkRY= +github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.0.0/go.mod h1:2e8rMJtl2+2j+HXbTBwnyGpm5Nou7KhvSfxOq8JpTag= github.com/AzureAD/microsoft-authentication-library-for-go v0.9.0 h1:UE9n9rkJF62ArLb1F3DEjRt8O3jLwMWdSoypKV4f3MU= github.com/AzureAD/microsoft-authentication-library-for-go v0.9.0/go.mod h1:kgDmCTgBzIEPFElEF+FK0SdjAor06dRq2Go927dnQ6o= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -23,8 +25,8 @@ github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzL github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= diff --git a/sdk/storage/azfile/internal/testcommon/clients_auth.go b/sdk/storage/azfile/internal/testcommon/clients_auth.go index 525a0e081aac..8e2e562116f0 100644 --- a/sdk/storage/azfile/internal/testcommon/clients_auth.go +++ b/sdk/storage/azfile/internal/testcommon/clients_auth.go @@ -12,8 +12,10 @@ import ( "errors" "fmt" "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" "github.com/Azure/azure-sdk-for-go/sdk/azcore/streaming" "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/azidentity" "github.com/Azure/azure-sdk-for-go/sdk/internal/recording" "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/directory" "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/file" @@ -22,6 +24,7 @@ import ( "github.com/stretchr/testify/require" "strings" "testing" + "time" ) type TestAccountType string @@ -44,6 +47,7 @@ const ( const ( FakeStorageAccount = "fakestorage" FakeStorageURL = "https://fakestorage.file.core.windows.net" + FakeToken = "faketoken" ) const ( @@ -125,6 +129,20 @@ func GetGenericConnectionString(accountType TestAccountType) (*string, error) { return &connectionString, nil } +type FakeCredential struct { +} + +func (c *FakeCredential) GetToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) { + return azcore.AccessToken{Token: FakeToken, ExpiresOn: time.Now().Add(time.Hour).UTC()}, nil +} + +func GetGenericTokenCredential() (azcore.TokenCredential, error) { + if recording.GetRecordMode() == recording.PlaybackMode { + return &FakeCredential{}, nil + } + return azidentity.NewDefaultAzureCredential(nil) +} + func GetServiceClientFromConnectionString(t *testing.T, accountType TestAccountType, options *service.ClientOptions) (*service.Client, error) { if options == nil { options = &service.ClientOptions{} diff --git a/sdk/storage/azfile/internal/testcommon/common.go b/sdk/storage/azfile/internal/testcommon/common.go index e83f8d00114d..11e61800da79 100644 --- a/sdk/storage/azfile/internal/testcommon/common.go +++ b/sdk/storage/azfile/internal/testcommon/common.go @@ -96,8 +96,11 @@ func GetRequiredEnv(name string) (string, error) { func BeforeTest(t *testing.T, suite string, test string) { const urlRegex = `https://\S+\.file\.core\.windows\.net` + const tokenRegex = `(?:Bearer\s).*` + require.NoError(t, recording.AddURISanitizer(FakeStorageURL, urlRegex, nil)) require.NoError(t, recording.AddHeaderRegexSanitizer("x-ms-copy-source", FakeStorageURL, urlRegex, nil)) + require.NoError(t, recording.AddHeaderRegexSanitizer("x-ms-copy-source-authorization", FakeToken, tokenRegex, nil)) // we freeze request IDs and timestamps to avoid creating noisy diffs // NOTE: we can't freeze time stamps as that breaks some tests that use if-modified-since etc (maybe it can be fixed?) //testframework.AddHeaderRegexSanitizer("X-Ms-Date", "Wed, 10 Aug 2022 23:34:14 GMT", "", nil) diff --git a/sdk/storage/azfile/lease/models.go b/sdk/storage/azfile/lease/models.go index e42ccc2b95b9..0de250f8aeb4 100644 --- a/sdk/storage/azfile/lease/models.go +++ b/sdk/storage/azfile/lease/models.go @@ -83,7 +83,6 @@ type ShareBreakOptions struct { // header does not appear with a break operation, a fixed-duration lease breaks after the remaining lease period elapses, // and an infinite lease breaks immediately. BreakPeriod *int32 - // TODO: Should snapshot be removed from the option bag // The snapshot parameter is an opaque DateTime value that, when present, specifies the share snapshot to query. ShareSnapshot *string // AccessConditions contains optional parameters to access leased entity. diff --git a/sdk/storage/azfile/share/models.go b/sdk/storage/azfile/share/models.go index 993858734f52..f222d14d0867 100644 --- a/sdk/storage/azfile/share/models.go +++ b/sdk/storage/azfile/share/models.go @@ -51,7 +51,6 @@ func (o *CreateOptions) format() *generated.ShareClientCreateOptions { type DeleteOptions struct { // Specifies the option include to delete the base share and all of its snapshots. DeleteSnapshots *DeleteSnapshotsOptionType - // TODO: Should snapshot be removed from the option bag // The snapshot parameter is an opaque DateTime value that, when present, specifies the share snapshot to query. ShareSnapshot *string // LeaseAccessConditions contains optional parameters to access leased entity. @@ -83,7 +82,6 @@ type RestoreOptions struct { // GetPropertiesOptions contains the optional parameters for the Client.GetProperties method. type GetPropertiesOptions struct { - // TODO: Should snapshot be removed from the option bag // The snapshot parameter is an opaque DateTime value that, when present, specifies the share snapshot to query. ShareSnapshot *string // LeaseAccessConditions contains optional parameters to access leased entity. From b8d50b2da743590e7f3d8207fc0667dfba0b21f9 Mon Sep 17 00:00:00 2001 From: Sourav Gupta Date: Fri, 28 Apr 2023 18:30:47 +0530 Subject: [PATCH 6/8] fix pipeline failures --- sdk/storage/azfile/README.md | 6 +++--- sdk/storage/azfile/file/client_test.go | 17 +++-------------- 2 files changed, 6 insertions(+), 17 deletions(-) diff --git a/sdk/storage/azfile/README.md b/sdk/storage/azfile/README.md index 2b6ba2b9a02e..013c2d022248 100644 --- a/sdk/storage/azfile/README.md +++ b/sdk/storage/azfile/README.md @@ -245,7 +245,7 @@ or contact [opencode@microsoft.com][coc_contact] with any additional questions or comments. -[source]: https://github.com/Azure/azure-sdk-for-go/tree/main/sdk/storage/azfile +[source]: https://github.com/Azure/azure-sdk-for-go/tree/main/sdk/storage [docs]: https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/storage/azfile [rest_docs]: https://docs.microsoft.com/rest/api/storageservices/file-service-rest-api [product_docs]: https://docs.microsoft.com/azure/storage/files/storage-files-introduction @@ -257,8 +257,8 @@ additional questions or comments. [storage_account_create_portal]: https://docs.microsoft.com/azure/storage/common/storage-quickstart-create-account?tabs=azure-portal [azure_sub]: https://azure.microsoft.com/free/ [azcore_response_error]: https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azcore#ResponseError -[file_error]: https://github.com/Azure/azure-sdk-for-go/tree/main/sdk/storage/azfile/fileerror/error_codes.go -[samples]: https://github.com/Azure/azure-sdk-for-go/blob/main/sdk/storage/azfile/file/examples_test.go +[file_error]: https://github.com/Azure/azure-sdk-for-go/tree/main/sdk/storage +[samples]: https://github.com/Azure/azure-sdk-for-go/blob/main/sdk/storage [storage_contrib]: https://github.com/Azure/azure-sdk-for-go/blob/main/CONTRIBUTING.md [cla]: https://cla.microsoft.com [coc]: https://opensource.microsoft.com/codeofconduct/ diff --git a/sdk/storage/azfile/file/client_test.go b/sdk/storage/azfile/file/client_test.go index fac6fcec029c..7061d362ecac 100644 --- a/sdk/storage/azfile/file/client_test.go +++ b/sdk/storage/azfile/file/client_test.go @@ -13,13 +13,11 @@ import ( "crypto/rand" "encoding/binary" "fmt" - "github.com/Azure/azure-sdk-for-go/sdk/azcore/log" "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" "github.com/Azure/azure-sdk-for-go/sdk/azcore/streaming" "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" "github.com/Azure/azure-sdk-for-go/sdk/internal/recording" "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob" - "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile" "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/file" "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/fileerror" "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/shared" @@ -2833,22 +2831,13 @@ func (f *FileRecordedTestsSuite) TestFileUploadDownloadSmallBuffer() { _require := require.New(f.T()) testName := f.T().Name() - var fileSize int64 = 10 * 1024 - listenerCalled := false - log.SetEvents(azfile.EventUpload, log.EventRequest, log.EventResponse) - log.SetListener(func(cls log.Event, msg string) { - if cls == azfile.EventUpload { - listenerCalled = true - _require.Equal(msg, fmt.Sprintf("file name %v actual size %v chunk-size 2048 chunk-count 5", testcommon.GenerateFileName(testName), fileSize)) - } - }) - svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) _require.NoError(err) shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) defer testcommon.DeleteShare(context.Background(), _require, shareClient) + var fileSize int64 = 10 * 1024 fClient := shareClient.NewRootDirectoryClient().NewFileClient(testcommon.GenerateFileName(testName)) _, err = fClient.Create(context.Background(), fileSize, nil) _require.NoError(err) @@ -2889,8 +2878,6 @@ func (f *FileRecordedTestsSuite) TestFileUploadDownloadSmallBuffer() { _require.Len(rangeList.Ranges, 1) _require.Equal(*rangeList.Ranges[0].Start, int64(0)) _require.Equal(*rangeList.Ranges[0].End, fileSize-1) - - _require.True(listenerCalled) } func (f *FileRecordedTestsSuite) TestFileUploadDownloadSmallFile() { @@ -3131,3 +3118,5 @@ func (f *FileRecordedTestsSuite) TestFileForceCloseHandlesDefault() { } // TODO: Add tests for retry header options + +// TODO: fix links in README: source, file_error, samples From a0fc25107c80982c2e7f2a6252e4c39c84226849 Mon Sep 17 00:00:00 2001 From: Sourav Gupta Date: Fri, 28 Apr 2023 18:52:06 +0530 Subject: [PATCH 7/8] Small fix --- sdk/storage/azfile/file/client_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/storage/azfile/file/client_test.go b/sdk/storage/azfile/file/client_test.go index 7061d362ecac..e498b9d66e65 100644 --- a/sdk/storage/azfile/file/client_test.go +++ b/sdk/storage/azfile/file/client_test.go @@ -1794,7 +1794,7 @@ func (f *FileRecordedTestsSuite) TestFileUploadRangeFromURLOffsetNegative() { _require.Equal(err.Error(), "invalid argument: source and destination offsets must be >= 0") } -func (f *FileRecordedTestsSuite) TestFileUploadRangeFromURLCopySourceAuthBlob() { +func (f *FileUnrecordedTestsSuite) TestFileUploadRangeFromURLCopySourceAuthBlob() { _require := require.New(f.T()) testName := f.T().Name() From 1b1b10c680b3d76e14e79a9a841202e3bd54b009 Mon Sep 17 00:00:00 2001 From: Sourav Gupta Date: Wed, 3 May 2023 10:42:02 +0530 Subject: [PATCH 8/8] err handling --- sdk/storage/azfile/file/mmf_windows.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sdk/storage/azfile/file/mmf_windows.go b/sdk/storage/azfile/file/mmf_windows.go index 4ae12b639842..b59e6b415776 100644 --- a/sdk/storage/azfile/file/mmf_windows.go +++ b/sdk/storage/azfile/file/mmf_windows.go @@ -26,7 +26,9 @@ func newMMB(size int64) (mmb, error) { if err != nil { return nil, os.NewSyscallError("CreateFileMapping", err) } - defer syscall.CloseHandle(hMMF) + defer func() { + _ = syscall.CloseHandle(hMMF) + }() addr, err := syscall.MapViewOfFile(hMMF, access, 0, 0, uintptr(size)) if err != nil {