use github repo as central
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
.vscode/
|
||||
@@ -1,12 +1,12 @@
|
||||
#
|
||||
# Copyright 2009-2017 Alibaba Cloud All rights reserved.
|
||||
#
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@@ -14,6 +14,15 @@
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
# coverage option
|
||||
OPTION (ENABLE_COVERAGE "Use gcov" ON)
|
||||
MESSAGE(STATUS ENABLE_COVERAGE=${ENABLE_COVERAGE})
|
||||
IF(ENABLE_COVERAGE)
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage")
|
||||
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs -ftest-coverage")
|
||||
# SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage")
|
||||
ENDIF()
|
||||
|
||||
configure_file(src/Config.h.in ${CMAKE_CURRENT_SOURCE_DIR}/include/alibabacloud/core/Config.h @ONLY)
|
||||
|
||||
set(core_public_header
|
||||
@@ -120,7 +129,7 @@ set(core_src
|
||||
src/sts/StsClient.cc
|
||||
src/sts/StsRequest.cc
|
||||
src/sts/model/AssumeRoleRequest.cc
|
||||
src/sts/model/AssumeRoleResult.cc
|
||||
src/sts/model/AssumeRoleResult.cc
|
||||
src/sts/model/GetCallerIdentityRequest.cc
|
||||
src/sts/model/GetCallerIdentityResult.cc
|
||||
)
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
* Copyright 2009-2017 Alibaba Cloud All rights reserved.
|
||||
*
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
* Copyright 2009-2017 Alibaba Cloud All rights reserved.
|
||||
*
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@@ -18,7 +18,7 @@
|
||||
#include "Executor.h"
|
||||
|
||||
static AlibabaCloud::Executor * executor = nullptr;
|
||||
|
||||
|
||||
void AlibabaCloud::InitializeSdk()
|
||||
{
|
||||
if (IsSdkInitialized())
|
||||
@@ -37,7 +37,7 @@ void AlibabaCloud::ShutdownSdk()
|
||||
{
|
||||
if (!IsSdkInitialized())
|
||||
return;
|
||||
|
||||
|
||||
executor->shutdown();
|
||||
delete executor;
|
||||
executor = nullptr;
|
||||
|
||||
@@ -106,7 +106,7 @@ void Executor::shutdown()
|
||||
{
|
||||
if (isShutdown())
|
||||
return;
|
||||
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> locker(tasksQueueMutex_);
|
||||
while (tasksQueue_.size() > 0) {
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
* Copyright 2009-2017 Alibaba Cloud All rights reserved.
|
||||
*
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@@ -99,7 +99,7 @@ HttpMessage::HeaderValueType HttpMessage::header(const HeaderNameType & name) co
|
||||
auto it = headers_.find(name);
|
||||
if (it != headers_.end())
|
||||
return it->second;
|
||||
else
|
||||
else
|
||||
return std::string();
|
||||
}
|
||||
|
||||
@@ -161,8 +161,9 @@ void HttpMessage::setBody(const char *data, size_t size)
|
||||
bodySize_ = 0;
|
||||
if (size) {
|
||||
bodySize_ = size;
|
||||
body_ = new char[size];
|
||||
body_ = new char[size + 1];
|
||||
std::copy(data, data + size, body_);
|
||||
body_[size] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ void StsAssumeRoleCredentialsProvider::loadCredentials()
|
||||
std::tm tm = {};
|
||||
#if defined(__GNUG__) && __GNUC__ < 5
|
||||
strptime(stsCredentials.expiration.c_str(), "%Y-%m-%dT%H:%M:%SZ", &tm);
|
||||
#else
|
||||
#else
|
||||
std::stringstream ss(stsCredentials.expiration);
|
||||
ss >> std::get_time(&tm, "%Y-%m-%dT%H:%M:%SZ");
|
||||
#endif
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
* Copyright 2009-2017 Alibaba Cloud All rights reserved.
|
||||
*
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@@ -45,7 +45,7 @@ std::string AlibabaCloud::GenerateUuid()
|
||||
|
||||
std::string AlibabaCloud::UrlEncode(const std::string & src)
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
CURL *curl = curl_easy_init();
|
||||
char *output = curl_easy_escape(curl, src.c_str(), src.size());
|
||||
std::string result(output);
|
||||
curl_free(output);
|
||||
@@ -89,7 +89,7 @@ std::string AlibabaCloud::ComputeContentMD5(const char * data, size_t size)
|
||||
#else
|
||||
unsigned char md[MD5_DIGEST_LENGTH];
|
||||
MD5(reinterpret_cast<const unsigned char*>(data), size, (unsigned char*)&md);
|
||||
|
||||
|
||||
char encodedData[100];
|
||||
EVP_EncodeBlock(reinterpret_cast<unsigned char*>(encodedData), md, MD5_DIGEST_LENGTH);
|
||||
return encodedData;
|
||||
@@ -99,10 +99,10 @@ std::string AlibabaCloud::ComputeContentMD5(const char * data, size_t size)
|
||||
void AlibabaCloud::StringReplace(std::string & src, const std::string & s1, const std::string & s2)
|
||||
{
|
||||
std::string::size_type pos =0;
|
||||
while ((pos = src.find(s1, pos)) != std::string::npos)
|
||||
while ((pos = src.find(s1, pos)) != std::string::npos)
|
||||
{
|
||||
src.replace(pos, s1.length(), s2);
|
||||
pos += s2.length();
|
||||
pos += s2.length();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
* Copyright 2009-2017 Alibaba Cloud All rights reserved.
|
||||
*
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
||||
24
test-coverage.sh
Executable file
24
test-coverage.sh
Executable file
@@ -0,0 +1,24 @@
|
||||
#!/bin/bash
|
||||
|
||||
action=$1
|
||||
|
||||
if [ $action == "init" ]; then
|
||||
echo 'init coverage'
|
||||
|
||||
lcov -d sdk_build -z
|
||||
lcov -d sdk_build -b . --no-external --initial -c -o initCoverage.info
|
||||
fi
|
||||
|
||||
echo 'run test'
|
||||
cd sdk_build
|
||||
ctest
|
||||
cd ..
|
||||
|
||||
echo 'create info after test'
|
||||
lcov -d sdk_build -b . --no-external -c -o testCoverage.info
|
||||
|
||||
echo 'generate html'
|
||||
genhtml -o coverageReport --prefix=`pwd` initCoverage.info testCoverage.info
|
||||
|
||||
echo 'check report ' `pwd`/coverageReport/index.html
|
||||
|
||||
69
test/core/CMakeLists.txt
Normal file
69
test/core/CMakeLists.txt
Normal file
@@ -0,0 +1,69 @@
|
||||
cmake_minimum_required(VERSION 2.8.2)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
|
||||
include(CTest)
|
||||
|
||||
if (CMAKE_VERSION VERSION_LESS 3.2)
|
||||
set(UPDATE_DISCONNECTED_IF_AVAILABLE "")
|
||||
else()
|
||||
set(UPDATE_DISCONNECTED_IF_AVAILABLE "UPDATE_DISCONNECTED 1")
|
||||
endif()
|
||||
|
||||
include(DownloadProject.cmake)
|
||||
download_project(PROJ googletest
|
||||
PREFIX CMAKE_SOURCE_DIR/test/googletest
|
||||
GIT_REPOSITORY https://github.com/google/googletest.git
|
||||
GIT_TAG master
|
||||
${UPDATE_DISCONNECTED_IF_AVAILABLE}
|
||||
)
|
||||
|
||||
# Prevent GoogleTest from overriding our compiler/linker options
|
||||
# when building with Visual Studio
|
||||
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
|
||||
|
||||
add_subdirectory(${googletest_SOURCE_DIR} ${googletest_BINARY_DIR})
|
||||
|
||||
# When using CMake 2.8.11 or later, header path dependencies
|
||||
# are automatically added to the gtest and gmock targets.
|
||||
# For earlier CMake versions, we have to explicitly add the
|
||||
# required directories to the header search path ourselves.
|
||||
if (CMAKE_VERSION VERSION_LESS 2.8.11)
|
||||
include_directories("${gtest_SOURCE_DIR}/include"
|
||||
"${gmock_SOURCE_DIR}/include")
|
||||
endif()
|
||||
|
||||
include_directories("../../core/include/")
|
||||
|
||||
add_executable(core_ut
|
||||
alibabacloud_ut.cc
|
||||
asynccallercontext_ut.cc
|
||||
clientconfiguration_ut.cc
|
||||
commonrequest_ut.cc
|
||||
commonresponse_ut.cc
|
||||
credentials_ut.cc
|
||||
curlhttpclient_ut.cc
|
||||
endpointprovider_ut.cc
|
||||
error_ut.cc
|
||||
executor_ut.cc
|
||||
httprequest_ut.cc
|
||||
httpresponse_ut.cc
|
||||
httpmessage_ut.cc
|
||||
hmacsha1signer_ut.cc
|
||||
networkproxy_ut.cc
|
||||
roaservicerequest_ut.cc
|
||||
rpcservicerequest_ut.cc
|
||||
runnable_ut.cc
|
||||
serviceresult_ut.cc
|
||||
servicerequest_ut.cc
|
||||
simplecredentialsprovider_ut.cc
|
||||
url_ut.cc
|
||||
utils_ut.cc)
|
||||
|
||||
set_target_properties(core_ut
|
||||
PROPERTIES
|
||||
OUTPUT_NAME ${TARGET_OUTPUT_NAME_PREFIX}core_ut
|
||||
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
|
||||
|
||||
target_link_libraries(core_ut core gtest gmock_main)
|
||||
add_test(NAME core_ut COMMAND core_ut)
|
||||
17
test/core/DownloadProject.CMakeLists.cmake.in
Normal file
17
test/core/DownloadProject.CMakeLists.cmake.in
Normal file
@@ -0,0 +1,17 @@
|
||||
# Distributed under the OSI-approved MIT License. See accompanying
|
||||
# file LICENSE or https://github.com/Crascit/DownloadProject for details.
|
||||
|
||||
cmake_minimum_required(VERSION 2.8.2)
|
||||
|
||||
project(${DL_ARGS_PROJ}-download NONE)
|
||||
|
||||
include(ExternalProject)
|
||||
ExternalProject_Add(${DL_ARGS_PROJ}-download
|
||||
${DL_ARGS_UNPARSED_ARGUMENTS}
|
||||
SOURCE_DIR "${DL_ARGS_SOURCE_DIR}"
|
||||
BINARY_DIR "${DL_ARGS_BINARY_DIR}"
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
INSTALL_COMMAND ""
|
||||
TEST_COMMAND ""
|
||||
)
|
||||
182
test/core/DownloadProject.cmake
Normal file
182
test/core/DownloadProject.cmake
Normal file
@@ -0,0 +1,182 @@
|
||||
# Distributed under the OSI-approved MIT License. See accompanying
|
||||
# file LICENSE or https://github.com/Crascit/DownloadProject for details.
|
||||
#
|
||||
# MODULE: DownloadProject
|
||||
#
|
||||
# PROVIDES:
|
||||
# download_project( PROJ projectName
|
||||
# [PREFIX prefixDir]
|
||||
# [DOWNLOAD_DIR downloadDir]
|
||||
# [SOURCE_DIR srcDir]
|
||||
# [BINARY_DIR binDir]
|
||||
# [QUIET]
|
||||
# ...
|
||||
# )
|
||||
#
|
||||
# Provides the ability to download and unpack a tarball, zip file, git repository,
|
||||
# etc. at configure time (i.e. when the cmake command is run). How the downloaded
|
||||
# and unpacked contents are used is up to the caller, but the motivating case is
|
||||
# to download source code which can then be included directly in the build with
|
||||
# add_subdirectory() after the call to download_project(). Source and build
|
||||
# directories are set up with this in mind.
|
||||
#
|
||||
# The PROJ argument is required. The projectName value will be used to construct
|
||||
# the following variables upon exit (obviously replace projectName with its actual
|
||||
# value):
|
||||
#
|
||||
# projectName_SOURCE_DIR
|
||||
# projectName_BINARY_DIR
|
||||
#
|
||||
# The SOURCE_DIR and BINARY_DIR arguments are optional and would not typically
|
||||
# need to be provided. They can be specified if you want the downloaded source
|
||||
# and build directories to be located in a specific place. The contents of
|
||||
# projectName_SOURCE_DIR and projectName_BINARY_DIR will be populated with the
|
||||
# locations used whether you provide SOURCE_DIR/BINARY_DIR or not.
|
||||
#
|
||||
# The DOWNLOAD_DIR argument does not normally need to be set. It controls the
|
||||
# location of the temporary CMake build used to perform the download.
|
||||
#
|
||||
# The PREFIX argument can be provided to change the base location of the default
|
||||
# values of DOWNLOAD_DIR, SOURCE_DIR and BINARY_DIR. If all of those three arguments
|
||||
# are provided, then PREFIX will have no effect. The default value for PREFIX is
|
||||
# CMAKE_BINARY_DIR.
|
||||
#
|
||||
# The QUIET option can be given if you do not want to show the output associated
|
||||
# with downloading the specified project.
|
||||
#
|
||||
# In addition to the above, any other options are passed through unmodified to
|
||||
# ExternalProject_Add() to perform the actual download, patch and update steps.
|
||||
# The following ExternalProject_Add() options are explicitly prohibited (they
|
||||
# are reserved for use by the download_project() command):
|
||||
#
|
||||
# CONFIGURE_COMMAND
|
||||
# BUILD_COMMAND
|
||||
# INSTALL_COMMAND
|
||||
# TEST_COMMAND
|
||||
#
|
||||
# Only those ExternalProject_Add() arguments which relate to downloading, patching
|
||||
# and updating of the project sources are intended to be used. Also note that at
|
||||
# least one set of download-related arguments are required.
|
||||
#
|
||||
# If using CMake 3.2 or later, the UPDATE_DISCONNECTED option can be used to
|
||||
# prevent a check at the remote end for changes every time CMake is run
|
||||
# after the first successful download. See the documentation of the ExternalProject
|
||||
# module for more information. It is likely you will want to use this option if it
|
||||
# is available to you. Note, however, that the ExternalProject implementation contains
|
||||
# bugs which result in incorrect handling of the UPDATE_DISCONNECTED option when
|
||||
# using the URL download method or when specifying a SOURCE_DIR with no download
|
||||
# method. Fixes for these have been created, the last of which is scheduled for
|
||||
# inclusion in CMake 3.8.0. Details can be found here:
|
||||
#
|
||||
# https://gitlab.kitware.com/cmake/cmake/commit/bdca68388bd57f8302d3c1d83d691034b7ffa70c
|
||||
# https://gitlab.kitware.com/cmake/cmake/issues/16428
|
||||
#
|
||||
# If you experience build errors related to the update step, consider avoiding
|
||||
# the use of UPDATE_DISCONNECTED.
|
||||
#
|
||||
# EXAMPLE USAGE:
|
||||
#
|
||||
# include(DownloadProject)
|
||||
# download_project(PROJ googletest
|
||||
# GIT_REPOSITORY https://github.com/google/googletest.git
|
||||
# GIT_TAG master
|
||||
# UPDATE_DISCONNECTED 1
|
||||
# QUIET
|
||||
# )
|
||||
#
|
||||
# add_subdirectory(${googletest_SOURCE_DIR} ${googletest_BINARY_DIR})
|
||||
#
|
||||
#========================================================================================
|
||||
|
||||
|
||||
set(_DownloadProjectDir "${CMAKE_CURRENT_LIST_DIR}")
|
||||
|
||||
include(CMakeParseArguments)
|
||||
|
||||
function(download_project)
|
||||
|
||||
set(options QUIET)
|
||||
set(oneValueArgs
|
||||
PROJ
|
||||
PREFIX
|
||||
DOWNLOAD_DIR
|
||||
SOURCE_DIR
|
||||
BINARY_DIR
|
||||
# Prevent the following from being passed through
|
||||
CONFIGURE_COMMAND
|
||||
BUILD_COMMAND
|
||||
INSTALL_COMMAND
|
||||
TEST_COMMAND
|
||||
)
|
||||
set(multiValueArgs "")
|
||||
|
||||
cmake_parse_arguments(DL_ARGS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||
|
||||
# Hide output if requested
|
||||
if (DL_ARGS_QUIET)
|
||||
set(OUTPUT_QUIET "OUTPUT_QUIET")
|
||||
else()
|
||||
unset(OUTPUT_QUIET)
|
||||
message(STATUS "Downloading/updating ${DL_ARGS_PROJ}")
|
||||
endif()
|
||||
|
||||
# Set up where we will put our temporary CMakeLists.txt file and also
|
||||
# the base point below which the default source and binary dirs will be.
|
||||
# The prefix must always be an absolute path.
|
||||
if (NOT DL_ARGS_PREFIX)
|
||||
set(DL_ARGS_PREFIX "${CMAKE_BINARY_DIR}")
|
||||
else()
|
||||
get_filename_component(DL_ARGS_PREFIX "${DL_ARGS_PREFIX}" ABSOLUTE
|
||||
BASE_DIR "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
endif()
|
||||
if (NOT DL_ARGS_DOWNLOAD_DIR)
|
||||
set(DL_ARGS_DOWNLOAD_DIR "${DL_ARGS_PREFIX}/${DL_ARGS_PROJ}-download")
|
||||
endif()
|
||||
|
||||
# Ensure the caller can know where to find the source and build directories
|
||||
if (NOT DL_ARGS_SOURCE_DIR)
|
||||
set(DL_ARGS_SOURCE_DIR "${DL_ARGS_PREFIX}/${DL_ARGS_PROJ}-src")
|
||||
endif()
|
||||
if (NOT DL_ARGS_BINARY_DIR)
|
||||
set(DL_ARGS_BINARY_DIR "${DL_ARGS_PREFIX}/${DL_ARGS_PROJ}-build")
|
||||
endif()
|
||||
set(${DL_ARGS_PROJ}_SOURCE_DIR "${DL_ARGS_SOURCE_DIR}" PARENT_SCOPE)
|
||||
set(${DL_ARGS_PROJ}_BINARY_DIR "${DL_ARGS_BINARY_DIR}" PARENT_SCOPE)
|
||||
|
||||
# The way that CLion manages multiple configurations, it causes a copy of
|
||||
# the CMakeCache.txt to be copied across due to it not expecting there to
|
||||
# be a project within a project. This causes the hard-coded paths in the
|
||||
# cache to be copied and builds to fail. To mitigate this, we simply
|
||||
# remove the cache if it exists before we configure the new project. It
|
||||
# is safe to do so because it will be re-generated. Since this is only
|
||||
# executed at the configure step, it should not cause additional builds or
|
||||
# downloads.
|
||||
file(REMOVE "${DL_ARGS_DOWNLOAD_DIR}/CMakeCache.txt")
|
||||
|
||||
# Create and build a separate CMake project to carry out the download.
|
||||
# If we've already previously done these steps, they will not cause
|
||||
# anything to be updated, so extra rebuilds of the project won't occur.
|
||||
# Make sure to pass through CMAKE_MAKE_PROGRAM in case the main project
|
||||
# has this set to something not findable on the PATH.
|
||||
configure_file("${_DownloadProjectDir}/DownloadProject.CMakeLists.cmake.in"
|
||||
"${DL_ARGS_DOWNLOAD_DIR}/CMakeLists.txt")
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}"
|
||||
-D "CMAKE_MAKE_PROGRAM:FILE=${CMAKE_MAKE_PROGRAM}"
|
||||
.
|
||||
RESULT_VARIABLE result
|
||||
${OUTPUT_QUIET}
|
||||
WORKING_DIRECTORY "${DL_ARGS_DOWNLOAD_DIR}"
|
||||
)
|
||||
if(result)
|
||||
message(FATAL_ERROR "CMake step for ${DL_ARGS_PROJ} failed: ${result}")
|
||||
endif()
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} --build .
|
||||
RESULT_VARIABLE result
|
||||
${OUTPUT_QUIET}
|
||||
WORKING_DIRECTORY "${DL_ARGS_DOWNLOAD_DIR}"
|
||||
)
|
||||
if(result)
|
||||
message(FATAL_ERROR "Build step for ${DL_ARGS_PROJ} failed: ${result}")
|
||||
endif()
|
||||
|
||||
endfunction()
|
||||
18
test/core/alibabacloud_ut.cc
Normal file
18
test/core/alibabacloud_ut.cc
Normal file
@@ -0,0 +1,18 @@
|
||||
#include "gtest/gtest.h"
|
||||
#include "alibabacloud/core/AlibabaCloud.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace AlibabaCloud;
|
||||
|
||||
|
||||
TEST(AlibabaCloudTest, basic) {
|
||||
InitializeSdk();
|
||||
EXPECT_TRUE(IsSdkInitialized() == true);
|
||||
InitializeSdk();
|
||||
EXPECT_TRUE(IsSdkInitialized() == true);
|
||||
|
||||
ShutdownSdk();
|
||||
EXPECT_TRUE(IsSdkInitialized() == false);
|
||||
ShutdownSdk();
|
||||
EXPECT_TRUE(IsSdkInitialized() == false);
|
||||
}
|
||||
18
test/core/asynccallercontext_ut.cc
Normal file
18
test/core/asynccallercontext_ut.cc
Normal file
@@ -0,0 +1,18 @@
|
||||
#include "gtest/gtest.h"
|
||||
#include "alibabacloud/core/AsyncCallerContext.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace AlibabaCloud;
|
||||
|
||||
|
||||
TEST(AsyncCallerContext, basic) {
|
||||
const std::string sys_generated_uuid = "643ce9ff-32b5-444c-814a-153b87a6aca8";
|
||||
const std::string init_uuid = "init_uuid_for_test";
|
||||
const std::string new_uuid = "new_uuid_for_test";
|
||||
AsyncCallerContext context(init_uuid);
|
||||
EXPECT_TRUE(context.uuid() == init_uuid);
|
||||
context.setUuid(new_uuid);
|
||||
EXPECT_TRUE(context.uuid() == new_uuid);
|
||||
AsyncCallerContext context_from_GenerateUuid = AsyncCallerContext();
|
||||
EXPECT_TRUE(context_from_GenerateUuid.uuid().length() == sys_generated_uuid.length());
|
||||
}
|
||||
31
test/core/clientconfiguration_ut.cc
Normal file
31
test/core/clientconfiguration_ut.cc
Normal file
@@ -0,0 +1,31 @@
|
||||
#include "gtest/gtest.h"
|
||||
#include "alibabacloud/core/ClientConfiguration.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace AlibabaCloud;
|
||||
|
||||
|
||||
TEST(ClientConfiguration, basic) {
|
||||
const std::string regionId = "cn-shanghai";
|
||||
const std::string regionId_new = "cn-beijing";
|
||||
const std::string endpoint = "ep-cn-shanghai";
|
||||
|
||||
const std::string hostname = "hostname";
|
||||
const std::string user = "user";
|
||||
const std::string password = "password";
|
||||
uint16_t port = 12345;
|
||||
const NetworkProxy proxy(NetworkProxy::Http, hostname, port, user, password);
|
||||
|
||||
ClientConfiguration config(regionId);
|
||||
EXPECT_TRUE(config.regionId() == regionId);
|
||||
|
||||
config.setEndpoint(endpoint);
|
||||
config.setProxy(proxy);
|
||||
config.setRegionId(regionId_new);
|
||||
EXPECT_TRUE(config.endpoint() == endpoint);
|
||||
EXPECT_TRUE(config.regionId() == regionId_new);
|
||||
EXPECT_TRUE(config.proxy().hostName() == hostname);
|
||||
EXPECT_TRUE(config.proxy().port() == port);
|
||||
EXPECT_TRUE(config.proxy().user() == user);
|
||||
EXPECT_TRUE(config.proxy().password() == password);
|
||||
}
|
||||
22
test/core/commonrequest_ut.cc
Normal file
22
test/core/commonrequest_ut.cc
Normal file
@@ -0,0 +1,22 @@
|
||||
#include "gtest/gtest.h"
|
||||
#include "alibabacloud/core/CommonRequest.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace AlibabaCloud;
|
||||
|
||||
TEST(CommonRequest, basic) {
|
||||
CommonRequest cr;
|
||||
|
||||
cr.setDomain("testDomain");
|
||||
cr.setHeaderParameter("name1", "value1");
|
||||
cr.setHttpMethod(HttpRequest::Method::Get);
|
||||
cr.setQueryParameter("name2", "value2");
|
||||
cr.setRequestPattern(CommonRequest::RequestPattern::RpcPattern);
|
||||
EXPECT_TRUE(cr.domain() == "testDomain");
|
||||
EXPECT_TRUE(cr.httpMethod() == HttpRequest::Method::Get);
|
||||
EXPECT_TRUE(cr.requestPattern() == CommonRequest::RequestPattern::RpcPattern);
|
||||
EXPECT_TRUE(cr.headerParameter("name1") == "value1");
|
||||
EXPECT_TRUE(cr.queryParameter("name2") == "value2");
|
||||
EXPECT_TRUE(cr.queryParameters()["name2"] == "value2");
|
||||
EXPECT_TRUE(cr.headerParameters()["name1"] == "value1");
|
||||
}
|
||||
14
test/core/commonresponse_ut.cc
Normal file
14
test/core/commonresponse_ut.cc
Normal file
@@ -0,0 +1,14 @@
|
||||
#include "gtest/gtest.h"
|
||||
#include "alibabacloud/core/CommonResponse.h"
|
||||
|
||||
|
||||
using namespace std;
|
||||
using namespace AlibabaCloud;
|
||||
|
||||
TEST(CommonResponse, basic) {
|
||||
CommonResponse cres("test_payload_");
|
||||
EXPECT_TRUE(cres.payload() == "test_payload_");
|
||||
|
||||
CommonResponse cres1;
|
||||
EXPECT_TRUE(cres1.payload() == "");
|
||||
}
|
||||
28
test/core/credentials_ut.cc
Normal file
28
test/core/credentials_ut.cc
Normal file
@@ -0,0 +1,28 @@
|
||||
#include "gtest/gtest.h"
|
||||
#include "alibabacloud/core/Credentials.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace AlibabaCloud;
|
||||
|
||||
TEST(CredentialsTest, basic) {
|
||||
const string access_key = "accessKeyId";
|
||||
const string access_secret = "accessKeySecret";
|
||||
const string session_token = "sessionToken";
|
||||
const string new_access_key = "new_accessKeyId";
|
||||
const string new_access_secret = "new_accessKeySecret";
|
||||
const string new_session_token = "new_sessionToken";
|
||||
|
||||
Credentials credentials(access_key, access_secret, session_token);
|
||||
|
||||
EXPECT_TRUE(credentials.accessKeyId() == access_key);
|
||||
EXPECT_TRUE(credentials.accessKeySecret() == access_secret);
|
||||
EXPECT_TRUE(credentials.sessionToken() == session_token);
|
||||
|
||||
credentials.setAccessKeyId(new_access_key);
|
||||
credentials.setAccessKeySecret(new_access_secret);
|
||||
credentials.setSessionToken(new_session_token);
|
||||
|
||||
EXPECT_TRUE(credentials.accessKeyId() == new_access_key);
|
||||
EXPECT_TRUE(credentials.accessKeySecret() == new_access_secret);
|
||||
EXPECT_TRUE(credentials.sessionToken() == new_session_token);
|
||||
}
|
||||
145
test/core/curlhttpclient_ut.cc
Normal file
145
test/core/curlhttpclient_ut.cc
Normal file
@@ -0,0 +1,145 @@
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "utils.h"
|
||||
#include "../include/gtest/gtest.h"
|
||||
#include "../include/gmock/gmock.h"
|
||||
#include "../../core/include/alibabacloud/core/Url.h"
|
||||
#include "../../core/include/alibabacloud/core/HttpRequest.h"
|
||||
#include "../../core/include/alibabacloud/core/HttpClient.h"
|
||||
#include "../../core/src/CurlHttpClient.h"
|
||||
|
||||
using namespace std;
|
||||
using ::testing::Return;
|
||||
using ::testing::DoAll;
|
||||
using ::testing::SetArgReferee;
|
||||
using ::testing::ReturnPointee;
|
||||
using ::testing::_;
|
||||
using ::testing::NiceMock;
|
||||
using ::testing::DefaultValue;
|
||||
|
||||
using namespace AlibabaCloud;
|
||||
|
||||
using namespace std;
|
||||
|
||||
class mockCurlHttpClient : public CurlHttpClient {
|
||||
public:
|
||||
MOCK_METHOD1(makeRequest, HttpResponseOutcome (const HttpRequest &request));
|
||||
};
|
||||
|
||||
// httpserver_for_ut port "echo text"
|
||||
// default port 8021
|
||||
// default text test/httpserver/index.html
|
||||
|
||||
TEST(CurlHttpClient, basic) {
|
||||
CurlHttpClient client;
|
||||
HttpRequest request;
|
||||
|
||||
utUtils utils;
|
||||
char dir[1024];
|
||||
utils.get_dir_exec(dir, nullptr);
|
||||
char httpserver_ut_with_args[10 * 1024];
|
||||
const string testBody = "CurlHttpClient test boday";
|
||||
snprintf(httpserver_ut_with_args, 10 * 1024, "%s/httpserver_for_ut 8021 \"%s\"", dir, testBody.c_str());
|
||||
|
||||
FILE* http = popen(httpserver_ut_with_args, "r");
|
||||
EXPECT_TRUE(http != nullptr);
|
||||
|
||||
// wait util httpserver started
|
||||
char buffer[100];
|
||||
usleep(10 * 1000);
|
||||
fgets(buffer, 100, http);
|
||||
|
||||
Url url;
|
||||
url.setHost("127.0.0.1");
|
||||
url.setPort(8021);
|
||||
|
||||
request.setMethod(HttpRequest::Method::Get);
|
||||
request.setUrl(url);
|
||||
|
||||
request.setHeader("head1", "value1");
|
||||
request.setHeader("head2", "value2");
|
||||
HttpClient::HttpResponseOutcome out = client.makeRequest(request);
|
||||
EXPECT_TRUE(out.result().body() == testBody);
|
||||
|
||||
request.setMethod(HttpRequest::Method::Put);
|
||||
request.setUrl(url);
|
||||
|
||||
HttpClient::HttpResponseOutcome out1 = client.makeRequest(request);
|
||||
EXPECT_TRUE(out1.result().body() == testBody);
|
||||
|
||||
request.setMethod(HttpRequest::Method::Post);
|
||||
request.setUrl(url);
|
||||
|
||||
HttpClient::HttpResponseOutcome out2 = client.makeRequest(request);
|
||||
EXPECT_TRUE(out2.result().body() == testBody);
|
||||
|
||||
pclose(http);
|
||||
}
|
||||
|
||||
TEST(CurlHttpClient, netWorkError) {
|
||||
CurlHttpClient client;
|
||||
HttpRequest request;
|
||||
HttpClient::HttpResponseOutcome out = client.makeRequest(request);
|
||||
EXPECT_TRUE(out.error().errorCode() == "NetworkError");
|
||||
EXPECT_TRUE(out.error().errorMessage() == "Failed to connect to host or proxy.");
|
||||
}
|
||||
|
||||
TEST(CurlHttpClient, netWorkErrorWithHttpProxy) {
|
||||
const std::string hostname = "hostname";
|
||||
const std::string user = "user";
|
||||
const std::string password = "password";
|
||||
uint16_t port = 12345;
|
||||
const NetworkProxy proxy(NetworkProxy::Http, hostname, port, user, password);
|
||||
|
||||
CurlHttpClient client;
|
||||
client.setProxy(proxy);
|
||||
|
||||
HttpRequest request;
|
||||
HttpClient::HttpResponseOutcome out = client.makeRequest(request);
|
||||
EXPECT_TRUE(out.error().errorCode() == "NetworkError");
|
||||
EXPECT_TRUE(out.error().errorMessage() == "Failed to connect to host or proxy.");
|
||||
}
|
||||
|
||||
TEST(CurlHttpClient, netWorkErrorWithSocks5Proxy) {
|
||||
const std::string hostname = "hostname";
|
||||
const std::string user = "user";
|
||||
const std::string password = "password";
|
||||
uint16_t port = 12345;
|
||||
const NetworkProxy proxy(NetworkProxy::Socks5, hostname, port, user, password);
|
||||
|
||||
CurlHttpClient client;
|
||||
client.setProxy(proxy);
|
||||
|
||||
HttpRequest request;
|
||||
HttpClient::HttpResponseOutcome out = client.makeRequest(request);
|
||||
EXPECT_TRUE(out.error().errorCode() == "NetworkError");
|
||||
EXPECT_TRUE(out.error().errorMessage() == "Failed to connect to host or proxy.");
|
||||
}
|
||||
|
||||
TEST(CurlHttpClient, mock) {
|
||||
CurlHttpClient client;
|
||||
HttpRequest request;
|
||||
|
||||
string body = "1234567";
|
||||
HttpResponse response(request);
|
||||
response.setStatusCode(200);
|
||||
response.setBody(body.c_str(), body.size());
|
||||
|
||||
NiceMock<mockCurlHttpClient> mclient;
|
||||
|
||||
HttpClient::HttpResponseOutcome res = HttpClient::HttpResponseOutcome(response);
|
||||
HttpClient::HttpResponseOutcome out1;
|
||||
|
||||
out1.error().setErrorCode("111");
|
||||
out1.error().setErrorMessage("this is a mock test");
|
||||
|
||||
DefaultValue<HttpClient::HttpResponseOutcome>::Set(res);
|
||||
|
||||
HttpRequest req;
|
||||
|
||||
EXPECT_CALL(mclient, makeRequest(_));
|
||||
|
||||
HttpClient::HttpResponseOutcome o = mclient.makeRequest(request);
|
||||
EXPECT_TRUE(res.result().body() == body);
|
||||
}
|
||||
69
test/core/endpointprovider_ut.cc
Normal file
69
test/core/endpointprovider_ut.cc
Normal file
@@ -0,0 +1,69 @@
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
#include "gtest/gtest.h"
|
||||
#include "alibabacloud/core/EndpointProvider.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace AlibabaCloud;
|
||||
using namespace AlibabaCloud::Location;
|
||||
|
||||
TEST(EndpointProvider, basic) {
|
||||
ClientConfiguration configuration("cn-hangzhou");
|
||||
|
||||
char* key = getenv("ENV_AccessKeyId");
|
||||
char* secret = getenv("ENV_AccessKeySecret");
|
||||
|
||||
bool no_key_provided = false;
|
||||
|
||||
string accessKeyId, accessKeySecret;
|
||||
if (key == nullptr) {
|
||||
accessKeyId = "no-AccessKeyId";
|
||||
no_key_provided = true;
|
||||
} else {
|
||||
accessKeyId = string(key);
|
||||
}
|
||||
if (secret == nullptr) {
|
||||
accessKeySecret = "no-AccessKeySecret";
|
||||
no_key_provided = true;
|
||||
} else {
|
||||
accessKeySecret = string(secret);
|
||||
}
|
||||
auto locationClient = std::make_shared<LocationClient>(accessKeyId, accessKeySecret, configuration);
|
||||
|
||||
EndpointProvider ep(locationClient, configuration.regionId(), "Ecs", "ecs");
|
||||
EndpointProvider::EndpointOutcome out = ep.getEndpoint();
|
||||
|
||||
if (no_key_provided) {
|
||||
EXPECT_TRUE(out.error().errorCode() == "InvalidAccessKeyId.NotFound");
|
||||
} else {
|
||||
EXPECT_TRUE(out.result() == "ecs-cn-hangzhou.aliyuncs.com");
|
||||
}
|
||||
}
|
||||
|
||||
TEST(EndpointProvider, basic1) {
|
||||
ClientConfiguration configuration("cn-hangzhou");
|
||||
|
||||
const string accessKeyId = "no-AccessKeyId";
|
||||
const string accessKeySecret = "no-AccessKeySecret";
|
||||
|
||||
auto locationClient = std::make_shared<LocationClient>(accessKeyId, accessKeySecret, configuration);
|
||||
|
||||
EndpointProvider ep(locationClient, configuration.regionId(), "Ecs");
|
||||
EndpointProvider::EndpointOutcome out = ep.getEndpoint();
|
||||
|
||||
EXPECT_TRUE(out.error().errorCode() == "InvalidRegionId");
|
||||
}
|
||||
|
||||
|
||||
TEST(EndpointProvider, basic2) {
|
||||
ClientConfiguration configuration("xxxcn-hangzhou");
|
||||
|
||||
const string accessKeyId = "no-AccessKeyId";
|
||||
const string accessKeySecret = "no-AccessKeySecret";
|
||||
|
||||
auto locationClient = std::make_shared<LocationClient>(accessKeyId, accessKeySecret, configuration);
|
||||
|
||||
EndpointProvider ep(locationClient, configuration.regionId(), "Ecs", "ecs");
|
||||
EndpointProvider::EndpointOutcome out = ep.getEndpoint();
|
||||
EXPECT_TRUE(out.error().errorCode() == "InvalidAccessKeyId.NotFound");
|
||||
}
|
||||
33
test/core/error_ut.cc
Normal file
33
test/core/error_ut.cc
Normal file
@@ -0,0 +1,33 @@
|
||||
#include "gtest/gtest.h"
|
||||
#include "alibabacloud/core/Error.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace AlibabaCloud;
|
||||
|
||||
TEST(Error, basic) {
|
||||
const std::string error_code = "errorCode";
|
||||
const std::string error_message = "errorMessage";
|
||||
const std::string host = "Host";
|
||||
const std::string request_id = "requestId";
|
||||
|
||||
Error error(error_code, error_message);
|
||||
EXPECT_TRUE(error.errorCode() == error_code);
|
||||
EXPECT_TRUE(error.errorMessage() == error_message);
|
||||
EXPECT_TRUE(error.host() == "");
|
||||
EXPECT_TRUE(error.requestId() == "");
|
||||
|
||||
error.setHost(host);
|
||||
error.setRequestId(request_id);
|
||||
EXPECT_TRUE(error.errorCode() == error_code);
|
||||
EXPECT_TRUE(error.errorMessage() == error_message);
|
||||
EXPECT_TRUE(error.host() == host);
|
||||
EXPECT_TRUE(error.requestId() == request_id);
|
||||
|
||||
const string code1 = "invalid regionId";
|
||||
const string message1 = "invalid regionId cn-xxxx";
|
||||
error.setErrorCode(code1);
|
||||
error.setErrorMessage(message1);
|
||||
|
||||
EXPECT_TRUE(error.errorCode() == code1);
|
||||
EXPECT_TRUE(error.errorMessage() == message1);
|
||||
}
|
||||
78
test/core/executor_ut.cc
Normal file
78
test/core/executor_ut.cc
Normal file
@@ -0,0 +1,78 @@
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
#include "gtest/gtest.h"
|
||||
#include "alibabacloud/core/Runnable.h"
|
||||
#include "../src/Executor.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace AlibabaCloud;
|
||||
|
||||
namespace {
|
||||
|
||||
static unsigned int nbr = 0;
|
||||
|
||||
static void f0() {
|
||||
usleep(3000);
|
||||
nbr |= 0x01;
|
||||
}
|
||||
|
||||
static void f1() {
|
||||
usleep(3000);
|
||||
nbr |= 0x02;
|
||||
}
|
||||
|
||||
static void f2() {
|
||||
usleep(3000);
|
||||
nbr |= 0x04;
|
||||
}
|
||||
|
||||
// there should be no exception
|
||||
TEST(Executor, basic) {
|
||||
std::function<void()> func0(f0);
|
||||
std::function<void()> func1(f1);
|
||||
std::function<void()> func2(f2);
|
||||
Runnable* rf0 = new Runnable(func0);
|
||||
Runnable* rf1 = new Runnable(func1);
|
||||
Runnable* rf2 = new Runnable(func2);
|
||||
|
||||
Executor* e = new Executor;
|
||||
EXPECT_TRUE(e->isShutdown() == true);
|
||||
|
||||
// thread created to execute tasks
|
||||
e->start();
|
||||
|
||||
// before
|
||||
EXPECT_TRUE(nbr == 0);
|
||||
|
||||
// push tasks to queue
|
||||
e->instance()->execute(rf0);
|
||||
e->instance()->execute(rf1);
|
||||
e->instance()->execute(rf2);
|
||||
|
||||
// shutdown removes tasks in queue
|
||||
e->shutdown();
|
||||
|
||||
// there is no time for task executing
|
||||
// maybe some tasks executed as the async reason
|
||||
EXPECT_TRUE(nbr != 0x07);
|
||||
|
||||
rf0 = new Runnable(func0);
|
||||
rf1 = new Runnable(func1);
|
||||
rf2 = new Runnable(func2);
|
||||
nbr = 0;
|
||||
e->execute(rf0);
|
||||
usleep(5000);
|
||||
// executor not started, nbr no changed
|
||||
EXPECT_TRUE(nbr == 0);
|
||||
|
||||
e->start();
|
||||
// there should be no more thread created
|
||||
e->start();
|
||||
e->instance()->execute(rf0);
|
||||
e->execute(rf1);
|
||||
e->execute(rf2);
|
||||
usleep(20000);
|
||||
EXPECT_TRUE(nbr == 0x07);
|
||||
e->shutdown();
|
||||
}
|
||||
}
|
||||
25
test/core/hmacsha1signer_ut.cc
Normal file
25
test/core/hmacsha1signer_ut.cc
Normal file
@@ -0,0 +1,25 @@
|
||||
#include "gtest/gtest.h"
|
||||
#include "alibabacloud/core/HmacSha1Signer.h"
|
||||
#include <openssl/hmac.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace AlibabaCloud;
|
||||
|
||||
TEST(HmacSha1Signer, assign) {
|
||||
|
||||
HmacSha1Signer sig;
|
||||
string sign = sig.generate("GET&%2F&AccessKeyId%3Dtestid%26Action%3DDescribeRegions"
|
||||
"%26Format%3DXML%26RegionId%3Dregion1%26SignatureMethod%3DHMAC-SHA1"
|
||||
"%26SignatureNonce%3DNwDAxvLU6tFE0DVb%26SignatureVersion%3D1.0"
|
||||
"%26TimeStamp%3D2012-12-26T10%253A33%253A56Z%26Version%3D2013-01-10",
|
||||
"testsecret&");
|
||||
EXPECT_TRUE("axE3FUHgDyfm9/+Iep0HpZXrRwE=" == sign);
|
||||
EXPECT_TRUE(sig.type() == HmacSha1Signer::HmacSha1);
|
||||
EXPECT_TRUE(sig.name() == "HMAC-SHA1");
|
||||
EXPECT_TRUE(sig.version() == "1.0");
|
||||
}
|
||||
|
||||
TEST(HmacSha1Signer, edge_from_empty_string) {
|
||||
HmacSha1Signer sign;
|
||||
EXPECT_TRUE(sign.generate("", "") == "");
|
||||
}
|
||||
56
test/core/httpmessage_ut.cc
Normal file
56
test/core/httpmessage_ut.cc
Normal file
@@ -0,0 +1,56 @@
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "alibabacloud/core/HttpRequest.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace AlibabaCloud;
|
||||
|
||||
TEST(HttpMessage, perRequest) {
|
||||
const std::string data = "Thu, 19 Oct 2017 04:38:27 GMT";
|
||||
HttpRequest req;
|
||||
req.setHeader("accept", "application/xml");
|
||||
EXPECT_TRUE(req.header("accept") == "application/xml");
|
||||
req.setHeader("Accept", "application/json");
|
||||
EXPECT_TRUE(req.header("accept") == "application/json");
|
||||
EXPECT_TRUE(req.headers().size() == 1);
|
||||
req.setHeader("Date", data);
|
||||
EXPECT_TRUE(req.headers().size() == 2);
|
||||
EXPECT_TRUE(req.header(HttpMessage::KnownHeader::Date) == data);
|
||||
|
||||
req.addHeader("header1", "value1");
|
||||
EXPECT_TRUE(req.header("header1") == "value1");
|
||||
EXPECT_TRUE(req.headers().size() == 3);
|
||||
|
||||
req.addHeader(HttpMessage::KnownHeader::ContentMD5, "testmd5sume");
|
||||
EXPECT_TRUE(req.header(HttpMessage::KnownHeader::ContentMD5) == "testmd5sume");
|
||||
EXPECT_TRUE(req.headers().size() == 4);
|
||||
|
||||
req.removeHeader("header1");
|
||||
EXPECT_TRUE(req.header("header1") == "");
|
||||
EXPECT_TRUE(req.headers().size() == 3);
|
||||
req.removeHeader(HttpMessage::KnownHeader::ContentMD5);
|
||||
EXPECT_TRUE(req.header(HttpMessage::KnownHeader::ContentMD5) == "");
|
||||
EXPECT_TRUE(req.headers().size() == 2);
|
||||
|
||||
string body = "this is a test body";
|
||||
|
||||
req.setBody(body.c_str(), body.size());
|
||||
EXPECT_TRUE(req.bodySize() == body.size());
|
||||
EXPECT_TRUE(req.hasBody());
|
||||
EXPECT_TRUE(req.body() != nullptr);
|
||||
|
||||
|
||||
}
|
||||
|
||||
class TestHttpMessage: public HttpMessage {
|
||||
public:
|
||||
TestHttpMessage(): HttpMessage(){}
|
||||
};
|
||||
|
||||
TEST(HttpMessage, A) {
|
||||
TestHttpMessage tm;
|
||||
TestHttpMessage ttm(tm);
|
||||
|
||||
}
|
||||
30
test/core/httprequest_ut.cc
Normal file
30
test/core/httprequest_ut.cc
Normal file
@@ -0,0 +1,30 @@
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
#include "gtest/gtest.h"
|
||||
#include "alibabacloud/core/HttpRequest.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace AlibabaCloud;
|
||||
|
||||
TEST(HttpRequest, basic) {
|
||||
const string src = "abc://username:password@example.com:123/path/data?key=value&key2=value2#fragid1";
|
||||
Url url;
|
||||
url.setScheme("abc");
|
||||
url.setUserName("username");
|
||||
url.setPassword("password");
|
||||
url.setHost("example.com");
|
||||
url.setPath("/path/data");
|
||||
url.setPort(123);
|
||||
url.setQuery("key=value&key2=value2");
|
||||
url.setFragment("fragid1");
|
||||
|
||||
HttpRequest http_request(url, HttpRequest::Method::Post);
|
||||
|
||||
EXPECT_TRUE(http_request.method() == HttpRequest::Method::Post);
|
||||
http_request.setMethod(HttpRequest::Method::Get);
|
||||
EXPECT_TRUE(http_request.method() == HttpRequest::Method::Get);
|
||||
|
||||
http_request.setUrl(url);
|
||||
Url rUrl = http_request.url();
|
||||
EXPECT_TRUE(rUrl.toString() == src);
|
||||
}
|
||||
18
test/core/httpresponse_ut.cc
Normal file
18
test/core/httpresponse_ut.cc
Normal file
@@ -0,0 +1,18 @@
|
||||
#include "gtest/gtest.h"
|
||||
#include "alibabacloud/core/HttpResponse.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace AlibabaCloud;
|
||||
|
||||
TEST(HttpResponse, basic) {
|
||||
HttpResponse r;
|
||||
r.setStatusCode(202);
|
||||
EXPECT_TRUE(r.statusCode() == 202);
|
||||
|
||||
Url url;
|
||||
url.setHost("example.com");
|
||||
HttpRequest req(url, HttpRequest::Method::Post);
|
||||
HttpResponse res(req);
|
||||
|
||||
EXPECT_TRUE(res.request().url().host() == "example.com");
|
||||
}
|
||||
21
test/core/networkproxy_ut.cc
Normal file
21
test/core/networkproxy_ut.cc
Normal file
@@ -0,0 +1,21 @@
|
||||
#include "gtest/gtest.h"
|
||||
#include "alibabacloud/core/NetworkProxy.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace AlibabaCloud;
|
||||
|
||||
TEST(NetworProxyTest, basic) {
|
||||
NetworkProxy proxy(NetworkProxy::Http);
|
||||
proxy.setHostName("abc.com");
|
||||
proxy.setPassword("myPassword");
|
||||
proxy.setPort(123);
|
||||
proxy.setUser("tester");
|
||||
|
||||
EXPECT_TRUE(proxy.type() == NetworkProxy::Http);
|
||||
proxy.setType(NetworkProxy::Socks5);
|
||||
EXPECT_TRUE(proxy.type() == NetworkProxy::Socks5);
|
||||
EXPECT_TRUE(proxy.hostName() == "abc.com");
|
||||
EXPECT_TRUE(proxy.password() == "myPassword");
|
||||
EXPECT_TRUE(proxy.user() == "tester");
|
||||
EXPECT_TRUE(proxy.port() == 123);
|
||||
}
|
||||
16
test/core/roaservicerequest_ut.cc
Normal file
16
test/core/roaservicerequest_ut.cc
Normal file
@@ -0,0 +1,16 @@
|
||||
#include "gtest/gtest.h"
|
||||
#include "alibabacloud/core/RoaServiceRequest.h"
|
||||
|
||||
|
||||
using namespace std;
|
||||
using namespace AlibabaCloud;
|
||||
|
||||
TEST(test_RoaServiceRequest, basic) {
|
||||
const string product = "ECS";
|
||||
const string version = "1.0";
|
||||
|
||||
RoaServiceRequest roa(product, version);
|
||||
EXPECT_TRUE(roa.version() == version);
|
||||
EXPECT_TRUE(roa.product() == product);
|
||||
}
|
||||
|
||||
18
test/core/rpcservicerequest_ut.cc
Normal file
18
test/core/rpcservicerequest_ut.cc
Normal file
@@ -0,0 +1,18 @@
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
#include "gtest/gtest.h"
|
||||
#include "alibabacloud/core/RpcServiceRequest.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace AlibabaCloud;
|
||||
|
||||
TEST(test_RpcServiceRequest, basic) {
|
||||
const string product = "ECS";
|
||||
const string version = "1.0";
|
||||
const string action = "testAction";
|
||||
RpcServiceRequest rpc(product, version, action);
|
||||
|
||||
EXPECT_TRUE(rpc.actionName() == action);
|
||||
EXPECT_TRUE(rpc.product() == product);
|
||||
EXPECT_TRUE(rpc.version() == version);
|
||||
}
|
||||
22
test/core/runnable_ut.cc
Normal file
22
test/core/runnable_ut.cc
Normal file
@@ -0,0 +1,22 @@
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
#include "gtest/gtest.h"
|
||||
#include "alibabacloud/core/Runnable.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace AlibabaCloud;
|
||||
|
||||
|
||||
static int nbr = 0;
|
||||
void foo() {
|
||||
nbr = 1;
|
||||
}
|
||||
|
||||
// there should be no exception
|
||||
TEST(Runnable, basic) {
|
||||
std::function<void()> func(foo);
|
||||
Runnable f(func);
|
||||
EXPECT_TRUE(nbr == 0);
|
||||
f.run();
|
||||
EXPECT_TRUE(nbr == 1);
|
||||
}
|
||||
110
test/core/servicerequest_ut.cc
Normal file
110
test/core/servicerequest_ut.cc
Normal file
@@ -0,0 +1,110 @@
|
||||
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "gtest/gtest.h"
|
||||
#include "alibabacloud/core/ServiceRequest.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace AlibabaCloud;
|
||||
|
||||
namespace AlibabaCloud{
|
||||
class TestServiceRequest: public ServiceRequest {
|
||||
public:
|
||||
explicit TestServiceRequest(const std::string &product, const std::string &version):
|
||||
ServiceRequest(product, version)
|
||||
{}
|
||||
explicit TestServiceRequest(const ServiceRequest &other):
|
||||
ServiceRequest(other)
|
||||
{}
|
||||
explicit TestServiceRequest(ServiceRequest &&other):
|
||||
ServiceRequest(other)
|
||||
{}
|
||||
|
||||
|
||||
void addParameter(const ParameterNameType &k, const ParameterValueType &v) {
|
||||
ServiceRequest::addParameter(k, v);
|
||||
}
|
||||
|
||||
void removeParameter(const ParameterNameType &k) {
|
||||
ServiceRequest::removeParameter(k);
|
||||
}
|
||||
|
||||
ServiceRequest::ParameterValueType parameter (const ParameterNameType &name) {
|
||||
return ServiceRequest::parameter(name);
|
||||
}
|
||||
|
||||
void setContent(const char* data, size_t size) {
|
||||
ServiceRequest::setContent(data, size);
|
||||
}
|
||||
void setParameter(const ParameterNameType &k, const ParameterValueType &v) {
|
||||
ServiceRequest::setParameter(k, v);
|
||||
}
|
||||
void setParameters(const ParameterCollection ¶ms) {
|
||||
ServiceRequest::setParameters(params);
|
||||
}
|
||||
|
||||
void setResourcePath (const std::string &p) {
|
||||
ServiceRequest::setResourcePath(p);
|
||||
}
|
||||
|
||||
void setProduct (const std::string &product) {
|
||||
ServiceRequest::setProduct(product);
|
||||
}
|
||||
|
||||
void setVersion(const std::string &version) {
|
||||
ServiceRequest::setVersion(version);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
TEST(ServiceRequestTest, basic) {
|
||||
|
||||
TestServiceRequest sr1("ECS", "1.0");
|
||||
TestServiceRequest sr2(sr1);
|
||||
|
||||
sr1.addParameter("k1", "v1");
|
||||
sr2.addParameter("k2", "v2");
|
||||
|
||||
ServiceRequest::ParameterCollection p1 = sr1.parameters();
|
||||
ServiceRequest::ParameterCollection p2 = sr2.parameters();
|
||||
|
||||
EXPECT_TRUE(sr1.parameter("k1") == "v1");
|
||||
sr1.addParameter("kx", "vx");
|
||||
EXPECT_TRUE(sr1.parameter("kx") == "vx");
|
||||
|
||||
EXPECT_TRUE(sr1.parameters().size() == 2);
|
||||
|
||||
sr1.removeParameter("k1");
|
||||
EXPECT_TRUE(sr1.parameters().size() == 1);
|
||||
|
||||
sr1.setParameter("ka", "va");
|
||||
EXPECT_TRUE(sr1.parameter("ka") == "va");
|
||||
|
||||
sr1.setContent("123456", 6);
|
||||
EXPECT_TRUE(sr1.contentSize() == 6);
|
||||
EXPECT_TRUE(sr1.hasContent() == true);
|
||||
EXPECT_TRUE(strncmp(sr1.content(), "123456", 6) == 0);
|
||||
|
||||
sr1.setContent("aliyunsdk", 9);
|
||||
EXPECT_TRUE(sr1.contentSize() == 9);
|
||||
EXPECT_TRUE(sr1.hasContent() == true);
|
||||
EXPECT_TRUE(strncmp(sr1.content(), "aliyunsdk", 9) == 0);
|
||||
|
||||
sr1.setProduct("OSS");
|
||||
EXPECT_TRUE(sr1.product() == "OSS");
|
||||
|
||||
sr1.setVersion("3.0");
|
||||
EXPECT_TRUE(sr1.version() == "3.0");
|
||||
|
||||
sr1.setResourcePath("http://abc.com/a/b/c");
|
||||
EXPECT_TRUE(sr1.resourcePath() == "http://abc.com/a/b/c");
|
||||
|
||||
ServiceRequest::ParameterCollection ps;
|
||||
ps["km"] = "vm";
|
||||
ps["kn"] = "vn";
|
||||
sr1.setParameters(ps);
|
||||
ServiceRequest::ParameterCollection pc = sr1.parameters();
|
||||
EXPECT_TRUE(pc.at("km") == "vm");
|
||||
EXPECT_TRUE(pc.at("kn") == "vn");
|
||||
}
|
||||
29
test/core/serviceresult_ut.cc
Normal file
29
test/core/serviceresult_ut.cc
Normal file
@@ -0,0 +1,29 @@
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
#include "gtest/gtest.h"
|
||||
#include "alibabacloud/core/ServiceResult.h"
|
||||
|
||||
|
||||
using namespace std;
|
||||
using namespace AlibabaCloud;
|
||||
|
||||
namespace AlibabaCloud{
|
||||
class myServiceResult: public ServiceResult {
|
||||
public:
|
||||
myServiceResult(){}
|
||||
|
||||
void setRequestId(const string request_id) {
|
||||
ServiceResult::setRequestId(request_id);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
TEST(ServiceResult, basic) {
|
||||
ServiceResult* service_result = new ServiceResult();
|
||||
EXPECT_TRUE(service_result->requestId() == "");
|
||||
myServiceResult* sr = new myServiceResult();
|
||||
sr->setRequestId("testRequestId");
|
||||
EXPECT_TRUE(sr->requestId() == "testRequestId");
|
||||
delete(service_result);
|
||||
delete(sr);
|
||||
}
|
||||
20
test/core/signer_ut.cc
Normal file
20
test/core/signer_ut.cc
Normal file
@@ -0,0 +1,20 @@
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "alibabacloud/core/Signer.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace AlibabaCloud;
|
||||
|
||||
namespace {
|
||||
TEST(Signer, basic) {
|
||||
|
||||
HmacSha1Signer sig;
|
||||
string sign = sig.generate("GET&%2F&AccessKeyId%3Dtestid%26Action%3DDescribeRegions"
|
||||
"%26Format%3DXML%26RegionId%3Dregion1%26SignatureMethod%3DHMAC-SHA1"
|
||||
"%26SignatureNonce%3DNwDAxvLU6tFE0DVb%26SignatureVersion%3D1.0"
|
||||
"%26TimeStamp%3D2012-12-26T10%253A33%253A56Z%26Version%3D2013-01-10",
|
||||
"testsecret&");
|
||||
EXPECT_TRUE("axE3FUHgDyfm9/+Iep0HpZXrRwE=" == sign);
|
||||
|
||||
}
|
||||
}
|
||||
23
test/core/simplecredentialsprovider_ut.cc
Normal file
23
test/core/simplecredentialsprovider_ut.cc
Normal file
@@ -0,0 +1,23 @@
|
||||
#include "gtest/gtest.h"
|
||||
#include "alibabacloud/core/Credentials.h"
|
||||
#include "alibabacloud/core/sts/StsClient.h"
|
||||
#include "alibabacloud/core/SimpleCredentialsProvider.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace AlibabaCloud;
|
||||
|
||||
TEST(SimpleCredentialsProvider, basic) {
|
||||
|
||||
const string access_key = "accessKeyId";
|
||||
const string access_secret = "accessKeySecret";
|
||||
Credentials credentials(access_key, access_secret);
|
||||
|
||||
SimpleCredentialsProvider p1(credentials);
|
||||
SimpleCredentialsProvider p2(access_key, access_secret);
|
||||
|
||||
EXPECT_TRUE(p1.getCredentials().accessKeyId() == access_key);
|
||||
EXPECT_TRUE(p1.getCredentials().accessKeySecret() == access_secret);
|
||||
|
||||
EXPECT_TRUE(p2.getCredentials().accessKeyId() == access_key);
|
||||
EXPECT_TRUE(p2.getCredentials().accessKeySecret() == access_secret);
|
||||
}
|
||||
118
test/core/url_ut.cc
Normal file
118
test/core/url_ut.cc
Normal file
@@ -0,0 +1,118 @@
|
||||
#include "gtest/gtest.h"
|
||||
#include "alibabacloud/core/Url.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace AlibabaCloud;
|
||||
|
||||
namespace {
|
||||
TEST(UrlTest, assign) {
|
||||
const string src = "abc://username:password@example.com:123/path/data?key=value&key2=value2#fragid1";
|
||||
Url url;
|
||||
url.setScheme("abc");
|
||||
url.setUserName("username");
|
||||
url.setPassword("password");
|
||||
url.setHost("example.com");
|
||||
url.setPath("/path/data");
|
||||
url.setPort(123);
|
||||
url.setQuery("key=value&key2=value2");
|
||||
url.setFragment("fragid1");
|
||||
EXPECT_TRUE(url.toString() == src);
|
||||
|
||||
EXPECT_TRUE(url.scheme() == "abc");
|
||||
EXPECT_TRUE(url.userName() == "username");
|
||||
EXPECT_TRUE(url.password() == "password");
|
||||
EXPECT_TRUE(url.host() == "example.com");
|
||||
EXPECT_TRUE(url.path() == "/path/data");
|
||||
EXPECT_TRUE(url.port() == 123);
|
||||
EXPECT_TRUE(url.query() == "key=value&key2=value2");
|
||||
EXPECT_TRUE(url.fragment() == "fragid1");
|
||||
|
||||
url.clear();
|
||||
EXPECT_TRUE(url.toString() == "");
|
||||
EXPECT_TRUE(url.scheme() == "");
|
||||
EXPECT_TRUE(url.userName() == "");
|
||||
EXPECT_TRUE(url.password() == "");
|
||||
EXPECT_TRUE(url.host() == "");
|
||||
EXPECT_TRUE(url.path() == "");
|
||||
EXPECT_TRUE(url.port() == -1);
|
||||
EXPECT_TRUE(url.query() == "");
|
||||
EXPECT_TRUE(url.fragment() == "");
|
||||
|
||||
url.fromString(src);
|
||||
|
||||
EXPECT_TRUE(url.scheme() == "abc");
|
||||
EXPECT_TRUE(url.userName() == "username");
|
||||
EXPECT_TRUE(url.password() == "password");
|
||||
EXPECT_TRUE(url.host() == "example.com");
|
||||
EXPECT_TRUE(url.path() == "/path/data");
|
||||
EXPECT_TRUE(url.port() == 123);
|
||||
EXPECT_TRUE(url.query() == "key=value&key2=value2");
|
||||
EXPECT_TRUE(url.fragment() == "fragid1");
|
||||
|
||||
Url newurl = url;
|
||||
EXPECT_TRUE(newurl.scheme() == "abc");
|
||||
EXPECT_TRUE(newurl.userName() == "username");
|
||||
EXPECT_TRUE(newurl.password() == "password");
|
||||
EXPECT_TRUE(newurl.host() == "example.com");
|
||||
EXPECT_TRUE(newurl.path() == "/path/data");
|
||||
EXPECT_TRUE(newurl.port() == 123);
|
||||
EXPECT_TRUE(newurl.query() == "key=value&key2=value2");
|
||||
EXPECT_TRUE(newurl.fragment() == "fragid1");
|
||||
}
|
||||
|
||||
TEST(UrlTest, from_string) {
|
||||
const string src = "http://oss.example.com";
|
||||
Url url(src);
|
||||
EXPECT_TRUE(url.scheme() == "http");
|
||||
EXPECT_TRUE(url.userName() == "");
|
||||
EXPECT_TRUE(url.password() == "");
|
||||
EXPECT_TRUE(url.host() == "oss.example.com");
|
||||
EXPECT_TRUE(url.path() == "/");
|
||||
EXPECT_TRUE(url.port() == -1);
|
||||
EXPECT_TRUE(url.query() == "");
|
||||
EXPECT_TRUE(url.fragment() == "");
|
||||
}
|
||||
|
||||
TEST(UrlTest, abnormal) {
|
||||
const string src = "http://oss.example.com";
|
||||
Url url(src);
|
||||
Url newurl = url;
|
||||
newurl.setPort(12345);
|
||||
EXPECT_TRUE(url.isEmpty() == false);
|
||||
EXPECT_TRUE(url.isValid());
|
||||
EXPECT_TRUE(newurl != url);
|
||||
EXPECT_TRUE(newurl.port() == 12345);
|
||||
}
|
||||
|
||||
TEST(UrlTest, abnormal_2) {
|
||||
const string src = "";
|
||||
Url empty_url;
|
||||
empty_url.fromString(src);
|
||||
EXPECT_TRUE(empty_url.isEmpty());
|
||||
Url url(src);
|
||||
Url newurl = url;
|
||||
EXPECT_TRUE(url == newurl);
|
||||
|
||||
newurl.setPort(12345);
|
||||
|
||||
EXPECT_TRUE(url.isEmpty() == true);
|
||||
EXPECT_TRUE(url.isValid() == false);
|
||||
EXPECT_TRUE(url.authority() == "");
|
||||
EXPECT_TRUE(newurl != url);
|
||||
EXPECT_TRUE(newurl.port() == 12345);
|
||||
newurl.setAuthority("");
|
||||
EXPECT_TRUE(newurl.host() == "");
|
||||
EXPECT_TRUE(newurl.port() == -1);
|
||||
EXPECT_TRUE(newurl.userInfo() == "");
|
||||
|
||||
newurl.setScheme("");
|
||||
EXPECT_TRUE(newurl.scheme() == "");
|
||||
|
||||
newurl.setUserInfo("userinfo");
|
||||
EXPECT_TRUE(newurl.userName() == "userinfo");
|
||||
|
||||
newurl.setUserInfo("user:password");
|
||||
EXPECT_TRUE(newurl.userName() == "user");
|
||||
EXPECT_TRUE(newurl.password() == "password");
|
||||
}
|
||||
}
|
||||
30
test/core/utils.h
Normal file
30
test/core/utils.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
class utUtils {
|
||||
public:
|
||||
void get_dir_exec(char* dir, char* exec) {
|
||||
char* filename = nullptr;
|
||||
if (readlink("/proc/self/exe", dir, 1024) < 0) {
|
||||
dir[0] = '\0';
|
||||
return;
|
||||
}
|
||||
filename = strrchr(dir, '/');
|
||||
if (filename == nullptr) {
|
||||
dir[0] = '\0';
|
||||
return;
|
||||
}
|
||||
++filename;
|
||||
if (exec) {
|
||||
sprintf(exec, "%s", filename);
|
||||
}
|
||||
|
||||
*filename = '\0';
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
63
test/core/utils_ut.cc
Normal file
63
test/core/utils_ut.cc
Normal file
@@ -0,0 +1,63 @@
|
||||
#include "gtest/gtest.h"
|
||||
#include "../../core/src/Utils.h"
|
||||
|
||||
|
||||
using namespace std;
|
||||
using namespace AlibabaCloud;
|
||||
|
||||
namespace {
|
||||
TEST(UtilsTest, ComputeContentMD5) {
|
||||
const std::string src = "abc://username:password@example.com:123/path/data?key=value&key2=value2#fragid1";
|
||||
const std::string md5 = ComputeContentMD5(src.c_str(), src.size());
|
||||
EXPECT_TRUE(md5 == "WL7+fwrxHSlBTsfU9WCSbA==");
|
||||
}
|
||||
|
||||
TEST(UtilsTest, GenerateUuid) {
|
||||
const std::string uuid1 = GenerateUuid();
|
||||
const std::string uuid2 = GenerateUuid();
|
||||
EXPECT_TRUE(uuid1 != uuid2);
|
||||
}
|
||||
|
||||
TEST(UtilsTest, HttpMethodToString){
|
||||
std::string method = HttpMethodToString(HttpRequest::Method::Head);
|
||||
EXPECT_TRUE(method == "HEAD");
|
||||
method = HttpMethodToString(HttpRequest::Method::Post);
|
||||
EXPECT_TRUE(method == "POST");
|
||||
method = HttpMethodToString(HttpRequest::Method::Put);
|
||||
EXPECT_TRUE(method == "PUT");
|
||||
method = HttpMethodToString(HttpRequest::Method::Delete);
|
||||
EXPECT_TRUE(method == "DELETE");
|
||||
method = HttpMethodToString(HttpRequest::Method::Connect);
|
||||
EXPECT_TRUE(method == "CONNECT");
|
||||
method = HttpMethodToString(HttpRequest::Method::Options);
|
||||
EXPECT_TRUE(method == "OPTIONS");
|
||||
method = HttpMethodToString(HttpRequest::Method::Patch);
|
||||
EXPECT_TRUE(method == "PATCH");
|
||||
method = HttpMethodToString(HttpRequest::Method::Trace);
|
||||
EXPECT_TRUE(method == "TRACE");
|
||||
method = HttpMethodToString(HttpRequest::Method::Get);
|
||||
EXPECT_TRUE(method == "GET");
|
||||
}
|
||||
|
||||
TEST(UtilsTest, StringReplace) {
|
||||
std::string src = "abc://username:password@example.com:123/path/data?key=value&key2=value2#fragid1";
|
||||
StringReplace(src, "abc", "http");
|
||||
EXPECT_TRUE(src == "http://username:password@example.com:123/path/data?key=value&key2=value2#fragid1");
|
||||
StringReplace(src, "value", "VALUE");
|
||||
EXPECT_TRUE(src == "http://username:password@example.com:123/path/data?key=VALUE&key2=VALUE2#fragid1");
|
||||
}
|
||||
|
||||
TEST(UtilsTest, Encode) {
|
||||
const std::string url = "http://username:password@example.com:123/path/data?key=value&key2=value2#fragid1";
|
||||
const std::string encoded = "http%3A%2F%2Fusername%3Apassword%40example.com%3A123%2Fpath%2Fdata%3Fkey%3Dvalue%26key2%3Dvalue2%23fragid1";
|
||||
const std::string enc = UrlEncode(url);
|
||||
EXPECT_TRUE(enc == encoded);
|
||||
}
|
||||
|
||||
TEST(UtilsTest, Decode) {
|
||||
const std::string url = "http://username:password@example.com:123/path/data?key=value&key2=value2#fragid1";
|
||||
const std::string encoded = "http%3A%2F%2Fusername%3Apassword%40example.com%3A123%2Fpath%2Fdata%3Fkey%3Dvalue%26key2%3Dvalue2%23fragid1";
|
||||
const std::string decoded = UrlDecode(encoded);
|
||||
EXPECT_TRUE(decoded == url);
|
||||
}
|
||||
}
|
||||
21
test/httpserver/CMakeLists.txt
Normal file
21
test/httpserver/CMakeLists.txt
Normal file
@@ -0,0 +1,21 @@
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
|
||||
add_executable(httpserver_for_ut
|
||||
HTTPServer.cpp
|
||||
ServerThread.cpp
|
||||
main.cpp
|
||||
)
|
||||
|
||||
# httpserver_for_ut use pthread
|
||||
find_package(Threads)
|
||||
target_link_libraries(httpserver_for_ut ${CMAKE_THREAD_LIBS_INIT})
|
||||
|
||||
# copy httpserver_for_ut to the same directory as the core_ut binary
|
||||
set_target_properties(httpserver_for_ut
|
||||
PROPERTIES
|
||||
OUTPUT_NAME httpserver_for_ut
|
||||
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
|
||||
|
||||
# httpserver_for_ut echo this message to client
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/index.html ${CMAKE_BINARY_DIR}/bin/index.html COPYONLY)
|
||||
118
test/httpserver/HTTPServer.cpp
Normal file
118
test/httpserver/HTTPServer.cpp
Normal file
@@ -0,0 +1,118 @@
|
||||
#include "HTTPServer.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
// the terminator logic, run in a separate thread
|
||||
|
||||
void *tfunc(void* obj) {
|
||||
((HTTPServer*) obj)->RunTerminator();
|
||||
}
|
||||
|
||||
void* sfunc(void* obj) {
|
||||
((HTTPServer*) obj)->RunServer();
|
||||
}
|
||||
|
||||
void error(string msg) {
|
||||
cerr << msg << endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void msg(string msg) {
|
||||
cout << msg << endl;
|
||||
}
|
||||
|
||||
HTTPServer::HTTPServer(int port) {
|
||||
this->portno = port;
|
||||
}
|
||||
|
||||
HTTPServer::~HTTPServer() {
|
||||
}
|
||||
|
||||
void HTTPServer::StartServer() {
|
||||
// socket(int domain, int type, int protocol)
|
||||
sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (sockfd < 0)
|
||||
error("Opening socket");
|
||||
|
||||
// clear the struct's memory
|
||||
bzero((char *) &serv_addr, sizeof (serv_addr));
|
||||
|
||||
// setup the host_addr structure
|
||||
serv_addr.sin_family = AF_INET;
|
||||
|
||||
// automatically be filled with current host's IP address which is localhost
|
||||
serv_addr.sin_addr.s_addr = INADDR_ANY;
|
||||
|
||||
// convert short to network port order
|
||||
serv_addr.sin_port = htons(portno);
|
||||
|
||||
// to avoid waiting for limbo connection when debugging
|
||||
int en = 1;
|
||||
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &en, sizeof (int));
|
||||
|
||||
// bind(int fd, struct sockaddr *local_addr, socklen_t addr_length)
|
||||
// This bind() call will bind the socket to the current IP address on our port
|
||||
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof (serv_addr)) < 0)
|
||||
error("On binding");
|
||||
// This listen() function will start filling the backlog queue with clients
|
||||
// The maximum size for the backlog queue to 1
|
||||
listen(sockfd, 1);
|
||||
|
||||
clilen = sizeof (cli_addr);
|
||||
|
||||
// create the server thread
|
||||
pthread_create(&server, NULL, sfunc, this);
|
||||
}
|
||||
|
||||
void HTTPServer::StartTerminator() {
|
||||
// create the terminator thread
|
||||
pthread_create(&terminator, NULL, tfunc, this);
|
||||
}
|
||||
|
||||
void HTTPServer::RunServer() {
|
||||
msg("Server is online!");
|
||||
while (true) {
|
||||
// The accept() function blocks untill the backlog has elements
|
||||
// It then stores the info of the client socket in newsockfd
|
||||
int csockn = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
|
||||
if (csockn < 0)
|
||||
msg("Failed on accept.");
|
||||
|
||||
printf("Incoming connection from %s port %ho\n",
|
||||
inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port));
|
||||
ServerThread* clt = new ServerThread(csockn);
|
||||
clt->Serve();
|
||||
aclients.push_front(clt);
|
||||
}
|
||||
}
|
||||
|
||||
void HTTPServer::RunTerminator() {
|
||||
while (true) {
|
||||
sleep(0.01);
|
||||
time_t now = time(NULL);
|
||||
int nc = aclients.size();
|
||||
int ttl = 1 / (double) (nc > 0 ? nc : 1); //in seconds
|
||||
for (list<ServerThread*>::iterator list_iter = aclients.begin(); list_iter != aclients.end();) {
|
||||
ServerThread* st = *list_iter;
|
||||
int runningtime = difftime(now, st->GetStartTime());
|
||||
if (st->IsMarked() || (runningtime >= ttl && st->Terminate(false))) {
|
||||
if (st->IsMarked())
|
||||
cout << "Client on socket " << st->GetSocket() << " self terminated" << endl;
|
||||
else
|
||||
cout << "Terminated client on socket " << st->GetSocket() << endl;
|
||||
delete st;
|
||||
list_iter = aclients.erase(list_iter);
|
||||
} else {
|
||||
list_iter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HTTPServer::Stop() {
|
||||
close(sockfd);
|
||||
if (server)
|
||||
pthread_cancel(server);
|
||||
if (terminator)
|
||||
pthread_cancel(terminator);
|
||||
}
|
||||
52
test/httpserver/HTTPServer.h
Normal file
52
test/httpserver/HTTPServer.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
/*
|
||||
* File: HTTPServer.h
|
||||
* Author: root
|
||||
*
|
||||
* Created on November 5, 2016, 5:46 PM
|
||||
*/
|
||||
|
||||
#ifndef HTTPSERVER_H
|
||||
#define HTTPSERVER_H
|
||||
#include <list>
|
||||
#include "ServerThread.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
class HTTPServer {
|
||||
public:
|
||||
HTTPServer(int port);
|
||||
HTTPServer(const HTTPServer& orig);
|
||||
virtual ~HTTPServer();
|
||||
void RunServer();
|
||||
void RunTerminator();
|
||||
void StartServer();
|
||||
void StartTerminator();
|
||||
void Stop();
|
||||
private:
|
||||
pthread_t server, terminator;
|
||||
// a list of active clients
|
||||
list<ServerThread*> aclients;
|
||||
// socket fields
|
||||
int sockfd, portno;
|
||||
sockaddr_in serv_addr, cli_addr;
|
||||
socklen_t clilen;
|
||||
};
|
||||
|
||||
#endif /* HTTPSERVER_H */
|
||||
|
||||
163
test/httpserver/ServerThread.cpp
Normal file
163
test/httpserver/ServerThread.cpp
Normal file
@@ -0,0 +1,163 @@
|
||||
#include "ServerThread.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
// entry point for all threads
|
||||
char echo_buffer[100 *1024];
|
||||
|
||||
void getExecDir(char*dir) {
|
||||
char* filename = nullptr;
|
||||
if (readlink("/proc/self/exe", dir, 1024) < 0) {
|
||||
dir[0] = '\0';
|
||||
return;
|
||||
}
|
||||
|
||||
filename = strrchr(dir, '/');
|
||||
if (filename == nullptr) {
|
||||
dir[0] = '\0';
|
||||
return;
|
||||
}
|
||||
++filename;
|
||||
*filename = '\0';
|
||||
sprintf(dir + strlen(dir), "%s", "index.html");
|
||||
return;
|
||||
}
|
||||
|
||||
void* run(void* obj) {
|
||||
((ServerThread*) obj)->Run();
|
||||
// when Run() finishes, mark for termination
|
||||
((ServerThread*) obj)->MarkFT();
|
||||
}
|
||||
|
||||
bool getExt(const char* path, char* ext) {
|
||||
int l = strlen(path), i = l;
|
||||
while (i > 0 && path[--i] != '.' && path[i] != '/');
|
||||
if (i == 0 || path[i] == '/') return false;
|
||||
for (int j = 0; i < l; ext[j++] = path[++i]);
|
||||
return true;
|
||||
}
|
||||
|
||||
int getHeader(char *header, const char *buffer, int rd) {
|
||||
int hl = 0;
|
||||
int i = 0;
|
||||
for (; hl < rd && strcmp(term, buffer + hl); hl++) {
|
||||
for (i = 0; i < 4; i++)
|
||||
if (term[i] != buffer[hl + i]) break;
|
||||
if (i == 4) break;
|
||||
header[hl] = buffer[hl];
|
||||
}
|
||||
header[hl] = '\0';
|
||||
return hl;
|
||||
}
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
ServerThread::ServerThread(int socket) {
|
||||
this->socket = socket;
|
||||
marked = serving = false;
|
||||
}
|
||||
|
||||
ServerThread::~ServerThread() {
|
||||
}
|
||||
// start serving in a separate thread
|
||||
|
||||
void ServerThread::Serve() {
|
||||
pthread_create(&tid, NULL, run, this);
|
||||
start = time(NULL);
|
||||
}
|
||||
// terminate the thread and close the socket
|
||||
|
||||
bool ServerThread::Terminate(bool force) {
|
||||
if (serving&&!force)return false;
|
||||
pthread_cancel(tid);
|
||||
close(socket);
|
||||
return true;
|
||||
}
|
||||
// run in current thread
|
||||
|
||||
void ServerThread::Run() {
|
||||
int rd, hl;
|
||||
while (1) {
|
||||
serving = false;
|
||||
rd = read(socket, buffer, BUFFERLENGTH - 1);
|
||||
if (rd <= 0) {
|
||||
// client disconnected mysteriously
|
||||
Terminate(true);
|
||||
break; // precautionary
|
||||
}
|
||||
// parse the header
|
||||
serving = true;
|
||||
char method[8], path[261], version[8], ext[5];
|
||||
strcpy(path, WORKDIR);
|
||||
// getExecDir(path);
|
||||
hl = getHeader(header, buffer, rd);
|
||||
sscanf(header, "%s %s %s", method, path + WDLEN, version);
|
||||
// handle default file name
|
||||
// if (!getExt(path, ext))strcat(path, "/index.html");
|
||||
getExecDir(path);
|
||||
|
||||
// handle the request
|
||||
if (!strcmp("GET", method) || !strcmp("PUT", method)) {
|
||||
|
||||
if (strlen(echo_buffer) > 0) {
|
||||
int size = strlen(echo_buffer);
|
||||
sprintf(buffer, "%s%d\r\n\r\n", "HTTP/1.1 200 OK\r\nContent-Length: ", size);
|
||||
send(socket, buffer, strlen(buffer), 0);
|
||||
send(socket, echo_buffer, size, 0);
|
||||
} else {
|
||||
// try to open the requested file
|
||||
FILE * file = fopen(path, "r");
|
||||
if (file) {
|
||||
fseek(file, 0, SEEK_END);
|
||||
int size = ftell(file);
|
||||
fseek(file, 0, 0);
|
||||
// send 200
|
||||
sprintf(buffer, "%s%d\r\n\r\n", "HTTP/1.1 200 OK\r\nContent-Length: ", size);
|
||||
send(socket, buffer, strlen(buffer), 0);
|
||||
cout << "200 " << path << endl;
|
||||
do {
|
||||
rd = fread(buffer, sizeof (char), BUFFERLENGTH, file);
|
||||
send(socket, buffer, rd, 0);
|
||||
} while (rd > 0);
|
||||
fclose(file);
|
||||
} else {
|
||||
// send 404
|
||||
sprintf(buffer, "%s\r\n\r\n", "HTTP/1.1 404 Not Found");
|
||||
send(socket, buffer, strlen(buffer), 0);
|
||||
cout << "404 " << path << endl;
|
||||
}
|
||||
}
|
||||
serving = false;
|
||||
Terminate(true);
|
||||
} else if (!strcmp("POST", method)) {
|
||||
if (fopen(path, "r") > 0) {
|
||||
sprintf(buffer, "%s\r\n\r\n", "HTTP/1.1 403 Forbidden");
|
||||
send(socket, buffer, strlen(buffer), 0);
|
||||
cout << "402 " << path << endl;
|
||||
continue;
|
||||
}
|
||||
FILE *file = fopen(path, "w+");
|
||||
if (file) {
|
||||
// send 200
|
||||
sprintf(buffer, "%s\r\n\r\n", "HTTP/1.1 200 OK");
|
||||
send(socket, buffer, strlen(buffer), 0);
|
||||
cout << "200 " << path << endl;
|
||||
// if client sent data after the header
|
||||
if (rd - hl > 4)
|
||||
fwrite(buffer + hl + 4, sizeof (char), rd - hl - 4, file);
|
||||
rd = read(socket, buffer, BUFFERLENGTH - 1);
|
||||
while (rd > 0) {
|
||||
fwrite(buffer, sizeof (char), rd, file);
|
||||
rd = read(socket, buffer, BUFFERLENGTH - 1);
|
||||
// TODO: implement blocks or read content length
|
||||
if (rd < BUFFERLENGTH - 1 || !strcmp(buffer - 4, term))
|
||||
break;
|
||||
}
|
||||
fclose(file);
|
||||
} else {
|
||||
sprintf(buffer, "%s\r\n\r\n", "HTTP/1.1 500 Internal Server Error");
|
||||
send(socket, buffer, strlen(buffer), 0);
|
||||
cout << "500 " << path << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
55
test/httpserver/ServerThread.h
Normal file
55
test/httpserver/ServerThread.h
Normal file
@@ -0,0 +1,55 @@
|
||||
#ifndef SERVERTHREAD_H
|
||||
#define SERVERTHREAD_H
|
||||
|
||||
#include <ctime>
|
||||
#include <pthread.h>
|
||||
#include <iostream>
|
||||
#include <ctime>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/socket.h>
|
||||
#include <string.h>
|
||||
|
||||
#define BUFFERLENGTH 8192
|
||||
#define WORKDIR "/tmp"
|
||||
#define WDLEN 11
|
||||
#define term "\r\n\r\n"
|
||||
|
||||
class ServerThread {
|
||||
private:
|
||||
int socket;
|
||||
pthread_t tid;
|
||||
std::time_t start;
|
||||
char buffer[BUFFERLENGTH];
|
||||
char header[BUFFERLENGTH];
|
||||
bool marked;
|
||||
bool serving;
|
||||
public:
|
||||
ServerThread(int socket);
|
||||
virtual ~ServerThread();
|
||||
void Serve();
|
||||
void Run();
|
||||
bool Terminate(bool force);
|
||||
|
||||
int GetSocket() {
|
||||
return this->socket;
|
||||
}
|
||||
|
||||
time_t GetStartTime() {
|
||||
return this->start;
|
||||
}
|
||||
|
||||
pthread_t GetThreadID() {
|
||||
return this->tid;
|
||||
}
|
||||
|
||||
void MarkFT() {
|
||||
marked = true;
|
||||
}
|
||||
|
||||
bool IsMarked() {
|
||||
return marked;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // SERVERTHREAD_H
|
||||
1
test/httpserver/index.html
Normal file
1
test/httpserver/index.html
Normal file
@@ -0,0 +1 @@
|
||||
{"Endpoints":{"Endpoint":[{"Protocols":{"Protocols":["HTTP","HTTPS"]},"Type":"openAPI","Namespace":"26842","Id":"cn-hangzhou","SerivceCode":"ecs","Endpoint":"ecs-cn-hangzhou.aliyuncs.com"}]},"RequestId":"9AF4C364-08A0-4C00-A002-9E4DF57E3389","Success":true}
|
||||
67
test/httpserver/main.cpp
Normal file
67
test/httpserver/main.cpp
Normal file
@@ -0,0 +1,67 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <iostream>
|
||||
#include "ServerThread.h"
|
||||
#include "HTTPServer.h"
|
||||
#include <pthread.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
extern char echo_buffer[100 *1024];
|
||||
|
||||
// command symbol table
|
||||
|
||||
enum _cmd {
|
||||
cunknown,
|
||||
cexit
|
||||
};
|
||||
|
||||
_cmd str2cmd(string cmdstr) {
|
||||
if (cmdstr == "x" || cmdstr == "exit" || cmdstr == "quit")
|
||||
return cexit;
|
||||
return cunknown;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
string cmd;
|
||||
bool running = true;
|
||||
int portno = 8021;
|
||||
// the first argument is always the work directory.
|
||||
if (argc == 2) {
|
||||
// get port number from arguments
|
||||
portno = atoi(argv[1]);
|
||||
echo_buffer[0] = '\0';
|
||||
}
|
||||
if (argc >= 3) {
|
||||
// get port number from arguments
|
||||
portno = atoi(argv[1]);
|
||||
snprintf(echo_buffer, sizeof(echo_buffer), "%s", argv[2]);
|
||||
}
|
||||
|
||||
|
||||
HTTPServer* server = new HTTPServer(portno);
|
||||
server->StartServer();
|
||||
// without the terminator, only the client can close the connection
|
||||
server->StartTerminator();
|
||||
while (running) {
|
||||
cin >> cmd;
|
||||
if (cmd != "")
|
||||
switch (str2cmd(cmd)) {
|
||||
case cexit:
|
||||
running = false;
|
||||
break;
|
||||
default:
|
||||
cout << "Unrecognized command." << endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
server->Stop();
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user