parent
153a6dd8b8
commit
50a4186d96
@ -2,6 +2,10 @@
|
||||
|
||||
## 1.0.0-beta.5 (Unreleased)
|
||||
|
||||
### New Features
|
||||
|
||||
- Added support for HTTP validators `ETag`.
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
- Make `ToLower` and `LocaleInvariantCaseInsensitiveEqual` internal by moving them from `Azure::Core::Strings` to `Azure::Core::Internal::Strings`.
|
||||
|
||||
@ -60,6 +60,7 @@ set(
|
||||
inc/azure/core/credentials.hpp
|
||||
inc/azure/core/datetime.hpp
|
||||
inc/azure/core/dll_import_export.hpp
|
||||
inc/azure/core/etag.hpp
|
||||
inc/azure/core/exception.hpp
|
||||
inc/azure/core/nullable.hpp
|
||||
inc/azure/core/operation.hpp
|
||||
|
||||
@ -15,6 +15,7 @@
|
||||
#include "azure/core/credentials.hpp"
|
||||
#include "azure/core/datetime.hpp"
|
||||
#include "azure/core/dll_import_export.hpp"
|
||||
#include "azure/core/etag.hpp"
|
||||
#include "azure/core/nullable.hpp"
|
||||
#include "azure/core/response.hpp"
|
||||
#include "azure/core/uuid.hpp"
|
||||
|
||||
195
sdk/core/azure-core/inc/azure/core/etag.hpp
Normal file
195
sdk/core/azure-core/inc/azure/core/etag.hpp
Normal file
@ -0,0 +1,195 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Define ETag.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "azure/core/nullable.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace Azure { namespace Core {
|
||||
|
||||
/**
|
||||
* @brief Represents an HTTP validator.
|
||||
*/
|
||||
class ETag {
|
||||
// ETag is a validator based on https://tools.ietf.org/html/rfc7232#section-2.3.2
|
||||
private:
|
||||
Nullable<std::string> m_value;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief The comparison type.
|
||||
*/
|
||||
enum class ETagComparison
|
||||
{
|
||||
Strong,
|
||||
Weak
|
||||
};
|
||||
|
||||
/*
|
||||
2.3.2. Comparison
|
||||
|
||||
There are two entity-tag comparison functions, depending on whether
|
||||
or not the comparison context allows the use of weak validators:
|
||||
|
||||
o Strong comparison: two entity-tags are equivalent if both are not
|
||||
weak and their opaque-tags match character-by-character.
|
||||
|
||||
o Weak comparison: two entity-tags are equivalent if their
|
||||
opaque-tags match character-by-character, regardless of either or
|
||||
both being tagged as "weak".
|
||||
|
||||
+--------+--------+-------------------+-----------------+
|
||||
| ETag 1 | ETag 2 | Strong Comparison | Weak Comparison |
|
||||
+--------+--------+-------------------+-----------------+
|
||||
| W/"1" | W/"1" | no match | match |
|
||||
| W/"1" | W/"2" | no match | no match |
|
||||
| W/"1" | "1" | no match | match |
|
||||
| "1" | "1" | match | match |
|
||||
+--------+--------+-------------------+-----------------+
|
||||
|
||||
// etag: //This is possible and means no etag is present
|
||||
// etag:""
|
||||
// etag:"*" //This means the etag is value '*'
|
||||
// etag:"some value" //This means the etag is value 'some value'
|
||||
// etag:/W"" //Weak eTag
|
||||
// etag:* //This is special, means any etag
|
||||
// If-Match header can do this
|
||||
// If-Match:"value1","value2","value3" // Do this if any of these match
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
* @brief Indicates whether two #ETag values are equal.
|
||||
* @param left #ETag to compare.
|
||||
* @param right #ETag to compare.
|
||||
* @param comparisonKind Determines what #ETagComparison to perform, default is
|
||||
* #ETagComparison Strong.
|
||||
* @return `true` if #ETag matches, `false` otherwise.
|
||||
*/
|
||||
static bool Equals(
|
||||
const ETag& left,
|
||||
const ETag& right,
|
||||
const ETagComparison comparisonKind = ETagComparison::Strong)
|
||||
{
|
||||
// ETags are != if one of the values is null
|
||||
if (!left.m_value || !right.m_value)
|
||||
{
|
||||
// Caveat, If both values are null then we consider the ETag equal
|
||||
return !left.m_value && !right.m_value;
|
||||
}
|
||||
|
||||
switch (comparisonKind)
|
||||
{
|
||||
case ETagComparison::Strong:
|
||||
// Strong comparison
|
||||
// If either is weak then there is no match
|
||||
// else tags must match character for character
|
||||
return !left.IsWeak() && !right.IsWeak()
|
||||
&& (left.m_value.GetValue().compare(right.m_value.GetValue()) == 0);
|
||||
break;
|
||||
|
||||
case ETagComparison::Weak:
|
||||
|
||||
auto leftStart = left.IsWeak() ? 2 : 0;
|
||||
auto rightStart = right.IsWeak() ? 2 : 0;
|
||||
|
||||
auto leftVal = left.m_value.GetValue();
|
||||
auto rightVal = right.m_value.GetValue();
|
||||
|
||||
// Compare if lengths are equal
|
||||
// Compare the strings character by character
|
||||
return ((leftVal.length() - leftStart) == (rightVal.length() - rightStart))
|
||||
&& (leftVal.compare(leftStart, leftVal.length() - leftStart, &rightVal[rightStart])
|
||||
== 0);
|
||||
break;
|
||||
}
|
||||
// Unknown comparison
|
||||
abort();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Construct an empty (null) #ETag.
|
||||
*/
|
||||
ETag() = default;
|
||||
|
||||
/**
|
||||
* @brief Construct a #ETag.
|
||||
* @param etag The string value representation.
|
||||
*/
|
||||
explicit ETag(std::string etag) : m_value(std::move(etag)) {}
|
||||
|
||||
/**
|
||||
* @brief Whether #ETag is present.
|
||||
* @return `true` if #ETag has a value, `false` otherwise.
|
||||
*/
|
||||
bool HasValue() const { return m_value.HasValue(); }
|
||||
|
||||
/*
|
||||
* @brief Returns the resource metadata represented as a string.
|
||||
* @return #std::string
|
||||
*/
|
||||
const std::string& ToString() const
|
||||
{
|
||||
if (!m_value.HasValue())
|
||||
{
|
||||
abort();
|
||||
}
|
||||
return m_value.GetValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Compare with \p other #ETag for equality.
|
||||
* @param other Other #ETag to compare with.
|
||||
* @return `true` if #ETag instances are equal according to strong validation, `false`
|
||||
* otherwise.
|
||||
*/
|
||||
bool operator==(const ETag& other) const
|
||||
{
|
||||
return Equals(*this, other, ETagComparison::Strong);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Compare with \p other #ETag for inequality.
|
||||
* @param other Other #ETag to compare with.
|
||||
* @return `true` if #ETag instances are not equal according to strong validation, `false`
|
||||
* otherwise.
|
||||
*/
|
||||
bool operator!=(const ETag& other) const { return !(*this == other); }
|
||||
|
||||
/**
|
||||
* @brief Specifies whether the #ETag is strong or weak.
|
||||
* @return `true` if #ETag is a weak validator, `false` otherwise.
|
||||
*/
|
||||
bool IsWeak() const
|
||||
{
|
||||
// Null ETag is considered Strong
|
||||
// Shortest valid weak etag has length of 4
|
||||
// W/""
|
||||
// Valid weak format must start with W/"
|
||||
// Must end with a /"
|
||||
const bool weak = m_value && (m_value.GetValue().length() >= 4)
|
||||
&& ((m_value.GetValue()[0] == 'W') && (m_value.GetValue()[1] == '/')
|
||||
&& (m_value.GetValue()[2] == '"')
|
||||
&& (m_value.GetValue()[m_value.GetValue().size() - 1] == '"'));
|
||||
|
||||
return weak;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief #ETag representing everything.
|
||||
* @notes The any #ETag is *, (unquoted). It is NOT the same as "*".
|
||||
*/
|
||||
static const ETag& Any()
|
||||
{
|
||||
static ETag any = ETag("*");
|
||||
return any;
|
||||
}
|
||||
};
|
||||
}} // namespace Azure::Core
|
||||
@ -35,6 +35,7 @@ add_executable (
|
||||
${CURL_OPTIONS_TESTS}
|
||||
${CURL_SESSION_TESTS}
|
||||
datetime.cpp
|
||||
etag.cpp
|
||||
http.cpp
|
||||
json.cpp
|
||||
logging.cpp
|
||||
|
||||
234
sdk/core/azure-core/test/ut/etag.cpp
Normal file
234
sdk/core/azure-core/test/ut/etag.cpp
Normal file
@ -0,0 +1,234 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <azure/core/etag.hpp>
|
||||
|
||||
#include <limits>
|
||||
|
||||
using namespace Azure::Core;
|
||||
|
||||
TEST(ETag, ToString)
|
||||
{
|
||||
auto et1 = ETag("tag");
|
||||
EXPECT_EQ(et1.ToString(), "tag");
|
||||
|
||||
auto et2 = ETag("\"tag\"");
|
||||
EXPECT_EQ(et2.ToString(), "\"tag\"");
|
||||
|
||||
auto et3 = ETag("W/\"weakETag\"");
|
||||
EXPECT_EQ(et3.ToString(), "W/\"weakETag\"");
|
||||
|
||||
auto strongETag
|
||||
= ETag("\"#$%&'()*+,-./"
|
||||
"0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\"");
|
||||
|
||||
EXPECT_EQ(
|
||||
strongETag.ToString(),
|
||||
"\"#$%&'()*+,-./"
|
||||
"0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\"");
|
||||
}
|
||||
|
||||
TEST(ETag, IsWeak)
|
||||
{
|
||||
auto et1 = ETag("tag");
|
||||
EXPECT_FALSE(et1.IsWeak());
|
||||
|
||||
auto et2 = ETag("\"tag\"");
|
||||
EXPECT_FALSE(et2.IsWeak());
|
||||
|
||||
auto et3 = ETag("W/\"weakETag\"");
|
||||
EXPECT_TRUE(et3.IsWeak());
|
||||
|
||||
auto et4 = ETag("W/\"\"");
|
||||
EXPECT_TRUE(et4.IsWeak());
|
||||
|
||||
auto any = ETag::Any();
|
||||
EXPECT_FALSE(any.IsWeak());
|
||||
}
|
||||
|
||||
TEST(ETag, Equals)
|
||||
{
|
||||
ETag empty;
|
||||
ETag empty2;
|
||||
|
||||
auto weakTag = ETag("W/\"\"");
|
||||
auto weakTag1 = ETag("W/\"1\"");
|
||||
auto weakTag2 = ETag("W/\"Two\"");
|
||||
auto strongTag1 = ETag("\"1\"");
|
||||
auto strongTag2 = ETag("\"Two\"");
|
||||
auto strongTagValidChars
|
||||
= ETag("\"#$%&'()*+,-./"
|
||||
"0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\"");
|
||||
auto weakTagValidChars
|
||||
= ETag("W/\"#$%&'()*+,-./"
|
||||
"0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\"");
|
||||
|
||||
EXPECT_TRUE(empty == empty);
|
||||
EXPECT_TRUE(empty2 == empty2);
|
||||
EXPECT_TRUE(empty == empty2);
|
||||
|
||||
EXPECT_FALSE(weakTag == weakTag);
|
||||
EXPECT_FALSE(weakTag1 == weakTag1);
|
||||
EXPECT_FALSE(weakTag2 == weakTag2);
|
||||
EXPECT_FALSE(weakTagValidChars == weakTagValidChars);
|
||||
EXPECT_TRUE(strongTag1 == strongTag1);
|
||||
EXPECT_TRUE(strongTag2 == strongTag2);
|
||||
EXPECT_TRUE(strongTagValidChars == strongTagValidChars);
|
||||
|
||||
EXPECT_TRUE(weakTag != weakTag);
|
||||
EXPECT_TRUE(weakTag1 != weakTag1);
|
||||
EXPECT_TRUE(weakTag2 != weakTag2);
|
||||
EXPECT_TRUE(weakTagValidChars != weakTagValidChars);
|
||||
EXPECT_FALSE(strongTag1 != strongTag1);
|
||||
EXPECT_FALSE(strongTag2 != strongTag2);
|
||||
EXPECT_FALSE(strongTagValidChars != strongTagValidChars);
|
||||
|
||||
EXPECT_FALSE(weakTag == weakTag1);
|
||||
EXPECT_FALSE(weakTag1 == weakTag);
|
||||
EXPECT_FALSE(weakTagValidChars == strongTagValidChars);
|
||||
|
||||
EXPECT_TRUE(weakTag != weakTag1);
|
||||
EXPECT_TRUE(weakTag1 != weakTag);
|
||||
EXPECT_TRUE(weakTagValidChars != strongTagValidChars);
|
||||
|
||||
EXPECT_FALSE(weakTag1 == weakTag2);
|
||||
EXPECT_FALSE(weakTag1 == strongTag1);
|
||||
EXPECT_FALSE(strongTag1 == weakTag1);
|
||||
|
||||
EXPECT_TRUE(weakTag1 != weakTag2);
|
||||
EXPECT_TRUE(weakTag1 != strongTag1);
|
||||
EXPECT_TRUE(strongTag1 != weakTag1);
|
||||
|
||||
EXPECT_FALSE(weakTag2 == strongTag2);
|
||||
EXPECT_FALSE(strongTag2 == weakTag2);
|
||||
|
||||
EXPECT_TRUE(weakTag2 != strongTag2);
|
||||
EXPECT_TRUE(strongTag2 != weakTag2);
|
||||
}
|
||||
|
||||
TEST(ETag, Any)
|
||||
{
|
||||
auto anyETag = ETag::Any();
|
||||
auto star = ETag("*");
|
||||
auto weakStar = ETag("W\"*\"");
|
||||
auto quotedStar = ETag("\"*\"");
|
||||
|
||||
auto strongETag
|
||||
= ETag("\"#$%&'()*+,-./"
|
||||
"0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\"");
|
||||
|
||||
EXPECT_TRUE(anyETag == anyETag);
|
||||
EXPECT_TRUE(anyETag == ETag::Any());
|
||||
EXPECT_FALSE(anyETag == strongETag);
|
||||
|
||||
EXPECT_TRUE(star == star);
|
||||
EXPECT_TRUE(star == ETag::Any());
|
||||
EXPECT_TRUE(star == anyETag);
|
||||
|
||||
EXPECT_FALSE(star == weakStar);
|
||||
EXPECT_FALSE(weakStar == anyETag);
|
||||
EXPECT_FALSE(quotedStar == weakStar);
|
||||
|
||||
EXPECT_FALSE(star == quotedStar);
|
||||
EXPECT_TRUE(anyETag == star);
|
||||
}
|
||||
|
||||
TEST(ETag, EqualsStrong)
|
||||
{
|
||||
// W/""
|
||||
auto weakTag = ETag("W/\"\"");
|
||||
// W/"1"
|
||||
auto weakTag1 = ETag("W/\"1\"");
|
||||
// W/"Two"
|
||||
auto weakTagTwo = ETag("W/\"Two\"");
|
||||
// W/"two"
|
||||
auto weakTagtwo = ETag("W/\"two\"");
|
||||
// "1"
|
||||
auto strongTag1 = ETag("\"1\"");
|
||||
// "Two"
|
||||
auto strongTagTwo = ETag("\"Two\"");
|
||||
// "two"
|
||||
auto strongTagtwo = ETag("\"two\"");
|
||||
|
||||
EXPECT_FALSE(ETag::Equals(weakTag, weakTag, ETag::ETagComparison::Strong));
|
||||
EXPECT_FALSE(ETag::Equals(weakTag1, weakTag1, ETag::ETagComparison::Strong));
|
||||
EXPECT_FALSE(ETag::Equals(weakTagTwo, weakTagTwo, ETag::ETagComparison::Strong));
|
||||
EXPECT_FALSE(ETag::Equals(weakTagtwo, weakTagtwo, ETag::ETagComparison::Strong));
|
||||
|
||||
EXPECT_TRUE(ETag::Equals(strongTag1, strongTag1, ETag::ETagComparison::Strong));
|
||||
EXPECT_TRUE(ETag::Equals(strongTagTwo, strongTagTwo, ETag::ETagComparison::Strong));
|
||||
EXPECT_TRUE(ETag::Equals(strongTagtwo, strongTagtwo, ETag::ETagComparison::Strong));
|
||||
|
||||
EXPECT_FALSE(ETag::Equals(weakTag, weakTag1, ETag::ETagComparison::Strong));
|
||||
EXPECT_FALSE(ETag::Equals(weakTag1, weakTag, ETag::ETagComparison::Strong));
|
||||
|
||||
EXPECT_FALSE(ETag::Equals(weakTag1, weakTagTwo, ETag::ETagComparison::Strong));
|
||||
EXPECT_FALSE(ETag::Equals(weakTagTwo, weakTag1, ETag::ETagComparison::Strong));
|
||||
|
||||
EXPECT_FALSE(ETag::Equals(weakTag1, strongTag1, ETag::ETagComparison::Strong));
|
||||
EXPECT_FALSE(ETag::Equals(strongTag1, weakTag1, ETag::ETagComparison::Strong));
|
||||
|
||||
EXPECT_FALSE(ETag::Equals(weakTagTwo, strongTagTwo, ETag::ETagComparison::Strong));
|
||||
EXPECT_FALSE(ETag::Equals(strongTagTwo, weakTagTwo, ETag::ETagComparison::Strong));
|
||||
|
||||
EXPECT_FALSE(ETag::Equals(strongTagTwo, weakTag1, ETag::ETagComparison::Strong));
|
||||
EXPECT_FALSE(ETag::Equals(weakTag1, strongTagTwo, ETag::ETagComparison::Strong));
|
||||
|
||||
EXPECT_FALSE(ETag::Equals(strongTagTwo, strongTagtwo, ETag::ETagComparison::Strong));
|
||||
EXPECT_FALSE(ETag::Equals(strongTagtwo, strongTagTwo, ETag::ETagComparison::Strong));
|
||||
|
||||
EXPECT_FALSE(ETag::Equals(weakTagTwo, weakTagtwo, ETag::ETagComparison::Strong));
|
||||
EXPECT_FALSE(ETag::Equals(weakTagtwo, weakTagTwo, ETag::ETagComparison::Strong));
|
||||
}
|
||||
|
||||
TEST(ETag, EqualsWeak)
|
||||
{
|
||||
// W/""
|
||||
auto weakTag = ETag("W/\"\"");
|
||||
// W/"1"
|
||||
auto weakTag1 = ETag("W/\"1\"");
|
||||
// W/"Two"
|
||||
auto weakTagTwo = ETag("W/\"Two\"");
|
||||
// W/"two"
|
||||
auto weakTagtwo = ETag("W/\"two\"");
|
||||
// "1"
|
||||
auto strongTag1 = ETag("\"1\"");
|
||||
// "Two"
|
||||
auto strongTagTwo = ETag("\"Two\"");
|
||||
// "two"
|
||||
auto strongTagtwo = ETag("\"two\"");
|
||||
|
||||
EXPECT_TRUE(ETag::Equals(weakTag, weakTag, ETag::ETagComparison::Weak));
|
||||
EXPECT_TRUE(ETag::Equals(weakTag1, weakTag1, ETag::ETagComparison::Weak));
|
||||
EXPECT_TRUE(ETag::Equals(weakTagTwo, weakTagTwo, ETag::ETagComparison::Weak));
|
||||
EXPECT_TRUE(ETag::Equals(weakTagtwo, weakTagtwo, ETag::ETagComparison::Weak));
|
||||
|
||||
EXPECT_TRUE(ETag::Equals(strongTag1, strongTag1, ETag::ETagComparison::Weak));
|
||||
EXPECT_TRUE(ETag::Equals(strongTagTwo, strongTagTwo, ETag::ETagComparison::Weak));
|
||||
|
||||
EXPECT_FALSE(ETag::Equals(weakTag, weakTag1, ETag::ETagComparison::Weak));
|
||||
EXPECT_FALSE(ETag::Equals(weakTag1, weakTag, ETag::ETagComparison::Weak));
|
||||
|
||||
EXPECT_FALSE(ETag::Equals(weakTag1, weakTagTwo, ETag::ETagComparison::Weak));
|
||||
EXPECT_FALSE(ETag::Equals(weakTagTwo, weakTag1, ETag::ETagComparison::Weak));
|
||||
|
||||
EXPECT_TRUE(ETag::Equals(weakTag1, strongTag1, ETag::ETagComparison::Weak));
|
||||
EXPECT_TRUE(ETag::Equals(strongTag1, weakTag1, ETag::ETagComparison::Weak));
|
||||
|
||||
EXPECT_TRUE(ETag::Equals(weakTagTwo, strongTagTwo, ETag::ETagComparison::Weak));
|
||||
EXPECT_TRUE(ETag::Equals(strongTagTwo, weakTagTwo, ETag::ETagComparison::Weak));
|
||||
|
||||
EXPECT_FALSE(ETag::Equals(strongTagTwo, weakTag1, ETag::ETagComparison::Weak));
|
||||
EXPECT_FALSE(ETag::Equals(weakTag1, strongTagTwo, ETag::ETagComparison::Weak));
|
||||
|
||||
EXPECT_FALSE(ETag::Equals(strongTagTwo, weakTagtwo, ETag::ETagComparison::Weak));
|
||||
EXPECT_FALSE(ETag::Equals(weakTagtwo, strongTagTwo, ETag::ETagComparison::Weak));
|
||||
|
||||
EXPECT_FALSE(ETag::Equals(strongTagTwo, strongTagtwo, ETag::ETagComparison::Weak));
|
||||
EXPECT_FALSE(ETag::Equals(strongTagtwo, strongTagTwo, ETag::ETagComparison::Weak));
|
||||
|
||||
EXPECT_FALSE(ETag::Equals(weakTagTwo, weakTagtwo, ETag::ETagComparison::Weak));
|
||||
EXPECT_FALSE(ETag::Equals(weakTagtwo, weakTagTwo, ETag::ETagComparison::Weak));
|
||||
}
|
||||
@ -17,13 +17,14 @@ class DllExportTest {
|
||||
AZ_CORE_DLLEXPORT static const bool DllExportHIncluded;
|
||||
};
|
||||
|
||||
TEST(Logging, simplifiedHeader)
|
||||
TEST(SimplifiedHeader, core)
|
||||
{
|
||||
EXPECT_NO_THROW(Azure::Core::Context c);
|
||||
EXPECT_NO_THROW(Azure::Core::DateTime(2020, 11, 03, 15, 30, 44));
|
||||
EXPECT_NO_THROW(Azure::Core::Nullable<int> n);
|
||||
EXPECT_NO_THROW(Azure::Core::ETag e);
|
||||
EXPECT_NO_THROW(Azure::Core::Http::RawResponse r(
|
||||
1, 1, Azure::Core::Http::HttpStatusCode::Accepted, "phrase"));
|
||||
EXPECT_NO_THROW(Azure::Core::Nullable<int> n);
|
||||
EXPECT_NO_THROW(Azure::Core::Uuid::CreateUuid());
|
||||
EXPECT_NO_THROW(Azure::Core::Details::Version::VersionString());
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user