Browse Source

add basic function test

update travis to run function test
zhangzifa 7 years ago
parent
commit
b429dcc915

+ 1 - 0
.gitignore

@@ -2,5 +2,6 @@ initCoverage.info
 testCoverage.info
 coverageReport/
 .vscode/
+ft_build/
 ut_build/
 sdk_build/

+ 1 - 0
.travis.yml

@@ -9,6 +9,7 @@ install:
 script:
   - ./unit_test.sh
   - ./generate_code_cov.sh
+  - ./function_test.sh
 
 after_success:
   - bash <(curl -s https://codecov.io/bash)

+ 92 - 80
CMakeLists.txt

@@ -1,80 +1,92 @@
-cmake_minimum_required(VERSION 3.1)
-
-cmake_policy(SET CMP0048 NEW)
-
-file(STRINGS "VERSION" version)
-
-project(alibabacloud-sdk VERSION ${version})
-
-message(STATUS "Project version: ${PROJECT_VERSION}")
-
-set(TARGET_OUTPUT_NAME_PREFIX "alibabacloud-sdk-" CACHE STRING "The target's output name prefix")
-option(BUILD_SHARED_LIBS  "Enable shared library" ON)
-option(BUILD_TESTS "Enable tests" ON)
-
-set(LIB_TYPE STATIC)
-if(BUILD_SHARED_LIBS)
-	set(LIB_TYPE SHARED)
-	add_definitions(-DALIBABACLOUD_SHARED)
-endif()
-
-set_property(GLOBAL
-	PROPERTY
-	USE_FOLDERS ON)
-
-set(CMAKE_CXX_STANDARD 11)
-
-include(ExternalProject)
-include(GNUInstallDirs)
-
-add_subdirectory(3rdparty)
-add_subdirectory(core)
-
-if(BUILD_TESTS)
-	enable_testing()
-	add_subdirectory(test/core)
-	add_subdirectory(test/httpserver)
-endif()
-add_subdirectory(ecs)
-add_subdirectory(slb)
-add_subdirectory(vpc)
-add_subdirectory(cdn)
-add_subdirectory(rds)
-add_subdirectory(cloudphoto)
-add_subdirectory(ess)
-add_subdirectory(tesladam)
-add_subdirectory(cms)
-add_subdirectory(afs)
-add_subdirectory(aegis)
-add_subdirectory(ehpc)
-add_subdirectory(cs)
-add_subdirectory(ccc)
-add_subdirectory(teslamaxcompute)
-add_subdirectory(push)
-add_subdirectory(csb)
-add_subdirectory(domain)
-add_subdirectory(green)
-add_subdirectory(hsm)
-add_subdirectory(dcdn)
-add_subdirectory(pvtz)
-add_subdirectory(cloudauth)
-add_subdirectory(dyvmsapi)
-add_subdirectory(drds)
-add_subdirectory(jarvis)
-add_subdirectory(scdn)
-add_subdirectory(live)
-add_subdirectory(rtc)
-add_subdirectory(chatbot)
-add_subdirectory(teslastream)
-add_subdirectory(mopen)
-add_subdirectory(mts)
-add_subdirectory(iot)
-add_subdirectory(linkface)
-add_subdirectory(ots)
-add_subdirectory(smartag)
-add_subdirectory(vod)
-add_subdirectory(ccs)
-add_subdirectory(saf)
-add_subdirectory(arms)
-add_subdirectory(lubancloud)
-add_subdirectory(alimt)
+cmake_minimum_required(VERSION 3.1)
+
+cmake_policy(SET CMP0048 NEW)
+
+file(STRINGS "VERSION" version)
+
+project(alibabacloud-sdk VERSION ${version})
+
+message(STATUS "Project version: ${PROJECT_VERSION}")
+
+set(TARGET_OUTPUT_NAME_PREFIX "alibabacloud-sdk-" CACHE STRING "The target's output name prefix")
+option(BUILD_SHARED_LIBS  "Enable shared library" ON)
+option(BUILD_UNIT_TESTS "Enable unit tests" OFF)
+option(BUILD_FUNCTION_TESTS "Enable function test" OFF)
+
+set(LIB_TYPE STATIC)
+if(BUILD_SHARED_LIBS)
+	set(LIB_TYPE SHARED)
+	add_definitions(-DALIBABACLOUD_SHARED)
+endif()
+
+set_property(GLOBAL
+	PROPERTY
+	USE_FOLDERS ON)
+
+set(CMAKE_CXX_STANDARD 11)
+
+include(ExternalProject)
+include(GNUInstallDirs)
+
+add_subdirectory(3rdparty)
+add_subdirectory(core)
+
+if(BUILD_UNIT_TESTS)
+	enable_testing()
+	add_subdirectory(test/core)
+	add_subdirectory(test/httpserver)
+endif()
+
+if(BUILD_FUNCTION_TESTS)
+	enable_testing()
+	add_subdirectory(test/function_test/cdn)
+  add_subdirectory(test/function_test/core)
+  add_subdirectory(test/function_test/ecs)
+  add_subdirectory(test/function_test/rds)
+  add_subdirectory(test/function_test/slb)
+  add_subdirectory(test/function_test/vpc)
+endif()
+
+add_subdirectory(ecs)
+add_subdirectory(slb)
+add_subdirectory(vpc)
+add_subdirectory(cdn)
+add_subdirectory(rds)
+add_subdirectory(cloudphoto)
+add_subdirectory(ess)
+add_subdirectory(tesladam)
+add_subdirectory(cms)
+add_subdirectory(afs)
+add_subdirectory(aegis)
+add_subdirectory(ehpc)
+add_subdirectory(cs)
+add_subdirectory(ccc)
+add_subdirectory(teslamaxcompute)
+add_subdirectory(push)
+add_subdirectory(csb)
+add_subdirectory(domain)
+add_subdirectory(green)
+add_subdirectory(hsm)
+add_subdirectory(dcdn)
+add_subdirectory(pvtz)
+add_subdirectory(cloudauth)
+add_subdirectory(dyvmsapi)
+add_subdirectory(drds)
+add_subdirectory(jarvis)
+add_subdirectory(scdn)
+add_subdirectory(live)
+add_subdirectory(rtc)
+add_subdirectory(chatbot)
+add_subdirectory(teslastream)
+add_subdirectory(mopen)
+add_subdirectory(mts)
+add_subdirectory(iot)
+add_subdirectory(linkface)
+add_subdirectory(ots)
+add_subdirectory(smartag)
+add_subdirectory(vod)
+add_subdirectory(ccs)
+add_subdirectory(saf)
+add_subdirectory(arms)
+add_subdirectory(lubancloud)
+add_subdirectory(alimt)

+ 15 - 0
function_test.sh

@@ -0,0 +1,15 @@
+#!/bin/bash
+
+cd `dirname $0`
+echo '-------build function test----------'
+
+FT_BUILD_DIR=ft_build
+rm -rf $FT_BUILD_DIR
+mkdir $FT_BUILD_DIR
+cd $FT_BUILD_DIR
+cmake -DBUILD_FUNCTION_TESTS=ON -DBUILD_UNIT_TESTS=OFF ..
+make cdn core ecs rds slb vpc cdn_ft core_ft ecs_ft rds_ft slb_ft vpc_ft
+
+echo '------- run function test -----------'
+
+ctest --verbose

+ 25 - 0
test/function_test/cdn/CMakeLists.txt

@@ -0,0 +1,25 @@
+cmake_minimum_required(VERSION 3.0)
+project(demo)
+set(CMAKE_CXX_STANDARD 11)
+if(CMAKE_HOST_WIN32)
+    include_directories("C:\\Program Files (x86)\\alibabacloud-sdk\\include")
+    link_directories("C:\\Program Files (x86)\\alibabacloud-sdk\\lib")
+endif()
+
+# note ft_build is the dir you build sdk
+
+include_directories("../../../core/include/")
+include_directories("../../../cdn/include/")
+link_directories(${CMAKE_SOURCE_DIR}/ft_build/lib)
+
+add_executable(cdn_ft cdn_describeCdnService_ft.cc)
+target_link_libraries(cdn_ft alibabacloud-sdk-core alibabacloud-sdk-cdn)
+
+target_link_libraries(cdn_ft core gtest gmock_main)
+
+set_target_properties(cdn_ft
+  PROPERTIES
+  OUTPUT_NAME ${TARGET_OUTPUT_NAME_PREFIX}cdn_ft
+  RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
+
+add_test(NAME cdn_ft COMMAND cdn_ft)

+ 31 - 0
test/function_test/cdn/cdn_describeCdnService_ft.cc

@@ -0,0 +1,31 @@
+#include <iostream>
+#include "../utils.h"
+#include "gtest/gtest.h"
+#include "alibabacloud/core/AlibabaCloud.h"
+#include "alibabacloud/cdn/CdnClient.h"
+
+using namespace std;
+using namespace AlibabaCloud;
+using namespace AlibabaCloud::Cdn;
+
+namespace {
+  TEST(cdn, describeCdnService) {
+    utUtils utils;
+    string key = utils.get_env("ENV_AccessKeyId");
+    string secret = utils.get_env("ENV_AccessKeySecret");
+    string uid = utils.get_env("ENV_TEST_UID");
+    InitializeSdk();
+    ClientConfiguration configuration("cn-hangzhou");
+    CdnClient client(key, secret, configuration);
+    Model::DescribeCdnServiceRequest request;
+    auto outcome = client.describeCdnService(request);
+    EXPECT_TRUE(outcome.isSuccess());
+    EXPECT_TRUE(outcome.error().errorCode().empty());
+    EXPECT_TRUE(outcome.result().getChangingChargeType() == "PayByTraffic");
+    EXPECT_TRUE(outcome.result().getInternetChargeType() == "PayByTraffic");
+    EXPECT_TRUE(outcome.result().getInstanceId() == uid);
+    EXPECT_TRUE(outcome.result().getOpeningTime() == "2019-01-02T09:16:34Z");
+    EXPECT_TRUE(outcome.result().getChangingAffectTime() == "2019-01-02T09:16:33Z");
+    ShutdownSdk();
+  }
+}

+ 49 - 0
test/function_test/core/CMakeLists.txt

@@ -0,0 +1,49 @@
+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/")
+link_directories(${CMAKE_SOURCE_DIR}/ft_build/lib)
+
+add_executable(core_ft
+   locationclient_ft.cc
+  )
+
+set_target_properties(core_ft
+  PROPERTIES
+  OUTPUT_NAME ${TARGET_OUTPUT_NAME_PREFIX}core_ft
+  RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
+
+target_link_libraries(core_ft core gtest gmock_main)
+add_test(NAME core_ft COMMAND core_ft)

+ 17 - 0
test/function_test/core/DownloadProject.CMakeLists.cmake.in

@@ -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 - 0
test/function_test/core/DownloadProject.cmake

@@ -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()

+ 202 - 0
test/function_test/core/locationclient_ft.cc

@@ -0,0 +1,202 @@
+#include <iostream>
+#include <stdio.h>
+#include "../utils.h"
+#include "gtest/gtest.h"
+#include "alibabacloud/core/AlibabaCloud.h"
+#include "alibabacloud/core/SimpleCredentialsProvider.h"
+#include "alibabacloud/core/location/LocationClient.h"
+
+using namespace std;
+using namespace AlibabaCloud;
+using namespace AlibabaCloud::Location;
+
+namespace {
+  utUtils utils;
+
+  const string key = utils.get_env("ENV_AccessKeyId");
+  const string secret = utils.get_env("ENV_AccessKeySecret");
+
+  TEST(LocationClient, basic) {
+    ClientConfiguration configuration("cn-hangzhou");
+    Model::DescribeEndpointsRequest req;
+    req.setId("cn-hangzhou");
+    req.setServiceCode("ecs");
+    req.setType("openAPI");
+
+    LocationClient client(key, secret, configuration);
+
+    LocationClient::DescribeEndpointsOutcome out = client.describeEndpoints(req);
+    EXPECT_TRUE(out.error().errorCode() == "");
+    EXPECT_TRUE(out.result().endpoints().size() == 1);
+    Model::DescribeEndpointsResult::Endpoint ep = out.result().endpoints()[0];
+
+    EXPECT_TRUE(ep.endpoint == "ecs-cn-hangzhou.aliyuncs.com");
+    EXPECT_TRUE(ep.id == "cn-hangzhou");
+    EXPECT_TRUE(ep.namespace_ == "26842" || ep.namespace_.empty());
+    EXPECT_TRUE(ep.type == "openAPI");
+    EXPECT_TRUE(ep.protocols.size() == 2);
+    std::vector<std::string>::iterator it;
+    std::vector<std::string> protocols = ep.protocols;
+
+    it = std::find(protocols.begin(), protocols.end(), string("HTTP"));
+    EXPECT_TRUE(it != protocols.end());
+
+    it = std::find(protocols.begin(), protocols.end(), string("HTTPS"));
+    EXPECT_TRUE(it != protocols.end());
+
+    EXPECT_TRUE(out.result().success());
+    const string req_id = "205302F3-6E1A-4D6F-82C5-2F165FB94038";
+    EXPECT_TRUE(out.result().requestId().length() == req_id.length());
+  }
+
+  TEST(LocationClient, credentials) {
+    Credentials credentials(key, secret);
+    ClientConfiguration configuration("cn-hangzhou");
+
+    Model::DescribeEndpointsRequest req;
+    req.setId("cn-hangzhou");
+    req.setServiceCode("ecs");
+    req.setType("openAPI");
+
+    LocationClient client(credentials, configuration);
+
+    LocationClient::DescribeEndpointsOutcome out = client.describeEndpoints(req);
+    EXPECT_TRUE(out.error().errorCode() == "");
+    EXPECT_TRUE(out.result().endpoints().size() == 1);
+    Model::DescribeEndpointsResult::Endpoint ep = out.result().endpoints()[0];
+
+    EXPECT_TRUE(ep.endpoint == "ecs-cn-hangzhou.aliyuncs.com");
+    EXPECT_TRUE(ep.id == "cn-hangzhou");
+    EXPECT_TRUE(ep.namespace_ == "26842" || ep.namespace_.empty());
+    EXPECT_TRUE(ep.type == "openAPI");
+    EXPECT_TRUE(ep.protocols.size() == 2);
+    std::vector<std::string>::iterator it;
+    std::vector<std::string> protocols = ep.protocols;
+
+    it = std::find(protocols.begin(), protocols.end(), string("HTTP"));
+    EXPECT_TRUE(it != protocols.end());
+
+    it = std::find(protocols.begin(), protocols.end(), string("HTTPS"));
+    EXPECT_TRUE(it != protocols.end());
+
+    EXPECT_TRUE(out.result().success());
+    const string req_id = "205302F3-6E1A-4D6F-82C5-2F165FB94038";
+    EXPECT_TRUE(out.result().requestId().length() == req_id.length());
+  }
+
+  TEST(LocationClient, credentials_another) {
+    Credentials credentials(key, secret);
+    ClientConfiguration configuration("cn-hangzhou");
+
+    Model::DescribeEndpointsRequest req;
+    req.setId("cn-hangzhou");
+    req.setServiceCode("ecs");
+    req.setType("openAPI");
+
+    LocationClient client(std::make_shared<SimpleCredentialsProvider>(credentials), configuration);
+
+    LocationClient::DescribeEndpointsOutcome out = client.describeEndpoints(req);
+    EXPECT_TRUE(out.error().errorCode() == "");
+    EXPECT_TRUE(out.result().endpoints().size() == 1);
+    Model::DescribeEndpointsResult::Endpoint ep = out.result().endpoints()[0];
+    EXPECT_TRUE(ep.endpoint == "ecs-cn-hangzhou.aliyuncs.com");
+    EXPECT_TRUE(ep.id == "cn-hangzhou");
+    EXPECT_TRUE(ep.namespace_ == "26842" || ep.namespace_.empty());
+    EXPECT_TRUE(ep.type == "openAPI");
+    EXPECT_TRUE(ep.protocols.size() == 2);
+    std::vector<std::string>::iterator it;
+    std::vector<std::string> protocols = ep.protocols;
+
+    it = std::find(protocols.begin(), protocols.end(), string("HTTP"));
+    EXPECT_TRUE(it != protocols.end());
+
+    it = std::find(protocols.begin(), protocols.end(), string("HTTPS"));
+    EXPECT_TRUE(it != protocols.end());
+
+    EXPECT_TRUE(out.result().success());
+    const string req_id = "205302F3-6E1A-4D6F-82C5-2F165FB94038";
+    EXPECT_TRUE(out.result().requestId().length() == req_id.length());
+  }
+
+
+  TEST(LocationClient, callable) {
+    InitializeSdk();
+    ClientConfiguration configuration("cn-hangzhou");
+    Model::DescribeEndpointsRequest req;
+    req.setId("cn-hangzhou");
+    req.setServiceCode("ecs");
+    req.setType("openAPI");
+
+    LocationClient client(key, secret, configuration);
+    LocationClient::DescribeEndpointsOutcomeCallable cb = client.describeEndpointsCallable(req);
+    LocationClient::DescribeEndpointsOutcome out = cb.get();
+
+    EXPECT_TRUE(out.error().errorCode() == "");
+    EXPECT_TRUE(out.result().endpoints().size() == 1);
+    Model::DescribeEndpointsResult::Endpoint ep = out.result().endpoints()[0];
+    EXPECT_TRUE(ep.endpoint == "ecs-cn-hangzhou.aliyuncs.com");
+    EXPECT_TRUE(ep.id == "cn-hangzhou");
+    EXPECT_TRUE(ep.namespace_ == "26842" || ep.namespace_.empty());
+    EXPECT_TRUE(ep.type == "openAPI");
+    EXPECT_TRUE(ep.protocols.size() == 2);
+    std::vector<std::string>::iterator it;
+    std::vector<std::string> protocols = ep.protocols;
+
+    it = std::find(protocols.begin(), protocols.end(), string("HTTP"));
+    EXPECT_TRUE(it != protocols.end());
+
+    it = std::find(protocols.begin(), protocols.end(), string("HTTPS"));
+    EXPECT_TRUE(it != protocols.end());
+
+    EXPECT_TRUE(out.result().success());
+    const string req_id = "205302F3-6E1A-4D6F-82C5-2F165FB94038";
+    EXPECT_TRUE(out.result().requestId().length() == req_id.length());
+    ShutdownSdk();
+  }
+
+  void cb(const LocationClient *client,
+          const Model::DescribeEndpointsRequest &req,
+          const LocationClient::DescribeEndpointsOutcome& out,
+          const std::shared_ptr<const AsyncCallerContext>& contex) {
+
+    EXPECT_TRUE(out.error().errorCode() == "");
+    EXPECT_TRUE(out.result().endpoints().size() == 1);
+    Model::DescribeEndpointsResult::Endpoint ep = out.result().endpoints()[0];
+    EXPECT_TRUE(ep.endpoint == "ecs-cn-hangzhou.aliyuncs.com");
+    EXPECT_TRUE(ep.id == "cn-hangzhou");
+    EXPECT_TRUE(ep.namespace_ == "26842" || ep.namespace_.empty());
+    EXPECT_TRUE(ep.type == "openAPI");
+    EXPECT_TRUE(ep.protocols.size() == 2);
+    std::vector<std::string>::iterator it;
+    std::vector<std::string> protocols = ep.protocols;
+
+    it = std::find(protocols.begin(), protocols.end(), string("HTTP"));
+    EXPECT_TRUE(it != protocols.end());
+
+    it = std::find(protocols.begin(), protocols.end(), string("HTTPS"));
+    EXPECT_TRUE(it != protocols.end());
+
+    EXPECT_TRUE(out.result().success());
+    const string req_id = "205302F3-6E1A-4D6F-82C5-2F165FB94038";
+    EXPECT_TRUE(out.result().requestId().length() == req_id.length());
+  }
+
+  TEST(LocationClient, async) {
+    InitializeSdk();
+
+    ClientConfiguration configuration("cn-hangzhou");
+    Model::DescribeEndpointsRequest req;
+    req.setId("cn-hangzhou");
+    req.setServiceCode("ecs");
+    req.setType("openAPI");
+
+    LocationClient client(key, secret, configuration);
+    LocationClient::DescribeEndpointsOutcome out;
+
+    const AsyncCallerContext context;
+
+    LocationClient::DescribeEndpointsAsyncHandler handler(cb);
+    client.describeEndpointsAsync(req, handler, std::make_shared<const AsyncCallerContext>(context));
+    ShutdownSdk();
+  }
+}

+ 26 - 0
test/function_test/ecs/CMakeLists.txt

@@ -0,0 +1,26 @@
+cmake_minimum_required(VERSION 3.0)
+project(demo)
+set(CMAKE_CXX_STANDARD 11)
+if(CMAKE_HOST_WIN32)
+    include_directories("C:\\Program Files (x86)\\alibabacloud-sdk\\include")
+    link_directories("C:\\Program Files (x86)\\alibabacloud-sdk\\lib")
+endif()
+
+# note ft_build is the dir you build sdk
+
+include_directories("../../../core/include/")
+include_directories("../../../ecs/include/")
+link_directories(${CMAKE_SOURCE_DIR}/ft_build/lib)
+
+
+add_executable(ecs_ft ecs_describeInstances_ft.cc)
+target_link_libraries(ecs_ft alibabacloud-sdk-core alibabacloud-sdk-ecs)
+
+target_link_libraries(ecs_ft core gtest gmock_main)
+
+set_target_properties(ecs_ft
+  PROPERTIES
+  OUTPUT_NAME ${TARGET_OUTPUT_NAME_PREFIX}ecs_ft
+  RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
+
+add_test(NAME ecs_ft COMMAND ecs_ft)

+ 28 - 0
test/function_test/ecs/ecs_describeInstances_ft.cc

@@ -0,0 +1,28 @@
+#include <iostream>
+#include "../utils.h"
+#include "gtest/gtest.h"
+#include "alibabacloud/core/AlibabaCloud.h"
+#include "alibabacloud/ecs/EcsClient.h"
+
+using namespace std;
+using namespace AlibabaCloud;
+using namespace AlibabaCloud::Ecs;
+
+namespace {
+  TEST(ecs, describeInstances) {
+    utUtils utils;
+    string key = utils.get_env("ENV_AccessKeyId");
+    string secret = utils.get_env("ENV_AccessKeySecret");
+
+    InitializeSdk();
+    ClientConfiguration configuration("cn-hangzhou");
+    EcsClient client(key, secret, configuration);
+    Model::DescribeInstancesRequest request;
+    request.setPageSize(10);
+    auto outcome = client.describeInstances(request);
+    EXPECT_TRUE(outcome.isSuccess());
+    EXPECT_TRUE(outcome.error().errorCode().empty());
+    EXPECT_TRUE(outcome.result().getTotalCount() == 16);
+    ShutdownSdk();
+  }
+}

+ 24 - 0
test/function_test/rds/CMakeLists.txt

@@ -0,0 +1,24 @@
+cmake_minimum_required(VERSION 3.0)
+project(demo)
+set(CMAKE_CXX_STANDARD 11)
+if(CMAKE_HOST_WIN32)
+    include_directories("C:\\Program Files (x86)\\alibabacloud-sdk\\include")
+    link_directories("C:\\Program Files (x86)\\alibabacloud-sdk\\lib")
+endif()
+
+# note ft_build is the dir you build sdk
+include_directories("../../../core/include/")
+include_directories("../../../rds/include/")
+link_directories(${CMAKE_SOURCE_DIR}/ft_build/lib)
+
+add_executable(rds_ft rds_describeDBInstances_ft.cc)
+target_link_libraries(rds_ft alibabacloud-sdk-core alibabacloud-sdk-rds)
+
+target_link_libraries(rds_ft core gtest gmock_main)
+
+set_target_properties(rds_ft
+  PROPERTIES
+  OUTPUT_NAME ${TARGET_OUTPUT_NAME_PREFIX}rds_ft
+  RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
+
+add_test(NAME rds_ft COMMAND rds_ft)

+ 27 - 0
test/function_test/rds/rds_describeDBInstances_ft.cc

@@ -0,0 +1,27 @@
+#include <iostream>
+#include "../utils.h"
+#include "gtest/gtest.h"
+#include "alibabacloud/core/AlibabaCloud.h"
+#include "alibabacloud/rds/RdsClient.h"
+
+using namespace std;
+using namespace AlibabaCloud;
+using namespace AlibabaCloud::Rds;
+
+namespace {
+  TEST(rds, describeDBInstances) {
+    utUtils utils;
+    string key = utils.get_env("ENV_AccessKeyId");
+    string secret = utils.get_env("ENV_AccessKeySecret");
+    InitializeSdk();
+    ClientConfiguration configuration("cn-hangzhou");
+    RdsClient client(key, secret, configuration);
+    Model::DescribeDBInstancesRequest request;
+    request.setPageSize(10);
+    auto outcome = client.describeDBInstances(request);
+    EXPECT_TRUE(outcome.isSuccess());
+    EXPECT_TRUE(outcome.error().errorCode().empty());
+    EXPECT_TRUE(outcome.result().getTotalRecordCount() == 0);
+    ShutdownSdk();
+  }
+}

+ 24 - 0
test/function_test/slb/CMakeLists.txt

@@ -0,0 +1,24 @@
+cmake_minimum_required(VERSION 3.0)
+project(demo)
+set(CMAKE_CXX_STANDARD 11)
+if(CMAKE_HOST_WIN32)
+    include_directories("C:\\Program Files (x86)\\alibabacloud-sdk\\include")
+    link_directories("C:\\Program Files (x86)\\alibabacloud-sdk\\lib")
+endif()
+
+# note ft_build is the dir you build sdk
+include_directories("../../../core/include/")
+include_directories("../../../slb/include/")
+link_directories(${CMAKE_SOURCE_DIR}/ft_build/lib)
+
+add_executable(slb_ft slb_describeLoadBalancers_ft.cc)
+target_link_libraries(slb_ft alibabacloud-sdk-core alibabacloud-sdk-slb)
+
+target_link_libraries(slb_ft core gtest gmock_main)
+
+set_target_properties(slb_ft
+  PROPERTIES
+  OUTPUT_NAME ${TARGET_OUTPUT_NAME_PREFIX}slb_ft
+  RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
+
+add_test(NAME slb_ft COMMAND slb_ft)

+ 27 - 0
test/function_test/slb/slb_describeLoadBalancers_ft.cc

@@ -0,0 +1,27 @@
+#include <iostream>
+#include "../utils.h"
+#include "gtest/gtest.h"
+#include "alibabacloud/core/AlibabaCloud.h"
+#include "alibabacloud/slb/SlbClient.h"
+
+using namespace std;
+using namespace AlibabaCloud;
+using namespace AlibabaCloud::Slb;
+
+namespace {
+  TEST(slb, describeLoadBalancers) {
+    utUtils utils;
+    string key = utils.get_env("ENV_AccessKeyId");
+    string secret = utils.get_env("ENV_AccessKeySecret");
+    InitializeSdk();
+    ClientConfiguration configuration("cn-hangzhou");
+    SlbClient client(key, secret, configuration);
+    Model::DescribeLoadBalancersRequest request;
+    request.setPageSize(10);
+    auto outcome = client.describeLoadBalancers(request);
+    EXPECT_TRUE(outcome.isSuccess());
+    EXPECT_TRUE(outcome.error().errorCode().empty());
+    EXPECT_TRUE(outcome.result().getTotalCount() == 0);
+    ShutdownSdk();
+  }
+}

+ 38 - 0
test/function_test/utils.h

@@ -0,0 +1,38 @@
+#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;
+  }
+
+  std::string get_env(const std::string env) {
+    char* value = getenv(env.c_str());
+    if (value == nullptr) {
+      return std::string();
+    }
+    return std::string(value);
+  }
+};
+
+
+

+ 24 - 0
test/function_test/vpc/CMakeLists.txt

@@ -0,0 +1,24 @@
+cmake_minimum_required(VERSION 3.0)
+project(demo)
+set(CMAKE_CXX_STANDARD 11)
+if(CMAKE_HOST_WIN32)
+    include_directories("C:\\Program Files (x86)\\alibabacloud-sdk\\include")
+    link_directories("C:\\Program Files (x86)\\alibabacloud-sdk\\lib")
+endif()
+
+# note ft_build is the dir you build sdk
+include_directories("../../../core/include/")
+include_directories("../../../vpc/include/")
+link_directories(${CMAKE_SOURCE_DIR}/ft_build/lib)
+
+add_executable(vpc_ft vpc_describeNatGateways_ft.cc)
+target_link_libraries(vpc_ft alibabacloud-sdk-core alibabacloud-sdk-vpc)
+
+target_link_libraries(vpc_ft core gtest gmock_main)
+
+set_target_properties(vpc_ft
+  PROPERTIES
+  OUTPUT_NAME ${TARGET_OUTPUT_NAME_PREFIX}vpc_ft
+  RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
+
+add_test(NAME vpc_ft COMMAND vpc_ft)

+ 27 - 0
test/function_test/vpc/vpc_describeNatGateways_ft.cc

@@ -0,0 +1,27 @@
+#include <iostream>
+#include "../utils.h"
+#include "gtest/gtest.h"
+#include "alibabacloud/core/AlibabaCloud.h"
+#include "alibabacloud/vpc/VpcClient.h"
+
+using namespace std;
+using namespace AlibabaCloud;
+using namespace AlibabaCloud::Vpc;
+
+namespace {
+  TEST(vpc, describeNatGateways) {
+    utUtils utils;
+    string key = utils.get_env("ENV_AccessKeyId");
+    string secret = utils.get_env("ENV_AccessKeySecret");
+    InitializeSdk();
+    ClientConfiguration configuration("cn-hangzhou");
+    VpcClient client(key, secret, configuration);
+    Model::DescribeNatGatewaysRequest request;
+    request.setPageSize(10);
+    auto outcome = client.describeNatGateways(request);
+    EXPECT_TRUE(outcome.isSuccess());
+    EXPECT_TRUE(outcome.error().errorCode().empty());
+    EXPECT_TRUE(outcome.result().getTotalCount() == 0);
+    ShutdownSdk();
+  }
+}

+ 1 - 1
unit_test.sh

@@ -7,7 +7,7 @@ UT_BUILD_DIR=ut_build
 rm -rf $UT_BUILD_DIR
 mkdir $UT_BUILD_DIR
 cd $UT_BUILD_DIR
-cmake ..
+cmake -DBUILD_FUNCTION_TESTS=OFF -DBUILD_UNIT_TESTS=ON ..
 make core_ut
 make httpserver_for_ut