Browse Source

Add new framework - C++/oatpp (#5044)

* Add oatpp async project src

* Add oatpp to .travis.yml file

* Quiet apt logs in dockerfile. Remove unused variable.
Leonid Stryzhevskyi 6 years ago
parent
commit
90f6bab0de

+ 1 - 0
.travis.yml

@@ -23,6 +23,7 @@ env:
     - "TESTDIR=C++/ulib"
     - "TESTDIR=C++/wt"
     - "TESTDIR=C++/drogon"
+    - "TESTDIR=C++/oatpp"
     - "TESTLANG=Clojure"
     - "TESTLANG=Crystal"
     - "TESTLANG=D"

+ 23 - 0
frameworks/C++/oatpp/README.md

@@ -0,0 +1,23 @@
+# Oat++ (AKA oatpp) Benchmarking Test
+
+- [Oat++ Github Repository](https://github.com/oatpp/oatpp)
+- [Oat++ Website](https://oatpp.io/)
+ 
+
+## Source for Tests
+
+### oatpp-async
+
+- [src-async](src-async/) - source code for oatpp test project implemented using oatpp async API.
+- [src-async/src/controller/MyController.hpp](src-async/src/controller/MyController.hpp) - Controller for `JSON`, `PLAINTEXT` endpoints.
+
+#### Test URLs
+
+- `JSON` - [http://127.0.0.1:8000/json](http://127.0.0.1:8000/json)
+- `PLAINTEXT` - [http://127.0.0.1:8000/plaintext](http://127.0.0.1:8000/plaintext) 
+
+## Contacts
+
+- Leonid Stryzhevskyi (Creator)
+   - Email: [[email protected]](mailto:[email protected])
+   - Github: [lganzzzo](https://github.com/lganzzzo)

+ 24 - 0
frameworks/C++/oatpp/benchmark_config.json

@@ -0,0 +1,24 @@
+{
+  "framework": "oatpp",
+  "tests": [{
+    "default": {
+      "json_url": "/json",
+      "plaintext_url": "/plaintext",
+      "port": 8000,
+      "approach": "Realistic",
+      "classification": "Micro",
+      "database": "None",
+      "framework": "oatpp-async",
+      "language": "C++",
+      "flavor": "None",
+      "orm": "Raw",
+      "platform": "None",
+      "webserver": "None",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "oatpp",
+      "notes": "Test of Oat++ Async API",
+      "versus": "None"
+    }
+  }]
+}

+ 38 - 0
frameworks/C++/oatpp/oatpp.dockerfile

@@ -0,0 +1,38 @@
+FROM debian:9
+
+RUN apt-get update
+
+RUN apt-get install -yqq cmake
+RUN apt-get install -yqq build-essential
+
+RUN apt-get install -yqq git
+
+#---------------------------------------------------------------
+# install oatpp
+
+WORKDIR /test
+
+RUN git clone https://github.com/oatpp/oatpp
+
+WORKDIR /test/oatpp
+
+RUN git checkout 68bbb14ec4bb6b67cfb5917c7c1ed9201f82d341
+
+WORKDIR /test/oatpp/build
+
+RUN cmake -DCMAKE_BUILD_TYPE=Release -DOATPP_BUILD_TESTS=OFF ..
+RUN make install
+
+#---------------------------------------------------------------
+# build test app
+
+ADD src-async /test/src-async
+
+WORKDIR /test/src-async/build
+
+RUN cmake -DCMAKE_BUILD_TYPE=Release ..
+RUN make
+
+EXPOSE 8000 8000
+
+CMD ./oatpp-async-test

+ 40 - 0
frameworks/C++/oatpp/src-async/.gitignore

@@ -0,0 +1,40 @@
+# Prerequisites
+*.d
+
+# Compiled Object files
+*.slo
+*.lo
+*.o
+*.obj
+
+# Precompiled Headers
+*.gch
+*.pch
+
+# Compiled Dynamic libraries
+*.so
+*.dylib
+*.dll
+
+# Fortran module files
+*.mod
+*.smod
+
+# Compiled Static libraries
+*.lai
+*.la
+*.a
+*.lib
+
+# Executables
+*.exe
+*.out
+*.app
+
+# custom build
+build/
+
+# idea
+.idea/
+cmake-build-debug/
+*/cmake-build-debug/

+ 35 - 0
frameworks/C++/oatpp/src-async/CMakeLists.txt

@@ -0,0 +1,35 @@
+cmake_minimum_required(VERSION 3.1)
+
+set(project_name oatpp-async-test) ## rename your project here
+
+project(${project_name})
+
+set(CMAKE_CXX_STANDARD 11)
+
+include_directories(src)
+
+add_executable(${project_name}
+        src/AppComponent.hpp
+        src/App.cpp
+        src/controller/MyController.hpp
+        src/dto/DTOs.hpp
+        src/Utils.cpp
+        src/Utils.hpp
+)
+
+## link libs
+
+find_package(oatpp 0.19.8 REQUIRED)
+
+target_link_libraries(${project_name}
+        PUBLIC oatpp::oatpp
+        PUBLIC oatpp::oatpp-test
+)
+
+set_target_properties(${project_name} PROPERTIES
+        CXX_STANDARD 11
+        CXX_EXTENSIONS OFF
+        CXX_STANDARD_REQUIRED ON
+        LINKER_LANGUAGE CXX
+)
+

+ 2 - 0
frameworks/C++/oatpp/src-async/README.md

@@ -0,0 +1,2 @@
+# oatpp-async-benchmark project
+ 

+ 53 - 0
frameworks/C++/oatpp/src-async/src/App.cpp

@@ -0,0 +1,53 @@
+
+#include "./controller/MyController.hpp"
+#include "./AppComponent.hpp"
+
+#include "oatpp/network/server/Server.hpp"
+
+#include <iostream>
+
+void run() {
+
+  /* Register Components in scope of run() method */
+  AppComponent components;
+
+  /* Get router component */
+  OATPP_COMPONENT(std::shared_ptr<oatpp::web::server::HttpRouter>, router);
+
+  /* Create MyController and add all of its endpoints to router */
+  auto myController = std::make_shared<MyController>();
+  myController->addEndpointsToRouter(router);
+
+  /* Get connection handler component */
+  OATPP_COMPONENT(std::shared_ptr<oatpp::network::server::ConnectionHandler>, connectionHandler);
+
+  /* Get connection provider component */
+  OATPP_COMPONENT(std::shared_ptr<oatpp::network::ServerConnectionProvider>, connectionProvider);
+
+  /* Create server which takes provided TCP connections and passes them to HTTP connection handler */
+  oatpp::network::server::Server server(connectionProvider, connectionHandler);
+
+  /* Priny info about server port */
+  OATPP_LOGI("MyApp", "Server running on port %s", connectionProvider->getProperty("port").getData());
+
+  /* Run server */
+  server.run();
+
+}
+
+int main(int argc, const char * argv[]) {
+
+  oatpp::base::Environment::init();
+
+  run();
+
+  /* Print how much objects were created during app running, and what have left-probably leaked */
+  /* Disable object counting for release builds using '-D OATPP_DISABLE_ENV_OBJECT_COUNTERS' flag for better performance */
+  std::cout << "\nEnvironment:\n";
+  std::cout << "objectsCount = " << oatpp::base::Environment::getObjectsCount() << "\n";
+  std::cout << "objectsCreated = " << oatpp::base::Environment::getObjectsCreated() << "\n\n";
+
+  oatpp::base::Environment::destroy();
+
+  return 0;
+}

+ 55 - 0
frameworks/C++/oatpp/src-async/src/AppComponent.hpp

@@ -0,0 +1,55 @@
+
+#ifndef AppComponent_hpp
+#define AppComponent_hpp
+
+#include "oatpp/web/server/AsyncHttpConnectionHandler.hpp"
+#include "oatpp/web/server/HttpRouter.hpp"
+#include "oatpp/network/server/SimpleTCPConnectionProvider.hpp"
+
+#include "oatpp/parser/json/mapping/ObjectMapper.hpp"
+
+#include "oatpp/core/macro/component.hpp"
+
+class AppComponent {
+public:
+
+  /**
+   * Create Async Executor
+   */
+  OATPP_CREATE_COMPONENT(std::shared_ptr<oatpp::async::Executor>, executor)([] {
+    return std::make_shared<oatpp::async::Executor>();
+  }());
+
+  /**
+   *  Create ConnectionProvider component which listens on the port
+   */
+  OATPP_CREATE_COMPONENT(std::shared_ptr<oatpp::network::ServerConnectionProvider>, serverConnectionProvider)([] {
+    return oatpp::network::server::SimpleTCPConnectionProvider::createShared(8000);
+  }());
+
+  /**
+   *  Create Router component
+   */
+  OATPP_CREATE_COMPONENT(std::shared_ptr<oatpp::web::server::HttpRouter>, httpRouter)([] {
+    return oatpp::web::server::HttpRouter::createShared();
+  }());
+
+  /**
+   *  Create ConnectionHandler component which uses Router component to route requests
+   */
+  OATPP_CREATE_COMPONENT(std::shared_ptr<oatpp::network::server::ConnectionHandler>, serverConnectionHandler)([] {
+    OATPP_COMPONENT(std::shared_ptr<oatpp::web::server::HttpRouter>, router); // get Router component
+    OATPP_COMPONENT(std::shared_ptr<oatpp::async::Executor>, executor); // get Async executor component
+    return oatpp::web::server::AsyncHttpConnectionHandler::createShared(router, executor);
+  }());
+
+  /**
+   *  Create ObjectMapper component to serialize/deserialize DTOs in Contoller's API
+   */
+  OATPP_CREATE_COMPONENT(std::shared_ptr<oatpp::data::mapping::ObjectMapper>, apiObjectMapper)([] {
+    return oatpp::parser::json::mapping::ObjectMapper::createShared();
+  }());
+
+};
+
+#endif /* AppComponent_hpp */

+ 29 - 0
frameworks/C++/oatpp/src-async/src/Utils.cpp

@@ -0,0 +1,29 @@
+
+#include "Utils.hpp"
+
+#include <chrono>
+
+oatpp::String Utils::renderTime() {
+
+  static thread_local time_t lastSecond = 0;
+  static thread_local oatpp::String rederedTime;
+
+  auto time = std::chrono::system_clock::now().time_since_epoch();
+  time_t seconds = (time_t)std::chrono::duration_cast<std::chrono::seconds>(time).count();
+
+  if(seconds != lastSecond) {
+
+    lastSecond = seconds;
+
+    struct tm now;
+    gmtime_r(&seconds, &now);
+    char buffer[50];
+    auto size = std::strftime(buffer, sizeof(buffer), "%a, %d %b %Y %T GMT", &now);
+
+    rederedTime = oatpp::String(buffer, size, true);
+
+  }
+
+  return rederedTime;
+
+}

+ 21 - 0
frameworks/C++/oatpp/src-async/src/Utils.hpp

@@ -0,0 +1,21 @@
+
+#ifndef OATPP_ASYNC_TEST_UTILS_HPP
+#define OATPP_ASYNC_TEST_UTILS_HPP
+
+#include "oatpp/core/Types.hpp"
+
+
+class Utils {
+public:
+
+  /**
+   * Currently oatpp has no default implementation for server time rendering.
+   * Implementing custom server time rendering for test purposes.
+   * @return
+   */
+  static oatpp::String renderTime();
+
+};
+
+
+#endif //OATPP_ASYNC_TEST_UTILS_HPP

+ 68 - 0
frameworks/C++/oatpp/src-async/src/controller/MyController.hpp

@@ -0,0 +1,68 @@
+
+#ifndef MyController_hpp
+#define MyController_hpp
+
+#include "dto/DTOs.hpp"
+
+#include "Utils.hpp"
+
+#include "oatpp/web/server/api/ApiController.hpp"
+#include "oatpp/core/macro/codegen.hpp"
+#include "oatpp/core/macro/component.hpp"
+
+/**
+ * Sample Api Controller.
+ */
+class MyController : public oatpp::web::server::api::ApiController {
+private:
+  typedef MyController __ControllerType;
+public:
+  /**
+   * Constructor with object mapper.
+   * @param objectMapper - default object mapper used to serialize/deserialize DTOs.
+   */
+  MyController(OATPP_COMPONENT(std::shared_ptr<ObjectMapper>, objectMapper))
+    : oatpp::web::server::api::ApiController(objectMapper)
+  {}
+public:
+  
+/**
+ *  Begin ENDPOINTs generation ('ApiController' codegen)
+ */
+#include OATPP_CODEGEN_BEGIN(ApiController)
+
+  ENDPOINT_ASYNC("GET", "/plaintext", Plaintext) {
+
+    ENDPOINT_ASYNC_INIT(Plaintext)
+
+    Action act() override {
+      const auto& response = controller->createResponse(Status::CODE_200, oatpp::String("Hello, World!", 13, false));
+      response->putHeader(Header::CONTENT_TYPE, oatpp::data::share::StringKeyLabel(nullptr, (p_char8)"text/plain", 10));
+      response->putHeader("Date", Utils::renderTime());
+      return _return(response);
+    }
+
+  };
+
+  ENDPOINT_ASYNC("GET", "/json", Json) {
+    
+    ENDPOINT_ASYNC_INIT(Json)
+    
+    Action act() override {
+      auto dto = MessageDto::createShared();
+      dto->message = oatpp::String("Hello, World!", 13, false);
+      const auto& response = controller->createDtoResponse(Status::CODE_200, dto);
+      response->putHeader("Date", Utils::renderTime());
+      return _return(response);
+    }
+    
+  };
+  
+/**
+ *  Finish ENDPOINTs generation ('ApiController' codegen)
+ */
+#include OATPP_CODEGEN_END(ApiController)
+  
+};
+
+#endif /* MyController_hpp */

+ 20 - 0
frameworks/C++/oatpp/src-async/src/dto/DTOs.hpp

@@ -0,0 +1,20 @@
+
+#ifndef DTOs_hpp
+#define DTOs_hpp
+
+#include "oatpp/core/data/mapping/type/Object.hpp"
+#include "oatpp/core/macro/codegen.hpp"
+
+#include OATPP_CODEGEN_BEGIN(DTO)
+
+class MessageDto : public oatpp::data::mapping::type::Object {
+
+  DTO_INIT(MessageDto, Object)
+
+  DTO_FIELD(String, message);
+
+};
+
+#include OATPP_CODEGEN_END(DTO)
+
+#endif /* DTOs_hpp */