update to the latest oatpp 1.4.0 API

This commit is contained in:
Leonid Stryzhevskyi 2024-05-15 04:57:29 +03:00
parent ed5251c580
commit 13437a9693
18 changed files with 97 additions and 98 deletions

View File

@ -1,11 +1,11 @@
cmake_minimum_required(VERSION 3.1 FATAL_ERROR)
cmake_minimum_required(VERSION 3.20 FATAL_ERROR)
###################################################################################################
## These variables are passed to oatpp-module-install.cmake script
## use these variables to configure module installation
set(OATPP_THIS_MODULE_NAME oatpp-swagger) ## name of the module (also name of folders in installation dirs)
set(OATPP_THIS_MODULE_VERSION "1.3.0") ## version of the module (also sufix of folders in installation dirs)
set(OATPP_THIS_MODULE_VERSION "1.4.0") ## version of the module (also sufix of folders in installation dirs)
set(OATPP_THIS_MODULE_LIBRARIES oatpp-swagger) ## list of libraries to find when find_package is called
set(OATPP_THIS_MODULE_TARGETS oatpp-swagger) ## list of targets to install
set(OATPP_THIS_MODULE_DIRECTORIES oatpp-swagger) ## list of directories to install

View File

@ -13,7 +13,7 @@ add_library(${OATPP_THIS_MODULE_NAME}
oatpp-swagger/oas3/Model.hpp)
set_target_properties(${OATPP_THIS_MODULE_NAME} PROPERTIES
CXX_STANDARD 11
CXX_STANDARD 17
CXX_EXTENSIONS OFF
CXX_STANDARD_REQUIRED ON
)

View File

@ -32,10 +32,10 @@
#include "oatpp/web/protocol/http/outgoing/StreamingBody.hpp"
#include "oatpp/web/server/api/ApiController.hpp"
#include "oatpp/parser/json/mapping/ObjectMapper.hpp"
#include "oatpp/json/ObjectMapper.hpp"
#include "oatpp/core/macro/codegen.hpp"
#include "oatpp/core/macro/component.hpp"
#include "oatpp/macro/codegen.hpp"
#include "oatpp/macro/component.hpp"
namespace oatpp { namespace swagger {
@ -79,20 +79,17 @@ public:
*/
static std::shared_ptr<AsyncController> createShared(const web::server::api::Endpoints& endpointsList,
OATPP_COMPONENT(std::shared_ptr<oatpp::swagger::DocumentInfo>, documentInfo),
OATPP_COMPONENT(std::shared_ptr<oatpp::swagger::Resources>, resources)){
auto serializerConfig = oatpp::parser::json::mapping::Serializer::Config::createShared();
serializerConfig->includeNullFields = false;
auto deserializerConfig = oatpp::parser::json::mapping::Deserializer::Config::createShared();
deserializerConfig->allowUnknownFields = false;
auto objectMapper = oatpp::parser::json::mapping::ObjectMapper::createShared(serializerConfig, deserializerConfig);
OATPP_COMPONENT(std::shared_ptr<oatpp::swagger::Resources>, resources))
{
auto objectMapper = std::make_shared<oatpp::json::ObjectMapper>();
objectMapper->serializerConfig().mapper.includeNullFields = false;
objectMapper->deserializerConfig().mapper.allowUnknownFields = false;
std::shared_ptr<Generator::Config> generatorConfig;
try {
generatorConfig = OATPP_GET_COMPONENT(std::shared_ptr<Generator::Config>);
} catch (std::runtime_error e) {
} catch (std::runtime_error) {
generatorConfig = std::make_shared<Generator::Config>();
}

View File

@ -31,11 +31,11 @@
#include "oatpp/web/server/api/ApiController.hpp"
#include "oatpp/parser/json/mapping/ObjectMapper.hpp"
#include "oatpp/json/ObjectMapper.hpp"
#include "oatpp/web/protocol/http/outgoing/StreamingBody.hpp"
#include "oatpp/core/macro/codegen.hpp"
#include "oatpp/core/macro/component.hpp"
#include "oatpp/macro/codegen.hpp"
#include "oatpp/macro/component.hpp"
namespace oatpp { namespace swagger {
@ -77,15 +77,12 @@ public:
*/
static std::shared_ptr<Controller> createShared(const web::server::api::Endpoints& endpointsList,
OATPP_COMPONENT(std::shared_ptr<oatpp::swagger::DocumentInfo>, documentInfo),
OATPP_COMPONENT(std::shared_ptr<oatpp::swagger::Resources>, resources)){
auto serializerConfig = oatpp::parser::json::mapping::Serializer::Config::createShared();
serializerConfig->includeNullFields = false;
auto deserializerConfig = oatpp::parser::json::mapping::Deserializer::Config::createShared();
deserializerConfig->allowUnknownFields = false;
auto objectMapper = oatpp::parser::json::mapping::ObjectMapper::createShared(serializerConfig, deserializerConfig);
OATPP_COMPONENT(std::shared_ptr<oatpp::swagger::Resources>, resources))
{
auto objectMapper = std::make_shared<oatpp::json::ObjectMapper>();
objectMapper->serializerConfig().mapper.includeNullFields = false;
objectMapper->deserializerConfig().mapper.allowUnknownFields = false;
std::shared_ptr<Generator::Config> generatorConfig;
try {

View File

@ -25,7 +25,7 @@
#ifndef oatpp_swagger_ControllerPaths_hpp
#define oatpp_swagger_ControllerPaths_hpp
#include "oatpp/core/Types.hpp"
#include "oatpp/Types.hpp"
namespace oatpp { namespace swagger {

View File

@ -24,8 +24,9 @@
#include "Generator.hpp"
#include "oatpp/core/utils/ConversionUtils.hpp"
#include "oatpp/core/data/stream/BufferStream.hpp"
#include "oatpp/utils/Conversion.hpp"
#include "oatpp/data/stream/BufferStream.hpp"
#include "oatpp/base/Log.hpp"
#include <limits>
@ -33,7 +34,7 @@ namespace oatpp { namespace swagger {
oatpp::String Generator::getEnumSchemaName(const Type* type) {
auto polymorphicDispatcher = static_cast<const data::mapping::type::__class::AbstractEnum::PolymorphicDispatcher*>(
auto polymorphicDispatcher = static_cast<const data::type::__class::AbstractEnum::PolymorphicDispatcher*>(
type->polymorphicDispatcher
);
@ -52,47 +53,47 @@ oatpp::Object<oas3::Schema> Generator::generateSchemaForSimpleType(const Type* t
auto result = oas3::Schema::createShared();
auto classId = type->classId.id;
if(classId == oatpp::data::mapping::type::__class::String::CLASS_ID.id) {
if(classId == oatpp::data::type::__class::String::CLASS_ID.id) {
result->type = "string";
if(property != nullptr && !property->info.pattern.empty()) {
result->pattern = property->info.pattern.c_str();
}
} else if(classId == oatpp::data::mapping::type::__class::Int8::CLASS_ID.id) {
} else if(classId == oatpp::data::type::__class::Int8::CLASS_ID.id) {
result->type = "integer";
result->minimum = std::numeric_limits<v_int8>::min();
result->maximum = std::numeric_limits<v_int8>::max();
} else if(classId == oatpp::data::mapping::type::__class::UInt8::CLASS_ID.id) {
} else if(classId == oatpp::data::type::__class::UInt8::CLASS_ID.id) {
result->type = "integer";
result->minimum = std::numeric_limits<v_uint8>::min();
result->maximum = std::numeric_limits<v_uint8>::max();
} else if(classId == oatpp::data::mapping::type::__class::Int16::CLASS_ID.id) {
} else if(classId == oatpp::data::type::__class::Int16::CLASS_ID.id) {
result->type = "integer";
result->minimum = std::numeric_limits<v_int16>::min();
result->maximum = std::numeric_limits<v_int16>::max();
} else if(classId == oatpp::data::mapping::type::__class::UInt16::CLASS_ID.id) {
} else if(classId == oatpp::data::type::__class::UInt16::CLASS_ID.id) {
result->type = "integer";
result->minimum = std::numeric_limits<v_uint16>::min();
result->maximum = std::numeric_limits<v_uint16>::max();
} else if(classId == oatpp::data::mapping::type::__class::Int32::CLASS_ID.id) {
} else if(classId == oatpp::data::type::__class::Int32::CLASS_ID.id) {
result->type = "integer";
result->minimum = std::numeric_limits<v_int32>::min();
result->maximum = std::numeric_limits<v_int32>::max();
} else if(classId == oatpp::data::mapping::type::__class::UInt32::CLASS_ID.id) {
} else if(classId == oatpp::data::type::__class::UInt32::CLASS_ID.id) {
result->type = "integer";
result->minimum = std::numeric_limits<v_uint32>::min();
result->maximum = std::numeric_limits<v_uint32>::max();
} else if(classId == oatpp::data::mapping::type::__class::Int64::CLASS_ID.id) {
} else if(classId == oatpp::data::type::__class::Int64::CLASS_ID.id) {
result->type = "integer";
result->format = "int64";
} else if(classId == oatpp::data::mapping::type::__class::UInt64::CLASS_ID.id) {
} else if(classId == oatpp::data::type::__class::UInt64::CLASS_ID.id) {
result->type = "integer";
} else if(classId == oatpp::data::mapping::type::__class::Float32::CLASS_ID.id) {
} else if(classId == oatpp::data::type::__class::Float32::CLASS_ID.id) {
result->type = "number";
result->format = "float";
} else if(classId == oatpp::data::mapping::type::__class::Float64::CLASS_ID.id) {
} else if(classId == oatpp::data::type::__class::Float64::CLASS_ID.id) {
result->type = "number";
result->format = "double";
} else if(classId == oatpp::data::mapping::type::__class::Boolean::CLASS_ID.id) {
} else if(classId == oatpp::data::type::__class::Boolean::CLASS_ID.id) {
result->type = "boolean";
} else {
return nullptr; // Unknown simple type;
@ -118,7 +119,7 @@ oatpp::Object<oas3::Schema> Generator::generateSchemaForTypeObject(const Type* t
result->type = "object";
result->properties = {};
auto polymorphicDispatcher = static_cast<const oatpp::data::mapping::type::__class::AbstractObject::PolymorphicDispatcher*>(
auto polymorphicDispatcher = static_cast<const oatpp::data::type::__class::AbstractObject::PolymorphicDispatcher*>(
type->polymorphicDispatcher
);
auto instance = polymorphicDispatcher->createObject();
@ -164,7 +165,7 @@ oatpp::Object<oas3::Schema> Generator::generateSchemaForEnum(const Type* type, b
}
auto polymorphicDispatcher = static_cast<const data::mapping::type::__class::AbstractEnum::PolymorphicDispatcher*>(
auto polymorphicDispatcher = static_cast<const data::type::__class::AbstractEnum::PolymorphicDispatcher*>(
type->polymorphicDispatcher
);
@ -172,7 +173,7 @@ oatpp::Object<oas3::Schema> Generator::generateSchemaForEnum(const Type* type, b
auto result = generateSchemaForType(interType, linkSchema, usedTypes);
result->enumValues = oatpp::List<oatpp::Any>::createShared();
auto interEnum = polymorphicDispatcher->getInterpretedEnum();
auto interEnum = polymorphicDispatcher->getInterpretedEnum(false);
for(auto& v : interEnum) {
result->enumValues->push_back(v);
}
@ -203,17 +204,17 @@ oatpp::Object<oas3::Schema> Generator::generateSchemaForType(const Type* type, b
auto classId = type->classId.id;
if(classId == oatpp::data::mapping::type::__class::AbstractObject::CLASS_ID.id) {
if(classId == oatpp::data::type::__class::AbstractObject::CLASS_ID.id) {
result = generateSchemaForTypeObject(type, linkSchema, usedTypes);
} else if(classId == oatpp::data::mapping::type::__class::AbstractVector::CLASS_ID.id) {
} else if(classId == oatpp::data::type::__class::AbstractVector::CLASS_ID.id) {
result = generateSchemaForCollection_1D(type, linkSchema, usedTypes, false);
} else if(classId == oatpp::data::mapping::type::__class::AbstractList::CLASS_ID.id) {
} else if(classId == oatpp::data::type::__class::AbstractList::CLASS_ID.id) {
result = generateSchemaForCollection_1D(type, linkSchema, usedTypes, false);
} else if(classId == oatpp::data::mapping::type::__class::AbstractUnorderedSet::CLASS_ID.id) {
} else if(classId == oatpp::data::type::__class::AbstractUnorderedSet::CLASS_ID.id) {
result = generateSchemaForCollection_1D(type, linkSchema, usedTypes, true);
} else if(classId == oatpp::data::mapping::type::__class::AbstractPairList::CLASS_ID.id) {
} else if(classId == oatpp::data::type::__class::AbstractPairList::CLASS_ID.id) {
result = generateSchemaForAbstractPairList(type, linkSchema, usedTypes, property);
} else if(classId == oatpp::data::mapping::type::__class::AbstractEnum::CLASS_ID.id) {
} else if(classId == oatpp::data::type::__class::AbstractEnum::CLASS_ID.id) {
result = generateSchemaForEnum(type, linkSchema, usedTypes, property);
} else {
result = generateSchemaForSimpleType(type, property, defaultValue);
@ -357,7 +358,7 @@ oatpp::Fields<Object<oas3::OperationResponse>> Generator::generateResponses(cons
}
response->description = hint.second.description.get() == nullptr ? hint.first.description : hint.second.description;
responses[oatpp::utils::conversion::int32ToStr(hint.first.code)] = response;
responses[oatpp::utils::Conversion::int32ToStr(hint.first.code)] = response;
}
@ -508,7 +509,7 @@ void Generator::decomposeObject(const Type* type, UsedTypes& decomposedTypes) {
decomposedTypes[type->nameQualifier] = type;
auto polymorphicDispatcher = static_cast<const oatpp::data::mapping::type::__class::AbstractObject::PolymorphicDispatcher*>(
auto polymorphicDispatcher = static_cast<const oatpp::data::type::__class::AbstractObject::PolymorphicDispatcher*>(
type->polymorphicDispatcher
);
auto properties = polymorphicDispatcher->getProperties();
@ -528,7 +529,7 @@ void Generator::decomposeMap(const Type* type, UsedTypes& decomposedTypes) {
OATPP_ASSERT(type && "[oatpp-swagger::oas3::Generator::decomposeMap()]: Error. Type should not be null.");
// The only possible JSON representation of a PairList<A, B> is A being a String, even if an numeric one
if (type->params.front()->classId.id == oatpp::data::mapping::type::__class::String::CLASS_ID.id) {
if (type->params.front()->classId.id == oatpp::data::type::__class::String::CLASS_ID.id) {
decomposeType(type->params.back(), decomposedTypes);
}
@ -546,17 +547,17 @@ void Generator::decomposeEnum(const Type* type, UsedTypes& decomposedTypes) {
void Generator::decomposeType(const Type* type, UsedTypes& decomposedTypes) {
OATPP_ASSERT(type && "[oatpp-swagger::oas3::Generator::decomposeType()]: Error. Type should not be null.");
auto classId = type->classId.id;
if(classId == oatpp::data::mapping::type::__class::AbstractObject::CLASS_ID.id){
if(classId == oatpp::data::type::__class::AbstractObject::CLASS_ID.id){
decomposeObject(type, decomposedTypes);
} else if(classId == oatpp::data::mapping::type::__class::AbstractVector::CLASS_ID.id){
} else if(classId == oatpp::data::type::__class::AbstractVector::CLASS_ID.id){
decomposeCollection_1D(type, decomposedTypes);
} else if(classId == oatpp::data::mapping::type::__class::AbstractList::CLASS_ID.id){
} else if(classId == oatpp::data::type::__class::AbstractList::CLASS_ID.id){
decomposeCollection_1D(type, decomposedTypes);
} else if(classId == oatpp::data::mapping::type::__class::AbstractUnorderedSet::CLASS_ID.id){
} else if(classId == oatpp::data::type::__class::AbstractUnorderedSet::CLASS_ID.id){
decomposeCollection_1D(type, decomposedTypes);
} else if(classId == oatpp::data::mapping::type::__class::AbstractPairList::CLASS_ID.id){
} else if(classId == oatpp::data::type::__class::AbstractPairList::CLASS_ID.id){
decomposeMap(type, decomposedTypes);
} else if(classId == oatpp::data::mapping::type::__class::AbstractEnum::CLASS_ID.id){
} else if(classId == oatpp::data::type::__class::AbstractEnum::CLASS_ID.id){
decomposeEnum(type, decomposedTypes);
}
}

View File

@ -30,7 +30,7 @@
#ifndef oatpp_swagger_Config_hpp
#define oatpp_swagger_Config_hpp
#include "oatpp/core/Types.hpp"
#include "oatpp/Types.hpp"
namespace oatpp { namespace swagger {

View File

@ -23,6 +23,9 @@
***************************************************************************/
#include "Resources.hpp"
#include "oatpp/base/Log.hpp"
#include <stdio.h>
#include <fstream>
@ -63,7 +66,7 @@ oatpp::String Resources::loadFromFile(const char* fileName) {
}
OATPP_LOGE("oatpp::swagger::Resources::loadFromFile()", "Can't load file '%s'", fullFilename->c_str());
OATPP_LOGe("oatpp::swagger::Resources::loadFromFile()", "Can't load file '{}'", fullFilename);
throw std::runtime_error("[oatpp::swagger::Resources::loadFromFile(...)]: Can't load file. Please make sure you specified full path to oatpp-swagger/res folder");
}

View File

@ -25,9 +25,9 @@
#ifndef oatpp_swagger_Resources_hpp
#define oatpp_swagger_Resources_hpp
#include "oatpp/core/Types.hpp"
#include "oatpp/core/data/stream/BufferStream.hpp"
#include "oatpp/core/data/stream/FileStream.hpp"
#include "oatpp/Types.hpp"
#include "oatpp/data/stream/BufferStream.hpp"
#include "oatpp/data/stream/FileStream.hpp"
#include <unordered_map>

View File

@ -27,7 +27,7 @@
namespace oatpp { namespace swagger {
namespace __class {
const oatpp::data::mapping::type::ClassId Binary::CLASS_ID("string");
const oatpp::data::type::ClassId Binary::CLASS_ID("string");
}
}}

View File

@ -25,8 +25,7 @@
#ifndef oatpp_swagger_Types_hpp
#define oatpp_swagger_Types_hpp
#include "oatpp/core/data/mapping/type/Type.hpp"
#include "oatpp/core/Types.hpp"
#include "oatpp/Types.hpp"
namespace oatpp { namespace swagger {
@ -49,7 +48,7 @@ namespace __class {
/**
* CLASS_NAME = `"string"`.
*/
static const oatpp::data::mapping::type::ClassId CLASS_ID;
static const oatpp::data::type::ClassId CLASS_ID;
/**
* Get type information.
@ -69,7 +68,7 @@ namespace __class {
* Usage example: `info->addConsumes<oatpp::swagger::Binary>("application/octet-stream");`.<br>
* For more info see: [Endpoint Annotation And API Documentation](/docs/components/api-controller/#endpoint-annotation-and-api-documentation).
*/
typedef oatpp::data::mapping::type::ObjectWrapper<std::string, __class::Binary> Binary;
typedef oatpp::data::type::ObjectWrapper<std::string, __class::Binary> Binary;
}}

View File

@ -31,8 +31,8 @@
#include "oatpp-swagger/Model.hpp"
#include "oatpp/core/data/mapping/type/Object.hpp"
#include "oatpp/core/macro/codegen.hpp"
#include "oatpp/data/type/Object.hpp"
#include "oatpp/macro/codegen.hpp"
namespace oatpp { namespace swagger { namespace oas3 {
#include OATPP_CODEGEN_BEGIN(DTO)

View File

@ -13,7 +13,7 @@ add_executable(module-tests
)
set_target_properties(module-tests PROPERTIES
CXX_STANDARD 11
CXX_STANDARD 17
CXX_EXTENSIONS OFF
CXX_STANDARD_REQUIRED ON
)

View File

@ -7,7 +7,7 @@
#include "test-controllers/TestAsyncController.hpp"
#include "oatpp-swagger/AsyncController.hpp"
#include "oatpp/parser/json/mapping/ObjectMapper.hpp"
#include "oatpp/json/ObjectMapper.hpp"
#include <iostream>
@ -57,7 +57,7 @@ namespace {
void AsyncControllerTest::onRun() {
// Create ObjectMapper
auto objectMapper = oatpp::parser::json::mapping::ObjectMapper::createShared();
auto objectMapper = std::make_shared<oatpp::json::ObjectMapper>();
// Register swagger components
SwaggerComponent swaggerComponent;
@ -71,7 +71,7 @@ void AsyncControllerTest::onRun() {
auto swaggerController = oatpp::swagger::AsyncController::createShared(docEndpoints);
// TODO test generated document here
OATPP_LOGV(TAG, "TODO implement test");
OATPP_LOGv(TAG, "TODO implement test");
}

View File

@ -7,8 +7,8 @@
#include "test-controllers/TestController.hpp"
#include "oatpp-swagger/Controller.hpp"
#include "oatpp/parser/json/mapping/ObjectMapper.hpp"
#include "oatpp/core/data/stream/BufferStream.hpp"
#include "oatpp/json/ObjectMapper.hpp"
#include "oatpp/data/stream/BufferStream.hpp"
#include <iostream>
@ -68,7 +68,7 @@ void ControllerTest::onRun() {
oatpp::data::stream::BufferOutputStream responseBuffer;
// Create ObjectMapper
auto objectMapper = oatpp::parser::json::mapping::ObjectMapper::createShared();
auto objectMapper = std::make_shared<oatpp::json::ObjectMapper>();
// Register swagger components
SwaggerComponent swaggerComponent;
@ -94,13 +94,13 @@ void ControllerTest::onRun() {
auto responseText = stream.toString();
oatpp::parser::Caret caret(responseText);
utils::parser::Caret caret(responseText);
caret.findChar('{');
auto document = objectMapper->readFromCaret<oatpp::Object<oatpp::swagger::oas3::Document>>(caret);
if (caret.hasError()) {
OATPP_LOGD(TAG, "error='%s', pos=%d", caret.getErrorMessage(), caret.getPosition());
OATPP_LOGd(TAG, "error='{}', pos={}", caret.getErrorMessage(), caret.getPosition());
}
OATPP_ASSERT(caret.hasError() == false);
@ -115,12 +115,12 @@ void ControllerTest::onRun() {
response->send(&stream, &responseBuffer, nullptr);
auto responseText = stream.toString();
OATPP_LOGD(TAG, responseText->c_str());
OATPP_LOGd(TAG, responseText);
}
// TODO test generated document here
OATPP_LOGV(TAG, "TODO implement test");
OATPP_LOGv(TAG, "TODO implement test");
}

View File

@ -7,8 +7,8 @@
#define oatpp_swagger_test_TestAsyncController_hpp
#include "oatpp/web/server/api/ApiController.hpp"
#include "oatpp/core/macro/codegen.hpp"
#include "oatpp/core/macro/component.hpp"
#include "oatpp/macro/codegen.hpp"
#include "oatpp/macro/component.hpp"
// DTO //-----------------------------------------------------------------------------
@ -122,7 +122,9 @@ public:
ENDPOINT_ASYNC_INIT(EchoDtoBody)
Action act() override {
return request->readBodyToDtoAsync<oatpp::Object<MessageDto>>(controller->getDefaultObjectMapper()).callbackTo(&EchoDtoBody::returnResponse);
return request->readBodyToDtoAsync<oatpp::Object<MessageDto>>(
controller->getContentMappers()->getMapper("application/json")
).callbackTo(&EchoDtoBody::returnResponse);
}
Action returnResponse(const oatpp::Object<MessageDto>& body){

View File

@ -6,12 +6,12 @@
#define OATPP_SWAGGER_TESTCONTROLLER_HPP
#include "oatpp/web/server/api/ApiController.hpp"
#include "oatpp/parser/json/mapping/ObjectMapper.hpp"
#include "oatpp/json/ObjectMapper.hpp"
#include "oatpp/core/data/mapping/type/Object.hpp"
#include "oatpp/data/type/Object.hpp"
#include "oatpp/core/macro/codegen.hpp"
#include "oatpp/core/macro/component.hpp"
#include "oatpp/macro/codegen.hpp"
#include "oatpp/macro/component.hpp"
// DTO //-----------------------------------------------------------------------------
@ -73,7 +73,7 @@ namespace __class {
class PointClass;
}
typedef oatpp::data::mapping::type::Primitive<VPoint, __class::PointClass> Point;
typedef oatpp::data::type::Primitive<VPoint, __class::PointClass> Point;
namespace __class {

View File

@ -11,19 +11,19 @@ void runTests() {
int main() {
oatpp::base::Environment::init();
oatpp::Environment::init();
runTests();
/* 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";
std::cout << "objectsCount = " << oatpp::Environment::getObjectsCount() << "\n";
std::cout << "objectsCreated = " << oatpp::Environment::getObjectsCreated() << "\n\n";
OATPP_ASSERT(oatpp::base::Environment::getObjectsCount() == 0);
OATPP_ASSERT(oatpp::Environment::getObjectsCount() == 0);
oatpp::base::Environment::destroy();
oatpp::Environment::destroy();
return 0;
}