Api view comments (#5408)

* mroe quotes

* dssf

* listTables -> queryTables

* move create/delete to the tableservice

* one more batch

* small refactor, added default data types

* oops

* clangs

* table sas builder

* sas test

* cspell

* add more test

* cspell

* hjhjh

* clang

* rename table-> tables

* clang

* partition and row key

* clang why?

* constructors, update tests

* IT WORKSSSSS

* PR comments

* wqe

* ewr

* enum operator

* clang

* dsaada

* sada

* assets.json

* clang

* Update sdk/tables/azure-data-tables/inc/azure/data/tables/enum_operators.hpp

Co-authored-by: Anton Kolesnyk <41349689+antkmsft@users.noreply.github.com>

* Update sdk/core/azure-core/test/ut/string_test.cpp

Co-authored-by: Anton Kolesnyk <41349689+antkmsft@users.noreply.github.com>

* the = enums

* assert and remove empty

* compact string tests

* clangs

* complement

* azureSasCredentials

* PR cpmments

* some extra

* clang 11

---------

Co-authored-by: Anton Kolesnyk <41349689+antkmsft@users.noreply.github.com>
This commit is contained in:
George Arama 2024-03-15 14:30:45 -07:00 committed by GitHub
parent d390750361
commit 84e4a81947
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
28 changed files with 1233 additions and 282 deletions

View File

@ -11,6 +11,7 @@
#include <algorithm>
#include <cstring>
#include <string>
#include <vector>
namespace Azure { namespace Core { namespace _internal {
@ -91,6 +92,33 @@ namespace Azure { namespace Core { namespace _internal {
std::transform(src.begin(), src.end(), src.begin(), [](auto c) { return ToUpper(c); });
return src;
}
static std::vector<std::string> Split(
const std::string& s,
char separator,
bool removeEmptyEntries = false)
{
std::vector<std::string> result;
const auto len = s.size();
size_t start = 0;
while (start < len)
{
auto end = s.find(separator, start);
if (end == std::string::npos)
{
end = len;
}
if (!removeEmptyEntries || start < end)
{
result.push_back(s.substr(start, end - start));
}
start = end + 1;
}
return result;
}
};
}}} // namespace Azure::Core::_internal

View File

@ -49,28 +49,6 @@ namespace Azure { namespace Core { namespace Test {
class PipelineTest : public Azure::Perf::PerfTest {
std::unique_ptr<HttpPipeline> m_pipeline;
static std::vector<std::string> SplitString(const std::string& s, char separator)
{
std::vector<std::string> result;
const auto len = s.size();
size_t start = 0;
while (start < len)
{
auto end = s.find(separator, start);
if (end == std::string::npos)
{
end = len;
}
result.push_back(s.substr(start, end - start));
start = end + 1;
}
return result;
}
public:
/**
* @brief Construct a new PipelineTest test.
@ -96,8 +74,8 @@ namespace Azure { namespace Core { namespace Test {
std::vector<std::unique_ptr<HttpPolicy>> policies2;
auto const total = m_options.GetMandatoryOption<int>("Count");
auto const policyNames
= SplitString(m_options.GetOptionOrDefault<std::string>("Policies", "TestPolicy"), ',');
auto const policyNames = Azure::Core::_internal::StringExtensions::Split(
m_options.GetOptionOrDefault<std::string>("Policies", "TestPolicy"), ',');
// we want a total number of policies added to the pipeline
// thus for loop total / number , depends on rounding but close enough
// since in each loop we add the whole set of desired policies

View File

@ -131,3 +131,112 @@ TEST(String, toUpper)
EXPECT_NE(StringExtensions::ToUpper("a"), "aA");
EXPECT_NE(StringExtensions::ToUpper("abc"), "abcd");
}
TEST(String, SplitEmpty)
{
using Azure::Core::_internal::StringExtensions;
{
std::vector<std::string> result = StringExtensions::Split("", ',');
EXPECT_TRUE(result.empty());
}
{
std::vector<std::string> result = StringExtensions::Split("", ',', true);
EXPECT_TRUE(result.empty());
}
}
TEST(String, Split3)
{
using Azure::Core::_internal::StringExtensions;
{
std::vector<std::string> result = StringExtensions::Split("1,2,3", ',');
ASSERT_EQ(result.size(), size_t{3});
EXPECT_EQ(result[0], "1");
EXPECT_EQ(result[1], "2");
EXPECT_EQ(result[2], "3");
}
{
std::vector<std::string> result = StringExtensions::Split("1,2,3", ',', true);
ASSERT_EQ(result.size(), size_t{3});
EXPECT_EQ(result[0], "1");
EXPECT_EQ(result[1], "2");
EXPECT_EQ(result[2], "3");
}
}
TEST(String, SplitBegin)
{
using Azure::Core::_internal::StringExtensions;
{
std::vector<std::string> result = StringExtensions::Split(",1,2,3", ',');
ASSERT_EQ(result.size(), size_t{4});
EXPECT_EQ(result[0], "");
EXPECT_EQ(result[1], "1");
EXPECT_EQ(result[2], "2");
EXPECT_EQ(result[3], "3");
}
{
std::vector<std::string> result = StringExtensions::Split(",1,2,3", ',', true);
ASSERT_EQ(result.size(), size_t{3});
EXPECT_EQ(result[0], "1");
EXPECT_EQ(result[1], "2");
EXPECT_EQ(result[2], "3");
}
}
TEST(String, SplitEnd)
{
using Azure::Core::_internal::StringExtensions;
{
std::vector<std::string> result = StringExtensions::Split("1,2,3,", ',');
ASSERT_EQ(result.size(), size_t{3});
EXPECT_EQ(result[0], "1");
EXPECT_EQ(result[1], "2");
EXPECT_EQ(result[2], "3");
}
{
std::vector<std::string> result = StringExtensions::Split("1,2,3,", ',', true);
ASSERT_EQ(result.size(), size_t{3});
EXPECT_EQ(result[0], "1");
EXPECT_EQ(result[1], "2");
EXPECT_EQ(result[2], "3");
}
}
TEST(String, SplitPartEmpty)
{
using Azure::Core::_internal::StringExtensions;
{
std::vector<std::string> result = StringExtensions::Split("1,,2,,3", ',');
ASSERT_EQ(result.size(), size_t{5});
EXPECT_EQ(result[0], "1");
EXPECT_EQ(result[1], "");
EXPECT_EQ(result[2], "2");
EXPECT_EQ(result[3], "");
EXPECT_EQ(result[4], "3");
}
{
std::vector<std::string> result = StringExtensions::Split("1,,2,,3", ',', true);
ASSERT_EQ(result.size(), size_t{3});
EXPECT_EQ(result[0], "1");
EXPECT_EQ(result[1], "2");
EXPECT_EQ(result[2], "3");
}
}
TEST(String, SplitSeparator)
{
using Azure::Core::_internal::StringExtensions;
{
std::vector<std::string> result = StringExtensions::Split(",,,,", ',');
ASSERT_EQ(result.size(), size_t{4});
EXPECT_EQ(result[0], "");
EXPECT_EQ(result[1], "");
EXPECT_EQ(result[2], "");
EXPECT_EQ(result[3], "");
}
{
std::vector<std::string> result = StringExtensions::Split(",,,,", ',', true);
ASSERT_EQ(result.size(), size_t{0});
}
}

View File

@ -2,5 +2,5 @@
"AssetsRepo": "Azure/azure-sdk-assets",
"AssetsRepoPrefixPath": "cpp",
"TagPrefix": "cpp/tables",
"Tag": "cpp/tables_a490279ed7"
"Tag": "cpp/tables_ca30219607"
}

View File

@ -42,7 +42,10 @@ endif()
set(
AZURE_DATA_TABLES_HEADER
inc/azure/data/tables/account_sas_builder.hpp
inc/azure/data/tables/credentials/azure_sas_credential.hpp
inc/azure/data/tables/credentials/shared_key_credential.hpp
inc/azure/data/tables/dll_import_export.hpp
inc/azure/data/tables/enum_operators.hpp
inc/azure/data/tables/internal/cryptography/hmacsha256.hpp
inc/azure/data/tables/internal/cryptography/url_encode.hpp
inc/azure/data/tables/internal/policies/service_version_policy.hpp
@ -57,8 +60,8 @@ set(
inc/azure/data/tables/rtti.hpp
inc/azure/data/tables.hpp
inc/azure/data/tables/tables_clients.hpp
inc/azure/data/tables/tables_sas_builder.hpp
inc/azure/data/tables/transactions.hpp
inc/azure/data/tables/credentials/shared_key_credential.hpp
)
set(
@ -66,6 +69,7 @@ set(
src/account_sas_builder.cpp
src/credentials/shared_key_credential.cpp
src/cryptography/hmacsha256.cpp
src/models.cpp
src/policies/shared_key_lite_policy.cpp
src/policies/shared_key_policy.cpp
src/policies/switch_to_secondary_policy.cpp
@ -74,6 +78,7 @@ set(
src/private/package_version.hpp
src/serializers.cpp
src/tables_clients.cpp
src/tables_sas_builder.cpp
src/transactions.cpp
src/xml_wrapper.cpp
)

View File

@ -8,9 +8,13 @@
#pragma once
#include "azure/data/tables/account_sas_builder.hpp"
#include "azure/data/tables/credentials/azure_sas_credential.hpp"
#include "azure/data/tables/credentials/shared_key_credential.hpp"
#include "azure/data/tables/dll_import_export.hpp"
#include "azure/data/tables/enum_operators.hpp"
#include "azure/data/tables/models.hpp"
#include "azure/data/tables/rtti.hpp"
#include "azure/data/tables/tables_clients.hpp"
#include "azure/data/tables/tables_sas_builder.hpp"
#include "azure/data/tables/transactions.hpp"

View File

@ -4,12 +4,12 @@
#pragma once
#include "azure/data/tables/credentials/shared_key_credential.hpp"
#include "azure/data/tables/enum_operators.hpp"
#include <azure/core/datetime.hpp>
#include <azure/core/nullable.hpp>
#include <string>
#include <type_traits>
namespace Azure { namespace Data { namespace Tables { namespace Sas {
@ -68,18 +68,6 @@ namespace Azure { namespace Data { namespace Tables { namespace Sas {
All = ~0,
};
inline AccountSasResource operator|(AccountSasResource lhs, AccountSasResource rhs)
{
using type = std::underlying_type_t<AccountSasResource>;
return static_cast<AccountSasResource>(static_cast<type>(lhs) | static_cast<type>(rhs));
}
inline AccountSasResource operator&(AccountSasResource lhs, AccountSasResource rhs)
{
using type = std::underlying_type_t<AccountSasResource>;
return static_cast<AccountSasResource>(static_cast<type>(lhs) & static_cast<type>(rhs));
}
/**
* @brief Specifies the services accessible from an account level shared access signature.
*/
@ -114,18 +102,6 @@ namespace Azure { namespace Data { namespace Tables { namespace Sas {
All = ~0,
};
inline AccountSasServices operator|(AccountSasServices lhs, AccountSasServices rhs)
{
using type = std::underlying_type_t<AccountSasServices>;
return static_cast<AccountSasServices>(static_cast<type>(lhs) | static_cast<type>(rhs));
}
inline AccountSasServices operator&(AccountSasServices lhs, AccountSasServices rhs)
{
using type = std::underlying_type_t<AccountSasServices>;
return static_cast<AccountSasServices>(static_cast<type>(lhs) & static_cast<type>(rhs));
}
/**
* @brief The list of permissions that can be set for an account's access policy.
*/
@ -202,24 +178,12 @@ namespace Azure { namespace Data { namespace Tables { namespace Sas {
All = ~0,
};
inline AccountSasPermissions operator|(AccountSasPermissions lhs, AccountSasPermissions rhs)
{
using type = std::underlying_type_t<AccountSasPermissions>;
return static_cast<AccountSasPermissions>(static_cast<type>(lhs) | static_cast<type>(rhs));
}
inline AccountSasPermissions operator&(AccountSasPermissions lhs, AccountSasPermissions rhs)
{
using type = std::underlying_type_t<AccountSasPermissions>;
return static_cast<AccountSasPermissions>(static_cast<type>(lhs) & static_cast<type>(rhs));
}
/**
* @brief AccountSasBuilder is used to generate an account level Shared Access Signature
* (SAS) for Azure Storage services.
*/
struct AccountSasBuilder final
{
class AccountSasBuilder final {
public:
/**
* @brief The optional signed protocol field specifies the protocol permitted for a
* request made with the SAS.
@ -293,5 +257,4 @@ namespace Azure { namespace Data { namespace Tables { namespace Sas {
private:
std::string Permissions;
};
}}}} // namespace Azure::Data::Tables::Sas

View File

@ -0,0 +1,47 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
#pragma once
#include <azure/core/http/http.hpp>
#include <memory>
#include <mutex>
#include <string>
namespace Azure { namespace Data { namespace Tables { namespace Credentials {
/**
* @brief Azure Shared Access Signature (SAS) credential.
*/
class AzureSasCredential final {
private:
std::string m_signature;
mutable std::mutex m_mutex;
public:
/**
* @brief Initializes a new instance of the AzureSasCredential.
*
* @param signature The signature for the SAS token.
*/
explicit AzureSasCredential(std::string signature) : m_signature(std::move(signature)) {}
/**
* @brief Get the signature for the SAS token.
*/
std::string GetSignature() const
{
std::lock_guard<std::mutex> guard(m_mutex);
return m_signature;
}
/**
* @brief Update the signature for the SAS token.
*/
void Update(std::string signature)
{
std::lock_guard<std::mutex> guard(m_mutex);
m_signature = std::move(signature);
}
};
}}}} // namespace Azure::Data::Tables::Credentials

View File

@ -14,7 +14,8 @@ namespace Azure { namespace Data { namespace Tables { namespace _detail { namesp
}}}}} // namespace Azure::Data::Tables::_detail::Policies
namespace Azure { namespace Data { namespace Tables { namespace Sas {
struct AccountSasBuilder;
class AccountSasBuilder;
class TablesSasBuilder;
}}}} // namespace Azure::Data::Tables::Sas
namespace Azure { namespace Data { namespace Tables { namespace Credentials {
@ -57,7 +58,8 @@ namespace Azure { namespace Data { namespace Tables { namespace Credentials {
private:
friend class Azure::Data::Tables::_detail::Policies::SharedKeyPolicy;
friend class Azure::Data::Tables::_detail::Policies::SharedKeyLitePolicy;
friend struct Azure::Data::Tables::Sas::AccountSasBuilder;
friend class Azure::Data::Tables::Sas::AccountSasBuilder;
friend class Azure::Data::Tables::Sas::TablesSasBuilder;
std::string GetAccountKey() const
{

View File

@ -0,0 +1,77 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
#pragma once
#include <type_traits>
namespace Azure { namespace Data { namespace Tables {
/**
* @brief Bitwise OR operator for enum class.
*/
template <class E, class = std::enable_if_t<std::is_enum<E>{}>>
constexpr E operator|(E lhs, E rhs)
{
using type = std::underlying_type_t<E>;
return static_cast<E>(static_cast<type>(lhs) | static_cast<type>(rhs));
}
/**
* @brief Bitwise OR EQUALS operator for enum class.
*/
template <class E, class = std::enable_if_t<std::is_enum<E>{}>>
constexpr E& operator|=(E& lhs, E rhs)
{
lhs = lhs | rhs;
return lhs;
}
/**
* @brief Bitwise AND operator for enum class.
*/
template <class E, class = std::enable_if_t<std::is_enum<E>{}>>
constexpr E operator&(E lhs, E rhs)
{
using type = std::underlying_type_t<E>;
return static_cast<E>(static_cast<type>(lhs) & static_cast<type>(rhs));
}
/**
* @brief Bitwise AND EQUALS operator for enum class.
*/
template <class E, class = std::enable_if_t<std::is_enum<E>{}>>
constexpr E& operator&=(E& lhs, E rhs)
{
lhs = lhs & rhs;
return lhs;
}
/**
* @brief Bitwise XOR operator for enum class.
*/
template <class E, class = std::enable_if_t<std::is_enum<E>{}>>
constexpr E operator^(E lhs, E rhs)
{
using type = std::underlying_type_t<E>;
return static_cast<E>(static_cast<type>(lhs) ^ static_cast<type>(rhs));
}
/**
* @brief Bitwise XOR EQUALS operator for enum class.
*/
template <class E, class = std::enable_if_t<std::is_enum<E>{}>>
constexpr E& operator^=(E& lhs, E rhs)
{
lhs = lhs ^ rhs;
return lhs;
}
/**
* @brief Bitwise COMPLEMENT operator for enum class.
*/
template <class E, class = std::enable_if_t<std::is_enum<E>{}>> constexpr E operator~(E rhs)
{
using type = std::underlying_type_t<E>;
return static_cast<E>(~static_cast<type>(rhs));
}
}}} // namespace Azure::Data::Tables

View File

@ -5,6 +5,8 @@
#include "azure/data/tables/internal/xml_wrapper.hpp"
#include "azure/data/tables/models.hpp"
#include <azure/core/internal/json/json.hpp>
#include <cstdint>
#include <memory>
#include <string>
@ -68,5 +70,10 @@ namespace Azure { namespace Data { namespace Tables { namespace _detail {
*/
static Models::TableServiceProperties ServicePropertiesFromXml(
std::vector<uint8_t> responseData);
/**
* @brief Deserialize a TableEntity from JSON.
*/
static Models::TableEntity DeserializeEntity(Azure::Core::Json::_internal::json json);
};
}}}} // namespace Azure::Data::Tables::_detail

View File

@ -4,6 +4,7 @@
#pragma once
#include "azure/data/tables/dll_import_export.hpp"
#include "azure/data/tables/enum_operators.hpp"
#include <azure/core/datetime.hpp>
#include <azure/core/internal/extendable_enumeration.hpp>
@ -18,11 +19,10 @@
#include <vector>
namespace Azure { namespace Data { namespace Tables {
class TableServicesClient;
class TableServiceClient;
class TableClient;
namespace Models {
/**
* @brief Table definition struct.
*/
@ -54,41 +54,17 @@ namespace Azure { namespace Data { namespace Tables {
* @brief Include this parameter to specify that the tables' metadata be returned as part of
* the response body.
*/
enum class ListTablesIncludeFlags
enum class QueryTablesIncludeFlags
{
None = 0,
Metadata = 1,
};
inline ListTablesIncludeFlags operator|(ListTablesIncludeFlags lhs, ListTablesIncludeFlags rhs)
{
using type = std::underlying_type_t<ListTablesIncludeFlags>;
return static_cast<ListTablesIncludeFlags>(static_cast<type>(lhs) | static_cast<type>(rhs));
}
inline ListTablesIncludeFlags& operator|=(
ListTablesIncludeFlags& lhs,
ListTablesIncludeFlags rhs)
{
lhs = lhs | rhs;
return lhs;
}
inline ListTablesIncludeFlags operator&(ListTablesIncludeFlags lhs, ListTablesIncludeFlags rhs)
{
using type = std::underlying_type_t<ListTablesIncludeFlags>;
return static_cast<ListTablesIncludeFlags>(static_cast<type>(lhs) & static_cast<type>(rhs));
}
inline ListTablesIncludeFlags& operator&=(
ListTablesIncludeFlags& lhs,
ListTablesIncludeFlags rhs)
{
lhs = lhs & rhs;
return lhs;
}
/**
* @brief List Tables options.
* @brief Query Tables options.
*
*/
struct ListTablesOptions final
struct QueryTablesOptions final
{
/**
* @brief Specifies a string that filters the results to return only tables whose name
@ -108,22 +84,22 @@ namespace Azure { namespace Data { namespace Tables {
/**
* @brief Specifies the maximum number of tables to return.
*/
Azure::Nullable<int32_t> PageSizeHint;
Azure::Nullable<std::int32_t> PageSizeHint;
/**
* @brief Specifies that the table's metadata be returned.
*/
Models::ListTablesIncludeFlags Include = Models::ListTablesIncludeFlags::None;
Models::QueryTablesIncludeFlags Include = Models::QueryTablesIncludeFlags::None;
};
/**
* @brief List tables paged response.
* @brief Query tables paged response.
*/
class ListTablesPagedResponse final
: public Azure::Core::PagedResponse<ListTablesPagedResponse> {
class QueryTablesPagedResponse final
: public Azure::Core::PagedResponse<QueryTablesPagedResponse> {
friend class Azure::Data::Tables::TableServicesClient;
friend class Azure::Core::PagedResponse<ListTablesPagedResponse>;
friend class Azure::Data::Tables::TableServiceClient;
friend class Azure::Core::PagedResponse<QueryTablesPagedResponse>;
public:
/**
@ -145,9 +121,9 @@ namespace Azure { namespace Data { namespace Tables {
/**
* Table Service Client.
*/
std::shared_ptr<TableServicesClient> m_tableServiceClient;
std::shared_ptr<TableServiceClient> m_tableServiceClient;
/** Operation options */
ListTablesOptions m_operationOptions;
QueryTablesOptions m_operationOptions;
private:
void OnNextPage(const Azure::Core::Context& context);
@ -166,7 +142,7 @@ namespace Azure { namespace Data { namespace Tables {
* Indicates the number of days that metrics or logging or soft-deleted data should be
* retained. All data older than this value will be deleted.
*/
Nullable<int32_t> Days;
Nullable<std::int32_t> Days;
};
/**
@ -253,7 +229,7 @@ namespace Azure { namespace Data { namespace Tables {
/**
* The maximum amount time that a browser should cache the preflight OPTIONS request.
*/
int32_t MaxAgeInSeconds = int32_t();
std::int32_t MaxAgeInSeconds = int32_t();
};
/**
@ -347,6 +323,43 @@ namespace Azure { namespace Data { namespace Tables {
std::string m_value;
};
/**
* @brief Table Entity Data Type.
*/
class TableEntityDataType final
: public Azure::Core::_internal::ExtendableEnumeration<TableEntityDataType> {
public:
/**
* @brief Construct a new TableEntityDataType object
*/
TableEntityDataType() = default;
/**
* @brief Construct a new TableEntityDataType object
*
* @param tableEntityDataType entity data type string.
*/
explicit TableEntityDataType(std::string tableEntityDataType)
: ExtendableEnumeration(std::move(tableEntityDataType))
{
}
/** Constant value of type TableEntityDataType:EdmBinary */
AZ_DATA_TABLES_DLLEXPORT const static TableEntityDataType EdmBinary;
/** Constant value of type TableEntityDataType:EdmBinary */
AZ_DATA_TABLES_DLLEXPORT const static TableEntityDataType EdmBoolean;
/** Constant value of type TableEntityDataType:EdmBinary */
AZ_DATA_TABLES_DLLEXPORT const static TableEntityDataType EdmDateTime;
/** Constant value of type TableEntityDataType:EdmBinary */
AZ_DATA_TABLES_DLLEXPORT const static TableEntityDataType EdmDouble;
/** Constant value of type TableEntityDataType:EdmBinary */
AZ_DATA_TABLES_DLLEXPORT const static TableEntityDataType EdmGuid;
/** Constant value of type TableEntityDataType:EdmBinary */
AZ_DATA_TABLES_DLLEXPORT const static TableEntityDataType EdmInt32;
/** Constant value of type TableEntityDataType:EdmBinary */
AZ_DATA_TABLES_DLLEXPORT const static TableEntityDataType EdmInt64;
/** Constant value of type TableEntityDataType:EdmBinary */
AZ_DATA_TABLES_DLLEXPORT const static TableEntityDataType EdmString;
};
/**
* @brief Geo-Replication information for the Secondary Storage Service.
*/
@ -380,7 +393,7 @@ namespace Azure { namespace Data { namespace Tables {
* @brief Delete result.
*
*/
struct DeleteResult final
struct DeleteTableResult final
{
};
@ -450,6 +463,12 @@ namespace Azure { namespace Data { namespace Tables {
* ETag
*/
Azure::Nullable<std::string> ETag;
/**
* @brief Table Entity data type.
*
*/
TableEntityDataType DataType;
};
/**
@ -486,7 +505,7 @@ namespace Azure { namespace Data { namespace Tables {
*
* @param other Upsert Entity options.
*/
CreateEntityOptions(UpsertEntityOptions const& other) { (void)other; }
explicit CreateEntityOptions(UpsertEntityOptions const& other) { (void)other; }
};
/**
@ -668,7 +687,7 @@ namespace Azure { namespace Data { namespace Tables {
private:
std::shared_ptr<TableClient> m_tableClient;
QueryEntitiesOptions m_operationOptions;
friend class Azure::Data::Tables::TableServicesClient;
friend class Azure::Data::Tables::TableServiceClient;
friend class Azure::Core::PagedResponse<QueryEntitiesPagedResponse>;
void OnNextPage(const Azure::Core::Context& context);

View File

@ -3,6 +3,7 @@
#pragma once
#include "azure/data/tables/credentials/azure_sas_credential.hpp"
#include "azure/data/tables/credentials/shared_key_credential.hpp"
#include "azure/data/tables/models.hpp"
#include "azure/data/tables/transactions.hpp"
@ -178,6 +179,21 @@ namespace Azure { namespace Data { namespace Tables {
std::string url,
const TableClientOptions& options = {});
/**
* @brief Initializes a new instance of tableClient.
*
* @param serviceUrl The service Url
* @param credential The SAS credential used to sign requests.
* @param tableName The name of the table.
* @param options Optional client options that define the transport pipeline policies for
* authentication, retries, etc., that are applied to every request.
*/
explicit TableClient(
const std::string& serviceUrl,
std::shared_ptr<Azure::Data::Tables::Credentials::AzureSasCredential> credential,
const std::string& tableName,
const TableClientOptions& options = {});
/**
* @brief Initializes a new instance of tableClient.
*
@ -192,22 +208,6 @@ namespace Azure { namespace Data { namespace Tables {
const std::string& tableName,
const TableClientOptions& options = {});
/**
* @brief Create the table indicated in the tableName field of the client.
*
* @param context for canceling long running operations.
* @return Create table result.
*/
Response<Models::Table> Create(Core::Context const& context = {});
/**
* @brief Delete the table indicated in the tableName field of the client.
*
* @param context for canceling long running operations.
* @return Delete table result.
*/
Response<Models::DeleteResult> Delete(Core::Context const& context = {});
/**
* @brief Get table access policy.
*
@ -300,6 +300,7 @@ namespace Azure { namespace Data { namespace Tables {
Models::QueryEntitiesPagedResponse QueryEntities(
Models::QueryEntitiesOptions const& options = {},
Core::Context const& context = {});
/**
* @brief Creates a new transaction.
*
@ -323,21 +324,20 @@ namespace Azure { namespace Data { namespace Tables {
std::shared_ptr<Core::Http::_internal::HttpPipeline> m_pipeline;
Core::Url m_url;
std::string m_tableName;
Models::TableEntity DeserializeEntity(Azure::Core::Json::_internal::json json);
};
/**
* @brief Table Services Client
* @brief Table Service Client
*/
class TableServicesClient final {
class TableServiceClient final {
public:
/**
* @brief Initializes a new instance of tableServicesClient.
* @brief Initializes a new instance of tableServiceClient.
*
* @param options Optional client options that define the transport pipeline policies for
* authentication, retries, etc., that are applied to every request.
*/
explicit TableServicesClient(const TableClientOptions& options = {});
explicit TableServiceClient(const TableClientOptions& options = {});
/**
* @brief Initializes a new instance of tableClient.
@ -347,7 +347,7 @@ namespace Azure { namespace Data { namespace Tables {
* @param options Optional client options that define the transport pipeline policies for
* authentication, retries, etc., that are applied to every request.
*/
explicit TableServicesClient(
explicit TableServiceClient(
const std::string& serviceUrl,
const TableClientOptions& options = {});
@ -360,7 +360,7 @@ namespace Azure { namespace Data { namespace Tables {
* @param options Optional client options that define the transport pipeline policies for
* authentication, retries, etc., that are applied to every request.
*/
explicit TableServicesClient(
explicit TableServiceClient(
const std::string& serviceUrl,
std::shared_ptr<Core::Credentials::TokenCredential> credential,
const TableClientOptions& options = {});
@ -374,31 +374,68 @@ namespace Azure { namespace Data { namespace Tables {
* @param options Optional client options that define the transport pipeline policies for
* authentication, retries, etc., that are applied to every request.
*/
explicit TableServicesClient(
explicit TableServiceClient(
const std::string& serviceUrl,
std::shared_ptr<Azure::Data::Tables::Credentials::SharedKeyCredential> credential,
const TableClientOptions& options = {});
/**
* @brief Initializes a new instance of tableClient.
*
* @param serviceUrl A url referencing the table that includes the name of the account and the
* name of the table.
* @param credential The SAS credential used to sign requests.
* @param options Optional client options that define the transport pipeline policies for
* authentication, retries, etc., that are applied to every request.
*/
explicit TableServiceClient(
const std::string& serviceUrl,
std::shared_ptr<Azure::Data::Tables::Credentials::AzureSasCredential> credential,
const TableClientOptions& options = {});
/**
* @brief Initializes a new instance of tableClient.
*
* @param connectionString the connection string used to initialize.
* @param options Optional client options that define the transport pipeline policies for
* authentication, retries, etc., that are applied to every request.
* @return TableServicesClient.
* @return TableServiceClient.
*/
static TableServicesClient CreateFromConnectionString(
static TableServiceClient CreateFromConnectionString(
const std::string& connectionString,
const TableClientOptions& options = {});
/**
* @brief List tables.
* @brief Create the table indicated in the tableName field of the client.
*
* @param context for canceling long running operations.
* @param tableName The name of the table to be created.
* @return Create table result.
*/
Response<Models::Table> CreateTable(
std::string const& tableName,
Core::Context const& context = {});
/**
* @brief Delete the table indicated in the tableName field of the client.
*
* @param context for canceling long running operations.
* @param tableName The name of the table to be deleted.
* @return Delete table result.
*/
Response<Models::DeleteTableResult> DeleteTable(
std::string const& tableName,
Core::Context const& context = {});
/**
* @brief Query tables.
*
* @param options Optional parameters to execute this function.
* @param context for canceling long running operations.
* @return List tables paged response.
*/
Models::ListTablesPagedResponse ListTables(
const Models::ListTablesOptions& options = {},
Models::QueryTablesPagedResponse QueryTables(
const Models::QueryTablesOptions& options = {},
const Azure::Core::Context& context = {}) const;
/**

View File

@ -0,0 +1,173 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
#pragma once
#include "azure/data/tables/account_sas_builder.hpp"
#include "azure/data/tables/credentials/shared_key_credential.hpp"
#include "azure/data/tables/enum_operators.hpp"
#include <azure/core/datetime.hpp>
#include <azure/core/nullable.hpp>
#include <string>
#include <type_traits>
namespace Azure { namespace Data { namespace Tables { namespace Sas {
/**
* @brief Defines the protocols permitted for Storage requests made with a shared
* access signature.
*/
enum class TablesSasProtocol
{
/**
* @brief No protocol has been specified. If no value is specified,
* the service will default to HttpsAndHttp.
*/
None = 0,
/**
* @brief Only requests issued over HTTPS or HTTP will be permitted.
*/
HttpsAndHttp = 1,
/**
* @brief Only requests issued over HTTPS will be permitted.
*/
Https = 2
};
/**
* @brief Contains the list of
* permissions that can be set for a table's access policy.
*/
enum class TablesSasPermissions
{
/**
* @brief Indicates that Read is permitted.
*/
Read = 1,
/**
* @brief Indicates that Add is permitted.
*/
Add = 2,
/**
* @brief Indicates that Delete is permitted.
*/
Delete = 4,
/**
* @brief Indicates that Update is permitted.
*/
Update = 8,
/**
* @brief Indicates that all permissions are set.
*/
All = ~0
};
/**
* @brief TableSasBuilder is used to generate a Shared Access Signature (SAS) for an Azure
* Storage Tables.
*/
class TablesSasBuilder final {
public:
/**
* @brief The optional signed protocol field specifies the protocol permitted for a
* request made with the SAS.
*/
SasProtocol Protocol;
/**
* @brief Optionally specify the time at which the shared access signature becomes
* valid. This timestamp will be truncated to second.
*/
Azure::Nullable<Azure::DateTime> StartsOn;
/**
* @brief The time at which the shared access signature becomes invalid. This field must
* be omitted if it has been specified in an associated stored access policy. This timestamp
* will be truncated to second.
*/
Azure::DateTime ExpiresOn;
/**
* @brief Specifies an IP address or a range of IP addresses from which to accept
* requests. If the IP address from which the request originates does not match the IP address
* or address range specified on the SAS token, the request is not authenticated. When
* specifying a range of IP addresses, note that the range is inclusive.
*/
Azure::Nullable<std::string> IPRange;
/**
* @brief An optional unique value up to 64 characters in length that correlates to an
* access policy specified for the table.
*/
std::string Identifier;
/**
* @brief The name of the table being made accessible.
*/
std::string TableName;
/**
* @brief The optional start of the partition key values range being made available.
*/
std::string PartitionKeyStart;
/**
* @brief The optional end of the partition key values range being made available.
*/
std::string PartitionKeyEnd;
/**
* @brief The optional start of the row key values range being made available.
*/
std::string RowKeyStart;
/**
* @brief The optional end of the partition key values range being made available.
*/
std::string RowKeyEnd;
/**
* @brief Sets the permissions for the table SAS.
*
* @param permissions The allowed permissions.
*/
void SetPermissions(TablesSasPermissions permissions);
/**
* @brief Sets the permissions for the SAS using a raw permissions string.
*
* @param rawPermissions Raw permissions string for the SAS.
*/
void SetPermissions(std::string rawPermissions) { Permissions = std::move(rawPermissions); }
/**
* @brief Uses the StorageSharedKeyCredential to sign this shared access signature, to produce
* the proper SAS query parameters for authentication requests.
*
* @param credential The storage account's shared key credential.
* @return The SAS query parameters used for authenticating requests.
*/
std::string GenerateSasToken(
const Azure::Data::Tables::Credentials::SharedKeyCredential& credential);
/**
* @brief Gets the canonical path for the shared access signature.
*
* @param credential The storage account's shared key credential.
* @return Canonical path.
*/
std::string GetCanonicalName(
const Azure::Data::Tables::Credentials::SharedKeyCredential& credential) const
{
return Azure::Core::_internal::StringExtensions::ToLower(
"/table/" + credential.AccountName + "/" + TableName);
}
private:
std::string Permissions;
};
}}}} // namespace Azure::Data::Tables::Sas

View File

@ -29,14 +29,14 @@ const std::string TableName = "table";
int main()
{
auto tableServiceClient = TableServicesClient::CreateFromConnectionString(GetConnectionString());
auto tableServiceClient = TableServiceClient::CreateFromConnectionString(GetConnectionString());
auto tableClient = TableClient::CreateFromConnectionString(GetConnectionString(), TableName);
// create new table
tableClient.Create();
tableServiceClient.CreateTable(TableName);
// list tables
auto tables = tableServiceClient.ListTables();
auto tables = tableServiceClient.QueryTables();
for (auto table : tables.Tables)
{
std::cout << table.TableName << std::endl;
@ -67,6 +67,6 @@ int main()
auto deleteResponse = tableClient.DeleteEntity(entity);
// delete existing table
tableClient.Delete();
tableServiceClient.DeleteTable(TableName);
return 0;
}

View File

@ -29,14 +29,14 @@ const std::string TableName = "sample1";
int main()
{
auto tableServiceClient = TableServicesClient::CreateFromConnectionString(GetConnectionString());
auto tableServiceClient = TableServiceClient::CreateFromConnectionString(GetConnectionString());
auto tableClient = TableClient::CreateFromConnectionString(GetConnectionString(), TableName);
// create new table
tableClient.Create();
tableServiceClient.CreateTable(TableName);
// list tables
auto tables = tableServiceClient.ListTables();
// query tables
auto tables = tableServiceClient.QueryTables();
// print table names
for (auto table : tables.Tables)
@ -44,6 +44,6 @@ int main()
std::cout << table.TableName << std::endl;
}
// delete existing table
tableClient.Delete();
tableServiceClient.DeleteTable(TableName);
return 0;
}

View File

@ -29,10 +29,10 @@ const std::string TableName = "sample1";
int main()
{
auto tableServiceClient = TableServicesClient::CreateFromConnectionString(GetConnectionString());
auto tableServiceClient = TableServiceClient::CreateFromConnectionString(GetConnectionString());
// list tables
auto tables = tableServiceClient.ListTables();
// query tables
auto tables = tableServiceClient.QueryTables();
// print table names
for (auto table : tables.Tables)

View File

@ -0,0 +1,15 @@
#include "azure/data/tables/models.hpp"
namespace Azure { namespace Data { namespace Tables { namespace Models {
const GeoReplicationStatus GeoReplicationStatus::Live("live");
const GeoReplicationStatus GeoReplicationStatus::Bootstrap("bootstrap");
const GeoReplicationStatus GeoReplicationStatus::Unavailable("unavailable");
const TableEntityDataType TableEntityDataType::EdmBinary("Edm.Binary");
const TableEntityDataType TableEntityDataType::EdmBoolean("Edm.Boolean");
const TableEntityDataType TableEntityDataType::EdmDateTime("Edm.DateTime");
const TableEntityDataType TableEntityDataType::EdmDouble("Edm.Double");
const TableEntityDataType TableEntityDataType::EdmGuid("Edm.Guid");
const TableEntityDataType TableEntityDataType::EdmInt32("Edm.Int32");
const TableEntityDataType TableEntityDataType::EdmInt64("Edm.Int64");
const TableEntityDataType TableEntityDataType::EdmString("Edm.String");
}}}} // namespace Azure::Data::Tables::Models

View File

@ -20,7 +20,6 @@ namespace Azure { namespace Data { namespace Tables { namespace _detail {
{
jsonRoot[entry.first] = entry.second;
}
jsonBody = jsonRoot.dump();
}
return jsonBody;
@ -28,38 +27,12 @@ namespace Azure { namespace Data { namespace Tables { namespace _detail {
std::string const Serializers::MergeEntity(Models::TableEntity const& tableEntity)
{
std::string jsonBody;
{
auto jsonRoot = Core::Json::_internal::json::object();
jsonRoot["PartitionKey"] = tableEntity.PartitionKey;
jsonRoot["RowKey"] = tableEntity.RowKey;
for (auto entry : tableEntity.Properties)
{
jsonRoot[entry.first] = entry.second;
}
jsonBody = jsonRoot.dump();
}
return jsonBody;
return CreateEntity(tableEntity);
}
std::string const Serializers::UpdateEntity(Models::TableEntity const& tableEntity)
{
std::string jsonBody;
{
auto jsonRoot = Core::Json::_internal::json::object();
jsonRoot["PartitionKey"] = tableEntity.PartitionKey;
jsonRoot["RowKey"] = tableEntity.RowKey;
for (auto entry : tableEntity.Properties)
{
jsonRoot[entry.first] = entry.second;
}
jsonBody = jsonRoot.dump();
}
return jsonBody;
return CreateEntity(tableEntity);
}
std::string const Serializers::SetAccessPolicy(Models::TableAccessPolicy const& tableAccessPolicy)
@ -539,4 +512,34 @@ namespace Azure { namespace Data { namespace Tables { namespace _detail {
}
return response;
}
Models::TableEntity Serializers::DeserializeEntity(Azure::Core::Json::_internal::json json)
{
Models::TableEntity tableEntity{};
if (json.contains("PartitionKey"))
{
tableEntity.PartitionKey = json["PartitionKey"].get<std::string>();
}
if (json.contains("RowKey"))
{
tableEntity.RowKey = json["RowKey"].get<std::string>();
}
if (json.contains("odata.etag"))
{
tableEntity.ETag = json["odata.etag"].get<std::string>();
}
for (auto properties : json.get<std::map<std::string, std::string>>())
{
if (properties.first.find("odata.type") != std::string::npos)
{
tableEntity.DataType = Models::TableEntityDataType(properties.second);
}
if (properties.first != "odata.metadata" && properties.first != "PartitionKey"
&& properties.first != "RowKey" && properties.first != "odata.etag")
{
tableEntity.Properties[properties.first] = properties.second;
}
}
return tableEntity;
}
}}}} // namespace Azure::Data::Tables::_detail

View File

@ -19,7 +19,7 @@ using namespace Azure::Data::Tables::_detail::Xml;
using namespace Azure::Data::Tables::Credentials::_detail;
using namespace Azure::Data::Tables::_detail;
TableServicesClient::TableServicesClient(const TableClientOptions& options)
TableServiceClient::TableServiceClient(const TableClientOptions& options)
{
TableClientOptions newOptions = options;
std::vector<std::unique_ptr<Azure::Core::Http::Policies::HttpPolicy>> perRetryPolicies;
@ -37,7 +37,7 @@ TableServicesClient::TableServicesClient(const TableClientOptions& options)
std::move(perOperationPolicies));
}
TableServicesClient::TableServicesClient(
TableServiceClient::TableServiceClient(
const std::string& serviceUrl,
const TableClientOptions& options)
{
@ -57,11 +57,11 @@ TableServicesClient::TableServicesClient(
std::move(perOperationPolicies));
}
TableServicesClient::TableServicesClient(
TableServiceClient::TableServiceClient(
const std::string& serviceUrl,
std::shared_ptr<Core::Credentials::TokenCredential> credential,
const TableClientOptions& options)
: TableServicesClient(options)
: TableServiceClient(options)
{
TableClientOptions newOptions = options;
@ -96,7 +96,7 @@ TableServicesClient::TableServicesClient(
std::move(perOperationPolicies));
}
TableServicesClient::TableServicesClient(
TableServiceClient::TableServiceClient(
const std::string& serviceUrl,
std::shared_ptr<Azure::Data::Tables::Credentials::SharedKeyCredential> credential,
const TableClientOptions& options)
@ -135,7 +135,15 @@ TableServicesClient::TableServicesClient(
std::move(perOperationPolicies2));
}
TableServicesClient TableServicesClient::CreateFromConnectionString(
TableServiceClient::TableServiceClient(
const std::string& serviceUrl,
std::shared_ptr<Azure::Data::Tables::Credentials::AzureSasCredential> credential,
const TableClientOptions& options)
: TableServiceClient(std::string{serviceUrl + credential->GetSignature()}, options)
{
}
TableServiceClient TableServiceClient::CreateFromConnectionString(
const std::string& connectionString,
const TableClientOptions& options)
{
@ -144,16 +152,16 @@ TableServicesClient TableServicesClient::CreateFromConnectionString(
if (parsedConnectionString.KeyCredential)
{
return TableServicesClient(
return TableServiceClient(
tablesUrl.GetAbsoluteUrl(), std::move(parsedConnectionString.KeyCredential), options);
}
else
{
return TableServicesClient(options);
return TableServiceClient(options);
}
}
Azure::Response<Models::PreflightCheckResult> TableServicesClient::PreflightCheck(
Azure::Response<Models::PreflightCheckResult> TableServiceClient::PreflightCheck(
Models::PreflightCheckOptions const& options,
Core::Context const& context)
{
@ -174,7 +182,7 @@ Azure::Response<Models::PreflightCheckResult> TableServicesClient::PreflightChec
return Response<Models::PreflightCheckResult>(std::move(response), std::move(rawResponse));
}
Azure::Response<Models::SetServicePropertiesResult> TableServicesClient::SetServiceProperties(
Azure::Response<Models::SetServicePropertiesResult> TableServiceClient::SetServiceProperties(
Models::SetServicePropertiesOptions const& options,
Core::Context const& context)
{
@ -204,7 +212,7 @@ Azure::Response<Models::SetServicePropertiesResult> TableServicesClient::SetServ
return Response<Models::SetServicePropertiesResult>(std::move(response), std::move(rawResponse));
}
Azure::Response<Models::TableServiceProperties> TableServicesClient::GetServiceProperties(
Azure::Response<Models::TableServiceProperties> TableServiceClient::GetServiceProperties(
Core::Context const& context)
{
auto url = m_url;
@ -227,7 +235,7 @@ Azure::Response<Models::TableServiceProperties> TableServicesClient::GetServiceP
return Response<Models::TableServiceProperties>(std::move(response), std::move(pRawResponse));
}
Azure::Response<Models::ServiceStatistics> TableServicesClient::GetStatistics(
Azure::Response<Models::ServiceStatistics> TableServiceClient::GetStatistics(
const Core::Context& context)
{
auto url = m_url;
@ -407,6 +415,19 @@ TableClient::TableClient(
std::move(perOperationPolicies2));
}
TableClient::TableClient(
const std::string& serviceUrl,
std::shared_ptr<Azure::Data::Tables::Credentials::AzureSasCredential> credential,
const std::string& tableName,
const TableClientOptions& options)
: TableClient(
std::string{
Azure::Core::Url(serviceUrl).GetAbsoluteUrl() + "/" + credential->GetSignature()},
tableName,
options)
{
}
TableClient TableClient::CreateFromConnectionString(
const std::string& connectionString,
const std::string& tableName,
@ -429,12 +450,14 @@ TableClient TableClient::CreateFromConnectionString(
}
}
Azure::Response<Models::Table> TableClient::Create(Core::Context const& context)
Azure::Response<Models::Table> TableServiceClient::CreateTable(
std::string const& tableName,
Core::Context const& context)
{
auto url = m_url;
url.AppendPath("Tables");
std::string jsonBody = Serializers::Create(m_tableName);
std::string jsonBody = Serializers::Create(tableName);
Core::IO::MemoryBodyStream requestBody(
reinterpret_cast<std::uint8_t const*>(jsonBody.data()), jsonBody.length());
@ -472,14 +495,14 @@ Azure::Response<Models::Table> TableClient::Create(Core::Context const& context)
return Response<Models::Table>(std::move(response), std::move(rawResponse));
}
void Models::ListTablesPagedResponse::OnNextPage(const Azure::Core::Context& context)
void Models::QueryTablesPagedResponse::OnNextPage(const Azure::Core::Context& context)
{
m_operationOptions.ContinuationToken = NextPageToken;
*this = m_tableServiceClient->ListTables(m_operationOptions, context);
*this = m_tableServiceClient->QueryTables(m_operationOptions, context);
}
Models::ListTablesPagedResponse TableServicesClient::ListTables(
Models::ListTablesOptions const& options,
Models::QueryTablesPagedResponse TableServiceClient::QueryTables(
Models::QueryTablesOptions const& options,
Azure::Core::Context const& context) const
{
auto url = m_url;
@ -498,7 +521,7 @@ Models::ListTablesPagedResponse TableServicesClient::ListTables(
throw Core::RequestFailedException(rawResponse);
}
Models::ListTablesPagedResponse response;
Models::QueryTablesPagedResponse response;
{
auto const& responseBody = rawResponse->GetBody();
std::string responseString = std::string(responseBody.begin(), responseBody.end());
@ -521,7 +544,7 @@ Models::ListTablesPagedResponse TableServicesClient::ListTables(
response.ServiceEndpoint = url.GetAbsoluteUrl();
response.Prefix = options.Prefix;
response.m_tableServiceClient = std::make_shared<TableServicesClient>(*this);
response.m_tableServiceClient = std::make_shared<TableServiceClient>(*this);
response.m_operationOptions = options;
response.CurrentPageToken = options.ContinuationToken.ValueOr(std::string());
response.RawResponse = std::move(response.RawResponse);
@ -585,10 +608,12 @@ Azure::Response<Models::TableAccessPolicy> TableClient::GetAccessPolicy(
return Response<Models::TableAccessPolicy>(std::move(response), std::move(pRawResponse));
}
Azure::Response<Models::DeleteResult> TableClient::Delete(Core::Context const& context)
Azure::Response<Models::DeleteTableResult> TableServiceClient::DeleteTable(
std::string const& tableName,
Core::Context const& context)
{
auto url = m_url;
url.AppendPath("Tables('" + m_tableName + "')");
url.AppendPath("Tables('" + tableName + "')");
Core::Http::Request request(Core::Http::HttpMethod::Delete, url);
@ -602,9 +627,9 @@ Azure::Response<Models::DeleteResult> TableClient::Delete(Core::Context const& c
throw Core::RequestFailedException(rawResponse);
}
Models::DeleteResult response{};
Models::DeleteTableResult response{};
return Response<Models::DeleteResult>(std::move(response), std::move(rawResponse));
return Response<Models::DeleteTableResult>(std::move(response), std::move(rawResponse));
}
Azure::Response<Models::CreateEntityResult> TableClient::CreateEntity(
@ -616,19 +641,7 @@ Azure::Response<Models::CreateEntityResult> TableClient::CreateEntity(
auto url = m_url;
url.AppendPath(m_tableName);
std::string jsonBody;
{
auto jsonRoot = Core::Json::_internal::json::object();
jsonRoot["PartitionKey"] = tableEntity.PartitionKey;
jsonRoot["RowKey"] = tableEntity.RowKey;
for (auto entry : tableEntity.Properties)
{
jsonRoot[entry.first] = entry.second;
}
jsonBody = jsonRoot.dump();
}
std::string jsonBody = Serializers::CreateEntity(tableEntity);
Core::IO::MemoryBodyStream requestBody(
reinterpret_cast<std::uint8_t const*>(jsonBody.data()), jsonBody.length());
@ -865,45 +878,19 @@ Models::QueryEntitiesPagedResponse TableClient::QueryEntities(
if (!jsonRoot.contains("value"))
{
response.TableEntities.emplace_back(DeserializeEntity(jsonRoot));
response.TableEntities.emplace_back(Serializers::DeserializeEntity(jsonRoot));
}
else
{
for (auto value : jsonRoot["value"])
{
response.TableEntities.emplace_back(DeserializeEntity(value));
response.TableEntities.emplace_back(Serializers::DeserializeEntity(value));
}
}
}
return response;
}
Models::TableEntity TableClient::DeserializeEntity(Azure::Core::Json::_internal::json json)
{
Models::TableEntity tableEntity{};
if (json.contains("PartitionKey"))
{
tableEntity.PartitionKey = json["PartitionKey"].get<std::string>();
}
if (json.contains("PartitionKey"))
{
tableEntity.RowKey = json["RowKey"].get<std::string>();
}
if (json.contains("PartitionKey"))
{
tableEntity.ETag = json["odata.etag"].get<std::string>();
}
for (auto properties : json.get<std::map<std::string, std::string>>())
{
if (properties.first != "odata.metadata" && properties.first != "PartitionKey"
&& properties.first != "RowKey" && properties.first != "odata.etag")
{
tableEntity.Properties[properties.first] = properties.second;
}
}
return tableEntity;
}
Transaction TableClient::CreateTransaction(std::string const& partitionKey)
{
return Transaction(m_url.GetAbsoluteUrl(), m_tableName, partitionKey);

View File

@ -0,0 +1,155 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
#include "azure/data/tables/tables_sas_builder.hpp"
#include "azure/data/tables/internal/cryptography/hmacsha256.hpp"
#include "azure/data/tables/internal/cryptography/url_encode.hpp"
#include <azure/core/base64.hpp>
#include <azure/core/http/http.hpp>
namespace Azure { namespace Data { namespace Tables { namespace Sas {
namespace {
constexpr static const char* SasVersion = "2019-07-07";
}
void TablesSasBuilder::SetPermissions(TablesSasPermissions permissions)
{
Permissions.clear();
// The order matters
if ((permissions & TablesSasPermissions::Read) == TablesSasPermissions::Read)
{
Permissions += "r";
}
if ((permissions & TablesSasPermissions::Add) == TablesSasPermissions::Add)
{
Permissions += "a";
}
if ((permissions & TablesSasPermissions::Update) == TablesSasPermissions::Update)
{
Permissions += "u";
}
if ((permissions & TablesSasPermissions::Delete) == TablesSasPermissions::Delete)
{
Permissions += "d";
}
}
std::string TablesSasBuilder::GenerateSasToken(
const Azure::Data::Tables::Credentials::SharedKeyCredential& credential)
{
std::string canonicalName
= Azure::Data::Tables::_detail::Cryptography::UrlUtils::UrlEncodeQueryParameter(
GetCanonicalName(credential));
std::string protocol = _detail::SasProtocolToString(Protocol);
std::string startsOnStr = StartsOn.HasValue()
? StartsOn.Value().ToString(
Azure::DateTime::DateFormat::Rfc3339, Azure::DateTime::TimeFractionFormat::Truncate)
: "";
std::string expiresOnStr = ExpiresOn.ToString(
Azure::DateTime::DateFormat::Rfc3339, Azure::DateTime::TimeFractionFormat::Truncate);
// the order here matters
std::string stringToSign = Permissions + "\n" + startsOnStr + "\n" + expiresOnStr + "\n"
+ canonicalName + "\n" + Identifier + "\n" + (IPRange.HasValue() ? IPRange.Value() : "")
+ "\n" + protocol + "\n" + SasVersion + "\n" + PartitionKeyStart + "\n" + RowKeyStart + "\n"
+ PartitionKeyEnd + "\n" + RowKeyEnd;
std::string signature = Azure::Core::Convert::Base64Encode(
Azure::Data::Tables::_detail::Cryptography::HmacSha256::Compute(
std::vector<uint8_t>(stringToSign.begin(), stringToSign.end()),
Azure::Core::Convert::Base64Decode(credential.GetAccountKey())));
Azure::Core::Url builder;
builder.AppendQueryParameter(
"sv",
Azure::Data::Tables::_detail::Cryptography::UrlUtils::UrlEncodeQueryParameter(SasVersion));
builder.AppendQueryParameter(
"tn",
Azure::Data::Tables::_detail::Cryptography::UrlUtils::UrlEncodeQueryParameter(TableName));
builder.AppendQueryParameter(
"spr",
Azure::Data::Tables::_detail::Cryptography::UrlUtils::UrlEncodeQueryParameter(protocol));
if (!startsOnStr.empty())
{
builder.AppendQueryParameter(
"st",
Azure::Data::Tables::_detail::Cryptography::UrlUtils::UrlEncodeQueryParameter(
startsOnStr));
}
if (!expiresOnStr.empty())
{
builder.AppendQueryParameter(
"se",
Azure::Data::Tables::_detail::Cryptography::UrlUtils::UrlEncodeQueryParameter(
expiresOnStr));
}
if (IPRange.HasValue())
{
builder.AppendQueryParameter(
"sip",
Azure::Data::Tables::_detail::Cryptography::UrlUtils::UrlEncodeQueryParameter(
IPRange.Value()));
}
if (!Identifier.empty())
{
builder.AppendQueryParameter(
"si",
Azure::Data::Tables::_detail::Cryptography::UrlUtils::UrlEncodeQueryParameter(
Identifier));
}
if (!Permissions.empty())
{
builder.AppendQueryParameter(
"sp",
Azure::Data::Tables::_detail::Cryptography::UrlUtils::UrlEncodeQueryParameter(
Permissions));
}
builder.AppendQueryParameter(
"sig",
Azure::Data::Tables::_detail::Cryptography::UrlUtils::UrlEncodeQueryParameter(signature));
if (!PartitionKeyStart.empty())
{
builder.AppendQueryParameter(
"spk",
Azure::Data::Tables::_detail::Cryptography::UrlUtils::UrlEncodeQueryParameter(
PartitionKeyStart));
if (!PartitionKeyEnd.empty())
{
builder.AppendQueryParameter(
"epk",
Azure::Data::Tables::_detail::Cryptography::UrlUtils::UrlEncodeQueryParameter(
PartitionKeyEnd));
}
}
if (!RowKeyStart.empty())
{
builder.AppendQueryParameter(
"srk",
Azure::Data::Tables::_detail::Cryptography::UrlUtils::UrlEncodeQueryParameter(
RowKeyStart));
if (!RowKeyEnd.empty())
{
builder.AppendQueryParameter(
"erk",
Azure::Data::Tables::_detail::Cryptography::UrlUtils::UrlEncodeQueryParameter(
RowKeyEnd));
}
}
return builder.GetAbsoluteUrl();
}
}}}} // namespace Azure::Data::Tables::Sas

View File

@ -16,7 +16,10 @@ SetUpTestProxy("sdk/tables")
add_executable (
azure-data-tables-test
enum_operators_test.hpp
enum_operators_test.cpp
macro_guard.cpp
sas_test.cpp
serializers_test.hpp
serializers_test.cpp
shared_key_lite_policy_test.cpp

View File

@ -0,0 +1,147 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
#include "enum_operators_test.hpp"
using namespace Azure::Data::Tables::Sas;
using namespace Azure::Data::Tables;
namespace Azure { namespace Data { namespace Test {
TEST(EnumOperator, AndTest)
{
{
constexpr auto val = TestEnum::One & TestEnum::Two;
EXPECT_EQ(val, TestEnum::Zero);
}
{
auto val = TestEnum::One & TestEnum::One;
EXPECT_EQ(val, TestEnum::One);
}
{
auto val = TestEnum::Two & TestEnum::One;
EXPECT_EQ(val, TestEnum::Zero);
}
{
auto val = TestEnum::Two & TestEnum::Two;
EXPECT_EQ(val, TestEnum::Two);
}
{
auto val = TestEnum::One;
val &= TestEnum::Two;
EXPECT_EQ(val, TestEnum::Zero);
}
{
auto val = TestEnum::One;
val &= TestEnum::One;
EXPECT_EQ(val, TestEnum::One);
}
{
auto val = TestEnum::Two;
val &= TestEnum::One;
EXPECT_EQ(val, TestEnum::Zero);
}
{
auto val = TestEnum::Two;
val &= TestEnum::Two;
EXPECT_EQ(val, TestEnum::Two);
}
}
TEST(EnumOperator, OrTest)
{
{
constexpr auto val = TestEnum::One | TestEnum::Two;
EXPECT_EQ(val, TestEnum::Three);
}
{
auto val = TestEnum::One | TestEnum::One;
EXPECT_EQ(val, TestEnum::One);
}
{
auto val = TestEnum::Two | TestEnum::One;
EXPECT_EQ(val, TestEnum::Three);
}
{
auto val = TestEnum::Two | TestEnum::Two;
EXPECT_EQ(val, TestEnum::Two);
}
{
auto val = TestEnum::One;
val |= TestEnum::Two;
EXPECT_EQ(val, TestEnum::Three);
}
{
auto val = TestEnum::One;
val |= TestEnum::One;
EXPECT_EQ(val, TestEnum::One);
}
{
auto val = TestEnum::Two;
val |= TestEnum::One;
EXPECT_EQ(val, TestEnum::Three);
}
{
auto val = TestEnum::Two;
val |= TestEnum::Two;
EXPECT_EQ(val, TestEnum::Two);
}
}
TEST(EnumOperator, XorTest)
{
{
constexpr auto val = TestEnum::One ^ TestEnum::Two;
EXPECT_EQ(val, TestEnum::Three);
}
{
auto val = TestEnum::One ^ TestEnum::One;
EXPECT_EQ(val, TestEnum::Zero);
}
{
auto val = TestEnum::Two ^ TestEnum::One;
EXPECT_EQ(val, TestEnum::Three);
}
{
auto val = TestEnum::Two ^ TestEnum::Two;
EXPECT_EQ(val, TestEnum::Zero);
}
{
auto val = TestEnum::One;
val ^= TestEnum::Two;
EXPECT_EQ(val, TestEnum::Three);
}
{
auto val = TestEnum::One;
val ^= TestEnum::One;
EXPECT_EQ(val, TestEnum::Zero);
}
{
auto val = TestEnum::Two;
val ^= TestEnum::One;
EXPECT_EQ(val, TestEnum::Three);
}
{
auto val = TestEnum::Two;
val ^= TestEnum::Two;
EXPECT_EQ(val, TestEnum::Zero);
}
}
TEST(EnumOperator, ComplementTest)
{
{
constexpr auto val = ~TestEnum::Zero;
EXPECT_EQ(val, TestEnum::All);
}
{
auto val = ~TestEnum::All;
EXPECT_EQ(val, TestEnum::Zero);
}
{
auto val = ~~TestEnum::Zero;
EXPECT_EQ(val, TestEnum::Zero);
}
{
auto val = ~~TestEnum::One;
EXPECT_EQ(val, TestEnum::One);
}
}
}}} // namespace Azure::Data::Test

View File

@ -0,0 +1,21 @@
#pragma once
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
// clang-format off
#include "azure/data/tables/account_sas_builder.hpp"
#include "azure/data/tables/tables_sas_builder.hpp"
#include "test/ut/test_base.hpp"
namespace Azure { namespace Data { namespace Test {
enum class TestEnum
{
Zero = 0,
One = 1,
Two = 2,
Three = 3,
All = ~0
};
class EnumOperator : public Azure::Core::Test::TestBase {};
}}} // namespace Azure::Data::Test

View File

@ -0,0 +1,133 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
#include "sas_test.hpp"
#include <chrono>
#include <sstream>
#include <string>
#include <thread>
using namespace Azure::Data::Tables::Sas;
// cspell: words rwdxylacupitf raud bqft
namespace Azure { namespace Data { namespace Test {
TEST(SasTest, TableSasBuilderTestAllSet)
{
TablesSasBuilder sasBuilder;
sasBuilder.SetPermissions(TablesSasPermissions::All);
sasBuilder.Protocol = SasProtocol::HttpsAndHttp;
sasBuilder.StartsOn
= Azure::DateTime::Parse("2020-08-18T00:00:00Z", Azure::DateTime::DateFormat::Rfc3339);
sasBuilder.ExpiresOn
= Azure::DateTime::Parse("2022-08-18T00:00:00Z", Azure::DateTime::DateFormat::Rfc3339);
sasBuilder.Identifier = "myIdentifier";
sasBuilder.IPRange = "iprange";
sasBuilder.TableName = "myTableName";
sasBuilder.RowKeyEnd = "myRowKeyEnd";
sasBuilder.RowKeyStart = "myRowKeyStart";
sasBuilder.PartitionKeyStart = "myStartPartitionKey";
sasBuilder.PartitionKeyEnd = "myEndPartitionKey";
std::string key = "accountKey";
Azure::Data::Tables::Credentials::SharedKeyCredential cred(
"accountName",
Azure::Core::Convert::Base64Encode(std::vector<uint8_t>(key.begin(), key.end())));
auto sasToken = sasBuilder.GenerateSasToken(cred);
auto sasParts = SasTest::ParseQueryParameters(sasToken);
EXPECT_EQ(sasParts.at("si"), "myIdentifier");
EXPECT_EQ(sasParts.at("sp"), "raud");
EXPECT_EQ(sasParts.at("st"), "2020-08-18T00:00:00Z");
EXPECT_EQ(sasParts.at("se"), "2022-08-18T00:00:00Z");
EXPECT_EQ(sasParts.at("sip"), "iprange");
EXPECT_EQ(sasParts.at("spr"), "https,http");
EXPECT_FALSE(sasParts.at("sig").empty());
EXPECT_EQ(sasParts.at("srk"), "myRowKeyStart");
EXPECT_EQ(sasParts.at("erk"), "myRowKeyEnd");
EXPECT_EQ(sasParts.at("spk"), "myStartPartitionKey");
EXPECT_EQ(sasParts.at("?epk"), "myEndPartitionKey");
}
TEST(SasTest, TableSasBuilderTestSomeSet)
{
TablesSasBuilder sasBuilder;
sasBuilder.Protocol = SasProtocol::HttpsAndHttp;
sasBuilder.ExpiresOn
= Azure::DateTime::Parse("2022-03-11T11:13:52Z", Azure::DateTime::DateFormat::Rfc3339);
sasBuilder.SetPermissions(TablesSasPermissions::Add);
sasBuilder.TableName = "someTableName";
std::string key = "*";
Azure::Data::Tables::Credentials::SharedKeyCredential cred(
"someaccount",
Azure::Core::Convert::Base64Encode(std::vector<uint8_t>(key.begin(), key.end())));
auto sasToken = sasBuilder.GenerateSasToken(cred);
auto sasParts = SasTest::ParseQueryParameters(sasToken);
EXPECT_EQ(sasParts.at("?se"), "2022-03-11T11:13:52Z");
EXPECT_EQ(sasParts.at("sp"), "a");
EXPECT_EQ(sasParts.at("spr"), "https,http");
EXPECT_EQ(sasParts.at("tn"), "someTableName");
}
TEST(SasTest, TableSasBuilderTestMin)
{
TablesSasBuilder sasBuilder;
sasBuilder.ExpiresOn
= Azure::DateTime::Parse("2022-08-18T00:00:00Z", Azure::DateTime::DateFormat::Rfc3339);
std::string key = "accountKey";
Azure::Data::Tables::Credentials::SharedKeyCredential cred(
"accountName",
Azure::Core::Convert::Base64Encode(std::vector<uint8_t>(key.begin(), key.end())));
auto sasToken = sasBuilder.GenerateSasToken(cred);
auto sasParts = SasTest::ParseQueryParameters(sasToken);
EXPECT_FALSE(sasParts.at("sig").empty());
}
TEST(SasTest, AccountSasBuilderTestAllSet)
{
AccountSasBuilder sasBuilder;
sasBuilder.SetPermissions(AccountSasPermissions::All);
sasBuilder.Protocol = SasProtocol::HttpsAndHttp;
sasBuilder.StartsOn
= Azure::DateTime::Parse("2020-08-18T00:00:00Z", Azure::DateTime::DateFormat::Rfc3339);
sasBuilder.ExpiresOn
= Azure::DateTime::Parse("2022-08-18T00:00:00Z", Azure::DateTime::DateFormat::Rfc3339);
sasBuilder.IPRange = "iprange";
sasBuilder.EncryptionScope = "myScope";
sasBuilder.ResourceTypes = AccountSasResource::All;
sasBuilder.Services = AccountSasServices::All;
std::string key = "accountKey";
Azure::Data::Tables::Credentials::SharedKeyCredential cred(
"accountName",
Azure::Core::Convert::Base64Encode(std::vector<uint8_t>(key.begin(), key.end())));
auto sasToken = sasBuilder.GenerateSasToken(cred);
auto sasParts = SasTest::ParseQueryParameters(sasToken);
EXPECT_EQ(sasParts.at("?se"), "2022-08-18T00:00:00Z");
EXPECT_EQ(sasParts.at("ses"), "myScope");
EXPECT_FALSE(sasParts.at("sig").empty());
EXPECT_EQ(sasParts.at("sip"), "iprange");
EXPECT_EQ(sasParts.at("sp"), "rwdxylacupitf");
EXPECT_EQ(sasParts.at("spr"), "https,http");
EXPECT_EQ(sasParts.at("srt"), "sco");
EXPECT_EQ(sasParts.at("ss"), "bqft");
EXPECT_EQ(sasParts.at("st"), "2020-08-18T00:00:00Z");
EXPECT_EQ(sasParts.at("sv"), "2023-08-03");
}
TEST(SasTest, AccountSasBuilderTestMin)
{
AccountSasBuilder sasBuilder;
sasBuilder.SetPermissions(AccountSasPermissions::All);
sasBuilder.ExpiresOn
= Azure::DateTime::Parse("2022-08-18T00:00:00Z", Azure::DateTime::DateFormat::Rfc3339);
std::string key = "accountKey";
Azure::Data::Tables::Credentials::SharedKeyCredential cred(
"accountName",
Azure::Core::Convert::Base64Encode(std::vector<uint8_t>(key.begin(), key.end())));
auto sasToken = sasBuilder.GenerateSasToken(cred);
auto sasParts = SasTest::ParseQueryParameters(sasToken);
EXPECT_FALSE(sasParts.at("sig").empty());
}
}}} // namespace Azure::Data::Test

View File

@ -0,0 +1,30 @@
#pragma once
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
#include "azure/data/tables/account_sas_builder.hpp"
#include "azure/data/tables/tables_sas_builder.hpp"
#include "test/ut/test_base.hpp"
namespace Azure { namespace Data { namespace Test {
class SasTest : public Azure::Core::Test::TestBase {
public:
static std::map<std::string, std::string> ParseQueryParameters(const std::string& query)
{
std::map<std::string, std::string> result;
auto parameters = Azure::Core::_internal::StringExtensions::Split(query, '&');
for (const auto& p : parameters)
{
auto keyValue = Azure::Core::_internal::StringExtensions::Split(p, '=');
if (keyValue.size() == 2)
{
result[keyValue[0]] = keyValue[1];
}
}
return result;
}
};
}}} // namespace Azure::Data::Test

View File

@ -4,12 +4,14 @@
#include "table_client_test.hpp"
#include "azure/data/tables/account_sas_builder.hpp"
#include "azure/data/tables/tables_sas_builder.hpp"
#include <azure/core/internal/strings.hpp>
#include <chrono>
#include <string>
#include <thread>
using namespace Azure::Data;
namespace Azure { namespace Data { namespace Test {
std::shared_ptr<Azure::Core::Credentials::TokenCredential> m_credential;
@ -34,8 +36,8 @@ namespace Azure { namespace Data { namespace Test {
switch (param)
{
case AuthType::ConnectionString:
m_tableServiceClient = std::make_shared<Tables::TableServicesClient>(
Tables::TableServicesClient::CreateFromConnectionString(
m_tableServiceClient = std::make_shared<Tables::TableServiceClient>(
Tables::TableServiceClient::CreateFromConnectionString(
GetEnv("STANDARD_STORAGE_CONNECTION_STRING"), clientOptions));
m_tableClient = std::make_shared<Tables::TableClient>(
Tables::TableClient::CreateFromConnectionString(
@ -43,8 +45,8 @@ namespace Azure { namespace Data { namespace Test {
break;
case AuthType::Key:
m_credential = GetTestCredential();
m_tableServiceClient = std::make_shared<Tables::TableServicesClient>(
Azure::Data::Tables::TableServicesClient(
m_tableServiceClient = std::make_shared<Tables::TableServiceClient>(
Azure::Data::Tables::TableServiceClient(
"https://" + GetAccountName() + ".table.core.windows.net/",
m_credential,
clientOptions));
@ -63,15 +65,23 @@ namespace Azure { namespace Data { namespace Test {
sasBuilder.Services = Azure::Data::Tables::Sas::AccountSasServices::All;
sasBuilder.Protocol = Azure::Data::Tables::Sas::SasProtocol::HttpsOnly;
sasBuilder.SetPermissions(Azure::Data::Tables::Sas::AccountSasPermissions::All);
auto sasToken = sasBuilder.GenerateSasToken(*creds);
m_tableServiceClient
= std::make_shared<Tables::TableServicesClient>(Tables::TableServicesClient(
"https://" + GetAccountName() + ".table.core.windows.net/" + sasToken,
clientOptions));
m_tableClient = std::make_shared<Tables::TableClient>(Tables::TableClient(
"https://" + GetAccountName() + ".table.core.windows.net/" + sasToken,
m_tableName,
tableClientOptions));
std::string serviceUrl = "https://" + GetAccountName() + ".table.core.windows.net/";
auto sasCreds = std::make_shared<Azure::Data::Tables::Credentials::AzureSasCredential>(
sasBuilder.GenerateSasToken(*creds));
m_tableServiceClient = std::make_shared<Tables::TableServiceClient>(
Tables::TableServiceClient(serviceUrl, sasCreds, clientOptions));
Azure::Data::Tables::Sas::TablesSasBuilder tableSasBuilder;
tableSasBuilder.Protocol = Azure::Data::Tables::Sas::SasProtocol::HttpsOnly;
tableSasBuilder.StartsOn = std::chrono::system_clock::now() - std::chrono::minutes(5);
tableSasBuilder.ExpiresOn = std::chrono::system_clock::now() + std::chrono::minutes(60);
tableSasBuilder.SetPermissions(Azure::Data::Tables::Sas::TablesSasPermissions::All);
tableSasBuilder.TableName = m_tableName;
auto tableSasCreds
= std::make_shared<Azure::Data::Tables::Credentials::AzureSasCredential>(
tableSasBuilder.GenerateSasToken(*creds));
m_tableClient = std::make_shared<Tables::TableClient>(
Tables::TableClient(serviceUrl, tableSasCreds, m_tableName, tableClientOptions));
break;
}
}
@ -83,8 +93,7 @@ namespace Azure { namespace Data { namespace Test {
{
try
{
auto deleteResponse = m_tableClient->Delete();
auto deleteResponse = m_tableServiceClient->DeleteTable(m_tableName);
}
catch (...)
{
@ -115,7 +124,7 @@ namespace Azure { namespace Data { namespace Test {
TEST_P(TablesClientTest, CreateTable)
{
auto createResponse = m_tableClient->Create();
auto createResponse = m_tableServiceClient->CreateTable(m_tableName);
EXPECT_EQ(createResponse.Value.TableName, m_tableName);
EXPECT_EQ(createResponse.Value.EditLink, "Tables('" + m_tableName + "')");
EXPECT_TRUE(createResponse.Value.Type.find(".Tables") != std::string::npos);
@ -129,7 +138,7 @@ namespace Azure { namespace Data { namespace Test {
SkipTest();
return;
}
auto createResponse = m_tableClient->Create();
auto createResponse = m_tableServiceClient->CreateTable(m_tableName);
auto getResponse = m_tableClient->GetAccessPolicy();
EXPECT_EQ(getResponse.Value.SignedIdentifiers.size(), 0);
@ -142,7 +151,7 @@ namespace Azure { namespace Data { namespace Test {
SkipTest();
return;
}
auto createResponse = m_tableClient->Create();
auto createResponse = m_tableServiceClient->CreateTable(m_tableName);
Azure::Data::Tables::Models::TableAccessPolicy newPolicy{};
Azure::Data::Tables::Models::SignedIdentifier newIdentifier{};
newIdentifier.Id = "testid";
@ -179,12 +188,11 @@ namespace Azure { namespace Data { namespace Test {
}
else
{
auto createResponse = m_tableServiceClient->CreateTable(m_tableName);
auto createResponse = m_tableClient->Create();
Azure::Data::Tables::Models::QueryTablesOptions listOptions;
Azure::Data::Tables::Models::ListTablesOptions listOptions;
auto listResponse = m_tableServiceClient->ListTables(listOptions);
auto listResponse = m_tableServiceClient->QueryTables(listOptions);
for (auto table : listResponse.Tables)
{
@ -201,9 +209,9 @@ namespace Azure { namespace Data { namespace Test {
TEST_P(TablesClientTest, DeleteTable)
{
auto createResponse = m_tableClient->Create();
auto createResponse = m_tableServiceClient->CreateTable(m_tableName);
auto response = m_tableClient->Delete();
auto response = m_tableServiceClient->DeleteTable(m_tableName);
EXPECT_EQ(response.RawResponse->GetStatusCode(), Azure::Core::Http::HttpStatusCode::NoContent);
}
@ -266,7 +274,7 @@ namespace Azure { namespace Data { namespace Test {
entity.RowKey = "R1";
entity.Properties["Name"] = "Azure";
entity.Properties["Product"] = "Tables";
auto createResponse = m_tableClient->Create();
auto createResponse = m_tableServiceClient->CreateTable(m_tableName);
auto response = m_tableClient->CreateEntity(entity);
EXPECT_EQ(response.RawResponse->GetStatusCode(), Azure::Core::Http::HttpStatusCode::NoContent);
@ -287,7 +295,7 @@ namespace Azure { namespace Data { namespace Test {
entity.RowKey = "R1";
entity.Properties["Name"] = "Azure";
entity.Properties["Product"] = "Tables";
auto createResponse = m_tableClient->Create();
auto createResponse = m_tableServiceClient->CreateTable(m_tableName);
auto response = m_tableClient->CreateEntity(entity);
EXPECT_EQ(response.RawResponse->GetStatusCode(), Azure::Core::Http::HttpStatusCode::NoContent);
EXPECT_FALSE(response.Value.ETag.empty());
@ -322,7 +330,7 @@ namespace Azure { namespace Data { namespace Test {
entity.RowKey = "R1";
entity.Properties["Name"] = "Azure";
entity.Properties["Product"] = "Tables";
auto createResponse = m_tableClient->Create();
auto createResponse = m_tableServiceClient->CreateTable(m_tableName);
auto response = m_tableClient->CreateEntity(entity);
EXPECT_EQ(response.RawResponse->GetStatusCode(), Azure::Core::Http::HttpStatusCode::NoContent);
EXPECT_FALSE(response.Value.ETag.empty());
@ -357,7 +365,7 @@ namespace Azure { namespace Data { namespace Test {
entity.RowKey = "R1";
entity.Properties["Name"] = "Azure";
entity.Properties["Product"] = "Tables";
auto createResponse = m_tableClient->Create();
auto createResponse = m_tableServiceClient->CreateTable(m_tableName);
auto response = m_tableClient->CreateEntity(entity);
EXPECT_EQ(response.RawResponse->GetStatusCode(), Azure::Core::Http::HttpStatusCode::NoContent);
EXPECT_FALSE(response.Value.ETag.empty());
@ -393,7 +401,7 @@ namespace Azure { namespace Data { namespace Test {
entity.RowKey = "R1";
entity.Properties["Name"] = "Azure";
entity.Properties["Product"] = "Tables";
auto createResponse = m_tableClient->Create();
auto createResponse = m_tableServiceClient->CreateTable(m_tableName);
auto response = m_tableClient->UpsertEntity(entity);
EXPECT_EQ(response.RawResponse->GetStatusCode(), Azure::Core::Http::HttpStatusCode::NoContent);
EXPECT_FALSE(response.Value.ETag.empty());
@ -433,7 +441,7 @@ namespace Azure { namespace Data { namespace Test {
entity.RowKey = "R1";
entity.Properties["Name"] = "Azure";
entity.Properties["Product"] = "Tables";
auto createResponse = m_tableClient->Create();
auto createResponse = m_tableServiceClient->CreateTable(m_tableName);
auto response = m_tableClient->CreateEntity(entity);
EXPECT_EQ(response.RawResponse->GetStatusCode(), Azure::Core::Http::HttpStatusCode::NoContent);
EXPECT_FALSE(response.Value.ETag.empty());
@ -473,7 +481,7 @@ namespace Azure { namespace Data { namespace Test {
entity2.RowKey = "R1";
entity2.Properties["Name"] = "Azure";
entity2.Properties["Product"] = "Tables";
auto createResponse = m_tableClient->Create();
auto createResponse = m_tableServiceClient->CreateTable(m_tableName);
auto transaction = m_tableClient->CreateTransaction("P1");
transaction.CreateEntity(entity);
@ -501,7 +509,7 @@ namespace Azure { namespace Data { namespace Test {
entity2.RowKey = "R2";
entity2.Properties["Name"] = "Azure";
entity2.Properties["Product"] = "Tables";
auto createResponse = m_tableClient->Create();
auto createResponse = m_tableServiceClient->CreateTable(m_tableName);
auto transaction = m_tableClient->CreateTransaction("P1");
transaction.CreateEntity(entity);
@ -529,7 +537,7 @@ namespace Azure { namespace Data { namespace Test {
entity2.RowKey = "R2";
entity2.Properties["Name"] = "Azure";
entity2.Properties["Product"] = "Tables";
auto createResponse = m_tableClient->Create();
auto createResponse = m_tableServiceClient->CreateTable(m_tableName);
auto transaction = m_tableClient->CreateTransaction("P1");
transaction.CreateEntity(entity);
@ -563,7 +571,7 @@ namespace Azure { namespace Data { namespace Test {
entity2.RowKey = "R1";
entity2.Properties["Name"] = "Azure2";
entity2.Properties["Product"] = "Tables3";
auto createResponse = m_tableClient->Create();
auto createResponse = m_tableServiceClient->CreateTable(m_tableName);
auto transaction = m_tableClient->CreateTransaction("P1");
transaction.CreateEntity(entity);
@ -596,7 +604,7 @@ namespace Azure { namespace Data { namespace Test {
entity2.RowKey = "R1";
entity2.Properties["Name"] = "Azure2";
entity2.Properties["Product"] = "Tables3";
auto createResponse = m_tableClient->Create();
auto createResponse = m_tableServiceClient->CreateTable(m_tableName);
auto transaction = m_tableClient->CreateTransaction("P1");
transaction.CreateEntity(entity);

View File

@ -55,7 +55,7 @@ namespace Azure { namespace Data { namespace Test {
protected:
std::string m_tableName;
std::shared_ptr<Tables::TableServicesClient> m_tableServiceClient;
std::shared_ptr<Tables::TableServiceClient> m_tableServiceClient;
std::shared_ptr<Tables::TableClient> m_tableClient;
};
}}} // namespace Azure::Data::Test