Add a few simple unit tests to boost coverage (#3163)
This commit is contained in:
parent
12a2ca31bc
commit
a2b2b74080
@ -915,7 +915,7 @@ void CurlConnection::Shutdown()
|
||||
#elif defined(AZ_PLATFORM_WINDOWS)
|
||||
::shutdown(m_curlSocket, SD_BOTH);
|
||||
#endif
|
||||
m_isShutDown = true;
|
||||
CurlNetworkConnection::Shutdown();
|
||||
}
|
||||
|
||||
// Read from socket and return the number of bytes taken from socket
|
||||
|
||||
@ -57,7 +57,7 @@ namespace Azure { namespace Core { namespace Http {
|
||||
*
|
||||
*/
|
||||
class CurlNetworkConnection {
|
||||
protected:
|
||||
private:
|
||||
bool m_isShutDown = false;
|
||||
|
||||
public:
|
||||
|
||||
@ -46,7 +46,7 @@ add_executable (
|
||||
${CURL_OPTIONS_TESTS}
|
||||
${CURL_SESSION_TESTS}
|
||||
datetime_test.cpp
|
||||
environmentLogLevelListener_test.cpp
|
||||
environment_log_level_listener_test.cpp
|
||||
etag_test.cpp
|
||||
http_test.cpp
|
||||
http_test.hpp
|
||||
|
||||
@ -161,6 +161,16 @@ namespace Azure { namespace Core { namespace Test {
|
||||
EXPECT_EQ(values->second.begin()->get()->GetConnectionKey(), expectedConnectionKey);
|
||||
}
|
||||
|
||||
{
|
||||
Azure::Core::Http::CurlSession::ResponseBufferParser responseParser;
|
||||
EXPECT_EQ(responseParser.ExtractResponse(), nullptr);
|
||||
|
||||
const uint8_t responseBuf[] = "HTTP/1.1 200 OK\r\n\r\n";
|
||||
static_cast<void>(responseParser.Parse(responseBuf, sizeof(responseBuf) - 1));
|
||||
EXPECT_NE(responseParser.ExtractResponse(), nullptr);
|
||||
EXPECT_EQ(responseParser.ExtractResponse(), nullptr);
|
||||
}
|
||||
|
||||
// Test re-using same custom config
|
||||
{
|
||||
// Creating a new connection with default options
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
#include <azure/core/datetime.hpp>
|
||||
|
||||
#include <chrono>
|
||||
#include <ctime>
|
||||
#include <limits>
|
||||
|
||||
using namespace Azure;
|
||||
@ -373,6 +374,18 @@ TEST(DateTime, ParseTimeRfc3339BoundaryCases)
|
||||
"2038-01-19T03:13:07-00:01",
|
||||
"2038-01-19T03:14:07Z"); // INT_MAX after subtacting 1
|
||||
TestDateTimeRoundtrip("2038-01-19T03:14:07-00:00", "2038-01-19T03:14:07Z");
|
||||
|
||||
// No ':' in time zone offset
|
||||
EXPECT_THROW(
|
||||
DateTime::Parse("2001-01-01T00:00:00+12345", DateTime::DateFormat::Rfc3339),
|
||||
std::invalid_argument);
|
||||
}
|
||||
|
||||
TEST(DateTime, ParseUnrecognizedFormat)
|
||||
{
|
||||
EXPECT_THROW(
|
||||
DateTime::Parse("2001-01-01T00:00:00", static_cast<DateTime::DateFormat>(42)),
|
||||
std::invalid_argument);
|
||||
}
|
||||
|
||||
TEST(DateTime, ParseTimeRfc3339UsesEachTimezoneDigit)
|
||||
@ -819,3 +832,66 @@ TEST(DateTime, ParseRoundUpInvalidDate)
|
||||
static_cast<void>(DateTime::Parse("9999-12-31T23:59:60", DateTime::DateFormat::Rfc3339)),
|
||||
std::invalid_argument);
|
||||
}
|
||||
|
||||
TEST(DateTime, ToSystemClock)
|
||||
{
|
||||
if (DateTime(std::chrono::system_clock::time_point::min())
|
||||
> DateTime(DateTime::time_point::min()))
|
||||
{
|
||||
EXPECT_THROW(
|
||||
static_cast<void>(static_cast<std::chrono::system_clock::time_point>(
|
||||
DateTime(DateTime::time_point::min()))),
|
||||
std::invalid_argument);
|
||||
}
|
||||
|
||||
if (DateTime(std::chrono::system_clock::time_point::max())
|
||||
> DateTime(DateTime::time_point::max()))
|
||||
{
|
||||
EXPECT_THROW(
|
||||
static_cast<void>(static_cast<std::chrono::system_clock::time_point>(
|
||||
DateTime(DateTime::time_point::max()))),
|
||||
std::invalid_argument);
|
||||
}
|
||||
|
||||
{
|
||||
auto const tt = std::chrono::system_clock::to_time_t(
|
||||
static_cast<std::chrono::system_clock::time_point>(DateTime(2021, 7, 8, 15, 34, 56)));
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
// warning C4996: 'gmtime': This function or variable may be unsafe. Consider using gmtime_s
|
||||
// instead.
|
||||
#pragma warning(disable : 4996)
|
||||
#endif
|
||||
auto const tm = std::gmtime(&tt);
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
// https://en.cppreference.com/w/cpp/chrono/c/tm
|
||||
EXPECT_EQ(tm->tm_year, (2021 - 1900)); // std::tm::tm_year is 1900-based.
|
||||
EXPECT_EQ(tm->tm_mon, 6); // std::tm::tm_mon is 0-based.
|
||||
EXPECT_EQ(tm->tm_mday, 8);
|
||||
EXPECT_EQ(tm->tm_hour, 15);
|
||||
EXPECT_EQ(tm->tm_min, 34);
|
||||
EXPECT_EQ(tm->tm_sec, 56);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(DateTime, OutOfToStringRange)
|
||||
{
|
||||
using namespace std::literals::chrono_literals;
|
||||
|
||||
const DateTime underflow(DateTime(0001) - 1s);
|
||||
const DateTime overflow(DateTime(9999, 12, 31, 23, 59, 59) + 1s);
|
||||
|
||||
EXPECT_THROW(static_cast<void>(underflow.ToString()), std::invalid_argument);
|
||||
EXPECT_THROW(static_cast<void>(overflow.ToString()), std::invalid_argument);
|
||||
}
|
||||
|
||||
TEST(DateTime, LeapYear)
|
||||
{
|
||||
EXPECT_NO_THROW(static_cast<void>(DateTime(2021, 1, 29)));
|
||||
EXPECT_NO_THROW(static_cast<void>(DateTime(2021, 2, 28)));
|
||||
EXPECT_THROW(static_cast<void>(DateTime(2021, 2, 29)), std::invalid_argument);
|
||||
}
|
||||
|
||||
@ -200,3 +200,20 @@ TEST_F(EnvironmentLogLevelListenerTest, GetLogListenerInformational)
|
||||
EXPECT_NE(buffer.str().find("INFO : message"), std::string::npos);
|
||||
std::cerr.rdbuf(old);
|
||||
}
|
||||
|
||||
TEST_F(EnvironmentLogLevelListenerTest, GetLogListenerUnknown)
|
||||
{
|
||||
EnvironmentLogLevelListener::SetInitialized(false);
|
||||
SetLogLevel("verbose");
|
||||
|
||||
std::stringstream buffer;
|
||||
std::streambuf* old = std::cerr.rdbuf(buffer.rdbuf());
|
||||
|
||||
std::string text = buffer.str(); // text will now contain "Bla\n"
|
||||
auto listener = EnvironmentLogLevelListener::GetLogListener();
|
||||
|
||||
listener(static_cast<Logger::Level>(42), "message");
|
||||
EXPECT_NE(listener, nullptr);
|
||||
EXPECT_NE(buffer.str().find("????? : message"), std::string::npos);
|
||||
std::cerr.rdbuf(old);
|
||||
}
|
||||
@ -32,6 +32,8 @@ TEST(RequestFailedException, JSONError)
|
||||
EXPECT_EQ(exception.ErrorCode, "503");
|
||||
EXPECT_EQ(exception.RequestId, "1");
|
||||
EXPECT_EQ(exception.ClientRequestId, "2");
|
||||
EXPECT_EQ(exception.ReasonPhrase, "retry please :");
|
||||
EXPECT_EQ(exception.what(), std::string("Received an HTTP unsuccessful status code."));
|
||||
}
|
||||
|
||||
TEST(RequestFailedException, JSONErrorNoError)
|
||||
@ -55,4 +57,49 @@ TEST(RequestFailedException, JSONErrorNoError)
|
||||
EXPECT_EQ(exception.ErrorCode, "");
|
||||
EXPECT_EQ(exception.RequestId, "1");
|
||||
EXPECT_EQ(exception.ClientRequestId, "2");
|
||||
EXPECT_EQ(exception.ReasonPhrase, "retry please :");
|
||||
EXPECT_EQ(exception.what(), std::string("Received an HTTP unsuccessful status code."));
|
||||
}
|
||||
|
||||
TEST(RequestFailedException, EmptyValues)
|
||||
{
|
||||
auto response = std::make_unique<Azure::Core::Http::RawResponse>(
|
||||
1, 1, Azure::Core::Http::HttpStatusCode::None, std::string());
|
||||
|
||||
auto exception = Azure::Core::RequestFailedException(response);
|
||||
|
||||
EXPECT_EQ(exception.StatusCode, Azure::Core::Http::HttpStatusCode::None);
|
||||
EXPECT_EQ(exception.Message, std::string());
|
||||
EXPECT_EQ(exception.ErrorCode, std::string());
|
||||
EXPECT_EQ(exception.RequestId, std::string());
|
||||
EXPECT_EQ(exception.ClientRequestId, std::string());
|
||||
EXPECT_EQ(exception.ReasonPhrase, std::string());
|
||||
EXPECT_EQ(exception.what(), std::string("Received an HTTP unsuccessful status code."));
|
||||
}
|
||||
|
||||
TEST(RequestFailedException, Message)
|
||||
{
|
||||
auto response = std::make_unique<Azure::Core::Http::RawResponse>(
|
||||
1, 1, Azure::Core::Http::HttpStatusCode::ServiceUnavailable, "retry please :");
|
||||
static constexpr uint8_t const responseBody[]
|
||||
= "{\"error\":{ \"code\":\"503\", \"message\":\"JT\"}}";
|
||||
static constexpr uint8_t const responseBodyStream[]
|
||||
= "{\"error\":{ \"code\":\"503\", \"message\":\"JT\"}}";
|
||||
|
||||
response->SetHeader(HttpShared::ContentType, "application/json");
|
||||
response->SetHeader(HttpShared::MsRequestId, "1");
|
||||
response->SetHeader(HttpShared::MsClientRequestId, "2");
|
||||
response->SetBody(std::vector<uint8_t>(responseBody, responseBody + sizeof(responseBody)));
|
||||
response->SetBodyStream(std::make_unique<Azure::Core::IO::MemoryBodyStream>(
|
||||
responseBodyStream, sizeof(responseBodyStream) - 1));
|
||||
|
||||
auto exception = Azure::Core::RequestFailedException("Msg", std::move(response));
|
||||
|
||||
EXPECT_EQ(exception.StatusCode, Azure::Core::Http::HttpStatusCode::ServiceUnavailable);
|
||||
EXPECT_EQ(exception.Message, "Msg");
|
||||
EXPECT_EQ(exception.ErrorCode, "");
|
||||
EXPECT_EQ(exception.RequestId, "1");
|
||||
EXPECT_EQ(exception.ClientRequestId, "2");
|
||||
EXPECT_EQ(exception.ReasonPhrase, "retry please :");
|
||||
EXPECT_EQ(exception.what(), std::string("Msg"));
|
||||
}
|
||||
|
||||
@ -13,7 +13,7 @@ using Azure::Core::Http::Policies::LogOptions;
|
||||
// cspell:ignore qparam
|
||||
|
||||
namespace {
|
||||
void SendRequest(LogOptions const& logOptions)
|
||||
void SendRequest(LogOptions const& logOptions, std::string const& portAndPath = "")
|
||||
{
|
||||
using namespace Azure::Core;
|
||||
using namespace Azure::Core::IO;
|
||||
@ -51,13 +51,12 @@ void SendRequest(LogOptions const& logOptions)
|
||||
|
||||
Request request(
|
||||
HttpMethod::Get,
|
||||
Url("https://"
|
||||
"www.microsoft.com"
|
||||
"?qparam1=qVal1"
|
||||
"&Qparam2=Qval2"
|
||||
"&qParam3=qval3"
|
||||
"&qparam%204=qval%204"
|
||||
"&qparam%25204=QVAL%25204"),
|
||||
Url(std::string("https://www.microsoft.com") + portAndPath
|
||||
+ "?qparam1=qVal1"
|
||||
"&Qparam2=Qval2"
|
||||
"&qParam3=qval3"
|
||||
"&qparam%204=qval%204"
|
||||
"&qparam%25204=QVAL%25204"),
|
||||
bodyStream.get());
|
||||
|
||||
request.SetHeader("hEaDeR1", "HvAlUe1");
|
||||
@ -154,6 +153,35 @@ TEST(LogPolicy, Default)
|
||||
EXPECT_TRUE(EndsWith(entry2.Message, "ms) : 200 OKAY"));
|
||||
}
|
||||
|
||||
TEST(LogPolicy, PortAndPath)
|
||||
{
|
||||
TestLogger const Log;
|
||||
SendRequest(LogOptions(), ":8080/path");
|
||||
|
||||
EXPECT_EQ(Log.Entries.size(), 2);
|
||||
|
||||
auto const entry1 = Log.Entries.at(0);
|
||||
auto const entry2 = Log.Entries.at(1);
|
||||
|
||||
EXPECT_EQ(entry1.Level, Logger::Level::Informational);
|
||||
EXPECT_EQ(entry2.Level, Logger::Level::Informational);
|
||||
|
||||
EXPECT_EQ(
|
||||
entry1.Message,
|
||||
"HTTP Request : GET https://www.microsoft.com:8080/path"
|
||||
"?Qparam2=REDACTED"
|
||||
"&qParam3=REDACTED"
|
||||
"&qparam%204=REDACTED"
|
||||
"&qparam%25204=REDACTED"
|
||||
"&qparam1=REDACTED"
|
||||
"\nheader1 : REDACTED"
|
||||
"\nheader2 : REDACTED"
|
||||
"\nx-ms-request-id : 6c536700-4c36-4e22-9161-76e7b3bf8269");
|
||||
|
||||
EXPECT_TRUE(StartsWith(entry2.Message, "HTTP Response ("));
|
||||
EXPECT_TRUE(EndsWith(entry2.Message, "ms) : 200 OKAY"));
|
||||
}
|
||||
|
||||
TEST(LogPolicy, Headers)
|
||||
{
|
||||
TestLogger const Log;
|
||||
|
||||
@ -51,3 +51,71 @@ TEST(Pipeline, refrefEmptyPipeline)
|
||||
std::vector<std::unique_ptr<Azure::Core::Http::Policies::HttpPolicy>>(0)),
|
||||
std::invalid_argument);
|
||||
}
|
||||
|
||||
TEST(Pipeline, AdditionalPolicies)
|
||||
{
|
||||
class TestPolicy : public Azure::Core::Http::Policies::HttpPolicy {
|
||||
int* m_cloneCount;
|
||||
|
||||
public:
|
||||
TestPolicy(int* cloneCount) : m_cloneCount(cloneCount) {}
|
||||
|
||||
std::unique_ptr<HttpPolicy> Clone() const override
|
||||
{
|
||||
++(*m_cloneCount);
|
||||
return std::make_unique<TestPolicy>(*this);
|
||||
}
|
||||
|
||||
std::unique_ptr<Azure::Core::Http::RawResponse> Send(
|
||||
Azure::Core::Http::Request& request,
|
||||
Azure::Core::Http::Policies::NextHttpPolicy nextPolicy,
|
||||
Azure::Core::Context const& context) const override
|
||||
{
|
||||
return nextPolicy.Send(request, context);
|
||||
}
|
||||
};
|
||||
|
||||
int perCallPolicyCloneCount = 0;
|
||||
int perCallClientPolicyCloneCount = 0;
|
||||
int perRetryPolicyCloneCount = 0;
|
||||
int perRetryClientPolicyCloneCount = 0;
|
||||
|
||||
auto options = Azure::Core::_internal::ClientOptions();
|
||||
|
||||
using PolicyVector = std::vector<std::unique_ptr<Azure::Core::Http::Policies::HttpPolicy>>;
|
||||
PolicyVector perCallPolicies;
|
||||
PolicyVector perRetryPolicies;
|
||||
|
||||
{
|
||||
struct InitHelper
|
||||
{
|
||||
PolicyVector* Policies;
|
||||
int* Counter;
|
||||
};
|
||||
|
||||
std::vector<InitHelper> const initializations = {
|
||||
{&perCallPolicies, &perCallPolicyCloneCount},
|
||||
{&options.PerOperationPolicies, &perCallClientPolicyCloneCount},
|
||||
{&perRetryPolicies, &perRetryPolicyCloneCount},
|
||||
{&options.PerRetryPolicies, &perRetryClientPolicyCloneCount},
|
||||
};
|
||||
|
||||
const int size = static_cast<int>(initializations.size());
|
||||
for (int i = 0; i < size; ++i)
|
||||
{
|
||||
for (int j = 0; j < i + 2; ++j)
|
||||
{
|
||||
initializations[i].Policies->emplace_back(
|
||||
std::make_unique<TestPolicy>(initializations[i].Counter));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT_NO_THROW(static_cast<void>(Azure::Core::Http::_internal::HttpPipeline(
|
||||
options, "Test", "1.0.0", std::move(perRetryPolicies), std::move(perCallPolicies))));
|
||||
|
||||
EXPECT_EQ(perCallPolicyCloneCount, 2);
|
||||
EXPECT_EQ(perCallClientPolicyCloneCount, 3);
|
||||
EXPECT_EQ(perRetryPolicyCloneCount, 4);
|
||||
EXPECT_EQ(perRetryClientPolicyCloneCount, 5);
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "azure/core/diagnostics/logger.hpp"
|
||||
#include "azure/core/http/policies/policy.hpp"
|
||||
#include "azure/core/internal/http/pipeline.hpp"
|
||||
|
||||
@ -54,8 +55,24 @@ public:
|
||||
int32_t,
|
||||
std::chrono::milliseconds&,
|
||||
double)> shouldRetryOnResponse)
|
||||
: RetryPolicy(retryOptions), m_shouldRetryOnTransportFailure(shouldRetryOnTransportFailure),
|
||||
m_shouldRetryOnResponse(shouldRetryOnResponse)
|
||||
: RetryPolicy(retryOptions),
|
||||
m_shouldRetryOnTransportFailure(
|
||||
shouldRetryOnTransportFailure != nullptr
|
||||
? shouldRetryOnTransportFailure
|
||||
: [&](auto options, auto attempt, auto retryAfter, auto jitter) {
|
||||
retryAfter = std::chrono::milliseconds(0);
|
||||
auto ignore = decltype(retryAfter)();
|
||||
return RetryPolicy::ShouldRetryOnTransportFailure(options, attempt, ignore, jitter);
|
||||
}),
|
||||
m_shouldRetryOnResponse(
|
||||
shouldRetryOnResponse != nullptr
|
||||
? shouldRetryOnResponse
|
||||
: [&](RawResponse const& response, auto options, auto attempt, auto retryAfter, auto jitter) {
|
||||
retryAfter = std::chrono::milliseconds(0);
|
||||
auto ignore = decltype(retryAfter)();
|
||||
return RetryPolicy::ShouldRetryOnResponse(
|
||||
response, options, attempt, ignore, jitter);
|
||||
})
|
||||
{
|
||||
}
|
||||
|
||||
@ -717,3 +734,79 @@ TEST(RetryPolicy, RetryAfter)
|
||||
EXPECT_EQ(retryAfter, 90s);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(RetryPolicy, LogMessages)
|
||||
{
|
||||
using Azure::Core::Diagnostics::Logger;
|
||||
|
||||
struct Log
|
||||
{
|
||||
struct Entry
|
||||
{
|
||||
Logger::Level Level;
|
||||
std::string Message;
|
||||
};
|
||||
|
||||
std::vector<Entry> Entries;
|
||||
|
||||
Log()
|
||||
{
|
||||
Logger::SetLevel(Logger::Level::Informational);
|
||||
Logger::SetListener([&](auto lvl, auto msg) { Entries.emplace_back(Entry{lvl, msg}); });
|
||||
}
|
||||
|
||||
~Log()
|
||||
{
|
||||
Logger::SetListener(nullptr);
|
||||
Logger::SetLevel(Logger::Level::Warning);
|
||||
}
|
||||
|
||||
} log;
|
||||
|
||||
{
|
||||
using namespace std::chrono_literals;
|
||||
RetryOptions const retryOptions{5, 10s, 5min, {HttpStatusCode::InternalServerError}};
|
||||
|
||||
auto requestNumber = 0;
|
||||
|
||||
std::vector<std::unique_ptr<Azure::Core::Http::Policies::HttpPolicy>> policies;
|
||||
policies.emplace_back(std::make_unique<RetryPolicyTest>(retryOptions, nullptr, nullptr));
|
||||
policies.emplace_back(std::make_unique<TestTransportPolicy>([&]() {
|
||||
++requestNumber;
|
||||
|
||||
if (requestNumber == 1)
|
||||
{
|
||||
throw TransportException("Cable Unplugged");
|
||||
}
|
||||
|
||||
return std::make_unique<RawResponse>(
|
||||
1,
|
||||
1,
|
||||
requestNumber == 2 ? HttpStatusCode::InternalServerError
|
||||
: HttpStatusCode::ServiceUnavailable,
|
||||
"Test");
|
||||
}));
|
||||
|
||||
Azure::Core::Http::_internal::HttpPipeline pipeline(policies);
|
||||
|
||||
Request request(HttpMethod::Get, Azure::Core::Url("https://www.microsoft.com"));
|
||||
pipeline.Send(request, Azure::Core::Context());
|
||||
}
|
||||
|
||||
EXPECT_EQ(log.Entries.size(), 5);
|
||||
|
||||
EXPECT_EQ(log.Entries[0].Level, Logger::Level::Warning);
|
||||
EXPECT_EQ(log.Entries[0].Message, "HTTP Transport error: Cable Unplugged");
|
||||
|
||||
EXPECT_EQ(log.Entries[1].Level, Logger::Level::Informational);
|
||||
EXPECT_EQ(log.Entries[1].Message, "HTTP Retry attempt #1 will be made in 0ms.");
|
||||
|
||||
EXPECT_EQ(log.Entries[2].Level, Logger::Level::Informational);
|
||||
EXPECT_EQ(log.Entries[2].Message, "HTTP status code 500 will be retried.");
|
||||
|
||||
EXPECT_EQ(log.Entries[3].Level, Logger::Level::Informational);
|
||||
EXPECT_EQ(log.Entries[3].Message, "HTTP Retry attempt #2 will be made in 0ms.");
|
||||
|
||||
EXPECT_EQ(log.Entries[4].Level, Logger::Level::Warning);
|
||||
EXPECT_EQ(log.Entries[4].Message, "HTTP status code 503 won't be retried.");
|
||||
}
|
||||
|
||||
@ -18,3 +18,27 @@ TEST(SHA, SHA256Test)
|
||||
for (size_t i = 0; i != shaResult.size(); i++)
|
||||
printf("%02x", shaResult[i]);
|
||||
}
|
||||
|
||||
TEST(SHA, SHA384Test)
|
||||
{
|
||||
Sha384Hash sha;
|
||||
Sha384Hash sha2;
|
||||
uint8_t data[] = "A";
|
||||
auto shaResult = sha.Final(data, sizeof(data));
|
||||
auto shaResult2 = sha2.Final(data, sizeof(data));
|
||||
EXPECT_EQ(shaResult, shaResult2);
|
||||
for (size_t i = 0; i != shaResult.size(); i++)
|
||||
printf("%02x", shaResult[i]);
|
||||
}
|
||||
|
||||
TEST(SHA, SHA512Test)
|
||||
{
|
||||
Sha512Hash sha;
|
||||
Sha512Hash sha2;
|
||||
uint8_t data[] = "A";
|
||||
auto shaResult = sha.Final(data, sizeof(data));
|
||||
auto shaResult2 = sha2.Final(data, sizeof(data));
|
||||
EXPECT_EQ(shaResult, shaResult2);
|
||||
for (size_t i = 0; i != shaResult.size(); i++)
|
||||
printf("%02x", shaResult[i]);
|
||||
}
|
||||
|
||||
@ -312,4 +312,22 @@ namespace Azure { namespace Core { namespace Test {
|
||||
EXPECT_EQ(url1.GetPath(), "x/y");
|
||||
EXPECT_EQ(url2.GetPath(), "x/y");
|
||||
}
|
||||
|
||||
TEST(URL, Decode)
|
||||
{
|
||||
EXPECT_EQ(Core::Url::Decode("+%61b"), " ab");
|
||||
EXPECT_THROW(Core::Url::Decode("%"), std::runtime_error);
|
||||
EXPECT_THROW(Core::Url::Decode("%GA"), std::runtime_error);
|
||||
EXPECT_THROW(Core::Url::Decode("%AG"), std::runtime_error);
|
||||
}
|
||||
|
||||
TEST(URL, AppendQueryParameters)
|
||||
{
|
||||
Core::Url url("http://www.microsoft.com??param=value");
|
||||
auto params = url.GetQueryParameters();
|
||||
|
||||
EXPECT_EQ(params.size(), 1);
|
||||
EXPECT_NE(params.find("param"), params.end());
|
||||
EXPECT_EQ(params["param"], "value");
|
||||
}
|
||||
}}} // namespace Azure::Core::Test
|
||||
|
||||
@ -43,8 +43,8 @@ stages:
|
||||
CtestExcludeRegex: azure-storage|azure-identity-livetest
|
||||
LiveTestCtestRegex: '"azure-core.|json-test"'
|
||||
LiveTestTimeoutInMinutes: 90 # default is 60 min. We need a little longer on worst case for Win+jsonTests
|
||||
LineCoverageTarget: 81
|
||||
BranchCoverageTarget: 43
|
||||
LineCoverageTarget: 93
|
||||
BranchCoverageTarget: 55
|
||||
Artifacts:
|
||||
- Name: azure-core
|
||||
Path: azure-core
|
||||
|
||||
Loading…
Reference in New Issue
Block a user