Ver código fonte

timeout support when create client or make request

zhangzifa 7 anos atrás
pai
commit
619a7827de

+ 1 - 0
.gitignore

@@ -7,6 +7,7 @@ Testing/
 ft_build/
 ut_build/
 sdk_build/
+examples/build/
 test/httpserver/node_modules
 test/httpserver/package-lock.json
 test/httpserver/nohup.out

+ 17 - 16
CMakeLists.txt

@@ -37,9 +37,10 @@ if(BUILD_UNIT_TESTS)
 endif()
 
 if(BUILD_FUNCTION_TESTS)
-	enable_testing()
-	add_subdirectory(test/function_test/cdn)
+  enable_testing()
+  add_subdirectory(test/function_test/cdn)
   add_subdirectory(test/function_test/core)
+  add_subdirectory(test/function_test/cs)
   add_subdirectory(test/function_test/ecs)
   add_subdirectory(test/function_test/nlp)
   add_subdirectory(test/function_test/rds)
@@ -90,17 +91,17 @@ add_subdirectory(saf)
 add_subdirectory(arms)
 add_subdirectory(lubancloud)
 add_subdirectory(alimt)
-
-add_subdirectory(xspace)
-add_subdirectory(jarvis-public)
-add_subdirectory(cbn)
-add_subdirectory(emr)
-add_subdirectory(ram)
-add_subdirectory(sts)
-add_subdirectory(gpdb)
-add_subdirectory(sas-api)
-add_subdirectory(cr)
-add_subdirectory(finmall)
-add_subdirectory(openanalytics)
-add_subdirectory(snsuapi)
-add_subdirectory(ubsms)
+add_subdirectory(xspace)
+add_subdirectory(jarvis-public)
+add_subdirectory(cbn)
+add_subdirectory(emr)
+add_subdirectory(ram)
+add_subdirectory(sts)
+add_subdirectory(gpdb)
+add_subdirectory(sas-api)
+add_subdirectory(cr)
+add_subdirectory(finmall)
+add_subdirectory(openanalytics)
+add_subdirectory(snsuapi)
+add_subdirectory(ubsms)
+

+ 67 - 0
README.md

@@ -157,6 +157,73 @@ Copy the above to ecs_test.cc, then build with the following command.
 ~$
 ```
 
+## Timeout Configuration
+
+CPP SDK uses libcurl to do HTTP transfer.
+
+- The following timeout parameters are used to for libcurl.
+
+ - `connectTimeout`: timeout for the connect phase. [Refer](https://curl.haxx.se/libcurl/c/CURLOPT_CONNECTTIMEOUT_MS.html).
+ - `readTimeout`: maximum time the request is allowed to take, [Refer](https://curl.haxx.se/libcurl/c/CURLOPT_TIMEOUT_MS.html)
+
+- Default Value
+ - `connectTimeout`: 5000ms
+ - `readTimeout`: 10000ms
+
+- You may specify `timeout` parameters when create a client or make a request.
+
+- Request timeout has higher priority than client timeout.
+
+- If you want to disable timeout feature, deliver `0` or `-1` to `setConnectTimeout` and `setReadTimeout`.
+
+The following code shows hot to specify `timeout` parameters, and the final connectTimeout is 1000ms and readTimeout 6000ms.
+
+```cpp
+#include <iostream>
+#include <alibabacloud/core/AlibabaCloud.h>
+#include <alibabacloud/ecs/EcsClient.h>
+
+using namespace AlibabaCloud;
+using namespace AlibabaCloud::Ecs;
+
+int main(int argc, char** argv) {
+  // Initialize the SDK
+  AlibabaCloud::InitializeSdk();
+
+  // Configure the ECS instance
+  ClientConfiguration configuration("<your-region-id>");
+  // specify timeout when create client.
+  configuration.setConnectTimeout(1500);
+  configuration.setReadTimeout(4000);
+
+  EcsClient client("<your-access-key-id>", "<your-access-key-secret>", configuration);
+
+  // Create an API request and set parameters
+  Model::DescribeInstancesRequest request;
+  request.setPageSize(10);
+  // specify timeout when request
+  request.setConnectTimeout(1000);
+  request.setReadTimeout(6000);
+
+  auto outcome = client.describeInstances(request);
+  if (!outcome.isSuccess()) {
+    // Handle exceptions
+    std::cout << outcome.error().errorCode() << std::endl;
+    AlibabaCloud::ShutdownSdk();
+    return -1;
+  }
+
+  std::cout << "totalCount: " << outcome.result().getTotalCount() << std::endl;
+
+  // Close the SDK
+  AlibabaCloud::ShutdownSdk();
+  return 0;
+}
+
+```
+
+
+
 **More [examples](https://github.com/aliyun/aliyun-openapi-cpp-sdk/tree/master/examples)**
 
 ## LICENSE

+ 70 - 0
README_zh.md

@@ -165,6 +165,76 @@ Linux 下
 ~$
 ```
 
+## Timeout 设置
+
+CPP SDK 使用 libcurl 作为底层 HTTP 传输库。
+
+- 下面两个参数用来传递超时参数到 libcurl。
+
+ - `connectTimeout`: 连接超时设置。 [参考](https://curl.haxx.se/libcurl/c/CURLOPT_CONNECTTIMEOUT_MS.html).
+
+ - `readTimeout`: 传输超时设置。[参考](https://curl.haxx.se/libcurl/c/CURLOPT_TIMEOUT_MS.html)
+
+- 默认值
+
+  - connectTimeout: 5000ms
+
+  - readTimeout: 10000ms
+
+- 可以在创建 Client 或者发 Requst 设置超时参数。
+
+-  Requst 设置优先级高于 Client 设置。
+
+- 输入 0 或者 -1 到 `setConnectTimeout` 和 `setReadTimeout` 可以禁用此功能。
+
+下面代码是设置超时参数的例子,由于 Request 优先级高于 Client,所以最终 `ConnectTimeout` 为 `1000ms`, `readTimeout` 为 `6000ms`。
+
+```cpp
+#include <iostream>
+#include <alibabacloud/core/AlibabaCloud.h>
+#include <alibabacloud/ecs/EcsClient.h>
+
+using namespace AlibabaCloud;
+using namespace AlibabaCloud::Ecs;
+
+int main(int argc, char** argv) {
+  // Initialize the SDK
+  AlibabaCloud::InitializeSdk();
+
+  // Configure the ECS instance
+  ClientConfiguration configuration("<your-region-id>");
+  // specify timeout when create client.
+  configuration.setConnectTimeout(1500);
+  configuration.setReadTimeout(4000);
+
+  EcsClient client("<your-access-key-id>", "<your-access-key-secret>", configuration);
+
+  // Create an API request and set parameters
+  Model::DescribeInstancesRequest request;
+  request.setPageSize(10);
+  // specify timeout when request
+  request.setConnectTimeout(1000);
+  request.setReadTimeout(6000);
+
+  auto outcome = client.describeInstances(request);
+  if (!outcome.isSuccess()) {
+    // Handle exceptions
+    std::cout << outcome.error().errorCode() << std::endl;
+    AlibabaCloud::ShutdownSdk();
+    return -1;
+  }
+
+  std::cout << "totalCount: " << outcome.result().getTotalCount() << std::endl;
+
+  // Close the SDK
+  AlibabaCloud::ShutdownSdk();
+  return 0;
+}
+
+```
+
+
+
 **更多 [例程](https://github.com/aliyun/aliyun-openapi-cpp-sdk/tree/master/examples) 请(参考)[https://github.com/aliyun/aliyun-openapi-cpp-sdk/blob/master/examples/README_zh.md]**
 
 ## 许可协议

+ 7 - 0
core/include/alibabacloud/core/AlibabaCloud.h

@@ -18,8 +18,15 @@
 #define CORE_INCLUDE_ALIBABACLOUD_CORE_ALIBABACLOUD_H_
 
 #include "CoreExport.h"
+#include <limits>
 
 namespace AlibabaCloud {
+
+const long kInvalidTimeout = (std::numeric_limits<long>::min)();
+
+const long kDefaultConnectTimeout = 5000;
+const long kDefaultReadTimeout = 10000;
+
 ALIBABACLOUD_CORE_EXPORT void InitializeSdk();
 ALIBABACLOUD_CORE_EXPORT bool IsSdkInitialized();
 ALIBABACLOUD_CORE_EXPORT void ShutdownSdk();

+ 7 - 0
core/include/alibabacloud/core/ClientConfiguration.h

@@ -38,10 +38,17 @@ class ALIBABACLOUD_CORE_EXPORT ClientConfiguration {
   void setProxy(const NetworkProxy &proxy);
   void setRegionId(const std::string &regionId);
 
+  long connectTimeout() const;
+  long readTimeout() const;
+  void setConnectTimeout(const long connectTimeout);
+  void setReadTimeout(const long readTimeout);
+
  private:
   std::string endpoint_;
   NetworkProxy proxy_;
   std::string regionId_;
+  long connectTimeout_;
+  long readTimeout_;
 };
 }  // namespace AlibabaCloud
 

+ 6 - 0
core/include/alibabacloud/core/HttpRequest.h

@@ -42,10 +42,16 @@ class ALIBABACLOUD_CORE_EXPORT HttpRequest : public HttpMessage {
   void setMethod(Method method);
   void setUrl(const Url &url);
   Url url()const;
+  long connectTimeout() const;
+  long readTimeout() const;
+  void setConnectTimeout(const long connectTimeout);
+  void setReadTimeout(const long readTimeout);
 
  private:
   Method method_;
   Url url_;
+  long connectTimeout_;
+  long readTimeout_;
 };
 }  // namespace AlibabaCloud
 #endif  // CORE_INCLUDE_ALIBABACLOUD_CORE_HTTPREQUEST_H_

+ 6 - 0
core/include/alibabacloud/core/ServiceRequest.h

@@ -39,6 +39,10 @@ class ALIBABACLOUD_CORE_EXPORT ServiceRequest {
   std::string resourcePath() const;
   std::string version() const;
   std::string scheme() const;
+  long connectTimeout() const;
+  long readTimeout() const;
+  void setConnectTimeout(const long connectTimeout);
+  void setReadTimeout(const long readTimeout);
 
  protected:
   ServiceRequest(const std::string &product, const std::string &version);
@@ -68,6 +72,8 @@ class ALIBABACLOUD_CORE_EXPORT ServiceRequest {
   std::string resourcePath_;
   std::string version_;
   std::string scheme_;
+  long connectTimeout_;
+  long readTimeout_;
 };
 }  // namespace AlibabaCloud
 

+ 1 - 2
core/include/alibabacloud/core/ServiceResult.h

@@ -26,14 +26,13 @@ class ALIBABACLOUD_CORE_EXPORT ServiceResult {
  public:
   ServiceResult();
   virtual ~ServiceResult();
-
   std::string requestId()const;
 
  protected:
   void setRequestId(const std::string &requestId);
 
  private:
-    std::string requestId_;
+  std::string requestId_;
 };
 }  // namespace AlibabaCloud
 

+ 20 - 1
core/src/ClientConfiguration.cc

@@ -15,6 +15,7 @@
  */
 
 #include <alibabacloud/core/ClientConfiguration.h>
+#include <alibabacloud/core/AlibabaCloud.h>
 
 namespace AlibabaCloud {
 
@@ -22,7 +23,9 @@ ClientConfiguration::ClientConfiguration(const std::string &regionId,
   const NetworkProxy &proxy):
   regionId_(regionId),
   proxy_(proxy),
-  endpoint_() {
+  endpoint_(),
+  connectTimeout_(kDefaultConnectTimeout),
+  readTimeout_(kDefaultReadTimeout) {
 }
 
 ClientConfiguration::~ClientConfiguration() {
@@ -52,4 +55,20 @@ void ClientConfiguration::setRegionId(const std::string &regionId) {
   regionId_ = regionId;
 }
 
+long ClientConfiguration::connectTimeout() const {
+  return connectTimeout_;
+}
+
+long ClientConfiguration::readTimeout() const {
+  return readTimeout_;
+}
+
+void ClientConfiguration::setConnectTimeout(const long connectTimeout) {
+  connectTimeout_ = connectTimeout;
+}
+
+void ClientConfiguration::setReadTimeout(const long readTimeout) {
+  readTimeout_ = readTimeout;
+}
+
 }  // namespace AlibabaCloud

+ 26 - 0
core/src/CommonClient.cc

@@ -14,6 +14,7 @@
 * limitations under the License.
 */
 
+#include <alibabacloud/core/AlibabaCloud.h>
 #include <alibabacloud/core/CommonClient.h>
 #include <alibabacloud/core/location/LocationClient.h>
 #include <alibabacloud/core/SimpleCredentialsProvider.h>
@@ -145,6 +146,19 @@ HttpRequest CommonClient::buildRoaHttpRequest(const std::string & endpoint,
 
   HttpRequest request(url);
   request.setMethod(method);
+
+  if (msg.connectTimeout() != kInvalidTimeout) {
+    request.setConnectTimeout(msg.connectTimeout());
+  } else {
+    request.setConnectTimeout(configuration().connectTimeout());
+  }
+
+  if (msg.readTimeout() != kInvalidTimeout) {
+    request.setReadTimeout(msg.readTimeout());
+  } else {
+    request.setReadTimeout(configuration().readTimeout());
+  }
+
   if (msg.headerParameter("Accept").empty()) {
     request.setHeader("Accept", "application/json");
   } else {
@@ -260,6 +274,18 @@ HttpRequest CommonClient::buildRpcHttpRequest(const std::string & endpoint,
   url.setQuery(queryString.str().substr(1));
 
   HttpRequest request(url);
+  if (msg.connectTimeout() != kInvalidTimeout) {
+    request.setConnectTimeout(msg.connectTimeout());
+  } else {
+    request.setConnectTimeout(configuration().connectTimeout());
+  }
+
+  if (msg.readTimeout() != kInvalidTimeout) {
+    request.setReadTimeout(msg.readTimeout());
+  } else {
+    request.setReadTimeout(configuration().readTimeout());
+  }
+
   request.setMethod(method);
   request.setHeader("Host", url.host());
   request.setHeader("x-sdk-client",

+ 71 - 57
core/src/CurlHttpClient.cc

@@ -20,12 +20,7 @@
 #include <sstream>
 #include <string>
 #include <vector>
-
-#include <iostream>
 #include <string.h>
-#include <stdio.h>
-
-using namespace std;
 
 namespace AlibabaCloud {
 
@@ -56,7 +51,6 @@ static size_t readCallback(void *ptr, size_t size, size_t nmemb, void *stream) {
   return len;
 }
 
-
 size_t recvBody(char *ptr, size_t size, size_t nmemb, void *userdata) {
   std::ostringstream &out = *static_cast<std::ostringstream*>(userdata);
   out << std::string(ptr, nmemb*size);
@@ -120,49 +114,52 @@ CurlHttpClient::makeRequest(const HttpRequest &request) {
   curl_easy_reset(curlHandle_);
   HttpResponse response(request);
 
+  long connect_timeout = request.connectTimeout();
+  long read_timeout = request.readTimeout();
+
   std::string url = request.url().toString();
   switch (request.method()) {
-  case HttpRequest::Method::Get:
-  break;
-  case HttpRequest::Method::Post: {
-    if (request.bodySize() > 0) {
-      curl_easy_setopt(curlHandle_, CURLOPT_POSTFIELDS, request.body());
-    } else {
-      curl_easy_setopt(curlHandle_, CURLOPT_POSTFIELDS, "");
+    case HttpRequest::Method::Get:
+    break;
+    case HttpRequest::Method::Post: {
+      if (request.bodySize() > 0) {
+        curl_easy_setopt(curlHandle_, CURLOPT_POSTFIELDS, request.body());
+      } else {
+        curl_easy_setopt(curlHandle_, CURLOPT_POSTFIELDS, "");
+      }
     }
-  }
-  break;
+    break;
 
-  case HttpRequest::Method::Put: {
-    uploadContext* ctx = (uploadContext *)malloc(sizeof(uploadContext));
-    // this is impossible, as the size is 24 Bytes
-    if (ctx == nullptr) {
-      return HttpResponseOutcome(
-        Error("MemoryAllocateError",
-          "There is not enough memory for http transfer."));
+    case HttpRequest::Method::Put: {
+      uploadContext* ctx = (uploadContext *)malloc(sizeof(uploadContext));
+      // this is impossible, as the size is 24 Bytes
+      if (ctx == nullptr) {
+        return HttpResponseOutcome(
+          Error("MemoryAllocateError",
+            "There is not enough memory for http transfer."));
+      }
+      ctx->data = request.body();
+      ctx->pos = request.body();
+      ctx->last = ctx->pos + request.bodySize();
+
+      curl_easy_setopt(curlHandle_, CURLOPT_READFUNCTION, readCallback);
+      curl_easy_setopt(curlHandle_, CURLOPT_UPLOAD, 1L);
+      curl_easy_setopt(curlHandle_, CURLOPT_READDATA, ctx);
     }
-    ctx->data = request.body();
-    ctx->pos = request.body();
-    ctx->last = ctx->pos + request.bodySize();
+    break;
 
-    curl_easy_setopt(curlHandle_, CURLOPT_READFUNCTION, readCallback);
-    curl_easy_setopt(curlHandle_, CURLOPT_UPLOAD, 1L);
-    curl_easy_setopt(curlHandle_, CURLOPT_READDATA, ctx);
-  }
-  break;
-
-  case HttpRequest::Method::Delete: {
-    curl_easy_setopt(curlHandle_, CURLOPT_CUSTOMREQUEST, "DELETE");
-    if (request.bodySize() > 0) {
-      curl_easy_setopt(curlHandle_, CURLOPT_POSTFIELDS, request.body());
-    } else {
-      curl_easy_setopt(curlHandle_, CURLOPT_POSTFIELDS, "");
+    case HttpRequest::Method::Delete: {
+      curl_easy_setopt(curlHandle_, CURLOPT_CUSTOMREQUEST, "DELETE");
+      if (request.bodySize() > 0) {
+        curl_easy_setopt(curlHandle_, CURLOPT_POSTFIELDS, request.body());
+      } else {
+        curl_easy_setopt(curlHandle_, CURLOPT_POSTFIELDS, "");
+      }
     }
-  }
-  break;
+    break;
 
-  default:
-  break;
+    default:
+    break;
   }
 
   curl_easy_setopt(curlHandle_, CURLOPT_URL, url.c_str());
@@ -171,6 +168,14 @@ CurlHttpClient::makeRequest(const HttpRequest &request) {
   curl_easy_setopt(curlHandle_, CURLOPT_HEADERDATA, &response);
   curl_easy_setopt(curlHandle_, CURLOPT_HEADERFUNCTION, recvHeaders);
 
+  if (connect_timeout > 0) {
+    curl_easy_setopt(curlHandle_, CURLOPT_CONNECTTIMEOUT_MS, connect_timeout);
+  }
+
+  if (read_timeout > 0) {
+    curl_easy_setopt(curlHandle_, CURLOPT_TIMEOUT_MS, read_timeout);
+  }
+
   curl_slist *list = nullptr;
   auto headers = request.headers();
   for (const auto &p : headers) {
@@ -190,22 +195,31 @@ CurlHttpClient::makeRequest(const HttpRequest &request) {
 
   CURLcode res = curl_easy_perform(curlHandle_);
   switch (res) {
-  case CURLE_OK: {
-    long response_code;
-    curl_easy_getinfo(curlHandle_, CURLINFO_RESPONSE_CODE, &response_code);
-    response.setStatusCode(response_code);
-    response.setBody(out.str().c_str(), out.str().length());
-    return HttpResponseOutcome(response);
-  }
-  case CURLE_SSL_CONNECT_ERROR:
-    return HttpResponseOutcome(
-      Error("SSLConnectError",
-        "A problem occurred somewhere in the SSL/TLS handshake."));
-  default:
-    return HttpResponseOutcome(
-      Error("NetworkError",
-        "Failed to connect to host or proxy: " +
-        HttpMethodToString(request.method()) + " " + request.url().toString()));
+    case CURLE_OK: {
+      long response_code;
+      curl_easy_getinfo(curlHandle_, CURLINFO_RESPONSE_CODE, &response_code);
+      response.setStatusCode(response_code);
+      response.setBody(out.str().c_str(), out.str().length());
+      return HttpResponseOutcome(response);
+    }
+    case CURLE_SSL_CONNECT_ERROR:
+      return HttpResponseOutcome(
+        Error("SSLConnectError",
+          "A problem occurred somewhere in the SSL/TLS handshake."));
+    case CURLE_OPERATION_TIMEDOUT:
+      return HttpResponseOutcome(
+        Error("OperationTimeoutError",
+          "Timeout (connectTimeout: " +
+          std::to_string(connect_timeout) + "ms, readTimeout: " +
+          std::to_string(read_timeout) + "ms) when connect or read data: " +
+          HttpMethodToString(request.method()) + " " + request.url().toString()));
+
+    default: {
+      return HttpResponseOutcome(
+        Error("NetworkError",
+          "Failed to connect to host or proxy: " +
+          HttpMethodToString(request.method()) + " " + request.url().toString()));
+    }
   }
 }
 

+ 20 - 1
core/src/HttpRequest.cc

@@ -15,13 +15,16 @@
  */
 
 #include <alibabacloud/core/HttpRequest.h>
+#include <alibabacloud/core/AlibabaCloud.h>
 
 namespace AlibabaCloud {
 
 HttpRequest::HttpRequest(const Url &url, Method method) :
   HttpMessage(),
   url_(url),
-  method_(method) {
+  method_(method),
+  connectTimeout_(kDefaultConnectTimeout),
+  readTimeout_(kDefaultReadTimeout) {
 }
 
 HttpRequest::~HttpRequest() {
@@ -44,4 +47,20 @@ Url HttpRequest::url()const {
   return url_;
 }
 
+long HttpRequest::connectTimeout() const {
+  return connectTimeout_;
+}
+
+long HttpRequest::readTimeout() const {
+  return readTimeout_;
+}
+
+void HttpRequest::setConnectTimeout(const long connectTimeout) {
+  connectTimeout_ = connectTimeout;
+}
+
+void HttpRequest::setReadTimeout(const long readTimeout) {
+  readTimeout_ = readTimeout;
+}
+
 }  // namespace AlibabaCloud

+ 13 - 0
core/src/RoaServiceClient.cc

@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <alibabacloud/core/AlibabaCloud.h>
 #include <alibabacloud/core/RoaServiceClient.h>
 #include <alibabacloud/core/HmacSha1Signer.h>
 #include <algorithm>
@@ -85,6 +86,18 @@ HttpRequest RoaServiceClient::buildHttpRequest(const std::string & endpoint,
 
   HttpRequest request(url);
   request.setMethod(method);
+  if (msg.connectTimeout() != kInvalidTimeout) {
+    request.setConnectTimeout(msg.connectTimeout());
+  } else {
+    request.setConnectTimeout(configuration().connectTimeout());
+  }
+
+  if (msg.readTimeout() != kInvalidTimeout) {
+    request.setReadTimeout(msg.readTimeout());
+  } else {
+    request.setReadTimeout(configuration().readTimeout());
+  }
+
   if (msg.parameter("Accept").empty()) {
     request.setHeader("Accept", "application/json");
   } else {

+ 13 - 0
core/src/RpcServiceClient.cc

@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <alibabacloud/core/AlibabaCloud.h>
 #include <alibabacloud/core/RpcServiceClient.h>
 #include <alibabacloud/core/HmacSha1Signer.h>
 #include <algorithm>
@@ -107,6 +108,18 @@ HttpRequest RpcServiceClient::buildHttpRequest(const std::string & endpoint,
   url.setQuery(queryString.str().substr(1));
 
   HttpRequest request(url);
+  if (msg.connectTimeout() != kInvalidTimeout) {
+    request.setConnectTimeout(msg.connectTimeout());
+  } else {
+    request.setConnectTimeout(configuration().connectTimeout());
+  }
+
+  if (msg.readTimeout() != kInvalidTimeout) {
+    request.setReadTimeout(msg.readTimeout());
+  } else {
+    request.setReadTimeout(configuration().readTimeout());
+  }
+
   request.setMethod(method);
   request.setHeader("Host", url.host());
   request.setHeader("x-sdk-client",

+ 0 - 1
core/src/RpcServiceRequest.cc

@@ -31,7 +31,6 @@ std::string RpcServiceRequest::actionName()const {
   return parameter("Action");
 }
 
-
 void RpcServiceRequest::setActionName(const std::string & name) {
   setParameter("Action", name);
 }

+ 25 - 2
core/src/ServiceRequest.cc

@@ -15,6 +15,7 @@
  */
 
 #include <alibabacloud/core/ServiceRequest.h>
+#include <alibabacloud/core/AlibabaCloud.h>
 
 namespace AlibabaCloud {
 
@@ -26,7 +27,9 @@ ServiceRequest::ServiceRequest(const std::string &product,
   product_(product),
   resourcePath_("/"),
   version_(version),
-  scheme_("https") {
+  scheme_("https"),
+  connectTimeout_(kInvalidTimeout),
+  readTimeout_(kInvalidTimeout) {
 }
 
 ServiceRequest::ServiceRequest(const ServiceRequest &other) :
@@ -36,7 +39,9 @@ ServiceRequest::ServiceRequest(const ServiceRequest &other) :
   product_(other.product_),
   resourcePath_(other.resourcePath_),
   version_(other.version_),
-  scheme_(other.scheme_) {
+  scheme_(other.scheme_),
+  connectTimeout_(other.connectTimeout_),
+  readTimeout_(other.readTimeout_) {
   setContent(other.content_, other.contentSize_);
 }
 
@@ -49,6 +54,8 @@ ServiceRequest& ServiceRequest::operator=(const ServiceRequest &other) {
     content_ = nullptr;
     contentSize_ = 0;
     params_ = other.params_;
+    connectTimeout_ = other.connectTimeout_;
+    readTimeout_ = other.readTimeout_;
     setContent(other.content_, other.contentSize_);
   }
   return *this;
@@ -152,4 +159,20 @@ std::string ServiceRequest::scheme() const {
   return scheme_;
 }
 
+long ServiceRequest::connectTimeout() const{
+  return connectTimeout_;
+}
+
+long ServiceRequest::readTimeout() const{
+  return readTimeout_;
+}
+
+void ServiceRequest::setConnectTimeout(const long connectTimeout) {
+  connectTimeout_ = connectTimeout;
+}
+
+void ServiceRequest::setReadTimeout(const long readTimeout) {
+  readTimeout_ = readTimeout;
+}
+
 }  // namespace AlibabaCloud

+ 1 - 1
function_test.sh

@@ -15,7 +15,7 @@ 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 nlp_ft rds_ft slb_ft vpc_ft
+$MAKE cdn core cs ecs rds slb vpc cdn_ft core_ft cs_ft ecs_ft nlp_ft rds_ft slb_ft vpc_ft
 
 echo '------- run function test -----------'
 

+ 2 - 1
test/core/CMakeLists.txt

@@ -77,7 +77,8 @@ add_executable(core_ut
   sts_model_assumerole_result_ut.cc
   sts_model_getcalleridentity_request_ut.cc
   sts_model_getcalleridentity_result_ut.cc
-  )
+  timeout_ut.cc
+)
 
 set_target_properties(core_ut
   PROPERTIES

+ 8 - 0
test/core/clientconfiguration_ut.cc

@@ -1,5 +1,6 @@
 #include "gtest/gtest.h"
 #include "alibabacloud/core/ClientConfiguration.h"
+#include "alibabacloud/core/AlibabaCloud.h"
 
 using namespace std;
 using namespace AlibabaCloud;
@@ -28,4 +29,11 @@ TEST(ClientConfiguration, basic) {
   EXPECT_TRUE(config.proxy().port() == port);
   EXPECT_TRUE(config.proxy().user() == user);
   EXPECT_TRUE(config.proxy().password() == password);
+
+  EXPECT_TRUE(config.connectTimeout() == kDefaultConnectTimeout);
+  EXPECT_TRUE(config.readTimeout() == kDefaultReadTimeout);
+  config.setConnectTimeout(1222);
+  config.setReadTimeout(23333);
+  EXPECT_TRUE(config.connectTimeout() == 1222);
+  EXPECT_TRUE(config.readTimeout() == 23333);
 }

+ 58 - 4
test/core/curlhttpclient_ut.cc

@@ -10,10 +10,6 @@
 #include "../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;
@@ -27,6 +23,64 @@ class mockCurlHttpClient : public CurlHttpClient {
   MOCK_METHOD1(makeRequest, HttpResponseOutcome (const HttpRequest &request));
 };
 
+TEST(CurlHttpClient, connectTimeout) {
+  CurlHttpClient client;
+  HttpRequest request;
+
+  Url url;
+  url.setScheme("http");
+  url.setHost("192.168.100.100");
+
+  request.setMethod(HttpRequest::Method::Get);
+  request.setUrl(url);
+  request.setConnectTimeout(100);
+  request.setReadTimeout(1000);
+  request.setHeader("Content-Type", "text/html");
+  HttpClient::HttpResponseOutcome out = client.makeRequest(request);
+  string errmsg = "Timeout (connectTimeout: 100ms, readTimeout: 1000ms) when connect or read data: GET http://192.168.100.100/";
+  EXPECT_TRUE(out.error().errorCode() == "OperationTimeoutError");
+  EXPECT_TRUE(out.error().errorMessage() == errmsg);
+}
+
+TEST(CurlHttpClient, defaultTimeout) {
+  CurlHttpClient client;
+  HttpRequest request;
+
+  Url url;
+  url.setScheme("http");
+  url.setHost("192.168.100.100");
+
+  request.setMethod(HttpRequest::Method::Get);
+  request.setUrl(url);
+  request.setHeader("Content-Type", "text/html");
+  HttpClient::HttpResponseOutcome out = client.makeRequest(request);
+  string errmsg = "Timeout (connectTimeout: 5000ms, readTimeout: 10000ms) when connect or read data: GET http://192.168.100.100/";
+  EXPECT_TRUE(out.error().errorCode() == "OperationTimeoutError");
+  EXPECT_TRUE(out.error().errorMessage() == errmsg);
+}
+
+TEST(CurlHttpClient, readTimeout) {
+  CurlHttpClient client;
+  HttpRequest request;
+
+  Url url;
+  url.setScheme("http");
+  url.setHost("127.0.0.1");
+  url.setPort(8021);
+  url.setPath("/readTimeoutTest");
+  url.setQuery("timeout=500");
+
+  request.setMethod(HttpRequest::Method::Get);
+  request.setUrl(url);
+  request.setConnectTimeout(233);
+  request.setReadTimeout(500);
+  request.setHeader("Content-Type", "text/html");
+  HttpClient::HttpResponseOutcome out = client.makeRequest(request);
+  string errmsg = "Timeout (connectTimeout: 233ms, readTimeout: 500ms) when connect or read data: GET http://127.0.0.1:8021/readTimeoutTest?timeout=500";
+
+  EXPECT_TRUE(out.error().errorCode() == "OperationTimeoutError");
+  EXPECT_TRUE(out.error().errorMessage() == errmsg);
+}
 
 TEST(CurlHttpClient, http_get) {
   CurlHttpClient client;

+ 13 - 6
test/core/httprequest_ut.cc

@@ -18,13 +18,20 @@ TEST(HttpRequest, basic) {
   url.setQuery("key=value&key2=value2");
   url.setFragment("fragid1");
 
-  HttpRequest http_request(url, HttpRequest::Method::Post);
+  HttpRequest req(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);
+  EXPECT_TRUE(req.method() == HttpRequest::Method::Post);
+  req.setMethod(HttpRequest::Method::Get);
+  EXPECT_TRUE(req.method() == HttpRequest::Method::Get);
 
-  http_request.setUrl(url);
-  Url rUrl = http_request.url();
+  req.setUrl(url);
+  Url rUrl = req.url();
   EXPECT_TRUE(rUrl.toString() == src);
+
+  EXPECT_TRUE(req.connectTimeout() == 5000);
+  EXPECT_TRUE(req.readTimeout() == 10000);
+  req.setConnectTimeout(12345);
+  req.setReadTimeout(3335);
+  EXPECT_TRUE(req.connectTimeout() == 12345);
+  EXPECT_TRUE(req.readTimeout() == 3335);
 }

+ 9 - 0
test/core/servicerequest_ut.cc

@@ -4,6 +4,7 @@
 #include <string.h>
 #include "gtest/gtest.h"
 #include "alibabacloud/core/ServiceRequest.h"
+#include "alibabacloud/core/AlibabaCloud.h"
 
 using namespace std;
 using namespace AlibabaCloud;
@@ -30,6 +31,7 @@ namespace {
     using ServiceRequest::setResourcePath;
     using ServiceRequest::setProduct;
     using ServiceRequest::setVersion;
+
   };
 
   TEST(ServiceRequest, basic) {
@@ -81,5 +83,12 @@ namespace {
     ServiceRequest::ParameterCollection pc = sr1.parameters();
     EXPECT_TRUE(pc.at("km") == "vm");
     EXPECT_TRUE(pc.at("kn") == "vn");
+
+    EXPECT_TRUE(sr1.connectTimeout() == kInvalidTimeout);
+    EXPECT_TRUE(sr1.readTimeout() == kInvalidTimeout);
+    sr1.setConnectTimeout(1234);
+    sr1.setReadTimeout(22233);
+    EXPECT_TRUE(sr1.connectTimeout() == 1234);
+    EXPECT_TRUE(sr1.readTimeout() == 22233);
   }
 }

+ 277 - 0
test/core/timeout_ut.cc

@@ -0,0 +1,277 @@
+
+#include <iostream>
+#include <stdio.h>
+#include "gtest/gtest.h"
+#include "../../core/src/Utils.h"
+#include "alibabacloud/core/Config.h"
+#include "alibabacloud/core/AlibabaCloud.h"
+#include "alibabacloud/core/CommonClient.h"
+#include "alibabacloud/core/CommonResponse.h"
+#include "alibabacloud/core/CommonRequest.h"
+#include "alibabacloud/core/SimpleCredentialsProvider.h"
+
+
+#include "alibabacloud/core/RoaServiceClient.h"
+#include "alibabacloud/core/RpcServiceClient.h"
+
+using namespace std;
+using namespace AlibabaCloud;
+
+const std::string unreachableDomain = "192.168.111.111";
+const std::string timeoutErrorCode = "OperationTimeoutError";
+
+const std::string defaultErrorMessage =
+  "Timeout (connectTimeout: 5000ms, readTimeout: 10000ms) when connect or read data: GET http://192.168.111.111/";
+
+long kClientConnectTimeout = 12;
+long kClientReadTimeout = 234;
+const std::string clientErrorMessage =
+  "Timeout (connectTimeout: 12ms, readTimeout: 234ms) when connect or read data: GET http://192.168.111.111/";
+
+long kRequestConnectTimeout = 33;
+long kRequestReadTimeout = 724;
+const std::string requestErrorMessage =
+  "Timeout (connectTimeout: 33ms, readTimeout: 724ms) when connect or read data: GET http://192.168.111.111/";
+
+TEST(timeout, DefaultCommonClientROA) {
+  ClientConfiguration configuration("cn-hangzhou");
+  CommonClient client("key", "secret", configuration);
+  CommonRequest request(CommonRequest::RoaPattern);
+  request.setScheme("http");
+  request.setDomain(unreachableDomain);
+  auto out = client.commonResponse(request);
+  EXPECT_TRUE(out.error().errorCode() == timeoutErrorCode);
+  EXPECT_TRUE(out.error().errorMessage() == defaultErrorMessage);
+}
+
+TEST(timeout, DefaultCommonClientRPC) {
+  ClientConfiguration configuration("cn-hangzhou");
+  CommonClient client("key", "secret", configuration);
+  CommonRequest request(CommonRequest::RpcPattern);
+  request.setScheme("http");
+  request.setDomain(unreachableDomain);
+  auto out = client.commonResponse(request);
+  EXPECT_TRUE(out.error().errorCode() == timeoutErrorCode);
+  EXPECT_TRUE(out.error().errorMessage().find(defaultErrorMessage) == 0);
+}
+
+
+TEST(timeout, clientCommonClientROA) {
+  ClientConfiguration configuration("cn-hangzhou");
+  configuration.setConnectTimeout(kClientConnectTimeout);
+  configuration.setReadTimeout(kClientReadTimeout);
+  CommonClient client("key", "secret", configuration);
+
+  CommonRequest request(CommonRequest::RoaPattern);
+  request.setScheme("http");
+  request.setDomain(unreachableDomain);
+  auto out = client.commonResponse(request);
+  EXPECT_TRUE(out.error().errorCode() == timeoutErrorCode);
+  EXPECT_TRUE(out.error().errorMessage() == clientErrorMessage);
+}
+
+TEST(timeout, clientCommonClientRPC) {
+  ClientConfiguration configuration("cn-hangzhou");
+  configuration.setConnectTimeout(kClientConnectTimeout);
+  configuration.setReadTimeout(kClientReadTimeout);
+  CommonClient client("key", "secret", configuration);
+
+  CommonRequest request(CommonRequest::RpcPattern);
+  request.setScheme("http");
+  request.setDomain(unreachableDomain);
+  auto out = client.commonResponse(request);
+  EXPECT_TRUE(out.error().errorCode() == timeoutErrorCode);
+  EXPECT_TRUE(out.error().errorMessage().find(clientErrorMessage) == 0);
+}
+
+TEST(timeout, requestCommonClientROA) {
+  ClientConfiguration configuration("cn-hangzhou");
+  CommonClient client("key", "secret", configuration);
+
+  CommonRequest request(CommonRequest::RoaPattern);
+  request.setScheme("http");
+  request.setDomain(unreachableDomain);
+  request.setConnectTimeout(kRequestConnectTimeout);
+  request.setReadTimeout(kRequestReadTimeout);
+  auto out = client.commonResponse(request);
+  EXPECT_TRUE(out.error().errorCode() == timeoutErrorCode);
+  EXPECT_TRUE(out.error().errorMessage() == requestErrorMessage);
+}
+
+TEST(timeout, requestCommonClientRPC) {
+  ClientConfiguration configuration("cn-hangzhou");
+  CommonClient client("key", "secret", configuration);
+
+  CommonRequest request(CommonRequest::RpcPattern);
+  request.setScheme("http");
+  request.setDomain(unreachableDomain);
+  request.setConnectTimeout(kRequestConnectTimeout);
+  request.setReadTimeout(kRequestReadTimeout);
+  auto out = client.commonResponse(request);
+  EXPECT_TRUE(out.error().errorCode() == timeoutErrorCode);
+  EXPECT_TRUE(out.error().errorMessage().find(requestErrorMessage) == 0);
+}
+
+TEST(timeout, clientRequestCommonClientROA) {
+  ClientConfiguration configuration("cn-hangzhou");
+  configuration.setConnectTimeout(kClientConnectTimeout);
+  configuration.setReadTimeout(kClientReadTimeout);
+  CommonClient client("key", "secret", configuration);
+
+  CommonRequest request(CommonRequest::RoaPattern);
+  request.setScheme("http");
+  request.setDomain(unreachableDomain);
+  request.setConnectTimeout(kRequestConnectTimeout);
+  request.setReadTimeout(kRequestReadTimeout);
+  auto out = client.commonResponse(request);
+  EXPECT_TRUE(out.error().errorCode() == timeoutErrorCode);
+  EXPECT_TRUE(out.error().errorMessage() == requestErrorMessage);
+}
+
+TEST(timeout, clientRequestCommonClientRPC) {
+  ClientConfiguration configuration("cn-hangzhou");
+  configuration.setConnectTimeout(kClientConnectTimeout);
+  configuration.setReadTimeout(kClientReadTimeout);
+  CommonClient client("key", "secret", configuration);
+
+  CommonRequest request(CommonRequest::RpcPattern);
+  request.setConnectTimeout(kRequestConnectTimeout);
+  request.setReadTimeout(kRequestReadTimeout);
+
+  request.setScheme("http");
+  request.setDomain(unreachableDomain);
+  auto out = client.commonResponse(request);
+  EXPECT_TRUE(out.error().errorCode() == timeoutErrorCode);
+  EXPECT_TRUE(out.error().errorMessage().find(requestErrorMessage) == 0);
+}
+
+class TestRoaClient : public RoaServiceClient {
+ public:
+  TestRoaClient(const std::string & servicename, const std::shared_ptr<CredentialsProvider> &credentialsProvider,
+    const ClientConfiguration &configuration,
+    const std::shared_ptr<Signer> &signer = std::make_shared<HmacSha1Signer>()):
+  RoaServiceClient(servicename, credentialsProvider, configuration, signer)
+  {}
+
+  JsonOutcome makeRequest(const std::string &endpoint, const RoaServiceRequest &msg, HttpRequest::Method method = HttpRequest::Method::Get)const {
+    return RoaServiceClient::makeRequest(endpoint, msg, method);
+  }
+};
+
+TEST(timeout, roaClientDefault) {
+  ClientConfiguration configuration("cn-hangzhou");
+  const Credentials credentials("key", "secret");
+  TestRoaClient client("any-service", std::make_shared<SimpleCredentialsProvider>(credentials), configuration);
+  RoaServiceRequest request("product", "version");
+  request.setScheme("http");
+  auto out = client.makeRequest(unreachableDomain, request, HttpRequest::Method::Get);
+  EXPECT_TRUE(out.error().errorCode() == timeoutErrorCode);
+  EXPECT_TRUE(out.error().errorMessage().find(defaultErrorMessage) == 0);
+}
+
+TEST(timeout, roaClientclient) {
+  ClientConfiguration configuration("cn-hangzhou");
+  configuration.setConnectTimeout(kClientConnectTimeout);
+  configuration.setReadTimeout(kClientReadTimeout);
+  const Credentials credentials("key", "secret");
+  TestRoaClient client("any-service", std::make_shared<SimpleCredentialsProvider>(credentials), configuration);
+  RoaServiceRequest request("product", "version");
+  request.setScheme("http");
+  auto out = client.makeRequest(unreachableDomain, request, HttpRequest::Method::Get);
+  EXPECT_TRUE(out.error().errorCode() == timeoutErrorCode);
+  EXPECT_TRUE(out.error().errorMessage().find(clientErrorMessage) == 0);
+}
+
+TEST(timeout, roaClientrequest) {
+  ClientConfiguration configuration("cn-hangzhou");
+  const Credentials credentials("key", "secret");
+  TestRoaClient client("any-service", std::make_shared<SimpleCredentialsProvider>(credentials), configuration);
+  RoaServiceRequest request("product", "version");
+  request.setScheme("http");
+  request.setConnectTimeout(kRequestConnectTimeout);
+  request.setReadTimeout(kRequestReadTimeout);
+  auto out = client.makeRequest(unreachableDomain, request, HttpRequest::Method::Get);
+  EXPECT_TRUE(out.error().errorCode() == timeoutErrorCode);
+  EXPECT_TRUE(out.error().errorMessage().find(requestErrorMessage) == 0);
+}
+
+TEST(timeout, roaClientclientrequest) {
+  ClientConfiguration configuration("cn-hangzhou");
+  configuration.setConnectTimeout(kClientConnectTimeout);
+  configuration.setReadTimeout(kClientReadTimeout);
+  const Credentials credentials("key", "secret");
+  TestRoaClient client("any-service", std::make_shared<SimpleCredentialsProvider>(credentials), configuration);
+  RoaServiceRequest request("product", "version");
+  request.setScheme("http");
+  request.setConnectTimeout(kRequestConnectTimeout);
+  request.setReadTimeout(kRequestReadTimeout);
+  auto out = client.makeRequest(unreachableDomain, request, HttpRequest::Method::Get);
+  EXPECT_TRUE(out.error().errorCode() == timeoutErrorCode);
+  EXPECT_TRUE(out.error().errorMessage().find(requestErrorMessage) == 0);
+}
+
+
+class TestRpcClient : public RpcServiceClient {
+ public:
+  TestRpcClient(const std::string & servicename, const std::shared_ptr<CredentialsProvider> &credentialsProvider,
+  const ClientConfiguration &configuration,
+  const std::shared_ptr<Signer> &signer = std::make_shared<HmacSha1Signer>()):
+  RpcServiceClient(servicename, credentialsProvider, configuration, signer)
+  {}
+
+  JsonOutcome makeRequest(const std::string &endpoint, const RpcServiceRequest &msg, HttpRequest::Method method = HttpRequest::Method::Get)const {
+    return RpcServiceClient::makeRequest(endpoint, msg, method);
+  }
+};
+
+TEST(timeout, rpcClientDefault) {
+  ClientConfiguration configuration("cn-hangzhou");
+  const Credentials credentials("key", "secret");
+  TestRpcClient client("any-service", std::make_shared<SimpleCredentialsProvider>(credentials), configuration);
+  RpcServiceRequest request("product", "version", "aciton");
+  request.setScheme("http");
+  auto out = client.makeRequest(unreachableDomain, request, HttpRequest::Method::Get);
+  EXPECT_TRUE(out.error().errorCode() == timeoutErrorCode);
+  EXPECT_TRUE(out.error().errorMessage().find(defaultErrorMessage) == 0);
+}
+
+TEST(timeout, rpcClientclient) {
+  ClientConfiguration configuration("cn-hangzhou");
+  configuration.setConnectTimeout(kClientConnectTimeout);
+  configuration.setReadTimeout(kClientReadTimeout);
+  const Credentials credentials("key", "secret");
+  TestRpcClient client("any-service", std::make_shared<SimpleCredentialsProvider>(credentials), configuration);
+  RpcServiceRequest request("product", "version", "aciton");
+  request.setScheme("http");
+  auto out = client.makeRequest(unreachableDomain, request, HttpRequest::Method::Get);
+  EXPECT_TRUE(out.error().errorCode() == timeoutErrorCode);
+  EXPECT_TRUE(out.error().errorMessage().find(clientErrorMessage) == 0);
+}
+
+TEST(timeout, rpcClientrequest) {
+  ClientConfiguration configuration("cn-hangzhou");
+  const Credentials credentials("key", "secret");
+  TestRpcClient client("any-service", std::make_shared<SimpleCredentialsProvider>(credentials), configuration);
+  RpcServiceRequest request("product", "version", "aciton");
+  request.setScheme("http");
+  request.setConnectTimeout(kRequestConnectTimeout);
+  request.setReadTimeout(kRequestReadTimeout);
+  auto out = client.makeRequest(unreachableDomain, request, HttpRequest::Method::Get);
+  EXPECT_TRUE(out.error().errorCode() == timeoutErrorCode);
+  EXPECT_TRUE(out.error().errorMessage().find(requestErrorMessage) == 0);
+}
+
+TEST(timeout, rpcClientclientrequest) {
+  ClientConfiguration configuration("cn-hangzhou");
+  configuration.setConnectTimeout(kClientConnectTimeout);
+  configuration.setReadTimeout(kClientReadTimeout);
+  const Credentials credentials("key", "secret");
+  TestRpcClient client("any-service", std::make_shared<SimpleCredentialsProvider>(credentials), configuration);
+  RpcServiceRequest request("product", "version", "aciton");
+  request.setScheme("http");
+  request.setConnectTimeout(kRequestConnectTimeout);
+  request.setReadTimeout(kRequestReadTimeout);
+  auto out = client.makeRequest(unreachableDomain, request, HttpRequest::Method::Get);
+  EXPECT_TRUE(out.error().errorCode() == timeoutErrorCode);
+  EXPECT_TRUE(out.error().errorMessage().find(requestErrorMessage) == 0);
+}

+ 26 - 0
test/function_test/cs/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("../../../cs/include/")
+link_directories(${CMAKE_SOURCE_DIR}/ft_build/lib)
+
+
+add_executable(cs_ft cs_describetemplates_ut.cc)
+target_link_libraries(cs_ft alibabacloud-sdk-core alibabacloud-sdk-cs)
+
+target_link_libraries(cs_ft core gtest gmock_main)
+
+set_target_properties(cs_ft
+  PROPERTIES
+  OUTPUT_NAME ${TARGET_OUTPUT_NAME_PREFIX}cs_ft
+  RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
+
+add_test(NAME cs_ft COMMAND cs_ft)

+ 88 - 0
test/function_test/cs/cs_describetemplates_ut.cc

@@ -0,0 +1,88 @@
+#include <iostream>
+#include "../utils.h"
+#include "gtest/gtest.h"
+#include "alibabacloud/core/AlibabaCloud.h"
+#include "alibabacloud/cs/CSClient.h"
+#include "alibabacloud/cs/model/CreateTemplateRequest.h"
+// #include "alibabacloud/core/CommonClient.h"
+// #include "alibabacloud/core/CommonRequest.h"
+#include "alibabacloud/core/sts/StsClient.h"
+#include "alibabacloud/core/StsAssumeRoleCredentialsProvider.h"
+
+
+using namespace std;
+using namespace AlibabaCloud;
+using namespace AlibabaCloud::CS;
+
+namespace {
+  TEST(cs, describeTemplatesError) {
+    utUtils utils;
+    string key = utils.get_env("ENV_AccessKeyId");
+    string secret = utils.get_env("ENV_AccessKeySecret");
+
+    InitializeSdk();
+    ClientConfiguration configuration("cn-hangzhou");
+    CSClient client(key, secret, configuration);
+    Model::DescribeTemplatesRequest request;
+    auto outcome = client.describeTemplates(request);
+    EXPECT_TRUE(outcome.error().errorCode() == "InvalidAction.NotFound");
+    EXPECT_TRUE(outcome.error().errorMessage() == "Specified api is not found, please check your url and method.");
+    ShutdownSdk();
+  }
+
+
+  TEST(cs, describeTemplatesClientTimeout) {
+    utUtils utils;
+    string key = utils.get_env("ENV_AccessKeyId");
+    string secret = utils.get_env("ENV_AccessKeySecret");
+
+    InitializeSdk();
+    ClientConfiguration configuration("cn-hangzhou");
+    configuration.setConnectTimeout(1);
+    configuration.setReadTimeout(123);
+
+    CSClient client(key, secret, configuration);
+    Model::DescribeTemplatesRequest request;
+    auto outcome = client.describeTemplates(request);
+    EXPECT_TRUE(outcome.error().errorCode() == "OperationTimeoutError");
+    EXPECT_TRUE(outcome.error().errorMessage().find("Timeout (connectTimeout: 1ms, readTimeout: 123ms) when connect or read") == 0);
+    ShutdownSdk();
+  }
+
+  TEST(cs, describeTemplatesRequstTimeout) {
+    utUtils utils;
+    string key = utils.get_env("ENV_AccessKeyId");
+    string secret = utils.get_env("ENV_AccessKeySecret");
+
+    InitializeSdk();
+    ClientConfiguration configuration("cn-hangzhou");
+    CSClient client(key, secret, configuration);
+    Model::DescribeTemplatesRequest request;
+    request.setConnectTimeout(11);
+    request.setReadTimeout(213);
+    auto outcome = client.describeTemplates(request);
+    EXPECT_TRUE(outcome.error().errorCode() == "OperationTimeoutError");
+    EXPECT_TRUE(outcome.error().errorMessage().find("Timeout (connectTimeout: 11ms, readTimeout: 213ms) when connect or read") == 0);
+    ShutdownSdk();
+  }
+
+  TEST(cs, describeTemplatesClientRequstTimeout) {
+    utUtils utils;
+    string key = utils.get_env("ENV_AccessKeyId");
+    string secret = utils.get_env("ENV_AccessKeySecret");
+
+    InitializeSdk();
+    ClientConfiguration configuration("cn-hangzhou");
+    configuration.setConnectTimeout(1);
+    configuration.setReadTimeout(123);
+
+    CSClient client(key, secret, configuration);
+    Model::DescribeTemplatesRequest request;
+    request.setConnectTimeout(11);
+    request.setReadTimeout(213);
+    auto outcome = client.describeTemplates(request);
+    EXPECT_TRUE(outcome.error().errorCode() == "OperationTimeoutError");
+    EXPECT_TRUE(outcome.error().errorMessage().find("Timeout (connectTimeout: 11ms, readTimeout: 213ms) when connect or read") == 0);
+    ShutdownSdk();
+  }
+}

+ 61 - 2
test/function_test/ecs/ecs_describeInstances_ft.cc

@@ -47,8 +47,8 @@ namespace {
 
     auto outcome = client.deleteInstance(delReq);
 
-    EXPECT_TRUE(outcome.error().errorCode() == "InvalidInstanceId.NotFound");
-    EXPECT_TRUE(outcome.error().errorMessage() == "The specified InstanceId does not exist.");
+    EXPECT_TRUE(outcome.error().errorCode() == "InvalidParameter");
+    EXPECT_TRUE(outcome.error().errorMessage() == "The specified parameter \"Force\" is not valid.");
     ShutdownSdk();
   }
 
@@ -111,4 +111,63 @@ namespace {
     EXPECT_TRUE(outcome.result().payload().find("\"Instances\":") != string::npos);
     ShutdownSdk();
   }
+
+
+  TEST(ecs, describeInstancesClientTimeout) {
+    utUtils utils;
+    string key = utils.get_env("ENV_AccessKeyId");
+    string secret = utils.get_env("ENV_AccessKeySecret");
+
+    InitializeSdk();
+    ClientConfiguration configuration("cn-hangzhou");
+    configuration.setConnectTimeout(1);
+    configuration.setReadTimeout(123);
+    EcsClient client(key, secret, configuration);
+    Model::DescribeInstancesRequest request;
+    request.setPageSize(10);
+
+    auto outcome = client.describeInstances(request);
+    EXPECT_TRUE(outcome.error().errorCode() == "OperationTimeoutError");
+    EXPECT_TRUE(outcome.error().errorMessage().find("Timeout (connectTimeout: 1ms, readTimeout: 123ms) when connect or read") == 0);
+    ShutdownSdk();
+  }
+
+  TEST(ecs, describeInstancesRequestTimeout) {
+    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);
+    request.setConnectTimeout(11);
+    request.setReadTimeout(213);
+    auto outcome = client.describeInstances(request);
+    EXPECT_TRUE(outcome.error().errorCode() == "OperationTimeoutError");
+    EXPECT_TRUE(outcome.error().errorMessage().find("Timeout (connectTimeout: 11ms, readTimeout: 213ms) when connect or read") == 0);
+    ShutdownSdk();
+  }
+
+
+  TEST(ecs, describeInstancesClientRequestTimeout) {
+    utUtils utils;
+    string key = utils.get_env("ENV_AccessKeyId");
+    string secret = utils.get_env("ENV_AccessKeySecret");
+
+    InitializeSdk();
+    ClientConfiguration configuration("cn-hangzhou");
+    configuration.setConnectTimeout(1);
+    configuration.setReadTimeout(123);
+    EcsClient client(key, secret, configuration);
+    Model::DescribeInstancesRequest request;
+    request.setPageSize(10);
+    request.setConnectTimeout(11);
+    request.setReadTimeout(213);
+    auto outcome = client.describeInstances(request);
+    EXPECT_TRUE(outcome.error().errorCode() == "OperationTimeoutError");
+    EXPECT_TRUE(outcome.error().errorMessage().find("Timeout (connectTimeout: 11ms, readTimeout: 213ms) when connect or read") == 0);
+    ShutdownSdk();
+  }
 }

+ 85 - 2
test/function_test/nlp/nlp_wordsegment_ft.cc

@@ -29,7 +29,6 @@ namespace {
     request.setContent(data, strlen(data));
     request.setHeaderParameter("Content-Type", "application/json;chrset=utf-8");
     request.setVersion("2018-04-08");
-
     auto outcome = client.commonResponse(request);
     EXPECT_TRUE(outcome.error().errorCode().empty());
     const std::string expected = "{\"data\":[{\"id\":0,\"word\":\"Iphone\"},{\"id\":1,\"word\":\" \"},{\"id\":2,\"word\":\"is\"},{\"id\":3,\"word\":\" \"},{\"id\":4,\"word\":\"a\"},{\"id\":5,\"word\":\" \"},{\"id\":6,\"word\":\"good\"},{\"id\":7,\"word\":\" \"},{\"id\":8,\"word\":\"choice\"},{\"id\":9,\"word\":\" \"},{\"id\":10,\"word\":\"专用\"},{\"id\":11,\"word\":\"数据线\"}]}";
@@ -56,10 +55,94 @@ namespace {
     request.setContent(data, strlen(data));
     request.setHeaderParameter("Content-Type", "application/json;chrset=utf-8");
     request.setVersion("2018-04-08");
-
     auto outcome = client.commonResponse(request);
     const string error = "{\"errorCode\":10007,\"errorMsg\":\"body json format invalid\"}";
     EXPECT_TRUE(outcome.error().detail() == error);
     AlibabaCloud::ShutdownSdk();
   }
+
+  TEST(nlp, wordsegmentClientTimeout) {
+    utUtils utils;
+    string key = utils.get_env("ENV_AccessKeyId");
+    string secret = utils.get_env("ENV_AccessKeySecret");
+
+    AlibabaCloud::InitializeSdk();
+    ClientConfiguration configuration("cn-shanghai");
+    configuration.setConnectTimeout(1);
+    configuration.setReadTimeout(123);
+    CommonClient client(key, secret, configuration);
+    // create request and assign parameters
+    CommonRequest request(CommonRequest::RoaPattern);
+    request.setScheme("http");
+    request.setDomain("nlp.cn-shanghai.aliyuncs.com");
+    request.setResourcePath("/nlp/api/wordsegment/general");
+    request.setHttpMethod(HttpRequest::Post);
+    const char * data = "{\"lang\":\"ZH\",\"text\":\"Iphone is a good choice 专用数据线\"}";
+    request.setContent(data, strlen(data));
+    request.setHeaderParameter("Content-Type", "application/json;chrset=utf-8");
+    request.setVersion("2018-04-08");
+
+    auto outcome = client.commonResponse(request);
+    EXPECT_TRUE(outcome.error().errorCode() == "OperationTimeoutError");
+    EXPECT_TRUE(outcome.error().errorMessage().find("Timeout (connectTimeout: 1ms, readTimeout: 123ms) when connect or read") == 0);
+    AlibabaCloud::ShutdownSdk();
+  }
+
+
+  TEST(nlp, wordsegmentRequestTimeout) {
+    utUtils utils;
+    string key = utils.get_env("ENV_AccessKeyId");
+    string secret = utils.get_env("ENV_AccessKeySecret");
+
+    AlibabaCloud::InitializeSdk();
+    ClientConfiguration configuration("cn-shanghai");
+
+    CommonClient client(key, secret, configuration);
+    // create request and assign parameters
+    CommonRequest request(CommonRequest::RoaPattern);
+    request.setScheme("http");
+    request.setDomain("nlp.cn-shanghai.aliyuncs.com");
+    request.setConnectTimeout(11);
+    request.setReadTimeout(213);
+    request.setResourcePath("/nlp/api/wordsegment/general");
+    request.setHttpMethod(HttpRequest::Post);
+    const char * data = "{\"lang\":\"ZH\",\"text\":\"Iphone is a good choice 专用数据线\"}";
+    request.setContent(data, strlen(data));
+    request.setHeaderParameter("Content-Type", "application/json;chrset=utf-8");
+    request.setVersion("2018-04-08");
+
+    auto outcome = client.commonResponse(request);
+    EXPECT_TRUE(outcome.error().errorCode() == "OperationTimeoutError");
+    EXPECT_TRUE(outcome.error().errorMessage().find("Timeout (connectTimeout: 11ms, readTimeout: 213ms) when connect or read") == 0);
+    AlibabaCloud::ShutdownSdk();
+  }
+
+  TEST(nlp, wordsegmentClientRequestTimeout) {
+    utUtils utils;
+    string key = utils.get_env("ENV_AccessKeyId");
+    string secret = utils.get_env("ENV_AccessKeySecret");
+
+    AlibabaCloud::InitializeSdk();
+    ClientConfiguration configuration("cn-shanghai");
+    configuration.setConnectTimeout(1);
+    configuration.setReadTimeout(123);
+    CommonClient client(key, secret, configuration);
+    // create request and assign parameters
+    CommonRequest request(CommonRequest::RoaPattern);
+    request.setScheme("http");
+    request.setDomain("nlp.cn-shanghai.aliyuncs.com");
+    request.setConnectTimeout(11);
+    request.setReadTimeout(213);
+    request.setResourcePath("/nlp/api/wordsegment/general");
+    request.setHttpMethod(HttpRequest::Post);
+    const char * data = "{\"lang\":\"ZH\",\"text\":\"Iphone is a good choice 专用数据线\"}";
+    request.setContent(data, strlen(data));
+    request.setHeaderParameter("Content-Type", "application/json;chrset=utf-8");
+    request.setVersion("2018-04-08");
+
+    auto outcome = client.commonResponse(request);
+    EXPECT_TRUE(outcome.error().errorCode() == "OperationTimeoutError");
+    EXPECT_TRUE(outcome.error().errorMessage().find("Timeout (connectTimeout: 11ms, readTimeout: 213ms) when connect or read") == 0);
+    AlibabaCloud::ShutdownSdk();
+  }
 }

+ 7 - 1
test/httpserver/http_test_server.js

@@ -13,7 +13,13 @@ app.use(bodyParser.json({ type: 'application/*+json' }))
 app.get('*', function (req, res) {
   console.log('GET req.params: ', req.params);
   console.log('GET req.query:  ', req.query);
-  res.send(JSON.stringify(req.query));
+  if (req.params[0] === '/readTimeoutTest') {
+    setTimeout(function() {
+      res.send("something");
+    }, Number(req.query.timeout) + 100);
+  } else {
+    res.send(JSON.stringify(req.query));
+  }
 });
 
 app.post('*', function (req, res) {