Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion client-lite/test/string_ops_tests.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "test_common.h"

#include "do_test_helpers.h"
#include "string_ops.h"
#include "test_helpers.h"

Expand Down Expand Up @@ -37,7 +38,7 @@ static void StringPartitionTester(const std::string& left, const std::string& ri
size_t numExpectedParts = 0;
if (expectedStr1) { ++numExpectedParts; }
if (expectedStr2) { ++numExpectedParts; }
auto fnLogStr = test_scope_exit([&]()
auto fnLogStr = dotest::util::scope_exit([&]()
{
std::cout << "Test string: \"" << testString << "\"\n";
if (parts.size() > 0) std::cout << "Partition1: \"" << parts[0] << "\"\n";
Expand Down
63 changes: 0 additions & 63 deletions client-lite/test/test_helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,66 +10,3 @@ class TestHelpers
// Disallow creating an instance of this object
TestHelpers() {}
};

template <typename TLambda>
class test_lambda_call
{
public:
test_lambda_call(const test_lambda_call&) = delete;
test_lambda_call& operator=(const test_lambda_call&) = delete;
test_lambda_call& operator=(test_lambda_call&& other) = delete;

explicit test_lambda_call(TLambda&& lambda) noexcept : _lambda(std::move(lambda))
{
static_assert(std::is_same<decltype(lambda()), void>::value, "scope_exit lambdas must not have a return value");
static_assert(!std::is_lvalue_reference<TLambda>::value && !std::is_rvalue_reference<TLambda>::value,
"scope_exit should only be directly used with a lambda");
}

test_lambda_call(test_lambda_call&& other) noexcept :
_lambda(std::move(other._lambda)),
_fCall(other._fCall)
{
other._fCall = false;
}

~test_lambda_call() noexcept
{
reset();
}

// Ensures the scope_exit lambda will not be called
void release() noexcept
{
_fCall = false;
}

// Executes the scope_exit lambda immediately if not yet run; ensures it will not run again
void reset() noexcept
{
if (_fCall)
{
_fCall = false;
_lambda();
}
}

// Returns true if the scope_exit lambda is still going to be executed
explicit operator bool() const noexcept
{
return _fCall;
}

protected:
TLambda _lambda;
bool _fCall { true };
};

// Returns an object that executes the given lambda when destroyed.
// Capture the object with 'auto'; use reset() to execute the lambda early or release() to avoid
// execution. Exceptions thrown in the lambda will fail-fast; use scope_exit_log to avoid.
template <typename TLambda>
inline auto test_scope_exit(TLambda&& lambda) noexcept
{
return test_lambda_call<TLambda>(std::forward<TLambda>(lambda));
}
63 changes: 63 additions & 0 deletions common/lib-dotestutil/do_test_helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,5 +65,68 @@ class DOTestException : public std::exception
const char* what() const noexcept override { return _msg.c_str(); }
};

template <typename TLambda>
class lambda_call
{
public:
lambda_call(const lambda_call&) = delete;
lambda_call& operator=(const lambda_call&) = delete;
lambda_call& operator=(lambda_call&& other) = delete;

explicit lambda_call(TLambda&& lambda) noexcept :
_lambda(std::move(lambda))
{
static_assert(std::is_same<decltype(lambda()), void>::value, "scope_exit lambdas must not have a return value");
static_assert(!std::is_lvalue_reference<TLambda>::value && !std::is_rvalue_reference<TLambda>::value,
"scope_exit should only be directly used with a lambda");
}

lambda_call(lambda_call&& other) noexcept :
_lambda(std::move(other._lambda)),
_fCall(other._fCall)
{
other._fCall = false;
}

~lambda_call() noexcept
{
reset();
}

// Ensures the scope_exit lambda will not be called
void release() noexcept
{
_fCall = false;
}

// Executes the scope_exit lambda immediately if not yet run; ensures it will not run again
void reset() noexcept
{
if (_fCall)
{
_fCall = false;
_lambda();
}
}

// Returns true if the scope_exit lambda is still going to be executed
explicit operator bool() const noexcept
{
return _fCall;
}

protected:
TLambda _lambda;
bool _fCall { true };
};

// Returns an object that executes the given lambda when destroyed.
// Capture the object with 'auto'; use reset() to execute the lambda early or release() to avoid execution.
template <typename TLambda>
inline auto scope_exit(TLambda&& lambda) noexcept
{
return lambda_call<TLambda>(std::forward<TLambda>(lambda));
}

} // namespace util
} // namespace dotest
13 changes: 1 addition & 12 deletions sdk-cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,6 @@ fixup_compile_options_for_arm()
# Include external libraries here
find_package(Boost COMPONENTS filesystem system REQUIRED)

# Cpprest Issues:
# 1. v2.10.10 min version (see required PR link below). cpprestsdk does not seem to support specifying this through cmake.
# https://github.com/microsoft/cpprestsdk/pull/1019/files
#
# 2. Installing libcpprest-dev via apt installs cpprest's cmake config files to a non-default cmake search path before v2.10.9
# See: https://github.com/microsoft/cpprestsdk/issues/686
# This issue has been patched but has not made its way to the stable branch for Ubuntu
# Since we are statically linking to v2.10.16 we no longer need to worry about the above as cpprest is patched to provide the proper package configuration metadata
find_package(cpprestsdk CONFIG REQUIRED)
Copy link
Contributor

@jimson-msft jimson-msft May 17, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can now also remove cpprest from the bootstrap scripts, can also look into removing them from the build machines once cpprest is removed from the agent #Closed


if (DO_BUILD_TESTS)
add_subdirectory(tests)
endif()
Expand Down Expand Up @@ -63,7 +53,6 @@ if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
"src/internal/rest"
"src/internal/util"
"src/internal"
${docs_common_includes}
${include_directories_for_arm}
)
target_compile_definitions(${DO_SDK_LIB_NAME} PRIVATE
Expand All @@ -76,7 +65,7 @@ if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
DO_PLUGIN_APT_BIN_NAME="${DO_PLUGIN_APT_BIN_NAME}"
)
target_link_libraries(${DO_SDK_LIB_NAME}
PRIVATE doversion cpprestsdk::cpprest
PRIVATE doversion
PUBLIC ${Boost_LIBRARIES}
)

Expand Down
2 changes: 1 addition & 1 deletion sdk-cpp/src/do_download.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ void download::download_url_to_path(const std::string& uri, const std::string& d
oneShotDownload.start();

download_status status;
bool timedOut;
bool timedOut = false;
do
{
if (isCancelled)
Expand Down
48 changes: 22 additions & 26 deletions sdk-cpp/src/internal/rest/download_rest.cpp
Original file line number Diff line number Diff line change
@@ -1,35 +1,34 @@

#include "download_rest.h"

#include <map>
#include <thread>

#include <cpprest/details/basic_types.h>

#include "do_exceptions_internal.h"
#include "do_exceptions.h"
#include "do_http_client.h"
#include "do_url_encode.h"

namespace msdo = microsoft::deliveryoptimization;
namespace cpprest_util_conv = utility::conversions;
using namespace std::chrono_literals; // NOLINT(build/namespaces)

const int g_maxNumRetryAttempts = 3;

const char* const g_downloadUriPart = "download";

namespace microsoft::deliveryoptimization::details
{

CDownloadRest::CDownloadRest(const std::string& uri, const std::string& downloadFilePath)
{
web::uri_builder builder(g_downloadUriPart);
builder.append_path(U("create"));

builder.append_query(U("Uri"), cpprest_util_conv::to_string_t(uri));
builder.append_query(U("DownloadFilePath"), cpprest_util_conv::to_string_t(downloadFilePath));
std::stringstream url;
url << g_downloadUriPart << "/create" << "?Uri=" << Url::EncodeDataString(uri) << "&DownloadFilePath="
<< Url::EncodeDataString(downloadFilePath);

for (int retryAttempts = 0; retryAttempts < g_maxNumRetryAttempts; retryAttempts++)
{
try
{
const auto respBody = CHttpClient::GetInstance().SendRequest(web::http::methods::POST, builder.to_string());
const auto respBody = CHttpClient::GetInstance().SendRequest(HttpRequest::POST, url.str());
_id = respBody.get<std::string>("Id");
return;
}
Expand Down Expand Up @@ -78,24 +77,23 @@ void CDownloadRest::Abort()

msdo::download_status CDownloadRest::GetStatus()
{
web::uri_builder builder(g_downloadUriPart);
builder.append_path(U("getstatus"));
builder.append_query(U("Id"), cpprest_util_conv::to_string_t(_id));
std::stringstream url;
url << g_downloadUriPart << "/getstatus" << "?Id=" << _id;

const auto respBody = CHttpClient::GetInstance().SendRequest(web::http::methods::GET, builder.to_string());
const auto respBody = CHttpClient::GetInstance().SendRequest(HttpRequest::GET, url.str());

uint64_t bytesTotal = respBody.get<uint64_t>("BytesTotal");
uint64_t bytesTransferred = respBody.get<uint64_t>("BytesTransferred");
int32_t errorCode = respBody.get<int32_t>("ErrorCode");
int32_t extendedErrorCode = respBody.get<int32_t>("ExtendedErrorCode");

static const std::map<utility::string_t, download_state> stateMap =
{{ U("Created"), download_state::created },
{ U("Transferring"), download_state::transferring },
{ U("Transferred"), download_state::transferred },
{ U("Finalized"), download_state::finalized },
{ U("Aborted"), download_state::aborted },
{ U("Paused"), download_state::paused }};
static const std::map<std::string, download_state> stateMap =
{{ "Created", download_state::created },
{ "Transferring", download_state::transferring },
{ "Transferred", download_state::transferred },
{ "Finalized", download_state::finalized },
{ "Aborted", download_state::aborted },
{ "Paused", download_state::paused }};

download_state status = download_state::created;
auto it = stateMap.find(respBody.get<std::string>("Status"));
Expand All @@ -114,11 +112,9 @@ msdo::download_status CDownloadRest::GetStatus()

void CDownloadRest::_DownloadOperationCall(const std::string& type)
{
web::uri_builder builder(g_downloadUriPart);
builder.append_path(cpprest_util_conv::to_string_t(type));
builder.append_query(U("Id"), cpprest_util_conv::to_string_t(_id));

(void)CHttpClient::GetInstance().SendRequest(web::http::methods::POST, builder.to_string());
std::stringstream url;
url << g_downloadUriPart << '/' << type << "?Id=" << _id;
(void)CHttpClient::GetInstance().SendRequest(HttpRequest::POST, url.str());
}

} // namespace microsoft::deliveryoptimization::details
Loading