refine impl of rename file/directory (#1991)

* fix bug: / was left out in rename source

* refine impl of rename file/directory
This commit is contained in:
JinmingHu 2021-03-30 11:58:33 +08:00 committed by GitHub
parent 88499ab1b6
commit b9c5c978ee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 363 additions and 242 deletions

View File

@ -16,6 +16,7 @@
#include "azure/storage/blobs/protocol/blob_rest_client.hpp"
namespace Azure { namespace Storage { namespace Files { namespace DataLake {
class DataLakeFileSystemClient;
class DataLakeDirectoryClient;
class DataLakeFileClient;
}}}} // namespace Azure::Storage::Files::DataLake
@ -353,8 +354,8 @@ namespace Azure { namespace Storage { namespace Blobs {
explicit BlobClient(
Azure::Core::Url blobUrl,
std::shared_ptr<Azure::Core::Http::_internal::HttpPipeline> pipeline,
Azure::Nullable<EncryptionKey> customerProvidedKey,
Azure::Nullable<std::string> encryptionScope)
Azure::Nullable<EncryptionKey> customerProvidedKey = Azure::Nullable<EncryptionKey>(),
Azure::Nullable<std::string> encryptionScope = Azure::Nullable<std::string>())
: m_blobUrl(std::move(blobUrl)), m_pipeline(std::move(pipeline)),
m_customerProvidedKey(std::move(customerProvidedKey)),
m_encryptionScope(std::move(encryptionScope))
@ -362,6 +363,7 @@ namespace Azure { namespace Storage { namespace Blobs {
}
friend class BlobContainerClient;
friend class Files::DataLake::DataLakeFileSystemClient;
friend class Files::DataLake::DataLakeDirectoryClient;
friend class Files::DataLake::DataLakeFileClient;
friend class BlobLeaseClient;

View File

@ -12,8 +12,16 @@
namespace Azure { namespace Storage { namespace Files { namespace DataLake { namespace _detail {
std::string GetBlobUrlFromUrl(const std::string& url);
std::string GetDfsUrlFromUrl(const std::string& url);
Azure::Core::Url GetBlobUrlFromUrl(const Azure::Core::Url& url);
Azure::Core::Url GetDfsUrlFromUrl(const Azure::Core::Url& url);
inline std::string GetBlobUrlFromUrl(const std::string& url)
{
return GetBlobUrlFromUrl(Azure::Core::Url(url)).GetAbsoluteUrl();
}
inline std::string GetDfsUrlFromUrl(const std::string& url)
{
return GetDfsUrlFromUrl(Azure::Core::Url(url)).GetAbsoluteUrl();
}
std::string SerializeMetadata(const Storage::Metadata& dataLakePropertiesMap);

View File

@ -86,16 +86,23 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake {
const RenameFileOptions& options,
const Azure::Core::Context& context) const
{
Azure::Nullable<std::string> destinationFileSystem = options.DestinationFileSystem;
if (!destinationFileSystem.HasValue() || destinationFileSystem.GetValue().empty())
std::string destinationFileSystem;
if (options.DestinationFileSystem.HasValue())
{
const auto& currentPath = m_pathUrl.GetPath();
std::string::const_iterator cur = currentPath.begin();
destinationFileSystem = _detail::GetSubstringTillDelimiter('/', currentPath, cur);
destinationFileSystem = options.DestinationFileSystem.GetValue();
}
else
{
const std::string& currentPath = m_pathUrl.GetPath();
destinationFileSystem = currentPath.substr(0, currentPath.find('/'));
}
auto sourceDfsUrl = m_pathUrl;
sourceDfsUrl.AppendPath(_internal::UrlEncodePath(fileName));
auto destinationDfsUrl = m_pathUrl;
destinationDfsUrl.SetPath(
destinationFileSystem.GetValue() + '/' + _internal::UrlEncodePath(destinationFilePath));
destinationDfsUrl.SetPath(_internal::UrlEncodePath(destinationFileSystem));
destinationDfsUrl.AppendPath(_internal::UrlEncodePath(destinationFilePath));
_detail::DataLakeRestClient::Path::CreateOptions protocolLayerOptions;
protocolLayerOptions.Mode = _detail::PathRenameMode::Legacy;
@ -109,16 +116,14 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake {
protocolLayerOptions.SourceIfNoneMatch = options.SourceAccessConditions.IfNoneMatch;
protocolLayerOptions.SourceIfModifiedSince = options.SourceAccessConditions.IfModifiedSince;
protocolLayerOptions.SourceIfUnmodifiedSince = options.SourceAccessConditions.IfUnmodifiedSince;
protocolLayerOptions.RenameSource
= "/" + m_pathUrl.GetPath() + _internal::UrlEncodePath(fileName);
protocolLayerOptions.RenameSource = "/" + sourceDfsUrl.GetPath();
auto result = _detail::DataLakeRestClient::Path::Create(
destinationDfsUrl, *m_pipeline, context, protocolLayerOptions);
// At this point, there is not more exception thrown, meaning the rename is successful.
// Initialize the file client.
auto blobClient = m_blobClient;
blobClient.m_blobUrl.SetPath(destinationDfsUrl.GetPath());
auto renamedFileClient
= DataLakeFileClient(std::move(destinationDfsUrl), std::move(blobClient), m_pipeline);
auto renamedBlobClient
= Blobs::BlobClient(_detail::GetBlobUrlFromUrl(destinationDfsUrl), m_pipeline);
auto renamedFileClient = DataLakeFileClient(
std::move(destinationDfsUrl), std::move(renamedBlobClient), m_pipeline);
return Azure::Response<DataLakeFileClient>(
std::move(renamedFileClient), result.ExtractRawResponse());
}
@ -129,17 +134,23 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake {
const RenameSubdirectoryOptions& options,
const Azure::Core::Context& context) const
{
Azure::Nullable<std::string> destinationFileSystem = options.DestinationFileSystem;
if (!destinationFileSystem.HasValue() || destinationFileSystem.GetValue().empty())
std::string destinationFileSystem;
if (options.DestinationFileSystem.HasValue())
{
const auto& currentPath = m_pathUrl.GetPath();
std::string::const_iterator cur = currentPath.begin();
destinationFileSystem = _detail::GetSubstringTillDelimiter('/', currentPath, cur);
destinationFileSystem = options.DestinationFileSystem.GetValue();
}
else
{
const std::string& currentPath = m_pathUrl.GetPath();
destinationFileSystem = currentPath.substr(0, currentPath.find('/'));
}
auto sourceDfsUrl = m_pathUrl;
sourceDfsUrl.AppendPath(_internal::UrlEncodePath(subdirectoryName));
auto destinationDfsUrl = m_pathUrl;
destinationDfsUrl.SetPath(
destinationFileSystem.GetValue() + '/'
+ _internal::UrlEncodePath(destinationDirectoryPath));
destinationDfsUrl.SetPath(_internal::UrlEncodePath(destinationFileSystem));
destinationDfsUrl.AppendPath(_internal::UrlEncodePath(destinationDirectoryPath));
_detail::DataLakeRestClient::Path::CreateOptions protocolLayerOptions;
protocolLayerOptions.Mode = _detail::PathRenameMode::Legacy;
@ -153,16 +164,14 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake {
protocolLayerOptions.SourceIfNoneMatch = options.SourceAccessConditions.IfNoneMatch;
protocolLayerOptions.SourceIfModifiedSince = options.SourceAccessConditions.IfModifiedSince;
protocolLayerOptions.SourceIfUnmodifiedSince = options.SourceAccessConditions.IfUnmodifiedSince;
protocolLayerOptions.RenameSource
= "/" + m_pathUrl.GetPath() + _internal::UrlEncodePath(subdirectoryName);
protocolLayerOptions.RenameSource = "/" + sourceDfsUrl.GetPath();
auto result = _detail::DataLakeRestClient::Path::Create(
destinationDfsUrl, *m_pipeline, context, protocolLayerOptions);
// At this point, there is not more exception thrown, meaning the rename is successful.
// Initialize the directory client.
auto blobClient = m_blobClient;
blobClient.m_blobUrl.SetPath(destinationDfsUrl.GetPath());
auto renamedDirectoryClient
= DataLakeDirectoryClient(std::move(destinationDfsUrl), std::move(blobClient), m_pipeline);
auto renamedBlobClient
= Blobs::BlobClient(_detail::GetBlobUrlFromUrl(destinationDfsUrl), m_pipeline);
auto renamedDirectoryClient = DataLakeDirectoryClient(
std::move(destinationDfsUrl), std::move(renamedBlobClient), m_pipeline);
return Azure::Response<DataLakeDirectoryClient>(
std::move(renamedDirectoryClient), result.ExtractRawResponse());
}

View File

@ -347,7 +347,46 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake {
const RenameFileOptions& options,
const Azure::Core::Context& context) const
{
return this->GetDirectoryClient("").RenameFile(fileName, destinationFilePath, options, context);
std::string destinationFileSystem;
if (options.DestinationFileSystem.HasValue())
{
destinationFileSystem = options.DestinationFileSystem.GetValue();
}
else
{
const std::string& currentPath = m_fileSystemUrl.GetPath();
destinationFileSystem = currentPath.substr(0, currentPath.find('/'));
}
auto sourceDfsUrl = m_fileSystemUrl;
sourceDfsUrl.AppendPath(_internal::UrlEncodePath(fileName));
auto destinationDfsUrl = m_fileSystemUrl;
destinationDfsUrl.SetPath(_internal::UrlEncodePath(destinationFileSystem));
destinationDfsUrl.AppendPath(_internal::UrlEncodePath(destinationFilePath));
_detail::DataLakeRestClient::Path::CreateOptions protocolLayerOptions;
protocolLayerOptions.Mode = _detail::PathRenameMode::Legacy;
protocolLayerOptions.SourceLeaseId = options.SourceAccessConditions.LeaseId;
protocolLayerOptions.LeaseIdOptional = options.AccessConditions.LeaseId;
protocolLayerOptions.IfMatch = options.AccessConditions.IfMatch;
protocolLayerOptions.IfNoneMatch = options.AccessConditions.IfNoneMatch;
protocolLayerOptions.IfModifiedSince = options.AccessConditions.IfModifiedSince;
protocolLayerOptions.IfUnmodifiedSince = options.AccessConditions.IfUnmodifiedSince;
protocolLayerOptions.SourceIfMatch = options.SourceAccessConditions.IfMatch;
protocolLayerOptions.SourceIfNoneMatch = options.SourceAccessConditions.IfNoneMatch;
protocolLayerOptions.SourceIfModifiedSince = options.SourceAccessConditions.IfModifiedSince;
protocolLayerOptions.SourceIfUnmodifiedSince = options.SourceAccessConditions.IfUnmodifiedSince;
protocolLayerOptions.RenameSource = "/" + sourceDfsUrl.GetPath();
auto result = _detail::DataLakeRestClient::Path::Create(
destinationDfsUrl, *m_pipeline, context, protocolLayerOptions);
auto renamedBlobClient
= Blobs::BlobClient(_detail::GetBlobUrlFromUrl(destinationDfsUrl), m_pipeline);
auto renamedFileClient = DataLakeFileClient(
std::move(destinationDfsUrl), std::move(renamedBlobClient), m_pipeline);
return Azure::Response<DataLakeFileClient>(
std::move(renamedFileClient), result.ExtractRawResponse());
}
Azure::Response<DataLakeDirectoryClient> DataLakeFileSystemClient::RenameDirectory(
@ -356,8 +395,46 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake {
const RenameDirectoryOptions& options,
const Azure::Core::Context& context) const
{
return this->GetDirectoryClient("").RenameSubdirectory(
directoryName, destinationDirectoryPath, options, context);
std::string destinationFileSystem;
if (options.DestinationFileSystem.HasValue())
{
destinationFileSystem = options.DestinationFileSystem.GetValue();
}
else
{
const std::string& currentPath = m_fileSystemUrl.GetPath();
destinationFileSystem = currentPath.substr(0, currentPath.find('/'));
}
auto sourceDfsUrl = m_fileSystemUrl;
sourceDfsUrl.AppendPath(_internal::UrlEncodePath(directoryName));
auto destinationDfsUrl = m_fileSystemUrl;
destinationDfsUrl.SetPath(_internal::UrlEncodePath(destinationFileSystem));
destinationDfsUrl.AppendPath(_internal::UrlEncodePath(destinationDirectoryPath));
_detail::DataLakeRestClient::Path::CreateOptions protocolLayerOptions;
protocolLayerOptions.Mode = _detail::PathRenameMode::Legacy;
protocolLayerOptions.SourceLeaseId = options.SourceAccessConditions.LeaseId;
protocolLayerOptions.LeaseIdOptional = options.AccessConditions.LeaseId;
protocolLayerOptions.IfMatch = options.AccessConditions.IfMatch;
protocolLayerOptions.IfNoneMatch = options.AccessConditions.IfNoneMatch;
protocolLayerOptions.IfModifiedSince = options.AccessConditions.IfModifiedSince;
protocolLayerOptions.IfUnmodifiedSince = options.AccessConditions.IfUnmodifiedSince;
protocolLayerOptions.SourceIfMatch = options.SourceAccessConditions.IfMatch;
protocolLayerOptions.SourceIfNoneMatch = options.SourceAccessConditions.IfNoneMatch;
protocolLayerOptions.SourceIfModifiedSince = options.SourceAccessConditions.IfModifiedSince;
protocolLayerOptions.SourceIfUnmodifiedSince = options.SourceAccessConditions.IfUnmodifiedSince;
protocolLayerOptions.RenameSource = "/" + sourceDfsUrl.GetPath();
auto result = _detail::DataLakeRestClient::Path::Create(
destinationDfsUrl, *m_pipeline, context, protocolLayerOptions);
auto renamedBlobClient
= Blobs::BlobClient(_detail::GetBlobUrlFromUrl(destinationDfsUrl), m_pipeline);
auto renamedDirectoryClient = DataLakeDirectoryClient(
std::move(destinationDfsUrl), std::move(renamedBlobClient), m_pipeline);
return Azure::Response<DataLakeDirectoryClient>(
std::move(renamedDirectoryClient), result.ExtractRawResponse());
}
}}}} // namespace Azure::Storage::Files::DataLake

View File

@ -13,25 +13,31 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { nam
const static std::string DfsEndPointIdentifier = ".dfs.";
const static std::string BlobEndPointIdentifier = ".blob.";
std::string GetBlobUrlFromUrl(const std::string& url)
Azure::Core::Url GetBlobUrlFromUrl(const Azure::Core::Url& url)
{
std::string result = url;
auto pos = result.find(DfsEndPointIdentifier);
if (pos != std::string::npos)
std::string host = url.GetHost();
auto pos = host.rfind(DfsEndPointIdentifier);
if (pos == std::string::npos)
{
result.replace(pos, DfsEndPointIdentifier.size(), BlobEndPointIdentifier);
return url;
}
host.replace(pos, DfsEndPointIdentifier.size(), BlobEndPointIdentifier);
Azure::Core::Url result = url;
result.SetHost(host);
return result;
}
std::string GetDfsUrlFromUrl(const std::string& url)
Azure::Core::Url GetDfsUrlFromUrl(const Azure::Core::Url& url)
{
std::string result = url;
auto pos = result.find(BlobEndPointIdentifier);
if (pos != std::string::npos)
std::string host = url.GetHost();
auto pos = host.rfind(BlobEndPointIdentifier);
if (pos == std::string::npos)
{
result.replace(pos, BlobEndPointIdentifier.size(), DfsEndPointIdentifier);
return url;
}
host.replace(pos, BlobEndPointIdentifier.size(), DfsEndPointIdentifier);
Azure::Core::Url result = url;
result.SetHost(host);
return result;
}

View File

@ -131,114 +131,146 @@ namespace Azure { namespace Storage { namespace Test {
}
}
TEST_F(DataLakeDirectoryClientTest, RenameFile)
{
const std::string baseDirectoryName = RandomString();
auto baseDirectoryClient = m_fileSystemClient->GetDirectoryClient(baseDirectoryName);
baseDirectoryClient.Create();
const std::string oldFilename = RandomString();
auto oldFileClient = baseDirectoryClient.GetSubdirectoryClient(oldFilename);
oldFileClient.Create();
const std::string newFilename = RandomString();
auto newFileClient
= *baseDirectoryClient.RenameFile(oldFilename, baseDirectoryName + "/" + newFilename);
EXPECT_NO_THROW(newFileClient.GetProperties());
EXPECT_NO_THROW(baseDirectoryClient.GetSubdirectoryClient(newFilename).GetProperties());
EXPECT_THROW(oldFileClient.GetProperties(), StorageException);
const std::string newFileSystemName = LowercaseRandomString();
const std::string newFilename2 = RandomString();
auto newFileSystem = m_dataLakeServiceClient->GetFileSystemClient(newFileSystemName);
newFileSystem.Create();
Files::DataLake::RenameFileOptions options;
options.DestinationFileSystem = newFileSystemName;
auto newFileClient2 = *baseDirectoryClient.RenameFile(newFilename, newFilename2, options);
EXPECT_NO_THROW(newFileClient2.GetProperties());
EXPECT_NO_THROW(newFileSystem.GetFileClient(newFilename2).GetProperties());
newFileSystem.Delete();
EXPECT_THROW(newFileClient.GetProperties(), StorageException);
}
TEST_F(DataLakeDirectoryClientTest, RenameFileAccessCondition)
{
const std::string baseDirectoryName = RandomString();
auto baseDirectoryClient = m_fileSystemClient->GetDirectoryClient(baseDirectoryName);
baseDirectoryClient.Create();
const std::string oldFilename = RandomString();
auto oldFileClient = baseDirectoryClient.GetSubdirectoryClient(oldFilename);
oldFileClient.Create();
const std::string newFilename = RandomString();
Files::DataLake::RenameFileOptions options;
options.SourceAccessConditions.IfModifiedSince = oldFileClient.GetProperties()->LastModified;
EXPECT_THROW(
baseDirectoryClient.RenameFile(oldFilename, newFilename, options), StorageException);
options = Files::DataLake::RenameFileOptions();
options.SourceAccessConditions.IfUnmodifiedSince
= oldFileClient.GetProperties()->LastModified - std::chrono::minutes(5);
EXPECT_THROW(
baseDirectoryClient.RenameFile(oldFilename, newFilename, options), StorageException);
options = Files::DataLake::RenameFileOptions();
options.SourceAccessConditions.IfMatch = DummyETag;
EXPECT_THROW(
baseDirectoryClient.RenameFile(oldFilename, newFilename, options), StorageException);
options = Files::DataLake::RenameFileOptions();
options.SourceAccessConditions.IfNoneMatch = oldFileClient.GetProperties()->ETag;
EXPECT_THROW(
baseDirectoryClient.RenameFile(oldFilename, newFilename, options), StorageException);
}
TEST_F(DataLakeDirectoryClientTest, RenameDirectory)
{
{
// Normal create/rename/delete.
std::vector<Files::DataLake::DataLakeDirectoryClient> directoryClients;
for (int32_t i = 0; i < 5; ++i)
{
auto client = m_fileSystemClient->GetDirectoryClient(RandomString());
EXPECT_NO_THROW(client.Create());
directoryClients.emplace_back(std::move(client));
}
std::vector<Files::DataLake::DataLakeDirectoryClient> newDirectoryClients;
for (auto& client : directoryClients)
{
auto newPath = RandomString();
EXPECT_NO_THROW(newDirectoryClients.emplace_back(
client.RenameSubdirectory("", newPath).ExtractValue()));
}
for (const auto& client : directoryClients)
{
EXPECT_THROW(client.DeleteEmpty(), StorageException);
}
for (const auto& client : newDirectoryClients)
{
EXPECT_NO_THROW(client.DeleteEmpty());
}
}
{
// Normal rename with last modified access condition.
std::vector<Files::DataLake::DataLakeDirectoryClient> directoryClient;
for (int32_t i = 0; i < 2; ++i)
{
auto client = m_fileSystemClient->GetDirectoryClient(RandomString());
EXPECT_NO_THROW(client.Create());
directoryClient.emplace_back(std::move(client));
}
for (auto& client : directoryClient)
{
auto response = client.GetProperties();
Files::DataLake::RenameDirectoryOptions options1;
options1.SourceAccessConditions.IfModifiedSince = response->LastModified;
EXPECT_TRUE(IsValidTime(response->LastModified));
EXPECT_THROW(client.RenameSubdirectory("", RandomString(), options1), StorageException);
Files::DataLake::RenameDirectoryOptions options2;
options2.SourceAccessConditions.IfUnmodifiedSince = response->LastModified;
auto newPath = RandomString();
EXPECT_NO_THROW(
client.RenameSubdirectory("", newPath, options2).ExtractValue().DeleteEmpty());
}
}
{
// Normal rename with if match access condition.
std::vector<Files::DataLake::DataLakeDirectoryClient> directoryClient;
for (int32_t i = 0; i < 2; ++i)
{
auto client = m_fileSystemClient->GetDirectoryClient(RandomString());
EXPECT_NO_THROW(client.Create());
directoryClient.emplace_back(std::move(client));
}
for (auto& client : directoryClient)
{
auto response = client.GetProperties();
Files::DataLake::RenameDirectoryOptions options1;
options1.SourceAccessConditions.IfNoneMatch = response->ETag;
EXPECT_THROW(client.RenameSubdirectory("", RandomString(), options1), StorageException);
Files::DataLake::RenameDirectoryOptions options2;
options2.SourceAccessConditions.IfMatch = response->ETag;
auto newPath = RandomString();
EXPECT_NO_THROW(
client.RenameSubdirectory("", newPath, options2).ExtractValue().DeleteEmpty());
}
}
{
// Rename to a destination file system.
std::vector<Files::DataLake::DataLakeDirectoryClient> directoryClient;
for (int32_t i = 0; i < 2; ++i)
{
auto client = m_fileSystemClient->GetDirectoryClient(RandomString());
EXPECT_NO_THROW(client.Create());
directoryClient.emplace_back(std::move(client));
}
{
// Rename to a non-existing file system will fail and source is not changed.
Files::DataLake::RenameDirectoryOptions options;
options.DestinationFileSystem = LowercaseRandomString();
for (auto& client : directoryClient)
{
EXPECT_THROW(client.RenameSubdirectory("", RandomString(), options), StorageException);
EXPECT_NO_THROW(client.GetProperties());
}
}
{
// Rename to an existing file system will succeed and changes URI.
auto newfileSystemName = LowercaseRandomString(10);
auto newfileSystemClient = std::make_shared<Files::DataLake::DataLakeFileSystemClient>(
Files::DataLake::DataLakeFileSystemClient::CreateFromConnectionString(
AdlsGen2ConnectionString(), newfileSystemName));
newfileSystemClient->Create();
Files::DataLake::RenameDirectoryOptions options;
options.DestinationFileSystem = newfileSystemName;
for (auto& client : directoryClient)
{
auto newPath = RandomString();
EXPECT_NO_THROW(
client.RenameSubdirectory("", newPath, options).ExtractValue().DeleteEmpty());
}
}
}
const std::string baseDirectoryName = RandomString();
auto baseDirectoryClient = m_fileSystemClient->GetDirectoryClient(baseDirectoryName);
baseDirectoryClient.Create();
const std::string oldDirectoryName = RandomString();
auto oldDirectoryClient = baseDirectoryClient.GetSubdirectoryClient(oldDirectoryName);
oldDirectoryClient.Create();
const std::string newDirectoryName = RandomString();
auto newDirectoryClient = *baseDirectoryClient.RenameSubdirectory(
oldDirectoryName, baseDirectoryName + "/" + newDirectoryName);
EXPECT_NO_THROW(newDirectoryClient.GetProperties());
EXPECT_NO_THROW(baseDirectoryClient.GetSubdirectoryClient(newDirectoryName).GetProperties());
EXPECT_THROW(oldDirectoryClient.GetProperties(), StorageException);
const std::string newFileSystemName = LowercaseRandomString();
const std::string newDirectoryName2 = RandomString();
auto newFileSystem = m_dataLakeServiceClient->GetFileSystemClient(newFileSystemName);
newFileSystem.Create();
Files::DataLake::RenameDirectoryOptions options;
options.DestinationFileSystem = newFileSystemName;
auto newDirectoryClient2
= *baseDirectoryClient.RenameSubdirectory(newDirectoryName, newDirectoryName2, options);
EXPECT_NO_THROW(newDirectoryClient2.GetProperties());
EXPECT_NO_THROW(newFileSystem.GetDirectoryClient(newDirectoryName2).GetProperties());
newFileSystem.Delete();
EXPECT_THROW(newDirectoryClient.GetProperties(), StorageException);
}
TEST_F(DataLakeDirectoryClientTest, RenameDirectoryAccessCondition)
{
const std::string baseDirectoryName = RandomString();
auto baseDirectoryClient = m_fileSystemClient->GetDirectoryClient(baseDirectoryName);
baseDirectoryClient.Create();
const std::string oldDirectoryName = RandomString();
auto oldDirectoryClient = baseDirectoryClient.GetSubdirectoryClient(oldDirectoryName);
oldDirectoryClient.Create();
const std::string newDirectoryName = RandomString();
Files::DataLake::RenameDirectoryOptions options;
options.SourceAccessConditions.IfModifiedSince
= oldDirectoryClient.GetProperties()->LastModified;
EXPECT_THROW(
baseDirectoryClient.RenameSubdirectory(oldDirectoryName, newDirectoryName, options),
StorageException);
options = Files::DataLake::RenameDirectoryOptions();
options.SourceAccessConditions.IfUnmodifiedSince
= oldDirectoryClient.GetProperties()->LastModified - std::chrono::minutes(5);
EXPECT_THROW(
baseDirectoryClient.RenameSubdirectory(oldDirectoryName, newDirectoryName, options),
StorageException);
options = Files::DataLake::RenameDirectoryOptions();
options.SourceAccessConditions.IfMatch = DummyETag;
EXPECT_THROW(
baseDirectoryClient.RenameSubdirectory(oldDirectoryName, newDirectoryName, options),
StorageException);
options = Files::DataLake::RenameDirectoryOptions();
options.SourceAccessConditions.IfNoneMatch = oldDirectoryClient.GetProperties()->ETag;
EXPECT_THROW(
baseDirectoryClient.RenameSubdirectory(oldDirectoryName, newDirectoryName, options),
StorageException);
}
TEST_F(DataLakeDirectoryClientTest, DirectoryMetadata)

View File

@ -130,90 +130,6 @@ namespace Azure { namespace Storage { namespace Test {
}
}
TEST_F(DataLakeFileClientTest, RenameFiles)
{
{
// Normal create/rename/delete.
auto fileName = RandomString();
EXPECT_NO_THROW(m_fileSystemClient->GetFileClient(fileName).Create());
std::shared_ptr<Files::DataLake::DataLakeFileClient> ret;
EXPECT_NO_THROW(
ret = std::make_shared<Files::DataLake::DataLakeFileClient>(
m_fileSystemClient->RenameFile(fileName, RandomString()).ExtractValue()));
EXPECT_THROW(m_fileSystemClient->GetFileClient(fileName).Delete(), StorageException);
EXPECT_NO_THROW(ret->Delete());
}
{
// Normal rename with last modified access condition.
auto fileName = RandomString();
auto fileClient = m_fileSystemClient->GetFileClient(fileName);
EXPECT_NO_THROW(fileClient.Create());
auto response = fileClient.GetProperties();
Files::DataLake::RenameFileOptions options1;
options1.SourceAccessConditions.IfModifiedSince = response->LastModified;
EXPECT_THROW(
m_fileSystemClient->RenameFile(fileName, RandomString(), options1), StorageException);
Files::DataLake::RenameFileOptions options2;
options2.SourceAccessConditions.IfUnmodifiedSince = response->LastModified;
std::shared_ptr<Files::DataLake::DataLakeFileClient> ret;
EXPECT_NO_THROW(
ret = std::make_shared<Files::DataLake::DataLakeFileClient>(
m_fileSystemClient->RenameFile(fileName, RandomString(), options2).ExtractValue()));
EXPECT_THROW(m_fileSystemClient->GetFileClient(fileName).Delete(), StorageException);
EXPECT_NO_THROW(ret->Delete());
}
{
// Normal rename with if match access condition.
auto fileName = RandomString();
auto fileClient = m_fileSystemClient->GetFileClient(fileName);
EXPECT_NO_THROW(fileClient.Create());
auto response = fileClient.GetProperties();
Files::DataLake::RenameFileOptions options1;
options1.SourceAccessConditions.IfNoneMatch = response->ETag;
EXPECT_THROW(
m_fileSystemClient->RenameFile(fileName, RandomString(), options1), StorageException);
Files::DataLake::RenameFileOptions options2;
options2.SourceAccessConditions.IfMatch = response->ETag;
std::shared_ptr<Files::DataLake::DataLakeFileClient> ret;
EXPECT_NO_THROW(
ret = std::make_shared<Files::DataLake::DataLakeFileClient>(
m_fileSystemClient->RenameFile(fileName, RandomString(), options2).ExtractValue()));
EXPECT_THROW(m_fileSystemClient->GetFileClient(fileName).Delete(), StorageException);
EXPECT_THROW(fileClient.GetProperties(), StorageException);
EXPECT_NO_THROW(ret->Delete());
}
{
// Rename to a destination file system.
auto fileName = RandomString();
auto fileClient = m_fileSystemClient->GetFileClient(fileName);
EXPECT_NO_THROW(fileClient.Create());
{
// Rename to a non-existing file system will fail but will not change URI.
Files::DataLake::RenameFileOptions options;
options.DestinationFileSystem = LowercaseRandomString();
EXPECT_THROW(
m_fileSystemClient->RenameFile(fileName, RandomString(), options), StorageException);
EXPECT_NO_THROW(fileClient.GetProperties());
}
{
// Rename to an existing file system will succeed and changes URI.
auto newfileSystemName = LowercaseRandomString(10);
auto newfileSystemClient = std::make_shared<Files::DataLake::DataLakeFileSystemClient>(
Files::DataLake::DataLakeFileSystemClient::CreateFromConnectionString(
AdlsGen2ConnectionString(), newfileSystemName));
newfileSystemClient->Create();
Files::DataLake::RenameFileOptions options;
options.DestinationFileSystem = newfileSystemName;
std::shared_ptr<Files::DataLake::DataLakeFileClient> ret;
EXPECT_NO_THROW(
ret = std::make_shared<Files::DataLake::DataLakeFileClient>(
m_fileSystemClient->RenameFile(fileName, RandomString(), options).ExtractValue()));
EXPECT_THROW(fileClient.GetProperties(), StorageException);
EXPECT_NO_THROW(ret->Delete());
}
}
}
TEST_F(DataLakeFileClientTest, FileMetadata)
{
auto metadata1 = RandomMetadata();

View File

@ -23,10 +23,11 @@ namespace Azure { namespace Storage { namespace Test {
void DataLakeFileSystemClientTest::SetUpTestSuite()
{
DataLakeServiceClientTest::SetUpTestSuite();
m_fileSystemName = LowercaseRandomString();
m_fileSystemClient = std::make_shared<Files::DataLake::DataLakeFileSystemClient>(
Files::DataLake::DataLakeFileSystemClient::CreateFromConnectionString(
AdlsGen2ConnectionString(), m_fileSystemName));
m_dataLakeServiceClient->GetFileSystemClient(m_fileSystemName));
m_fileSystemClient->Create();
m_directoryA = LowercaseRandomString();
@ -48,7 +49,11 @@ namespace Azure { namespace Storage { namespace Test {
}
}
void DataLakeFileSystemClientTest::TearDownTestSuite() { m_fileSystemClient->Delete(); }
void DataLakeFileSystemClientTest::TearDownTestSuite()
{
m_fileSystemClient->Delete();
DataLakeServiceClientTest::TearDownTestSuite();
}
std::vector<Files::DataLake::Models::PathItem> DataLakeFileSystemClientTest::ListAllPaths(
bool recursive,
@ -439,4 +444,69 @@ namespace Azure { namespace Storage { namespace Test {
EXPECT_EQ(Files::DataLake::Models::PublicAccessType::Path, ret->AccessType);
}
}
TEST_F(DataLakeFileSystemClientTest, RenameFile)
{
const std::string oldFilename = RandomString();
const std::string newFilename = RandomString();
auto oldFileClient = m_fileSystemClient->GetFileClient(oldFilename);
oldFileClient.Create();
auto newFileClient = *m_fileSystemClient->RenameFile(oldFilename, newFilename);
EXPECT_NO_THROW(newFileClient.GetProperties());
EXPECT_NO_THROW(m_fileSystemClient->GetFileClient(newFilename).GetProperties());
EXPECT_THROW(oldFileClient.GetProperties(), StorageException);
const std::string newFileSystemName = LowercaseRandomString();
const std::string newFilename2 = RandomString();
auto newFileSystem = m_dataLakeServiceClient->GetFileSystemClient(newFileSystemName);
newFileSystem.Create();
Files::DataLake::RenameFileOptions options;
options.DestinationFileSystem = newFileSystemName;
auto newFileClient2 = *m_fileSystemClient->RenameFile(newFilename, newFilename2, options);
EXPECT_NO_THROW(newFileClient2.GetProperties());
EXPECT_NO_THROW(newFileSystem.GetFileClient(newFilename2).GetProperties());
newFileSystem.Delete();
EXPECT_THROW(newFileClient.GetProperties(), StorageException);
}
TEST_F(DataLakeFileSystemClientTest, RenameDirectory)
{
const std::string oldDirectoryName = RandomString();
const std::string newDirectoryName = RandomString();
auto oldDirectoryClient = m_fileSystemClient->GetDirectoryClient(oldDirectoryName);
oldDirectoryClient.Create();
oldDirectoryClient.GetFileClient(RandomString()).Create();
oldDirectoryClient.GetSubdirectoryClient(RandomString()).Create();
auto newDirectoryClient
= *m_fileSystemClient->RenameDirectory(oldDirectoryName, newDirectoryName);
EXPECT_NO_THROW(newDirectoryClient.GetProperties());
EXPECT_NO_THROW(m_fileSystemClient->GetDirectoryClient(newDirectoryName).GetProperties());
EXPECT_THROW(oldDirectoryClient.GetProperties(), StorageException);
const std::string newFileSystemName = LowercaseRandomString();
const std::string newDirectoryName2 = RandomString();
auto newFileSystem = m_dataLakeServiceClient->GetFileSystemClient(newFileSystemName);
newFileSystem.Create();
Files::DataLake::RenameDirectoryOptions options;
options.DestinationFileSystem = newFileSystemName;
auto newDirectoryClient2
= *m_fileSystemClient->RenameDirectory(newDirectoryName, newDirectoryName2, options);
EXPECT_NO_THROW(newDirectoryClient2.GetProperties());
EXPECT_NO_THROW(newFileSystem.GetDirectoryClient(newDirectoryName2).GetProperties());
newFileSystem.Delete();
EXPECT_THROW(newDirectoryClient.GetProperties(), StorageException);
}
}}} // namespace Azure::Storage::Test

View File

@ -3,11 +3,12 @@
#include <azure/storage/files/datalake.hpp>
#include "datalake_service_client_test.hpp"
#include "test_base.hpp"
namespace Azure { namespace Storage { namespace Test {
class DataLakeFileSystemClientTest : public ::testing::Test {
class DataLakeFileSystemClientTest : public DataLakeServiceClientTest {
protected:
static void SetUpTestSuite();
static void TearDownTestSuite();