FullAsyncTest.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. /***************************************************************************
  2. *
  3. * Project _____ __ ____ _ _
  4. * ( _ ) /__\ (_ _)_| |_ _| |_
  5. * )(_)( /(__)\ )( (_ _)(_ _)
  6. * (_____)(__)(__)(__) |_| |_|
  7. *
  8. *
  9. * Copyright 2018-present, Leonid Stryzhevskyi <lganzzzo@gmail.com>
  10. *
  11. * Licensed under the Apache License, Version 2.0 (the "License");
  12. * you may not use this file except in compliance with the License.
  13. * You may obtain a copy of the License at
  14. *
  15. * http://www.apache.org/licenses/LICENSE-2.0
  16. *
  17. * Unless required by applicable law or agreed to in writing, software
  18. * distributed under the License is distributed on an "AS IS" BASIS,
  19. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  20. * See the License for the specific language governing permissions and
  21. * limitations under the License.
  22. *
  23. ***************************************************************************/
  24. #include "FullAsyncTest.hpp"
  25. #include "oatpp/web/app/Client.hpp"
  26. #include "oatpp/web/app/ControllerWithInterceptorsAsync.hpp"
  27. #include "oatpp/web/app/ControllerAsync.hpp"
  28. #include "oatpp/web/client/HttpRequestExecutor.hpp"
  29. #include "oatpp/web/server/AsyncHttpConnectionHandler.hpp"
  30. #include "oatpp/web/server/HttpRouter.hpp"
  31. #include "oatpp/parser/json/mapping/ObjectMapper.hpp"
  32. #include "oatpp/network/tcp/server/ConnectionProvider.hpp"
  33. #include "oatpp/network/tcp/client/ConnectionProvider.hpp"
  34. #include "oatpp/network/virtual_/client/ConnectionProvider.hpp"
  35. #include "oatpp/network/virtual_/server/ConnectionProvider.hpp"
  36. #include "oatpp/network/virtual_/Interface.hpp"
  37. #include "oatpp/core/data/resource/InMemoryData.hpp"
  38. #include "oatpp/core/macro/component.hpp"
  39. #include "oatpp-test/web/ClientServerTestRunner.hpp"
  40. namespace oatpp { namespace test { namespace web {
  41. namespace {
  42. typedef oatpp::web::mime::multipart::PartList PartList;
  43. typedef oatpp::web::protocol::http::outgoing::MultipartBody MultipartBody;
  44. class TestComponent {
  45. private:
  46. v_uint16 m_port;
  47. public:
  48. TestComponent(v_uint16 port)
  49. : m_port(port)
  50. {}
  51. OATPP_CREATE_COMPONENT(std::shared_ptr<oatpp::async::Executor>, executor)([] {
  52. return std::make_shared<oatpp::async::Executor>(1, 1, 1);
  53. }());
  54. OATPP_CREATE_COMPONENT(std::shared_ptr<oatpp::network::virtual_::Interface>, virtualInterface)([] {
  55. return oatpp::network::virtual_::Interface::obtainShared("virtualhost");
  56. }());
  57. OATPP_CREATE_COMPONENT(std::shared_ptr<oatpp::network::ServerConnectionProvider>, serverConnectionProvider)([this] {
  58. if(m_port == 0) {
  59. OATPP_COMPONENT(std::shared_ptr<oatpp::network::virtual_::Interface>, _interface);
  60. return std::static_pointer_cast<oatpp::network::ServerConnectionProvider>(
  61. oatpp::network::virtual_::server::ConnectionProvider::createShared(_interface)
  62. );
  63. }
  64. return std::static_pointer_cast<oatpp::network::ServerConnectionProvider>(
  65. oatpp::network::tcp::server::ConnectionProvider::createShared({"localhost", m_port})
  66. );
  67. }());
  68. OATPP_CREATE_COMPONENT(std::shared_ptr<oatpp::web::server::HttpRouter>, httpRouter)([] {
  69. return oatpp::web::server::HttpRouter::createShared();
  70. }());
  71. OATPP_CREATE_COMPONENT(std::shared_ptr<oatpp::network::ConnectionHandler>, serverConnectionHandler)([] {
  72. OATPP_COMPONENT(std::shared_ptr<oatpp::web::server::HttpRouter>, router);
  73. OATPP_COMPONENT(std::shared_ptr<oatpp::async::Executor>, executor);
  74. return oatpp::web::server::AsyncHttpConnectionHandler::createShared(router, executor);
  75. }());
  76. OATPP_CREATE_COMPONENT(std::shared_ptr<oatpp::data::mapping::ObjectMapper>, objectMapper)([] {
  77. return oatpp::parser::json::mapping::ObjectMapper::createShared();
  78. }());
  79. OATPP_CREATE_COMPONENT(std::shared_ptr<oatpp::network::ClientConnectionProvider>, clientConnectionProvider)([this] {
  80. if(m_port == 0) {
  81. OATPP_COMPONENT(std::shared_ptr<oatpp::network::virtual_::Interface>, _interface);
  82. return std::static_pointer_cast<oatpp::network::ClientConnectionProvider>(
  83. oatpp::network::virtual_::client::ConnectionProvider::createShared(_interface)
  84. );
  85. }
  86. return std::static_pointer_cast<oatpp::network::ClientConnectionProvider>(
  87. oatpp::network::tcp::client::ConnectionProvider::createShared({"localhost", m_port})
  88. );
  89. }());
  90. };
  91. std::shared_ptr<PartList> createMultipart(const std::unordered_map<oatpp::String, oatpp::String>& map) {
  92. auto multipart = oatpp::web::mime::multipart::PartList::createSharedWithRandomBoundary();
  93. for(auto& pair : map) {
  94. oatpp::web::mime::multipart::Headers partHeaders;
  95. auto part = std::make_shared<oatpp::web::mime::multipart::Part>(partHeaders);
  96. multipart->writeNextPartSimple(part);
  97. part->putHeader("Content-Disposition", "form-data; name=\"" + pair.first + "\"");
  98. part->setPayload(std::make_shared<oatpp::data::resource::InMemoryData>(pair.second));
  99. }
  100. return multipart;
  101. }
  102. }
  103. void FullAsyncTest::onRun() {
  104. TestComponent component(m_port);
  105. oatpp::test::web::ClientServerTestRunner runner;
  106. runner.addController(app::ControllerAsync::createShared());
  107. runner.addController(app::ControllerWithInterceptorsAsync::createShared());
  108. runner.run([this, &runner] {
  109. OATPP_COMPONENT(std::shared_ptr<oatpp::network::ClientConnectionProvider>, clientConnectionProvider);
  110. OATPP_COMPONENT(std::shared_ptr<oatpp::data::mapping::ObjectMapper>, objectMapper);
  111. auto requestExecutor = oatpp::web::client::HttpRequestExecutor::createShared(clientConnectionProvider);
  112. auto client = app::Client::createShared(requestExecutor, objectMapper);
  113. auto connection = client->getConnection();
  114. OATPP_ASSERT(connection);
  115. v_int32 iterationsStep = m_iterationsPerStep;
  116. auto lastTick = oatpp::base::Environment::getMicroTickCount();
  117. for(v_int32 i = 0; i < iterationsStep * 10; i ++) {
  118. //OATPP_LOGV("i", "%d", i);
  119. { // test simple GET
  120. auto response = client->getRoot(connection);
  121. OATPP_ASSERT(response->getStatusCode() == 200);
  122. auto value = response->readBodyToString();
  123. OATPP_ASSERT(value == "Hello World Async!!!");
  124. }
  125. { // test GET with path parameter
  126. auto response = client->getWithParams("my_test_param-Async", connection);
  127. OATPP_ASSERT(response->getStatusCode() == 200);
  128. auto dto = response->readBodyToDto<oatpp::Object<app::TestDto>>(objectMapper.get());
  129. OATPP_ASSERT(dto);
  130. OATPP_ASSERT(dto->testValue == "my_test_param-Async");
  131. }
  132. { // test GET with header parameter
  133. auto response = client->getWithHeaders("my_test_header-Async", connection);
  134. OATPP_ASSERT(response->getStatusCode() == 200);
  135. auto dto = response->readBodyToDto<oatpp::Object<app::TestDto>>(objectMapper.get());
  136. OATPP_ASSERT(dto);
  137. OATPP_ASSERT(dto->testValue == "my_test_header-Async");
  138. }
  139. { // test POST with body
  140. auto response = client->postBody("my_test_body-Async", connection);
  141. OATPP_ASSERT(response->getStatusCode() == 200);
  142. auto dto = response->readBodyToDto<oatpp::Object<app::TestDto>>(objectMapper.get());
  143. OATPP_ASSERT(dto);
  144. OATPP_ASSERT(dto->testValue == "my_test_body-Async");
  145. }
  146. { // test Big Echo with body
  147. oatpp::data::stream::BufferOutputStream stream;
  148. for(v_int32 i = 0; i < oatpp::data::buffer::IOBuffer::BUFFER_SIZE; i++) {
  149. stream.writeSimple("0123456789", 10);
  150. }
  151. auto data = stream.toString();
  152. auto response = client->echoBody(data, connection);
  153. OATPP_ASSERT(response->getStatusCode() == 200);
  154. auto returnedData = response->readBodyToString();
  155. OATPP_ASSERT(returnedData);
  156. OATPP_ASSERT(returnedData == data);
  157. }
  158. { // test Chunked body
  159. oatpp::String sample = "__abcdefghijklmnopqrstuvwxyz-0123456789";
  160. v_int32 numIterations = 10;
  161. oatpp::data::stream::BufferOutputStream stream;
  162. for(v_int32 i = 0; i < numIterations; i++) {
  163. stream.writeSimple(sample->data(), sample->size());
  164. }
  165. auto data = stream.toString();
  166. auto response = client->getChunked(sample, numIterations, connection);
  167. OATPP_ASSERT(response->getStatusCode() == 200);
  168. auto returnedData = response->readBodyToString();
  169. OATPP_ASSERT(returnedData);
  170. OATPP_ASSERT(returnedData == data);
  171. }
  172. { // Multipart body
  173. std::unordered_map<oatpp::String, oatpp::String> map;
  174. map["value1"] = "Hello";
  175. map["value2"] = "World";
  176. auto multipart = createMultipart(map);
  177. auto body = std::make_shared<MultipartBody>(multipart);
  178. auto response = client->multipartTest(i + 1, body);
  179. OATPP_ASSERT(response->getStatusCode() == 200);
  180. multipart = std::make_shared<oatpp::web::mime::multipart::PartList>(response->getHeaders());
  181. oatpp::web::mime::multipart::Reader multipartReader(multipart.get());
  182. multipartReader.setPartReader("value1", oatpp::web::mime::multipart::createInMemoryPartReader(10));
  183. multipartReader.setPartReader("value2", oatpp::web::mime::multipart::createInMemoryPartReader(10));
  184. response->transferBody(&multipartReader);
  185. OATPP_ASSERT(multipart->getAllParts().size() == 2);
  186. auto part1 = multipart->getNamedPart("value1");
  187. auto part2 = multipart->getNamedPart("value2");
  188. OATPP_ASSERT(part1);
  189. OATPP_ASSERT(part1->getPayload());
  190. OATPP_ASSERT(part2);
  191. OATPP_ASSERT(part2->getPayload());
  192. OATPP_ASSERT(part1->getPayload()->getInMemoryData() == "Hello");
  193. OATPP_ASSERT(part2->getPayload()->getInMemoryData() == "World");
  194. }
  195. { // test interceptor GET
  196. auto response = client->getInterceptors(connection);
  197. OATPP_ASSERT(response->getStatusCode() == 200);
  198. auto value = response->readBodyToString();
  199. OATPP_ASSERT(value == "Hello World Async!!!");
  200. }
  201. { // test host header
  202. auto response = client->getHostHeader(connection);
  203. OATPP_ASSERT(response->getStatusCode() == 200);
  204. auto value = response->readBodyToString();
  205. auto host = clientConnectionProvider->getProperty("host");
  206. OATPP_ASSERT(host);
  207. OATPP_ASSERT(value == host.toString() + ":" + oatpp::utils::conversion::int32ToStr(m_port));
  208. }
  209. if((i + 1) % iterationsStep == 0) {
  210. auto ticks = oatpp::base::Environment::getMicroTickCount() - lastTick;
  211. lastTick = oatpp::base::Environment::getMicroTickCount();
  212. OATPP_LOGV("i", "%d, tick=%d", i + 1, ticks);
  213. }
  214. }
  215. connection.reset();
  216. std::this_thread::sleep_for(std::chrono::milliseconds(200));
  217. }, std::chrono::minutes(10));
  218. OATPP_COMPONENT(std::shared_ptr<oatpp::async::Executor>, executor);
  219. executor->waitTasksFinished();
  220. executor->stop();
  221. executor->join();
  222. }
  223. }}}