From 08fe1d1f8317ace589d9052daeb76f7d88a67383 Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 27 May 2021 15:25:15 +0200 Subject: [PATCH 001/125] First setup of extreme carpaccio client --- clients/cpp/.gitignore | 709 ++++++++++++++++++ clients/cpp/CMakeLists.txt | 80 ++ clients/cpp/TODOLIST.md | 7 + clients/cpp/cmake/CPM.cmake | 507 +++++++++++++ clients/cpp/cmake/FindGoogleTest.cmake | 8 + clients/cpp/cmake/FindNlohmannJson.cmake | 14 + clients/cpp/cpp_easy_setup.bat | 49 ++ clients/cpp/cpp_easy_setup.sh | 85 +++ .../ExtremeCarpaccioClient.hpp | 11 + .../extreme_carpaccio_client/config.hpp | 14 + .../ExtremeCarpaccioClient.cpp | 51 ++ clients/cpp/src/main.cpp | 6 + .../cpp/test/ExtremeCarpaccioClientTest.cpp | 113 +++ 13 files changed, 1654 insertions(+) create mode 100644 clients/cpp/.gitignore create mode 100644 clients/cpp/CMakeLists.txt create mode 100644 clients/cpp/TODOLIST.md create mode 100644 clients/cpp/cmake/CPM.cmake create mode 100644 clients/cpp/cmake/FindGoogleTest.cmake create mode 100644 clients/cpp/cmake/FindNlohmannJson.cmake create mode 100644 clients/cpp/cpp_easy_setup.bat create mode 100644 clients/cpp/cpp_easy_setup.sh create mode 100644 clients/cpp/include/extreme_carpaccio_client/ExtremeCarpaccioClient.hpp create mode 100644 clients/cpp/include/extreme_carpaccio_client/config.hpp create mode 100644 clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp create mode 100644 clients/cpp/src/main.cpp create mode 100644 clients/cpp/test/ExtremeCarpaccioClientTest.cpp diff --git a/clients/cpp/.gitignore b/clients/cpp/.gitignore new file mode 100644 index 00000000..55846b24 --- /dev/null +++ b/clients/cpp/.gitignore @@ -0,0 +1,709 @@ + +# --------------------------------------------------------- +# Specific adjutments +# --------------------------------------------------------- + +# Intellij - ignore entirely .idea folder +**/.idea/** + +# ApprovalTests - generated golden master files +GoldenMasterTest.*.txt +*.txt.bak + +# --------------------------------------------------------- +# End of specific adjutments +# --------------------------------------------------------- + + +# Created by https://www.toptal.com/developers/gitignore/api/java,maven,eclipse,intellij,visualstudio,gradle,cmake,visualstudiocode,code-java,clion,diff +# Edit at https://www.toptal.com/developers/gitignore?templates=java,maven,eclipse,intellij,visualstudio,gradle,cmake,visualstudiocode,code-java,clion,diff + +### CLion ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +.idea/artifacts +.idea/compiler.xml +.idea/jarRepositories.xml +.idea/modules.xml +.idea/*.iml +.idea/modules +*.iml +*.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +### CLion Patch ### +# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 + +# *.iml +# modules.xml +# .idea/misc.xml +# *.ipr + +# Sonarlint plugin +# https://plugins.jetbrains.com/plugin/7973-sonarlint +.idea/**/sonarlint/ + +# SonarQube Plugin +# https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin +.idea/**/sonarIssues.xml + +# Markdown Navigator plugin +# https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced +.idea/**/markdown-navigator.xml +.idea/**/markdown-navigator-enh.xml +.idea/**/markdown-navigator/ + +# Cache file creation bug +# See https://youtrack.jetbrains.com/issue/JBR-2257 +.idea/$CACHE_FILE$ + +# CodeStream plugin +# https://plugins.jetbrains.com/plugin/12206-codestream +.idea/codestream.xml + +### CMake ### +CMakeLists.txt.user +CMakeCache.txt +CMakeFiles +CMakeScripts +Testing +Makefile +cmake_install.cmake +install_manifest.txt +compile_commands.json +CTestTestfile.cmake +_deps + +### CMake Patch ### +# External projects +*-prefix/ + +### Code-Java ### +# Language Support for Java(TM) by Red Hat extension for Visual Studio Code - https://marketplace.visualstudio.com/items?itemName=redhat.java + +.project +.classpath +factoryConfiguration.json + +### Diff ### +*.patch +*.diff + +### Eclipse ### +.metadata +bin/ +tmp/ +*.tmp +*.bak +*.swp +*~.nib +local.properties +.settings/ +.loadpath +.recommenders + +# External tool builders +.externalToolBuilders/ + +# Locally stored "Eclipse launch configurations" +*.launch + +# PyDev specific (Python IDE for Eclipse) +*.pydevproject + +# CDT-specific (C/C++ Development Tooling) +.cproject + +# CDT- autotools +.autotools + +# Java annotation processor (APT) +.factorypath + +# PDT-specific (PHP Development Tools) +.buildpath + +# sbteclipse plugin +.target + +# Tern plugin +.tern-project + +# TeXlipse plugin +.texlipse + +# STS (Spring Tool Suite) +.springBeans + +# Code Recommenders +.recommenders/ + +# Annotation Processing +.apt_generated/ +.apt_generated_test/ + +# Scala IDE specific (Scala & Java development for Eclipse) +.cache-main +.scala_dependencies +.worksheet + +# Uncomment this line if you wish to ignore the project description file. +# Typically, this file would be tracked if it contains build/dependency configurations: +#.project + +### Eclipse Patch ### +# Spring Boot Tooling +.sts4-cache/ + +### Intellij ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff + +# Generated files + +# Sensitive or high-churn files + +# Gradle + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/artifacts +# .idea/compiler.xml +# .idea/jarRepositories.xml +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake + +# Mongo Explorer plugin + +# File-based project format + +# IntelliJ + +# mpeltonen/sbt-idea plugin + +# JIRA plugin + +# Cursive Clojure plugin + +# Crashlytics plugin (for Android Studio and IntelliJ) + +# Editor-based Rest Client + +# Android studio 3.1+ serialized cache file + +### Intellij Patch ### +# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 + +# *.iml +# modules.xml +# .idea/misc.xml +# *.ipr + +# Sonarlint plugin +# https://plugins.jetbrains.com/plugin/7973-sonarlint + +# SonarQube Plugin +# https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin + +# Markdown Navigator plugin +# https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced + +# Cache file creation bug +# See https://youtrack.jetbrains.com/issue/JBR-2257 + +# CodeStream plugin +# https://plugins.jetbrains.com/plugin/12206-codestream + +### Java ### +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + +### Maven ### +target/ +pom.xml.tag +pom.xml.releaseBackup +pom.xml.versionsBackup +pom.xml.next +release.properties +dependency-reduced-pom.xml +buildNumber.properties +.mvn/timing.properties +# https://github.com/takari/maven-wrapper#usage-without-binary-jar +.mvn/wrapper/maven-wrapper.jar + +### VisualStudioCode ### +.vscode/* +!.vscode/tasks.json +!.vscode/launch.json +*.code-workspace + +### VisualStudioCode Patch ### +# Ignore all local history of files +.history +.ionide + +### Gradle ### +.gradle +build/ + +# Ignore Gradle GUI config +gradle-app.setting + +# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) +!gradle-wrapper.jar + +# Cache of project +.gradletasknamecache + +# # Work around https://youtrack.jetbrains.com/issue/IDEA-116898 +# gradle/wrapper/gradle-wrapper.properties + +### Gradle Patch ### +**/build/ + +### VisualStudio ### +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp_proj +*_wpftmp.csproj +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*[.json, .xml, .info] + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# End of https://www.toptal.com/developers/gitignore/api/java,maven,eclipse,intellij,visualstudio,gradle,cmake,visualstudiocode,code-java,clion,diff + + diff --git a/clients/cpp/CMakeLists.txt b/clients/cpp/CMakeLists.txt new file mode 100644 index 00000000..3b21ede7 --- /dev/null +++ b/clients/cpp/CMakeLists.txt @@ -0,0 +1,80 @@ +cmake_minimum_required(VERSION 3.19.3) + +project(Extreme-Carpaccio-Client CXX) + +set(CMAKE_CXX_STANDARD 14) +enable_testing() + +set_property(GLOBAL PROPERTY USE_FOLDERS ON) + +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib CACHE PATH "Where to place compiled static libraries.") +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib CACHE PATH "Where to place compiled shared libraries.") +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin CACHE PATH "Where to place compiled executables.") + +# We use CPM for 3rd-party dependencies management +include(cmake/CPM.cmake) +include(cmake/FindGoogleTest.cmake) +include(cmake/FindNlohmannJson.cmake) + +#Shared library +add_library(Extreme-Carpaccio-Client-shared SHARED) + +target_compile_definitions(Extreme-Carpaccio-Client-shared PRIVATE EXTREME_CARPACCIO_CLIENT_EXPORTS) + +target_sources(Extreme-Carpaccio-Client-shared + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp + PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/include/extreme_carpaccio_client/ExtremeCarpaccioClient.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/include/extreme_carpaccio_client/config.hpp +) + +target_include_directories(Extreme-Carpaccio-Client-shared + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/src + PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/include +) + +# Client executable +add_executable(Extreme-Carpaccio-Client) + +target_sources(Extreme-Carpaccio-Client + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/src/main.cpp +) + +target_link_libraries(Extreme-Carpaccio-Client + PRIVATE + Extreme-Carpaccio-Client-shared) + +# Test executable +add_executable(Extreme-Carpaccio-Client-test) + +target_sources(Extreme-Carpaccio-Client-test + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/test/ExtremeCarpaccioClientTest.cpp +) + +target_link_libraries(Extreme-Carpaccio-Client-test + PRIVATE + Extreme-Carpaccio-Client-shared + gtest_main) + +add_test(NAME ctest-Extreme-Carpaccio-Client COMMAND Extreme-Carpaccio-Client-test) + +#Globals +add_custom_target(Docs + SOURCES + ../README.md) + +set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT Extreme-Carpaccio-Client-test) +set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY XCODE_STARTUP_PROJECT Extreme-Carpaccio-Client-test) + +set_property(TARGET Extreme-Carpaccio-Client-shared PROPERTY FOLDER "ExtremeCarpaccioClient") +set_property(TARGET Extreme-Carpaccio-Client-test PROPERTY FOLDER "ExtremeCarpaccioClient") +set_property(TARGET Docs PROPERTY FOLDER "ExtremeCarpaccioClient") + +set_property(TARGET gtest gtest_main PROPERTY FOLDER "Third-Party/GoogleTest") + +set_property(GLOBAL PROPERTY PREDEFINED_TARGETS_FOLDER "CMake Generated") diff --git a/clients/cpp/TODOLIST.md b/clients/cpp/TODOLIST.md new file mode 100644 index 00000000..6c001ad7 --- /dev/null +++ b/clients/cpp/TODOLIST.md @@ -0,0 +1,7 @@ +# TO DO LIST + + + +## PARKING +- [ ] Clean gitignore file in cpp +- [ ] Ajouter dans le cmake le Json en thirdparty pour la soluation VS \ No newline at end of file diff --git a/clients/cpp/cmake/CPM.cmake b/clients/cpp/cmake/CPM.cmake new file mode 100644 index 00000000..625712e5 --- /dev/null +++ b/clients/cpp/cmake/CPM.cmake @@ -0,0 +1,507 @@ +# CPM.cmake - CMake's missing package manager +# =========================================== +# See https://github.com/TheLartians/CPM.cmake for usage and update instructions. +# +# MIT License +# ----------- +#[[ + Copyright (c) 2019 Lars Melchior + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +]] + +cmake_minimum_required(VERSION 3.14 FATAL_ERROR) + +set(CURRENT_CPM_VERSION 0.27.5) + +if(CPM_DIRECTORY) + if(NOT CPM_DIRECTORY STREQUAL CMAKE_CURRENT_LIST_DIR) + if (CPM_VERSION VERSION_LESS CURRENT_CPM_VERSION) + message(AUTHOR_WARNING "${CPM_INDENT} \ +A dependency is using a more recent CPM version (${CURRENT_CPM_VERSION}) than the current project (${CPM_VERSION}). \ +It is recommended to upgrade CPM to the most recent version. \ +See https://github.com/TheLartians/CPM.cmake for more information." + ) + endif() + return() + endif() + + get_property(CPM_INITIALIZED GLOBAL "" PROPERTY CPM_INITIALIZED SET) + if (CPM_INITIALIZED) + return() + endif() +endif() + +set_property(GLOBAL PROPERTY CPM_INITIALIZED true) + +option(CPM_USE_LOCAL_PACKAGES "Always try to use `find_package` to get dependencies" $ENV{CPM_USE_LOCAL_PACKAGES}) +option(CPM_LOCAL_PACKAGES_ONLY "Only use `find_package` to get dependencies" $ENV{CPM_LOCAL_PACKAGES_ONLY}) +option(CPM_DOWNLOAD_ALL "Always download dependencies from source" $ENV{CPM_DOWNLOAD_ALL}) +option(CPM_DONT_UPDATE_MODULE_PATH "Don't update the module path to allow using find_package" $ENV{CPM_DONT_UPDATE_MODULE_PATH}) +option(CPM_DONT_CREATE_PACKAGE_LOCK "Don't create a package lock file in the binary path" $ENV{CPM_DONT_CREATE_PACKAGE_LOCK}) +option(CPM_INCLUDE_ALL_IN_PACKAGE_LOCK "Add all packages added through CPM.cmake to the package lock" $ENV{CPM_INCLUDE_ALL_IN_PACKAGE_LOCK}) + +set(CPM_VERSION ${CURRENT_CPM_VERSION} CACHE INTERNAL "") +set(CPM_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} CACHE INTERNAL "") +set(CPM_FILE ${CMAKE_CURRENT_LIST_FILE} CACHE INTERNAL "") +set(CPM_PACKAGES "" CACHE INTERNAL "") +set(CPM_DRY_RUN OFF CACHE INTERNAL "Don't download or configure dependencies (for testing)") + +if(DEFINED ENV{CPM_SOURCE_CACHE}) + set(CPM_SOURCE_CACHE_DEFAULT $ENV{CPM_SOURCE_CACHE}) +else() + set(CPM_SOURCE_CACHE_DEFAULT OFF) +endif() + +set(CPM_SOURCE_CACHE ${CPM_SOURCE_CACHE_DEFAULT} CACHE PATH "Directory to downlaod CPM dependencies") + +if (NOT CPM_DONT_UPDATE_MODULE_PATH) + set(CPM_MODULE_PATH "${CMAKE_BINARY_DIR}/CPM_modules" CACHE INTERNAL "") + # remove old modules + FILE(REMOVE_RECURSE ${CPM_MODULE_PATH}) + file(MAKE_DIRECTORY ${CPM_MODULE_PATH}) + # locally added CPM modules should override global packages + set(CMAKE_MODULE_PATH "${CPM_MODULE_PATH};${CMAKE_MODULE_PATH}") +endif() + +if (NOT CPM_DONT_CREATE_PACKAGE_LOCK) + set(CPM_PACKAGE_LOCK_FILE "${CMAKE_BINARY_DIR}/cpm-package-lock.cmake" CACHE INTERNAL "") + file(WRITE ${CPM_PACKAGE_LOCK_FILE} "# CPM Package Lock\n# This file should be committed to version control\n\n") +endif() + +include(FetchContent) +include(CMakeParseArguments) + +# Initialize logging prefix +if(NOT CPM_INDENT) + set(CPM_INDENT "CPM:") +endif() + +function(cpm_find_package NAME VERSION) + string(REPLACE " " ";" EXTRA_ARGS "${ARGN}") + find_package(${NAME} ${VERSION} ${EXTRA_ARGS} QUIET) + if(${CPM_ARGS_NAME}_FOUND) + message(STATUS "${CPM_INDENT} using local package ${CPM_ARGS_NAME}@${VERSION}") + CPMRegisterPackage(${CPM_ARGS_NAME} "${VERSION}") + set(CPM_PACKAGE_FOUND YES PARENT_SCOPE) + else() + set(CPM_PACKAGE_FOUND NO PARENT_SCOPE) + endif() +endfunction() + +# Create a custom FindXXX.cmake module for a CPM package +# This prevents `find_package(NAME)` from finding the system library +function(CPMCreateModuleFile Name) + if (NOT CPM_DONT_UPDATE_MODULE_PATH) + # erase any previous modules + FILE(WRITE ${CPM_MODULE_PATH}/Find${Name}.cmake "include(${CPM_FILE})\n${ARGN}\nset(${Name}_FOUND TRUE)") + endif() +endfunction() + +# Find a package locally or fallback to CPMAddPackage +function(CPMFindPackage) + set(oneValueArgs + NAME + VERSION + GIT_TAG + FIND_PACKAGE_ARGUMENTS + ) + + cmake_parse_arguments(CPM_ARGS "" "${oneValueArgs}" "" ${ARGN}) + + if (NOT DEFINED CPM_ARGS_VERSION) + if (DEFINED CPM_ARGS_GIT_TAG) + cpm_get_version_from_git_tag("${CPM_ARGS_GIT_TAG}" CPM_ARGS_VERSION) + endif() + endif() + + if (CPM_DOWNLOAD_ALL) + CPMAddPackage(${ARGN}) + cpm_export_variables(${CPM_ARGS_NAME}) + return() + endif() + + CPMCheckIfPackageAlreadyAdded(${CPM_ARGS_NAME} "${CPM_ARGS_VERSION}" "${CPM_ARGS_OPTIONS}") + if (CPM_PACKAGE_ALREADY_ADDED) + cpm_export_variables(${CPM_ARGS_NAME}) + return() + endif() + + cpm_find_package(${CPM_ARGS_NAME} "${CPM_ARGS_VERSION}" ${CPM_ARGS_FIND_PACKAGE_ARGUMENTS}) + + if(NOT CPM_PACKAGE_FOUND) + CPMAddPackage(${ARGN}) + cpm_export_variables(${CPM_ARGS_NAME}) + endif() + +endfunction() + +# checks if a package has been added before +function(CPMCheckIfPackageAlreadyAdded CPM_ARGS_NAME CPM_ARGS_VERSION CPM_ARGS_OPTIONS) + if ("${CPM_ARGS_NAME}" IN_LIST CPM_PACKAGES) + CPMGetPackageVersion(${CPM_ARGS_NAME} CPM_PACKAGE_VERSION) + if("${CPM_PACKAGE_VERSION}" VERSION_LESS "${CPM_ARGS_VERSION}") + message(WARNING "${CPM_INDENT} requires a newer version of ${CPM_ARGS_NAME} (${CPM_ARGS_VERSION}) than currently included (${CPM_PACKAGE_VERSION}).") + endif() + if (CPM_ARGS_OPTIONS) + foreach(OPTION ${CPM_ARGS_OPTIONS}) + cpm_parse_option(${OPTION}) + if(NOT "${${OPTION_KEY}}" STREQUAL "${OPTION_VALUE}") + message(WARNING "${CPM_INDENT} ignoring package option for ${CPM_ARGS_NAME}: ${OPTION_KEY} = ${OPTION_VALUE} (${${OPTION_KEY}})") + endif() + endforeach() + endif() + cpm_get_fetch_properties(${CPM_ARGS_NAME}) + SET(${CPM_ARGS_NAME}_ADDED NO) + SET(CPM_PACKAGE_ALREADY_ADDED YES PARENT_SCOPE) + cpm_export_variables(${CPM_ARGS_NAME}) + else() + SET(CPM_PACKAGE_ALREADY_ADDED NO PARENT_SCOPE) + endif() +endfunction() + +# Download and add a package from source +function(CPMAddPackage) + + set(oneValueArgs + NAME + FORCE + VERSION + GIT_TAG + DOWNLOAD_ONLY + GITHUB_REPOSITORY + GITLAB_REPOSITORY + GIT_REPOSITORY + SOURCE_DIR + DOWNLOAD_COMMAND + FIND_PACKAGE_ARGUMENTS + NO_CACHE + GIT_SHALLOW + ) + + set(multiValueArgs + OPTIONS + ) + + cmake_parse_arguments(CPM_ARGS "" "${oneValueArgs}" "${multiValueArgs}" "${ARGN}") + + # Set default values for arguments + + if (NOT DEFINED CPM_ARGS_VERSION) + if (DEFINED CPM_ARGS_GIT_TAG) + cpm_get_version_from_git_tag("${CPM_ARGS_GIT_TAG}" CPM_ARGS_VERSION) + endif() + endif() + + if(CPM_ARGS_DOWNLOAD_ONLY) + set(DOWNLOAD_ONLY ${CPM_ARGS_DOWNLOAD_ONLY}) + else() + set(DOWNLOAD_ONLY NO) + endif() + + if (DEFINED CPM_ARGS_GITHUB_REPOSITORY) + set(CPM_ARGS_GIT_REPOSITORY "https://github.com/${CPM_ARGS_GITHUB_REPOSITORY}.git") + endif() + + if (DEFINED CPM_ARGS_GITLAB_REPOSITORY) + set(CPM_ARGS_GIT_REPOSITORY "https://gitlab.com/${CPM_ARGS_GITLAB_REPOSITORY}.git") + endif() + + if (DEFINED CPM_ARGS_GIT_REPOSITORY) + list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS GIT_REPOSITORY ${CPM_ARGS_GIT_REPOSITORY}) + if (NOT DEFINED CPM_ARGS_GIT_TAG) + set(CPM_ARGS_GIT_TAG v${CPM_ARGS_VERSION}) + endif() + endif() + + if (DEFINED CPM_ARGS_GIT_TAG) + list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS GIT_TAG ${CPM_ARGS_GIT_TAG}) + # If GIT_SHALLOW is explicitly specified, honor the value. + if (DEFINED CPM_ARGS_GIT_SHALLOW) + list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS GIT_SHALLOW ${CPM_ARGS_GIT_SHALLOW}) + endif() + endif() + + # Check if package has been added before + CPMCheckIfPackageAlreadyAdded(${CPM_ARGS_NAME} "${CPM_ARGS_VERSION}" "${CPM_ARGS_OPTIONS}") + if (CPM_PACKAGE_ALREADY_ADDED) + cpm_export_variables(${CPM_ARGS_NAME}) + return() + endif() + + # Check for manual overrides + if (NOT CPM_ARGS_FORCE AND NOT "${CPM_${CPM_ARGS_NAME}_SOURCE}" STREQUAL "") + set(PACKAGE_SOURCE ${CPM_${CPM_ARGS_NAME}_SOURCE}) + set(CPM_${CPM_ARGS_NAME}_SOURCE "") + CPMAddPackage( + NAME ${CPM_ARGS_NAME} + SOURCE_DIR ${PACKAGE_SOURCE} + FORCE True + OPTIONS ${CPM_ARGS_OPTIONS} + ) + cpm_export_variables(${CPM_ARGS_NAME}) + return() + endif() + + # Check for available declaration + if (NOT CPM_ARGS_FORCE AND NOT "${CPM_DECLARATION_${CPM_ARGS_NAME}}" STREQUAL "") + set(declaration ${CPM_DECLARATION_${CPM_ARGS_NAME}}) + set(CPM_DECLARATION_${CPM_ARGS_NAME} "") + CPMAddPackage(${declaration}) + cpm_export_variables(${CPM_ARGS_NAME}) + # checking again to ensure version and option compatibility + CPMCheckIfPackageAlreadyAdded(${CPM_ARGS_NAME} "${CPM_ARGS_VERSION}" "${CPM_ARGS_OPTIONS}") + return() + endif() + + if(CPM_USE_LOCAL_PACKAGES OR CPM_LOCAL_PACKAGES_ONLY) + cpm_find_package(${CPM_ARGS_NAME} "${CPM_ARGS_VERSION}" ${CPM_ARGS_FIND_PACKAGE_ARGUMENTS}) + + if(CPM_PACKAGE_FOUND) + cpm_export_variables(${CPM_ARGS_NAME}) + return() + endif() + + if(CPM_LOCAL_PACKAGES_ONLY) + message(SEND_ERROR "CPM: ${CPM_ARGS_NAME} not found via find_package(${CPM_ARGS_NAME} ${CPM_ARGS_VERSION})") + endif() + endif() + + CPMRegisterPackage("${CPM_ARGS_NAME}" "${CPM_ARGS_VERSION}") + + if (CPM_ARGS_OPTIONS) + foreach(OPTION ${CPM_ARGS_OPTIONS}) + cpm_parse_option(${OPTION}) + set(${OPTION_KEY} ${OPTION_VALUE} CACHE INTERNAL "") + endforeach() + endif() + + if (DEFINED CPM_ARGS_GIT_TAG) + set(PACKAGE_INFO "${CPM_ARGS_GIT_TAG}") + elseif (DEFINED CPM_ARGS_SOURCE_DIR) + set(PACKAGE_INFO "${CPM_ARGS_SOURCE_DIR}") + else() + set(PACKAGE_INFO "${CPM_ARGS_VERSION}") + endif() + + if (DEFINED CPM_ARGS_DOWNLOAD_COMMAND) + list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS DOWNLOAD_COMMAND ${CPM_ARGS_DOWNLOAD_COMMAND}) + elseif (DEFINED CPM_ARGS_SOURCE_DIR) + list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS SOURCE_DIR ${CPM_ARGS_SOURCE_DIR}) + elseif (CPM_SOURCE_CACHE AND NOT CPM_ARGS_NO_CACHE) + string(TOLOWER ${CPM_ARGS_NAME} lower_case_name) + set(origin_parameters ${CPM_ARGS_UNPARSED_ARGUMENTS}) + list(SORT origin_parameters) + string(SHA1 origin_hash "${origin_parameters}") + set(download_directory ${CPM_SOURCE_CACHE}/${lower_case_name}/${origin_hash}) + list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS SOURCE_DIR ${download_directory}) + if (EXISTS ${download_directory}) + # disable the download command to allow offline builds + list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS DOWNLOAD_COMMAND "${CMAKE_COMMAND}") + set(PACKAGE_INFO "${download_directory}") + else() + # Enable shallow clone when GIT_TAG is not a commit hash. + # Our guess may not be accurate, but it should guarantee no commit hash get mis-detected. + if (NOT DEFINED CPM_ARGS_GIT_SHALLOW) + cpm_is_git_tag_commit_hash("${CPM_ARGS_GIT_TAG}" IS_HASH) + if (NOT ${IS_HASH}) + list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS GIT_SHALLOW TRUE) + endif() + endif() + + # remove timestamps so CMake will re-download the dependency + file(REMOVE_RECURSE ${CMAKE_BINARY_DIR}/_deps/${lower_case_name}-subbuild) + set(PACKAGE_INFO "${PACKAGE_INFO} -> ${download_directory}") + endif() + endif() + + CPMCreateModuleFile(${CPM_ARGS_NAME} "CPMAddPackage(${ARGN})") + + if (CPM_PACKAGE_LOCK_ENABLED) + if ((CPM_ARGS_VERSION AND NOT CPM_ARGS_SOURCE_DIR) OR CPM_INCLUDE_ALL_IN_PACKAGE_LOCK) + cpm_add_to_package_lock(${CPM_ARGS_NAME} "${ARGN}") + elseif(CPM_ARGS_SOURCE_DIR) + cpm_add_comment_to_package_lock(${CPM_ARGS_NAME} "local directory") + else() + cpm_add_comment_to_package_lock(${CPM_ARGS_NAME} "${ARGN}") + endif() + endif() + + cpm_declare_fetch("${CPM_ARGS_NAME}" "${CPM_ARGS_VERSION}" "${PACKAGE_INFO}" "${CPM_ARGS_UNPARSED_ARGUMENTS}") + cpm_fetch_package("${CPM_ARGS_NAME}" "${DOWNLOAD_ONLY}") + cpm_get_fetch_properties("${CPM_ARGS_NAME}") + + SET(${CPM_ARGS_NAME}_ADDED YES) + cpm_export_variables("${CPM_ARGS_NAME}") +endfunction() + +# Fetch a previously declared package +macro(CPMGetPackage Name) + if (DEFINED "CPM_DECLARATION_${Name}") + CPMAddPackage( + NAME ${Name} + ) + else() + message(SEND_ERROR "Cannot retrieve package ${Name}: no declaration available") + endif() +endmacro() + +# export variables available to the caller to the parent scope +# expects ${CPM_ARGS_NAME} to be set +macro(cpm_export_variables name) + SET(${name}_SOURCE_DIR "${${name}_SOURCE_DIR}" PARENT_SCOPE) + SET(${name}_BINARY_DIR "${${name}_BINARY_DIR}" PARENT_SCOPE) + SET(${name}_ADDED "${${name}_ADDED}" PARENT_SCOPE) +endmacro() + +# declares a package, so that any call to CPMAddPackage for the +# package name will use these arguments instead. +# Previous declarations will not be overriden. +macro(CPMDeclarePackage Name) + if (NOT DEFINED "CPM_DECLARATION_${Name}") + set("CPM_DECLARATION_${Name}" "${ARGN}") + endif() +endmacro() + +function(cpm_add_to_package_lock Name) + if (NOT CPM_DONT_CREATE_PACKAGE_LOCK) + file(APPEND ${CPM_PACKAGE_LOCK_FILE} "# ${Name}\nCPMDeclarePackage(${Name} \"${ARGN}\")\n") + endif() +endfunction() + +function(cpm_add_comment_to_package_lock Name) + if (NOT CPM_DONT_CREATE_PACKAGE_LOCK) + file(APPEND ${CPM_PACKAGE_LOCK_FILE} "# ${Name} (unversioned)\n# CPMDeclarePackage(${Name} \"${ARGN}\")\n") + endif() +endfunction() + +# includes the package lock file if it exists and creates a target +# `cpm-write-package-lock` to update it +macro(CPMUsePackageLock file) + if (NOT CPM_DONT_CREATE_PACKAGE_LOCK) + get_filename_component(CPM_ABSOLUTE_PACKAGE_LOCK_PATH ${file} ABSOLUTE) + if(EXISTS ${CPM_ABSOLUTE_PACKAGE_LOCK_PATH}) + include(${CPM_ABSOLUTE_PACKAGE_LOCK_PATH}) + endif() + if (NOT TARGET cpm-update-package-lock) + add_custom_target(cpm-update-package-lock COMMAND ${CMAKE_COMMAND} -E copy ${CPM_PACKAGE_LOCK_FILE} ${CPM_ABSOLUTE_PACKAGE_LOCK_PATH}) + endif() + set(CPM_PACKAGE_LOCK_ENABLED true) + endif() +endmacro() + +# registers a package that has been added to CPM +function(CPMRegisterPackage PACKAGE VERSION) + list(APPEND CPM_PACKAGES ${PACKAGE}) + set(CPM_PACKAGES ${CPM_PACKAGES} CACHE INTERNAL "") + set("CPM_PACKAGE_${PACKAGE}_VERSION" ${VERSION} CACHE INTERNAL "") +endfunction() + +# retrieve the current version of the package to ${OUTPUT} +function(CPMGetPackageVersion PACKAGE OUTPUT) + set(${OUTPUT} "${CPM_PACKAGE_${PACKAGE}_VERSION}" PARENT_SCOPE) +endfunction() + +# declares a package in FetchContent_Declare +function (cpm_declare_fetch PACKAGE VERSION INFO) + message(STATUS "${CPM_INDENT} adding package ${PACKAGE}@${VERSION} (${INFO})") + + if (${CPM_DRY_RUN}) + message(STATUS "${CPM_INDENT} package not declared (dry run)") + return() + endif() + + FetchContent_Declare(${PACKAGE} + ${ARGN} + ) +endfunction() + +# returns properties for a package previously defined by cpm_declare_fetch +function (cpm_get_fetch_properties PACKAGE) + if (${CPM_DRY_RUN}) + return() + endif() + FetchContent_GetProperties(${PACKAGE}) + string(TOLOWER ${PACKAGE} lpackage) + SET(${PACKAGE}_SOURCE_DIR "${${lpackage}_SOURCE_DIR}" PARENT_SCOPE) + SET(${PACKAGE}_BINARY_DIR "${${lpackage}_BINARY_DIR}" PARENT_SCOPE) +endfunction() + +# downloads a previously declared package via FetchContent +function (cpm_fetch_package PACKAGE DOWNLOAD_ONLY) + if (${CPM_DRY_RUN}) + message(STATUS "${CPM_INDENT} package ${PACKAGE} not fetched (dry run)") + return() + endif() + + if(DOWNLOAD_ONLY) + FetchContent_GetProperties(${PACKAGE}) + if(NOT ${PACKAGE}_POPULATED) + FetchContent_Populate(${PACKAGE}) + endif() + else() + set(CPM_OLD_INDENT "${CPM_INDENT}") + set(CPM_INDENT "${CPM_INDENT} ${PACKAGE}:") + FetchContent_MakeAvailable(${PACKAGE}) + set(CPM_INDENT "${CPM_OLD_INDENT}") + endif() +endfunction() + +# splits a package option +function(cpm_parse_option OPTION) + string(REGEX MATCH "^[^ ]+" OPTION_KEY ${OPTION}) + string(LENGTH ${OPTION} OPTION_LENGTH) + string(LENGTH ${OPTION_KEY} OPTION_KEY_LENGTH) + if (OPTION_KEY_LENGTH STREQUAL OPTION_LENGTH) + # no value for key provided, assume user wants to set option to "ON" + set(OPTION_VALUE "ON") + else() + math(EXPR OPTION_KEY_LENGTH "${OPTION_KEY_LENGTH}+1") + string(SUBSTRING ${OPTION} "${OPTION_KEY_LENGTH}" "-1" OPTION_VALUE) + endif() + set(OPTION_KEY "${OPTION_KEY}" PARENT_SCOPE) + set(OPTION_VALUE "${OPTION_VALUE}" PARENT_SCOPE) +endfunction() + +# guesses the package version from a git tag +function(cpm_get_version_from_git_tag GIT_TAG RESULT) + string(LENGTH ${GIT_TAG} length) + if (length EQUAL 40) + # GIT_TAG is probably a git hash + SET(${RESULT} 0 PARENT_SCOPE) + else() + string(REGEX MATCH "v?([0123456789.]*).*" _ ${GIT_TAG}) + SET(${RESULT} ${CMAKE_MATCH_1} PARENT_SCOPE) + endif() +endfunction() + +# guesses if the git tag is a commit hash or an actual tag or a branch nane. +function(cpm_is_git_tag_commit_hash GIT_TAG RESULT) + string(LENGTH "${GIT_TAG}" length) + # full hash has 40 characters, and short hash has at least 7 characters. + if (length LESS 7 OR length GREATER 40) + SET(${RESULT} 0 PARENT_SCOPE) + else() + if (${GIT_TAG} MATCHES "^[a-fA-F0-9]+$") + SET(${RESULT} 1 PARENT_SCOPE) + else() + SET(${RESULT} 0 PARENT_SCOPE) + endif() + endif() +endfunction() diff --git a/clients/cpp/cmake/FindGoogleTest.cmake b/clients/cpp/cmake/FindGoogleTest.cmake new file mode 100644 index 00000000..739cfe0d --- /dev/null +++ b/clients/cpp/cmake/FindGoogleTest.cmake @@ -0,0 +1,8 @@ +# Fetch googletest + +CPMFindPackage( + NAME googletest + GITHUB_REPOSITORY google/googletest + GIT_TAG master + OPTIONS "INSTALL_GTEST OFF" "gtest_force_shared_crt" "BUILD_GMOCK OFF" +) \ No newline at end of file diff --git a/clients/cpp/cmake/FindNlohmannJson.cmake b/clients/cpp/cmake/FindNlohmannJson.cmake new file mode 100644 index 00000000..b62ef379 --- /dev/null +++ b/clients/cpp/cmake/FindNlohmannJson.cmake @@ -0,0 +1,14 @@ +# Fetch nlohmann_json + +CPMFindPackage( + NAME nlohmann_json + VERSION 3.6.1 + # the git repo is incredibly large, so we download the archived include directory + URL https://github.com/nlohmann/json/releases/download/v3.6.1/include.zip + URL_HASH SHA256=69cc88207ce91347ea530b227ff0776db82dcb8de6704e1a3d74f4841bc651cf +) + +if (nlohmann_json_ADDED) + add_library(nlohmann_json INTERFACE IMPORTED) + target_include_directories(nlohmann_json INTERFACE ${nlohmann_json_SOURCE_DIR}) +endif() \ No newline at end of file diff --git a/clients/cpp/cpp_easy_setup.bat b/clients/cpp/cpp_easy_setup.bat new file mode 100644 index 00000000..195f2977 --- /dev/null +++ b/clients/cpp/cpp_easy_setup.bat @@ -0,0 +1,49 @@ + +setlocal + +set OS=win64 +set ARCH=x64 +set ARCHIVE_EXTENSION=zip +set CMAKE_BIN_DIR=bin +set CMAKE=cmake.exe +set CTEST=ctest.exe +set CMAKE_GENERATOR_OPTIONS=-G "Visual Studio 15 2017 Win64" + +set CMAKE_VERSION=3.19.3 +set CMAKE_EXPECTED_DIR=cmake-%CMAKE_VERSION%-%OS%-%ARCH% +set CMAKE_EXPECTED_ARCHIVE_FILE=%CMAKE_EXPECTED_DIR%.%ARCHIVE_EXTENSION% +set CMAKE_ARCHIVE_URL="http://github.com/Kitware/CMake/releases/download/v%CMAKE_VERSION%/%CMAKE_EXPECTED_ARCHIVE_FILE%" +set CMAKE_HOME=cmake-%OS%-%ARCH% + +set BUILD_DIR=build +if not exist %BUILD_DIR% ( + mkdir %BUILD_DIR% +) +pushd %BUILD_DIR% + +set CMAKE_BUILD_DIR=cmake +if not exist %CMAKE_BUILD_DIR% ( + mkdir %CMAKE_BUILD_DIR% +) +pushd %CMAKE_BUILD_DIR% + +if not exist %CMAKE_EXPECTED_ARCHIVE_FILE% ( + powershell -command "Invoke-WebRequest %CMAKE_ARCHIVE_URL% -OutFile %CMAKE_EXPECTED_ARCHIVE_FILE%" + powershell -command "Expand-Archive -Force '%~dp0\%BUILD_DIR%\%CMAKE_BUILD_DIR%\%CMAKE_EXPECTED_ARCHIVE_FILE%' '%~dp0\%BUILD_DIR%\%CMAKE_BUILD_DIR%'" + powershell -command "Rename-Item %CMAKE_EXPECTED_DIR% %CMAKE_HOME%" +) + +pushd .. + +set CMAKE_BIN_PATH=%CMAKE_BUILD_DIR%\%CMAKE_HOME%\%CMAKE_BIN_DIR% + +%CMAKE_BIN_PATH%\%CMAKE% %CMAKE_GENERATOR_OPTIONS% -S .. -B . +%CMAKE_BIN_PATH%\%CMAKE% --build . --config Debug +%CMAKE_BIN_PATH%\%CTEST% --output-on-failure -C Debug + +popd + +popd + +popd + diff --git a/clients/cpp/cpp_easy_setup.sh b/clients/cpp/cpp_easy_setup.sh new file mode 100644 index 00000000..bb9e05e8 --- /dev/null +++ b/clients/cpp/cpp_easy_setup.sh @@ -0,0 +1,85 @@ +#!/usr/bin/env sh + +set -eu + +case $(uname -s) in +Darwin) + os="macos" + arch="universal" + archive_extension="tar.gz" + cmake_bin_dir="CMake.app/Contents/bin" + cmake="cmake" + ctest="ctest" + cmake_generator_options="-G \"Xcode\"" + ;; +Linux) + os="Linux" + arch="x86_64" + archive_extension="tar.gz" + cmake_bin_dir="bin" + cmake="cmake" + ctest="ctest" + cmake_generator_options="-G \"Unix Makefiles\"" + ;; +MINGW64_NT-*) + os="win64" + arch="x64" + archive_extension="zip" + cmake_bin_dir="bin" + cmake="cmake.exe" + ctest="ctest.exe" + cmake_generator_options="-G \"Visual Studio 15 2017 Win64\"" + ;; +*) + echo "os $(uname -s) is currently not supported." + exit 1 + ;; +esac + +base_dir=$(dirname -- "$0") +cd "${base_dir}" + +cmake_version="3.19.3" +cmake_expected_dir="cmake-${cmake_version}-${os}-${arch}" +cmake_expected_archive_file="${cmake_expected_dir}.${archive_extension}" +cmake_archive_url="http://github.com/Kitware/CMake/releases/download/v${cmake_version}/${cmake_expected_archive_file}" +cmake_home="cmake-${os}-${arch}" + +build_dir="build" +mkdir -p "${build_dir}" +cd "${build_dir}" + +cmake_build_dir="cmake" +mkdir -p "${cmake_build_dir}" +cd "${cmake_build_dir}" + +if ! [ -f "${cmake_expected_archive_file}" ] +then + echo "-- Downloading ${cmake_expected_archive_file}" + curl -# -L "${cmake_archive_url}" -o "${cmake_expected_archive_file}" + + echo "-- Extracting cmake ${cmake_version}" + case "${archive_extension}" in + zip) + unzip -q -o "${cmake_expected_archive_file}" + ;; + tar.gz) + tar zxf "${cmake_expected_archive_file}" + ;; + *) + echo "Archive format ${archive_extension} is currently not supported." + exit 1 + ;; + esac + + [ -d "${cmake_home}" ] && rm -Rf "${cmake_home}" + mv "${cmake_expected_dir}" "${cmake_home}" +fi + +cd .. + +cmake_bin_path="${cmake_build_dir}/${cmake_home}/${cmake_bin_dir}" + +eval ${cmake_bin_path}/${cmake} "${cmake_generator_options}" -S .. -B . +${cmake_bin_path}/${cmake} --build . --config Debug +${cmake_bin_path}/${ctest} --output-on-failure -C Debug diff --git a/clients/cpp/include/extreme_carpaccio_client/ExtremeCarpaccioClient.hpp b/clients/cpp/include/extreme_carpaccio_client/ExtremeCarpaccioClient.hpp new file mode 100644 index 00000000..dde16240 --- /dev/null +++ b/clients/cpp/include/extreme_carpaccio_client/ExtremeCarpaccioClient.hpp @@ -0,0 +1,11 @@ + +#include + +#include + +namespace kata { +namespace bowling_game { + EXTREME_CARPACCIO_CLIENT_API int bowlingScore(const std::vector & rolls); + +} // namespace bowling_game +} // namespace kata diff --git a/clients/cpp/include/extreme_carpaccio_client/config.hpp b/clients/cpp/include/extreme_carpaccio_client/config.hpp new file mode 100644 index 00000000..d73dbe0f --- /dev/null +++ b/clients/cpp/include/extreme_carpaccio_client/config.hpp @@ -0,0 +1,14 @@ +#ifndef EXTREME_CARPACCIO_CLIENT_CONFIG +#define EXTREME_CARPACCIO_CLIENT_CONFIG + +#ifdef _MSC_VER +#ifdef EXTREME_CARPACCIO_CLIENT_EXPORTS +#define EXTREME_CARPACCIO_CLIENT_API __declspec(dllexport) +#else +#define EXTREME_CARPACCIO_CLIENT_API __declspec(dllimport) +#endif +#else +#define EXTREME_CARPACCIO_CLIENT_API +#endif + +#endif // EXTREME_CARPACCIO_CLIENT_CONFIG diff --git a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp new file mode 100644 index 00000000..48512d26 --- /dev/null +++ b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp @@ -0,0 +1,51 @@ + +#include + +#include +#include + +namespace kata { +namespace bowling_game { + +const size_t TOTAL_PINS = 10; +const size_t TOTAL_FRAMES = 10; + +static bool isSpare(const std::vector & rolls, size_t frameIndex) +{ + return rolls[frameIndex] + rolls[frameIndex + 1] == TOTAL_PINS; +} + +static bool isStrike(const std::vector& rolls, size_t frameIndex) +{ + return rolls[frameIndex] == TOTAL_PINS; +} + +int bowlingScore(const std::vector & rolls) +{ + int score = 0; + size_t frameIndex = 0; + + for(size_t frame = 0; frame < TOTAL_FRAMES; ++frame) + { + if(isStrike(rolls, frameIndex)) + { + score += TOTAL_PINS + rolls[frameIndex+1] + rolls[frameIndex+2]; + frameIndex++; + } + else if (isSpare(rolls, frameIndex)) + { + score += TOTAL_PINS + rolls[frameIndex+2]; + frameIndex += 2; + } + else + { + score += rolls[frameIndex] + rolls[frameIndex + 1]; + frameIndex += 2; + } + } + + return score; +} + +} // namespace bowling_game +} // namespace kata diff --git a/clients/cpp/src/main.cpp b/clients/cpp/src/main.cpp new file mode 100644 index 00000000..e6b9bb0f --- /dev/null +++ b/clients/cpp/src/main.cpp @@ -0,0 +1,6 @@ + + +int main() +{ + +} \ No newline at end of file diff --git a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp new file mode 100644 index 00000000..72de4a57 --- /dev/null +++ b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp @@ -0,0 +1,113 @@ + +#include + +#include + +#include + +using namespace kata::bowling_game; + +TEST(BowlingGame, acceptance_test) +{ + EXPECT_EQ(133, bowlingScore(std::vector{1, 4, 4, 5, 6, 4, 5, 5, 10, 0, 1, 7, 3, 6, 4, 10, 2, 8, 6})); +} + +TEST(BowlingGame, one_pin_at_first) +{ + EXPECT_EQ(1, bowlingScore(std::vector{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})); +} + +TEST(BowlingGame, gutter_game) +{ + EXPECT_EQ(0, bowlingScore(std::vector{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})); +} + +TEST(BowlingGame, several_pins_at_first) +{ + EXPECT_EQ(6, bowlingScore(std::vector{6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})); +} + +TEST(BowlingGame, several_pins_at_second_roll) +{ + EXPECT_EQ(5, bowlingScore(std::vector{0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})); +} + +TEST(BowlingGame, several_pins_at_first_2_rolls) +{ + EXPECT_EQ(8, bowlingScore(std::vector{3, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})); +} + +TEST(BowlingGame, several_pins_at_last_rolls) +{ + EXPECT_EQ(7, bowlingScore(std::vector{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7})); +} + +TEST(BowlingGame, several_pins_at_first_3_rolls) +{ + EXPECT_EQ(9, bowlingScore(std::vector{1, 3, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})); +} + +TEST(BowlingGame, 3_pins_at_all_rolls) +{ + EXPECT_EQ(60, bowlingScore(std::vector{3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3})); +} + +TEST(BowlingGame, one_spare_at_beginning) +{ + EXPECT_EQ(18, bowlingScore(std::vector{6, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})); +} + +TEST(BowlingGame, another_spare_at_beginning) +{ + EXPECT_EQ(16, bowlingScore(std::vector{5, 5, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})); +} + +TEST(BowlingGame, spare_at_frame_2) +{ + EXPECT_EQ(14, bowlingScore(std::vector{0, 0, 3, 7, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})); +} + +TEST(BowlingGame, spare_at_frame_3) +{ + EXPECT_EQ(24, bowlingScore(std::vector{0, 0, 0, 0, 7, 3, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})); +} + +TEST(BowlingGame, spare_at_last_frame) +{ + EXPECT_EQ(13, bowlingScore(std::vector{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 4, 3})); +} + +TEST(BowlingGame, 5_pins_at_all_rolls) +{ + EXPECT_EQ(150, bowlingScore(std::vector{5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5})); +} + +TEST(BowlingGame, fake_spare_between_first_2_frames) +{ + EXPECT_EQ(11, bowlingScore(std::vector{0, 5, 5, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})); +} + +TEST(BowlingGame, one_strike_at_beginning) +{ + EXPECT_EQ(20, bowlingScore(std::vector{10, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})); +} + +TEST(BowlingGame, another_strike_at_beginning) +{ + EXPECT_EQ(18, bowlingScore(std::vector{10, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})); +} + +TEST(BowlingGame, one_strike_at_frame_2) +{ + EXPECT_EQ(14, bowlingScore(std::vector{0, 0, 10, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})); +} + +TEST(BowlingGame, one_strike_at_last_frame) +{ + EXPECT_EQ(17, bowlingScore(std::vector{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 3, 4})); +} + +TEST(BowlingGame, perfect_game) +{ + EXPECT_EQ(300, bowlingScore(std::vector(12, 10))); +} From b234e15b65bf9afd5ace9548d3534ea2e8ba2b18 Mon Sep 17 00:00:00 2001 From: Damien Menanteau Date: Thu, 27 May 2021 16:45:44 +0200 Subject: [PATCH 002/125] Add Boost library for HTTP client --- clients/cpp/CMakeLists.txt | 2 + clients/cpp/cmake/CPM.cmake | 743 +++++++++++++----- clients/cpp/cmake/FindBoost.cmake | 11 + clients/cpp/cmake/FindCurl.cmake | 7 + clients/cpp/cmake/FindGoogleTest.cmake | 7 +- clients/cpp/cmake/FindHttpClient.cmake | 8 + clients/cpp/cmake/FindNlohmannJson.cmake | 11 +- .../ExtremeCarpaccioClient.hpp | 8 +- .../ExtremeCarpaccioClient.cpp | 45 +- .../cpp/test/ExtremeCarpaccioClientTest.cpp | 119 +-- 10 files changed, 636 insertions(+), 325 deletions(-) create mode 100644 clients/cpp/cmake/FindBoost.cmake create mode 100644 clients/cpp/cmake/FindCurl.cmake create mode 100644 clients/cpp/cmake/FindHttpClient.cmake diff --git a/clients/cpp/CMakeLists.txt b/clients/cpp/CMakeLists.txt index 3b21ede7..c0300930 100644 --- a/clients/cpp/CMakeLists.txt +++ b/clients/cpp/CMakeLists.txt @@ -15,6 +15,7 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin CACHE PATH "Where to include(cmake/CPM.cmake) include(cmake/FindGoogleTest.cmake) include(cmake/FindNlohmannJson.cmake) +include(cmake/FindBoost.cmake) #Shared library add_library(Extreme-Carpaccio-Client-shared SHARED) @@ -73,6 +74,7 @@ set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY XCODE_STARTUP_PROJEC set_property(TARGET Extreme-Carpaccio-Client-shared PROPERTY FOLDER "ExtremeCarpaccioClient") set_property(TARGET Extreme-Carpaccio-Client-test PROPERTY FOLDER "ExtremeCarpaccioClient") +set_property(TARGET Extreme-Carpaccio-Client PROPERTY FOLDER "ExtremeCarpaccioClient") set_property(TARGET Docs PROPERTY FOLDER "ExtremeCarpaccioClient") set_property(TARGET gtest gtest_main PROPERTY FOLDER "Third-Party/GoogleTest") diff --git a/clients/cpp/cmake/CPM.cmake b/clients/cpp/cmake/CPM.cmake index 625712e5..81714da3 100644 --- a/clients/cpp/cmake/CPM.cmake +++ b/clients/cpp/cmake/CPM.cmake @@ -1,11 +1,11 @@ # CPM.cmake - CMake's missing package manager # =========================================== -# See https://github.com/TheLartians/CPM.cmake for usage and update instructions. +# See https://github.com/cpm-cmake/CPM.cmake for usage and update instructions. # # MIT License # ----------- #[[ - Copyright (c) 2019 Lars Melchior + Copyright (c) 2021 Lars Melchior and additional contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -28,40 +28,75 @@ cmake_minimum_required(VERSION 3.14 FATAL_ERROR) -set(CURRENT_CPM_VERSION 0.27.5) +set(CURRENT_CPM_VERSION 1.0.0-development-version) if(CPM_DIRECTORY) if(NOT CPM_DIRECTORY STREQUAL CMAKE_CURRENT_LIST_DIR) - if (CPM_VERSION VERSION_LESS CURRENT_CPM_VERSION) - message(AUTHOR_WARNING "${CPM_INDENT} \ + if(CPM_VERSION VERSION_LESS CURRENT_CPM_VERSION) + message( + AUTHOR_WARNING + "${CPM_INDENT} \ A dependency is using a more recent CPM version (${CURRENT_CPM_VERSION}) than the current project (${CPM_VERSION}). \ It is recommended to upgrade CPM to the most recent version. \ -See https://github.com/TheLartians/CPM.cmake for more information." +See https://github.com/cpm-cmake/CPM.cmake for more information." ) endif() + if(${CMAKE_VERSION} VERSION_LESS "3.17.0") + include(FetchContent) + endif() return() endif() - get_property(CPM_INITIALIZED GLOBAL "" PROPERTY CPM_INITIALIZED SET) - if (CPM_INITIALIZED) + get_property( + CPM_INITIALIZED GLOBAL "" + PROPERTY CPM_INITIALIZED + SET + ) + if(CPM_INITIALIZED) return() endif() endif() set_property(GLOBAL PROPERTY CPM_INITIALIZED true) -option(CPM_USE_LOCAL_PACKAGES "Always try to use `find_package` to get dependencies" $ENV{CPM_USE_LOCAL_PACKAGES}) -option(CPM_LOCAL_PACKAGES_ONLY "Only use `find_package` to get dependencies" $ENV{CPM_LOCAL_PACKAGES_ONLY}) +option(CPM_USE_LOCAL_PACKAGES "Always try to use `find_package` to get dependencies" + $ENV{CPM_USE_LOCAL_PACKAGES} +) +option(CPM_LOCAL_PACKAGES_ONLY "Only use `find_package` to get dependencies" + $ENV{CPM_LOCAL_PACKAGES_ONLY} +) option(CPM_DOWNLOAD_ALL "Always download dependencies from source" $ENV{CPM_DOWNLOAD_ALL}) -option(CPM_DONT_UPDATE_MODULE_PATH "Don't update the module path to allow using find_package" $ENV{CPM_DONT_UPDATE_MODULE_PATH}) -option(CPM_DONT_CREATE_PACKAGE_LOCK "Don't create a package lock file in the binary path" $ENV{CPM_DONT_CREATE_PACKAGE_LOCK}) -option(CPM_INCLUDE_ALL_IN_PACKAGE_LOCK "Add all packages added through CPM.cmake to the package lock" $ENV{CPM_INCLUDE_ALL_IN_PACKAGE_LOCK}) - -set(CPM_VERSION ${CURRENT_CPM_VERSION} CACHE INTERNAL "") -set(CPM_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} CACHE INTERNAL "") -set(CPM_FILE ${CMAKE_CURRENT_LIST_FILE} CACHE INTERNAL "") -set(CPM_PACKAGES "" CACHE INTERNAL "") -set(CPM_DRY_RUN OFF CACHE INTERNAL "Don't download or configure dependencies (for testing)") +option(CPM_DONT_UPDATE_MODULE_PATH "Don't update the module path to allow using find_package" + $ENV{CPM_DONT_UPDATE_MODULE_PATH} +) +option(CPM_DONT_CREATE_PACKAGE_LOCK "Don't create a package lock file in the binary path" + $ENV{CPM_DONT_CREATE_PACKAGE_LOCK} +) +option(CPM_INCLUDE_ALL_IN_PACKAGE_LOCK + "Add all packages added through CPM.cmake to the package lock" + $ENV{CPM_INCLUDE_ALL_IN_PACKAGE_LOCK} +) + +set(CPM_VERSION + ${CURRENT_CPM_VERSION} + CACHE INTERNAL "" +) +set(CPM_DIRECTORY + ${CMAKE_CURRENT_LIST_DIR} + CACHE INTERNAL "" +) +set(CPM_FILE + ${CMAKE_CURRENT_LIST_FILE} + CACHE INTERNAL "" +) +set(CPM_PACKAGES + "" + CACHE INTERNAL "" +) +set(CPM_DRY_RUN + OFF + CACHE INTERNAL "Don't download or configure dependencies (for testing)" +) if(DEFINED ENV{CPM_SOURCE_CACHE}) set(CPM_SOURCE_CACHE_DEFAULT $ENV{CPM_SOURCE_CACHE}) @@ -69,28 +104,99 @@ else() set(CPM_SOURCE_CACHE_DEFAULT OFF) endif() -set(CPM_SOURCE_CACHE ${CPM_SOURCE_CACHE_DEFAULT} CACHE PATH "Directory to downlaod CPM dependencies") +set(CPM_SOURCE_CACHE + ${CPM_SOURCE_CACHE_DEFAULT} + CACHE PATH "Directory to download CPM dependencies" +) -if (NOT CPM_DONT_UPDATE_MODULE_PATH) - set(CPM_MODULE_PATH "${CMAKE_BINARY_DIR}/CPM_modules" CACHE INTERNAL "") +if(NOT CPM_DONT_UPDATE_MODULE_PATH) + set(CPM_MODULE_PATH + "${CMAKE_BINARY_DIR}/CPM_modules" + CACHE INTERNAL "" + ) # remove old modules - FILE(REMOVE_RECURSE ${CPM_MODULE_PATH}) + file(REMOVE_RECURSE ${CPM_MODULE_PATH}) file(MAKE_DIRECTORY ${CPM_MODULE_PATH}) # locally added CPM modules should override global packages set(CMAKE_MODULE_PATH "${CPM_MODULE_PATH};${CMAKE_MODULE_PATH}") endif() -if (NOT CPM_DONT_CREATE_PACKAGE_LOCK) - set(CPM_PACKAGE_LOCK_FILE "${CMAKE_BINARY_DIR}/cpm-package-lock.cmake" CACHE INTERNAL "") - file(WRITE ${CPM_PACKAGE_LOCK_FILE} "# CPM Package Lock\n# This file should be committed to version control\n\n") +if(NOT CPM_DONT_CREATE_PACKAGE_LOCK) + set(CPM_PACKAGE_LOCK_FILE + "${CMAKE_BINARY_DIR}/cpm-package-lock.cmake" + CACHE INTERNAL "" + ) + file(WRITE ${CPM_PACKAGE_LOCK_FILE} + "# CPM Package Lock\n# This file should be committed to version control\n\n" + ) endif() include(FetchContent) -include(CMakeParseArguments) + +# Try to infer package name from git repository uri (path or url) +function(cpm_package_name_from_git_uri URI RESULT) + if("${URI}" MATCHES "([^/:]+)/?.git/?$") + set(${RESULT} + ${CMAKE_MATCH_1} + PARENT_SCOPE + ) + else() + unset(${RESULT} PARENT_SCOPE) + endif() +endfunction() + +# Try to infer package name and version from a url +function(cpm_package_name_and_ver_from_url url outName outVer) + if(url MATCHES "[/\\?]([a-zA-Z0-9_\\.-]+)\\.(tar|tar\\.gz|tar\\.bz2|zip|ZIP)(\\?|/|$)") + # We matched an archive + set(filename "${CMAKE_MATCH_1}") + + if(filename MATCHES "([a-zA-Z0-9_\\.-]+)[_-]v?(([0-9]+\\.)*[0-9]+[a-zA-Z0-9]*)") + # We matched - (ie foo-1.2.3) + set(${outName} + "${CMAKE_MATCH_1}" + PARENT_SCOPE + ) + set(${outVer} + "${CMAKE_MATCH_2}" + PARENT_SCOPE + ) + elseif(filename MATCHES "(([0-9]+\\.)+[0-9]+[a-zA-Z0-9]*)") + # We couldn't find a name, but we found a version + # + # In many cases (which we don't handle here) the url would look something like + # `irrelevant/ACTUAL_PACKAGE_NAME/irrelevant/1.2.3.zip`. In such a case we can't possibly + # distinguish the package name from the irrelevant bits. Moreover if we try to match the + # package name from the filename, we'd get bogus at best. + unset(${outName} PARENT_SCOPE) + set(${outVer} + "${CMAKE_MATCH_1}" + PARENT_SCOPE + ) + else() + # Boldly assume that the file name is the package name. + # + # Yes, something like `irrelevant/ACTUAL_NAME/irrelevant/download.zip` will ruin our day, but + # such cases should be quite rare. No popular service does this... we think. + set(${outName} + "${filename}" + PARENT_SCOPE + ) + unset(${outVer} PARENT_SCOPE) + endif() + else() + # No ideas yet what to do with non-archives + unset(${outName} PARENT_SCOPE) + unset(${outVer} PARENT_SCOPE) + endif() +endfunction() # Initialize logging prefix if(NOT CPM_INDENT) - set(CPM_INDENT "CPM:") + set(CPM_INDENT + "CPM:" + CACHE INTERNAL "" + ) endif() function(cpm_find_package NAME VERSION) @@ -99,46 +205,49 @@ function(cpm_find_package NAME VERSION) if(${CPM_ARGS_NAME}_FOUND) message(STATUS "${CPM_INDENT} using local package ${CPM_ARGS_NAME}@${VERSION}") CPMRegisterPackage(${CPM_ARGS_NAME} "${VERSION}") - set(CPM_PACKAGE_FOUND YES PARENT_SCOPE) + set(CPM_PACKAGE_FOUND + YES + PARENT_SCOPE + ) else() - set(CPM_PACKAGE_FOUND NO PARENT_SCOPE) + set(CPM_PACKAGE_FOUND + NO + PARENT_SCOPE + ) endif() endfunction() -# Create a custom FindXXX.cmake module for a CPM package -# This prevents `find_package(NAME)` from finding the system library -function(CPMCreateModuleFile Name) - if (NOT CPM_DONT_UPDATE_MODULE_PATH) +# Create a custom FindXXX.cmake module for a CPM package This prevents `find_package(NAME)` from +# finding the system library +function(cpm_create_module_file Name) + if(NOT CPM_DONT_UPDATE_MODULE_PATH) # erase any previous modules - FILE(WRITE ${CPM_MODULE_PATH}/Find${Name}.cmake "include(${CPM_FILE})\n${ARGN}\nset(${Name}_FOUND TRUE)") + file(WRITE ${CPM_MODULE_PATH}/Find${Name}.cmake + "include(${CPM_FILE})\n${ARGN}\nset(${Name}_FOUND TRUE)" + ) endif() endfunction() # Find a package locally or fallback to CPMAddPackage function(CPMFindPackage) - set(oneValueArgs - NAME - VERSION - GIT_TAG - FIND_PACKAGE_ARGUMENTS - ) + set(oneValueArgs NAME VERSION GIT_TAG FIND_PACKAGE_ARGUMENTS) cmake_parse_arguments(CPM_ARGS "" "${oneValueArgs}" "" ${ARGN}) - if (NOT DEFINED CPM_ARGS_VERSION) - if (DEFINED CPM_ARGS_GIT_TAG) + if(NOT DEFINED CPM_ARGS_VERSION) + if(DEFINED CPM_ARGS_GIT_TAG) cpm_get_version_from_git_tag("${CPM_ARGS_GIT_TAG}" CPM_ARGS_VERSION) endif() endif() - if (CPM_DOWNLOAD_ALL) + if(CPM_DOWNLOAD_ALL) CPMAddPackage(${ARGN}) cpm_export_variables(${CPM_ARGS_NAME}) return() endif() - CPMCheckIfPackageAlreadyAdded(${CPM_ARGS_NAME} "${CPM_ARGS_VERSION}" "${CPM_ARGS_OPTIONS}") - if (CPM_PACKAGE_ALREADY_ADDED) + cpm_check_if_package_already_added(${CPM_ARGS_NAME} "${CPM_ARGS_VERSION}") + if(CPM_PACKAGE_ALREADY_ADDED) cpm_export_variables(${CPM_ARGS_NAME}) return() endif() @@ -153,58 +262,131 @@ function(CPMFindPackage) endfunction() # checks if a package has been added before -function(CPMCheckIfPackageAlreadyAdded CPM_ARGS_NAME CPM_ARGS_VERSION CPM_ARGS_OPTIONS) - if ("${CPM_ARGS_NAME}" IN_LIST CPM_PACKAGES) +function(cpm_check_if_package_already_added CPM_ARGS_NAME CPM_ARGS_VERSION) + if("${CPM_ARGS_NAME}" IN_LIST CPM_PACKAGES) CPMGetPackageVersion(${CPM_ARGS_NAME} CPM_PACKAGE_VERSION) if("${CPM_PACKAGE_VERSION}" VERSION_LESS "${CPM_ARGS_VERSION}") - message(WARNING "${CPM_INDENT} requires a newer version of ${CPM_ARGS_NAME} (${CPM_ARGS_VERSION}) than currently included (${CPM_PACKAGE_VERSION}).") - endif() - if (CPM_ARGS_OPTIONS) - foreach(OPTION ${CPM_ARGS_OPTIONS}) - cpm_parse_option(${OPTION}) - if(NOT "${${OPTION_KEY}}" STREQUAL "${OPTION_VALUE}") - message(WARNING "${CPM_INDENT} ignoring package option for ${CPM_ARGS_NAME}: ${OPTION_KEY} = ${OPTION_VALUE} (${${OPTION_KEY}})") - endif() - endforeach() + message( + WARNING + "${CPM_INDENT} requires a newer version of ${CPM_ARGS_NAME} (${CPM_ARGS_VERSION}) than currently included (${CPM_PACKAGE_VERSION})." + ) endif() cpm_get_fetch_properties(${CPM_ARGS_NAME}) - SET(${CPM_ARGS_NAME}_ADDED NO) - SET(CPM_PACKAGE_ALREADY_ADDED YES PARENT_SCOPE) + set(${CPM_ARGS_NAME}_ADDED NO) + set(CPM_PACKAGE_ALREADY_ADDED + YES + PARENT_SCOPE + ) cpm_export_variables(${CPM_ARGS_NAME}) else() - SET(CPM_PACKAGE_ALREADY_ADDED NO PARENT_SCOPE) + set(CPM_PACKAGE_ALREADY_ADDED + NO + PARENT_SCOPE + ) endif() endfunction() +# Parse the argument of CPMAddPackage in case a single one was provided and convert it to a list of +# arguments which can then be parsed idiomatically. For example gh:foo/bar@1.2.3 will be converted +# to: GITHUB_REPOSITORY;foo/bar;VERSION;1.2.3 +function(cpm_parse_add_package_single_arg arg outArgs) + # Look for a scheme + if("${arg}" MATCHES "^([a-zA-Z]+):(.+)$") + string(TOLOWER "${CMAKE_MATCH_1}" scheme) + set(uri "${CMAKE_MATCH_2}") + + # Check for CPM-specific schemes + if(scheme STREQUAL "gh") + set(out "GITHUB_REPOSITORY;${uri}") + set(packageType "git") + elseif(scheme STREQUAL "gl") + set(out "GITLAB_REPOSITORY;${uri}") + set(packageType "git") + # A CPM-specific scheme was not found. Looks like this is a generic URL so try to determine + # type + elseif(arg MATCHES ".git/?(@|#|$)") + set(out "GIT_REPOSITORY;${arg}") + set(packageType "git") + else() + # Fall back to a URL + set(out "URL;${arg}") + set(packageType "archive") + + # We could also check for SVN since FetchContent supports it, but SVN is so rare these days. + # We just won't bother with the additional complexity it will induce in this function. SVN is + # done by multi-arg + endif() + else() + if(arg MATCHES ".git/?(@|#|$)") + set(out "GIT_REPOSITORY;${arg}") + set(packageType "git") + else() + # Give up + message(FATAL_ERROR "CPM: Can't determine package type of '${arg}'") + endif() + endif() + + # For all packages we interpret @... as version. Only replace the last occurence. Thus URIs + # containing '@' can be used + string(REGEX REPLACE "@([^@]+)$" ";VERSION;\\1" out "${out}") + + # Parse the rest according to package type + if(packageType STREQUAL "git") + # For git repos we interpret #... as a tag or branch or commit hash + string(REGEX REPLACE "#([^#]+)$" ";GIT_TAG;\\1" out "${out}") + elseif(packageType STREQUAL "archive") + # For archives we interpret #... as a URL hash. + string(REGEX REPLACE "#([^#]+)$" ";URL_HASH;\\1" out "${out}") + # We don't try to parse the version if it's not provided explicitly. cpm_get_version_from_url + # should do this at a later point + else() + # We should never get here. This is an assertion and hitting it means there's a bug in the code + # above. A packageType was set, but not handled by this if-else. + message(FATAL_ERROR "CPM: Unsupported package type '${packageType}' of '${arg}'") + endif() + + set(${outArgs} + ${out} + PARENT_SCOPE + ) +endfunction() + # Download and add a package from source function(CPMAddPackage) + list(LENGTH ARGN argnLength) + if(argnLength EQUAL 1) + cpm_parse_add_package_single_arg("${ARGN}" ARGN) + + # The shorthand syntax implies EXCLUDE_FROM_ALL + set(ARGN "${ARGN};EXCLUDE_FROM_ALL;YES") + endif() set(oneValueArgs - NAME - FORCE - VERSION - GIT_TAG - DOWNLOAD_ONLY - GITHUB_REPOSITORY - GITLAB_REPOSITORY - GIT_REPOSITORY - SOURCE_DIR - DOWNLOAD_COMMAND - FIND_PACKAGE_ARGUMENTS - NO_CACHE - GIT_SHALLOW + NAME + FORCE + VERSION + GIT_TAG + DOWNLOAD_ONLY + GITHUB_REPOSITORY + GITLAB_REPOSITORY + GIT_REPOSITORY + SOURCE_DIR + DOWNLOAD_COMMAND + FIND_PACKAGE_ARGUMENTS + NO_CACHE + GIT_SHALLOW + EXCLUDE_FROM_ALL + SOURCE_SUBDIR ) - set(multiValueArgs - OPTIONS - ) + set(multiValueArgs URL OPTIONS) cmake_parse_arguments(CPM_ARGS "" "${oneValueArgs}" "${multiValueArgs}" "${ARGN}") # Set default values for arguments - if (NOT DEFINED CPM_ARGS_VERSION) - if (DEFINED CPM_ARGS_GIT_TAG) + if(NOT DEFINED CPM_ARGS_VERSION) + if(DEFINED CPM_ARGS_GIT_TAG) cpm_get_version_from_git_tag("${CPM_ARGS_GIT_TAG}" CPM_ARGS_VERSION) endif() endif() @@ -215,38 +397,72 @@ function(CPMAddPackage) set(DOWNLOAD_ONLY NO) endif() - if (DEFINED CPM_ARGS_GITHUB_REPOSITORY) + if(DEFINED CPM_ARGS_GITHUB_REPOSITORY) set(CPM_ARGS_GIT_REPOSITORY "https://github.com/${CPM_ARGS_GITHUB_REPOSITORY}.git") endif() - if (DEFINED CPM_ARGS_GITLAB_REPOSITORY) + if(DEFINED CPM_ARGS_GITLAB_REPOSITORY) set(CPM_ARGS_GIT_REPOSITORY "https://gitlab.com/${CPM_ARGS_GITLAB_REPOSITORY}.git") endif() - if (DEFINED CPM_ARGS_GIT_REPOSITORY) + if(DEFINED CPM_ARGS_GIT_REPOSITORY) list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS GIT_REPOSITORY ${CPM_ARGS_GIT_REPOSITORY}) - if (NOT DEFINED CPM_ARGS_GIT_TAG) + if(NOT DEFINED CPM_ARGS_GIT_TAG) set(CPM_ARGS_GIT_TAG v${CPM_ARGS_VERSION}) endif() + + # If a name wasn't provided, try to infer it from the git repo + if(NOT DEFINED CPM_ARGS_NAME) + cpm_package_name_from_git_uri(${CPM_ARGS_GIT_REPOSITORY} CPM_ARGS_NAME) + endif() endif() - if (DEFINED CPM_ARGS_GIT_TAG) + set(CPM_SKIP_FETCH FALSE) + + if(DEFINED CPM_ARGS_GIT_TAG) list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS GIT_TAG ${CPM_ARGS_GIT_TAG}) # If GIT_SHALLOW is explicitly specified, honor the value. - if (DEFINED CPM_ARGS_GIT_SHALLOW) + if(DEFINED CPM_ARGS_GIT_SHALLOW) list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS GIT_SHALLOW ${CPM_ARGS_GIT_SHALLOW}) endif() endif() + if(DEFINED CPM_ARGS_URL) + # If a name or version aren't provided, try to infer them from the URL + list(GET CPM_ARGS_URL 0 firstUrl) + cpm_package_name_and_ver_from_url(${firstUrl} nameFromUrl verFromUrl) + # If we fail to obtain name and version from the first URL, we could try other URLs if any. + # However multiple URLs are expected to be quite rare, so for now we won't bother. + + # If the caller provided their own name and version, they trump the inferred ones. + if(NOT DEFINED CPM_ARGS_NAME) + set(CPM_ARGS_NAME ${nameFromUrl}) + endif() + if(NOT DEFINED CPM_ARGS_VERSION) + set(CPM_ARGS_VERSION ${verFromUrl}) + endif() + + list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS URL "${CPM_ARGS_URL}") + endif() + + # Check for required arguments + + if(NOT DEFINED CPM_ARGS_NAME) + message( + FATAL_ERROR + "CPM: 'NAME' was not provided and couldn't be automatically inferred for package added with arguments: '${ARGN}'" + ) + endif() + # Check if package has been added before - CPMCheckIfPackageAlreadyAdded(${CPM_ARGS_NAME} "${CPM_ARGS_VERSION}" "${CPM_ARGS_OPTIONS}") - if (CPM_PACKAGE_ALREADY_ADDED) + cpm_check_if_package_already_added(${CPM_ARGS_NAME} "${CPM_ARGS_VERSION}") + if(CPM_PACKAGE_ALREADY_ADDED) cpm_export_variables(${CPM_ARGS_NAME}) return() endif() # Check for manual overrides - if (NOT CPM_ARGS_FORCE AND NOT "${CPM_${CPM_ARGS_NAME}_SOURCE}" STREQUAL "") + if(NOT CPM_ARGS_FORCE AND NOT "${CPM_${CPM_ARGS_NAME}_SOURCE}" STREQUAL "") set(PACKAGE_SOURCE ${CPM_${CPM_ARGS_NAME}_SOURCE}) set(CPM_${CPM_ARGS_NAME}_SOURCE "") CPMAddPackage( @@ -260,13 +476,13 @@ function(CPMAddPackage) endif() # Check for available declaration - if (NOT CPM_ARGS_FORCE AND NOT "${CPM_DECLARATION_${CPM_ARGS_NAME}}" STREQUAL "") + if(NOT CPM_ARGS_FORCE AND NOT "${CPM_DECLARATION_${CPM_ARGS_NAME}}" STREQUAL "") set(declaration ${CPM_DECLARATION_${CPM_ARGS_NAME}}) set(CPM_DECLARATION_${CPM_ARGS_NAME} "") CPMAddPackage(${declaration}) cpm_export_variables(${CPM_ARGS_NAME}) # checking again to ensure version and option compatibility - CPMCheckIfPackageAlreadyAdded(${CPM_ARGS_NAME} "${CPM_ARGS_VERSION}" "${CPM_ARGS_OPTIONS}") + cpm_check_if_package_already_added(${CPM_ARGS_NAME} "${CPM_ARGS_VERSION}") return() endif() @@ -279,62 +495,73 @@ function(CPMAddPackage) endif() if(CPM_LOCAL_PACKAGES_ONLY) - message(SEND_ERROR "CPM: ${CPM_ARGS_NAME} not found via find_package(${CPM_ARGS_NAME} ${CPM_ARGS_VERSION})") + message( + SEND_ERROR + "CPM: ${CPM_ARGS_NAME} not found via find_package(${CPM_ARGS_NAME} ${CPM_ARGS_VERSION})" + ) endif() endif() CPMRegisterPackage("${CPM_ARGS_NAME}" "${CPM_ARGS_VERSION}") - if (CPM_ARGS_OPTIONS) - foreach(OPTION ${CPM_ARGS_OPTIONS}) - cpm_parse_option(${OPTION}) - set(${OPTION_KEY} ${OPTION_VALUE} CACHE INTERNAL "") - endforeach() - endif() - - if (DEFINED CPM_ARGS_GIT_TAG) + if(DEFINED CPM_ARGS_GIT_TAG) set(PACKAGE_INFO "${CPM_ARGS_GIT_TAG}") - elseif (DEFINED CPM_ARGS_SOURCE_DIR) + elseif(DEFINED CPM_ARGS_SOURCE_DIR) set(PACKAGE_INFO "${CPM_ARGS_SOURCE_DIR}") else() set(PACKAGE_INFO "${CPM_ARGS_VERSION}") endif() - if (DEFINED CPM_ARGS_DOWNLOAD_COMMAND) + if(DEFINED FETCHCONTENT_BASE_DIR) + # respect user's FETCHCONTENT_BASE_DIR if set + set(CPM_FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR}) + else() + set(CPM_FETCHCONTENT_BASE_DIR ${CMAKE_BINARY_DIR}/_deps) + endif() + + if(DEFINED CPM_ARGS_DOWNLOAD_COMMAND) list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS DOWNLOAD_COMMAND ${CPM_ARGS_DOWNLOAD_COMMAND}) - elseif (DEFINED CPM_ARGS_SOURCE_DIR) + elseif(DEFINED CPM_ARGS_SOURCE_DIR) list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS SOURCE_DIR ${CPM_ARGS_SOURCE_DIR}) - elseif (CPM_SOURCE_CACHE AND NOT CPM_ARGS_NO_CACHE) + elseif(CPM_SOURCE_CACHE AND NOT CPM_ARGS_NO_CACHE) string(TOLOWER ${CPM_ARGS_NAME} lower_case_name) set(origin_parameters ${CPM_ARGS_UNPARSED_ARGUMENTS}) list(SORT origin_parameters) string(SHA1 origin_hash "${origin_parameters}") set(download_directory ${CPM_SOURCE_CACHE}/${lower_case_name}/${origin_hash}) list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS SOURCE_DIR ${download_directory}) - if (EXISTS ${download_directory}) - # disable the download command to allow offline builds - list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS DOWNLOAD_COMMAND "${CMAKE_COMMAND}") - set(PACKAGE_INFO "${download_directory}") + if(EXISTS ${download_directory}) + # avoid FetchContent modules to improve performance + set(${CPM_ARGS_NAME}_BINARY_DIR ${CPM_FETCHCONTENT_BASE_DIR}/${lower_case_name}-build) + set(${CPM_ARGS_NAME}_ADDED YES) + set(${CPM_ARGS_NAME}_SOURCE_DIR ${download_directory}) + cpm_add_subdirectory( + "${CPM_ARGS_NAME}" "${DOWNLOAD_ONLY}" + "${${CPM_ARGS_NAME}_SOURCE_DIR}/${CPM_ARGS_SOURCE_SUBDIR}" "${${CPM_ARGS_NAME}_BINARY_DIR}" + "${CPM_ARGS_EXCLUDE_FROM_ALL}" "${CPM_ARGS_OPTIONS}" + ) + set(CPM_SKIP_FETCH TRUE) + set(PACKAGE_INFO "${PACKAGE_INFO} at ${download_directory}") else() - # Enable shallow clone when GIT_TAG is not a commit hash. - # Our guess may not be accurate, but it should guarantee no commit hash get mis-detected. - if (NOT DEFINED CPM_ARGS_GIT_SHALLOW) + # Enable shallow clone when GIT_TAG is not a commit hash. Our guess may not be accurate, but + # it should guarantee no commit hash get mis-detected. + if(NOT DEFINED CPM_ARGS_GIT_SHALLOW) cpm_is_git_tag_commit_hash("${CPM_ARGS_GIT_TAG}" IS_HASH) - if (NOT ${IS_HASH}) + if(NOT ${IS_HASH}) list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS GIT_SHALLOW TRUE) endif() endif() # remove timestamps so CMake will re-download the dependency - file(REMOVE_RECURSE ${CMAKE_BINARY_DIR}/_deps/${lower_case_name}-subbuild) - set(PACKAGE_INFO "${PACKAGE_INFO} -> ${download_directory}") + file(REMOVE_RECURSE ${CPM_FETCHCONTENT_BASE_DIR}/${lower_case_name}-subbuild) + set(PACKAGE_INFO "${PACKAGE_INFO} to ${download_directory}") endif() endif() - CPMCreateModuleFile(${CPM_ARGS_NAME} "CPMAddPackage(${ARGN})") + cpm_create_module_file(${CPM_ARGS_NAME} "CPMAddPackage(${ARGN})") - if (CPM_PACKAGE_LOCK_ENABLED) - if ((CPM_ARGS_VERSION AND NOT CPM_ARGS_SOURCE_DIR) OR CPM_INCLUDE_ALL_IN_PACKAGE_LOCK) + if(CPM_PACKAGE_LOCK_ENABLED) + if((CPM_ARGS_VERSION AND NOT CPM_ARGS_SOURCE_DIR) OR CPM_INCLUDE_ALL_IN_PACKAGE_LOCK) cpm_add_to_package_lock(${CPM_ARGS_NAME} "${ARGN}") elseif(CPM_ARGS_SOURCE_DIR) cpm_add_comment_to_package_lock(${CPM_ARGS_NAME} "local directory") @@ -343,64 +570,89 @@ function(CPMAddPackage) endif() endif() - cpm_declare_fetch("${CPM_ARGS_NAME}" "${CPM_ARGS_VERSION}" "${PACKAGE_INFO}" "${CPM_ARGS_UNPARSED_ARGUMENTS}") - cpm_fetch_package("${CPM_ARGS_NAME}" "${DOWNLOAD_ONLY}") - cpm_get_fetch_properties("${CPM_ARGS_NAME}") + message( + STATUS "${CPM_INDENT} adding package ${CPM_ARGS_NAME}@${CPM_ARGS_VERSION} (${PACKAGE_INFO})" + ) + + if(NOT CPM_SKIP_FETCH) + cpm_declare_fetch( + "${CPM_ARGS_NAME}" "${CPM_ARGS_VERSION}" "${PACKAGE_INFO}" "${CPM_ARGS_UNPARSED_ARGUMENTS}" + ) + cpm_fetch_package("${CPM_ARGS_NAME}") + cpm_add_subdirectory( + "${CPM_ARGS_NAME}" "${DOWNLOAD_ONLY}" + "${${CPM_ARGS_NAME}_SOURCE_DIR}/${CPM_ARGS_SOURCE_SUBDIR}" "${${CPM_ARGS_NAME}_BINARY_DIR}" + "${CPM_ARGS_EXCLUDE_FROM_ALL}" "${CPM_ARGS_OPTIONS}" + ) + cpm_get_fetch_properties("${CPM_ARGS_NAME}") + endif() - SET(${CPM_ARGS_NAME}_ADDED YES) + set(${CPM_ARGS_NAME}_ADDED YES) cpm_export_variables("${CPM_ARGS_NAME}") endfunction() # Fetch a previously declared package macro(CPMGetPackage Name) - if (DEFINED "CPM_DECLARATION_${Name}") - CPMAddPackage( - NAME ${Name} - ) + if(DEFINED "CPM_DECLARATION_${Name}") + CPMAddPackage(NAME ${Name}) else() message(SEND_ERROR "Cannot retrieve package ${Name}: no declaration available") endif() endmacro() -# export variables available to the caller to the parent scope -# expects ${CPM_ARGS_NAME} to be set +# export variables available to the caller to the parent scope expects ${CPM_ARGS_NAME} to be set macro(cpm_export_variables name) - SET(${name}_SOURCE_DIR "${${name}_SOURCE_DIR}" PARENT_SCOPE) - SET(${name}_BINARY_DIR "${${name}_BINARY_DIR}" PARENT_SCOPE) - SET(${name}_ADDED "${${name}_ADDED}" PARENT_SCOPE) + set(${name}_SOURCE_DIR + "${${name}_SOURCE_DIR}" + PARENT_SCOPE + ) + set(${name}_BINARY_DIR + "${${name}_BINARY_DIR}" + PARENT_SCOPE + ) + set(${name}_ADDED + "${${name}_ADDED}" + PARENT_SCOPE + ) endmacro() -# declares a package, so that any call to CPMAddPackage for the -# package name will use these arguments instead. -# Previous declarations will not be overriden. +# declares a package, so that any call to CPMAddPackage for the package name will use these +# arguments instead. Previous declarations will not be overriden. macro(CPMDeclarePackage Name) - if (NOT DEFINED "CPM_DECLARATION_${Name}") + if(NOT DEFINED "CPM_DECLARATION_${Name}") set("CPM_DECLARATION_${Name}" "${ARGN}") endif() endmacro() function(cpm_add_to_package_lock Name) - if (NOT CPM_DONT_CREATE_PACKAGE_LOCK) - file(APPEND ${CPM_PACKAGE_LOCK_FILE} "# ${Name}\nCPMDeclarePackage(${Name} \"${ARGN}\")\n") + if(NOT CPM_DONT_CREATE_PACKAGE_LOCK) + cpm_prettify_package_arguments(PRETTY_ARGN false ${ARGN}) + file(APPEND ${CPM_PACKAGE_LOCK_FILE} "# ${Name}\nCPMDeclarePackage(${Name}\n${PRETTY_ARGN})\n") endif() endfunction() function(cpm_add_comment_to_package_lock Name) - if (NOT CPM_DONT_CREATE_PACKAGE_LOCK) - file(APPEND ${CPM_PACKAGE_LOCK_FILE} "# ${Name} (unversioned)\n# CPMDeclarePackage(${Name} \"${ARGN}\")\n") + if(NOT CPM_DONT_CREATE_PACKAGE_LOCK) + cpm_prettify_package_arguments(PRETTY_ARGN true ${ARGN}) + file(APPEND ${CPM_PACKAGE_LOCK_FILE} + "# ${Name} (unversioned)\n# CPMDeclarePackage(${Name}\n${PRETTY_ARGN}#)\n" + ) endif() endfunction() -# includes the package lock file if it exists and creates a target -# `cpm-write-package-lock` to update it +# includes the package lock file if it exists and creates a target `cpm-write-package-lock` to +# update it macro(CPMUsePackageLock file) - if (NOT CPM_DONT_CREATE_PACKAGE_LOCK) + if(NOT CPM_DONT_CREATE_PACKAGE_LOCK) get_filename_component(CPM_ABSOLUTE_PACKAGE_LOCK_PATH ${file} ABSOLUTE) if(EXISTS ${CPM_ABSOLUTE_PACKAGE_LOCK_PATH}) include(${CPM_ABSOLUTE_PACKAGE_LOCK_PATH}) endif() - if (NOT TARGET cpm-update-package-lock) - add_custom_target(cpm-update-package-lock COMMAND ${CMAKE_COMMAND} -E copy ${CPM_PACKAGE_LOCK_FILE} ${CPM_ABSOLUTE_PACKAGE_LOCK_PATH}) + if(NOT TARGET cpm-update-package-lock) + add_custom_target( + cpm-update-package-lock COMMAND ${CMAKE_COMMAND} -E copy ${CPM_PACKAGE_LOCK_FILE} + ${CPM_ABSOLUTE_PACKAGE_LOCK_PATH} + ) endif() set(CPM_PACKAGE_LOCK_ENABLED true) endif() @@ -409,85 +661,146 @@ endmacro() # registers a package that has been added to CPM function(CPMRegisterPackage PACKAGE VERSION) list(APPEND CPM_PACKAGES ${PACKAGE}) - set(CPM_PACKAGES ${CPM_PACKAGES} CACHE INTERNAL "") - set("CPM_PACKAGE_${PACKAGE}_VERSION" ${VERSION} CACHE INTERNAL "") + set(CPM_PACKAGES + ${CPM_PACKAGES} + CACHE INTERNAL "" + ) + set("CPM_PACKAGE_${PACKAGE}_VERSION" + ${VERSION} + CACHE INTERNAL "" + ) endfunction() # retrieve the current version of the package to ${OUTPUT} function(CPMGetPackageVersion PACKAGE OUTPUT) - set(${OUTPUT} "${CPM_PACKAGE_${PACKAGE}_VERSION}" PARENT_SCOPE) + set(${OUTPUT} + "${CPM_PACKAGE_${PACKAGE}_VERSION}" + PARENT_SCOPE + ) endfunction() # declares a package in FetchContent_Declare -function (cpm_declare_fetch PACKAGE VERSION INFO) - message(STATUS "${CPM_INDENT} adding package ${PACKAGE}@${VERSION} (${INFO})") - - if (${CPM_DRY_RUN}) +function(cpm_declare_fetch PACKAGE VERSION INFO) + if(${CPM_DRY_RUN}) message(STATUS "${CPM_INDENT} package not declared (dry run)") return() endif() - FetchContent_Declare(${PACKAGE} - ${ARGN} - ) + FetchContent_Declare(${PACKAGE} ${ARGN}) endfunction() # returns properties for a package previously defined by cpm_declare_fetch -function (cpm_get_fetch_properties PACKAGE) - if (${CPM_DRY_RUN}) +function(cpm_get_fetch_properties PACKAGE) + if(${CPM_DRY_RUN}) return() endif() FetchContent_GetProperties(${PACKAGE}) string(TOLOWER ${PACKAGE} lpackage) - SET(${PACKAGE}_SOURCE_DIR "${${lpackage}_SOURCE_DIR}" PARENT_SCOPE) - SET(${PACKAGE}_BINARY_DIR "${${lpackage}_BINARY_DIR}" PARENT_SCOPE) + set(${PACKAGE}_SOURCE_DIR + "${${lpackage}_SOURCE_DIR}" + PARENT_SCOPE + ) + set(${PACKAGE}_BINARY_DIR + "${${lpackage}_BINARY_DIR}" + PARENT_SCOPE + ) endfunction() -# downloads a previously declared package via FetchContent -function (cpm_fetch_package PACKAGE DOWNLOAD_ONLY) - if (${CPM_DRY_RUN}) - message(STATUS "${CPM_INDENT} package ${PACKAGE} not fetched (dry run)") - return() - endif() +# adds a package as a subdirectory if viable, according to provided options +function( + cpm_add_subdirectory + PACKAGE + DOWNLOAD_ONLY + SOURCE_DIR + BINARY_DIR + EXCLUDE + OPTIONS +) + if(NOT DOWNLOAD_ONLY AND EXISTS ${SOURCE_DIR}/CMakeLists.txt) + if(EXCLUDE) + set(addSubdirectoryExtraArgs EXCLUDE_FROM_ALL) + else() + set(addSubdirectoryExtraArgs "") + endif() + if(OPTIONS) + # the policy allows us to change options without caching + cmake_policy(SET CMP0077 NEW) + set(CMAKE_POLICY_DEFAULT_CMP0077 NEW) - if(DOWNLOAD_ONLY) - FetchContent_GetProperties(${PACKAGE}) - if(NOT ${PACKAGE}_POPULATED) - FetchContent_Populate(${PACKAGE}) + foreach(OPTION ${OPTIONS}) + cpm_parse_option(${OPTION}) + set(${OPTION_KEY} ${OPTION_VALUE}) + endforeach() endif() - else() set(CPM_OLD_INDENT "${CPM_INDENT}") set(CPM_INDENT "${CPM_INDENT} ${PACKAGE}:") - FetchContent_MakeAvailable(${PACKAGE}) + add_subdirectory(${SOURCE_DIR} ${BINARY_DIR} ${addSubdirectoryExtraArgs}) set(CPM_INDENT "${CPM_OLD_INDENT}") endif() endfunction() +# downloads a previously declared package via FetchContent and exports the variables +# `${PACKAGE}_SOURCE_DIR` and `${PACKAGE}_BINARY_DIR` to the parent scope +function(cpm_fetch_package PACKAGE) + if(${CPM_DRY_RUN}) + message(STATUS "${CPM_INDENT} package ${PACKAGE} not fetched (dry run)") + return() + endif() + + FetchContent_GetProperties(${PACKAGE}) + + if(NOT ${lower_case_name}_POPULATED) + FetchContent_Populate(${PACKAGE}) + endif() + + string(TOLOWER "${PACKAGE}" lower_case_name) + set(${PACKAGE}_SOURCE_DIR + ${${lower_case_name}_SOURCE_DIR} + PARENT_SCOPE + ) + set(${PACKAGE}_BINARY_DIR + ${${lower_case_name}_BINARY_DIR} + PARENT_SCOPE + ) +endfunction() + # splits a package option function(cpm_parse_option OPTION) string(REGEX MATCH "^[^ ]+" OPTION_KEY ${OPTION}) string(LENGTH ${OPTION} OPTION_LENGTH) string(LENGTH ${OPTION_KEY} OPTION_KEY_LENGTH) - if (OPTION_KEY_LENGTH STREQUAL OPTION_LENGTH) + if(OPTION_KEY_LENGTH STREQUAL OPTION_LENGTH) # no value for key provided, assume user wants to set option to "ON" set(OPTION_VALUE "ON") else() math(EXPR OPTION_KEY_LENGTH "${OPTION_KEY_LENGTH}+1") string(SUBSTRING ${OPTION} "${OPTION_KEY_LENGTH}" "-1" OPTION_VALUE) endif() - set(OPTION_KEY "${OPTION_KEY}" PARENT_SCOPE) - set(OPTION_VALUE "${OPTION_VALUE}" PARENT_SCOPE) + set(OPTION_KEY + "${OPTION_KEY}" + PARENT_SCOPE + ) + set(OPTION_VALUE + "${OPTION_VALUE}" + PARENT_SCOPE + ) endfunction() # guesses the package version from a git tag function(cpm_get_version_from_git_tag GIT_TAG RESULT) string(LENGTH ${GIT_TAG} length) - if (length EQUAL 40) + if(length EQUAL 40) # GIT_TAG is probably a git hash - SET(${RESULT} 0 PARENT_SCOPE) + set(${RESULT} + 0 + PARENT_SCOPE + ) else() string(REGEX MATCH "v?([0123456789.]*).*" _ ${GIT_TAG}) - SET(${RESULT} ${CMAKE_MATCH_1} PARENT_SCOPE) + set(${RESULT} + ${CMAKE_MATCH_1} + PARENT_SCOPE + ) endif() endfunction() @@ -495,13 +808,87 @@ endfunction() function(cpm_is_git_tag_commit_hash GIT_TAG RESULT) string(LENGTH "${GIT_TAG}" length) # full hash has 40 characters, and short hash has at least 7 characters. - if (length LESS 7 OR length GREATER 40) - SET(${RESULT} 0 PARENT_SCOPE) + if(length LESS 7 OR length GREATER 40) + set(${RESULT} + 0 + PARENT_SCOPE + ) else() - if (${GIT_TAG} MATCHES "^[a-fA-F0-9]+$") - SET(${RESULT} 1 PARENT_SCOPE) + if(${GIT_TAG} MATCHES "^[a-fA-F0-9]+$") + set(${RESULT} + 1 + PARENT_SCOPE + ) else() - SET(${RESULT} 0 PARENT_SCOPE) + set(${RESULT} + 0 + PARENT_SCOPE + ) endif() endif() endfunction() + +function(cpm_prettify_package_arguments OUT_VAR IS_IN_COMMENT) + set(oneValueArgs + NAME + FORCE + VERSION + GIT_TAG + DOWNLOAD_ONLY + GITHUB_REPOSITORY + GITLAB_REPOSITORY + GIT_REPOSITORY + SOURCE_DIR + DOWNLOAD_COMMAND + FIND_PACKAGE_ARGUMENTS + NO_CACHE + GIT_SHALLOW + ) + set(multiValueArgs OPTIONS) + cmake_parse_arguments(CPM_ARGS "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + foreach(oneArgName ${oneValueArgs}) + if(DEFINED CPM_ARGS_${oneArgName}) + if(${IS_IN_COMMENT}) + string(APPEND PRETTY_OUT_VAR "#") + endif() + if(${oneArgName} STREQUAL "SOURCE_DIR") + string(REPLACE ${CMAKE_SOURCE_DIR} "\${CMAKE_SOURCE_DIR}" CPM_ARGS_${oneArgName} + ${CPM_ARGS_${oneArgName}} + ) + endif() + string(APPEND PRETTY_OUT_VAR " ${oneArgName} ${CPM_ARGS_${oneArgName}}\n") + endif() + endforeach() + foreach(multiArgName ${multiValueArgs}) + if(DEFINED CPM_ARGS_${multiArgName}) + if(${IS_IN_COMMENT}) + string(APPEND PRETTY_OUT_VAR "#") + endif() + string(APPEND PRETTY_OUT_VAR " ${multiArgName}\n") + foreach(singleOption ${CPM_ARGS_${multiArgName}}) + if(${IS_IN_COMMENT}) + string(APPEND PRETTY_OUT_VAR "#") + endif() + string(APPEND PRETTY_OUT_VAR " \"${singleOption}\"\n") + endforeach() + endif() + endforeach() + + if(NOT "${CPM_ARGS_UNPARSED_ARGUMENTS}" STREQUAL "") + if(${IS_IN_COMMENT}) + string(APPEND PRETTY_OUT_VAR "#") + endif() + string(APPEND PRETTY_OUT_VAR " ") + foreach(CPM_ARGS_UNPARSED_ARGUMENT ${CPM_ARGS_UNPARSED_ARGUMENTS}) + string(APPEND PRETTY_OUT_VAR " ${CPM_ARGS_UNPARSED_ARGUMENT}") + endforeach() + string(APPEND PRETTY_OUT_VAR "\n") + endif() + + set(${OUT_VAR} + ${PRETTY_OUT_VAR} + PARENT_SCOPE + ) + +endfunction() \ No newline at end of file diff --git a/clients/cpp/cmake/FindBoost.cmake b/clients/cpp/cmake/FindBoost.cmake new file mode 100644 index 00000000..bd357e9d --- /dev/null +++ b/clients/cpp/cmake/FindBoost.cmake @@ -0,0 +1,11 @@ +# Fetch Boost + +CPMAddPackage("gh:Orphis/boost-cmake#7f97a08b64bd5d2e53e932ddf80c40544cf45edf@1.71.0") + +#CPMFindPackage( +# NAME Boost +# GITHUB_REPOSITORY Orphis/boost-cmake +# VERSION 1.67.0 +# # setting FIND_PACKAGE_ARGUMENTS allow usage with `CPM_USE_LOCAL_PACKAGES` +# FIND_PACKAGE_ARGUMENTS "COMPONENTS system" +#) \ No newline at end of file diff --git a/clients/cpp/cmake/FindCurl.cmake b/clients/cpp/cmake/FindCurl.cmake new file mode 100644 index 00000000..06f98d54 --- /dev/null +++ b/clients/cpp/cmake/FindCurl.cmake @@ -0,0 +1,7 @@ +# Fetch googletest + +CPMFindPackage( + NAME HTTPClient + GITHUB_REPOSITORY embeddedmz/httpclient-cpp + GIT_TAG master +) \ No newline at end of file diff --git a/clients/cpp/cmake/FindGoogleTest.cmake b/clients/cpp/cmake/FindGoogleTest.cmake index 739cfe0d..727996b1 100644 --- a/clients/cpp/cmake/FindGoogleTest.cmake +++ b/clients/cpp/cmake/FindGoogleTest.cmake @@ -1,8 +1,9 @@ # Fetch googletest -CPMFindPackage( +CPMAddPackage( NAME googletest GITHUB_REPOSITORY google/googletest - GIT_TAG master + GIT_TAG release-1.10.0 + VERSION 1.10.0 OPTIONS "INSTALL_GTEST OFF" "gtest_force_shared_crt" "BUILD_GMOCK OFF" -) \ No newline at end of file +) diff --git a/clients/cpp/cmake/FindHttpClient.cmake b/clients/cpp/cmake/FindHttpClient.cmake new file mode 100644 index 00000000..739cfe0d --- /dev/null +++ b/clients/cpp/cmake/FindHttpClient.cmake @@ -0,0 +1,8 @@ +# Fetch googletest + +CPMFindPackage( + NAME googletest + GITHUB_REPOSITORY google/googletest + GIT_TAG master + OPTIONS "INSTALL_GTEST OFF" "gtest_force_shared_crt" "BUILD_GMOCK OFF" +) \ No newline at end of file diff --git a/clients/cpp/cmake/FindNlohmannJson.cmake b/clients/cpp/cmake/FindNlohmannJson.cmake index b62ef379..7e279ad7 100644 --- a/clients/cpp/cmake/FindNlohmannJson.cmake +++ b/clients/cpp/cmake/FindNlohmannJson.cmake @@ -11,4 +11,13 @@ CPMFindPackage( if (nlohmann_json_ADDED) add_library(nlohmann_json INTERFACE IMPORTED) target_include_directories(nlohmann_json INTERFACE ${nlohmann_json_SOURCE_DIR}) -endif() \ No newline at end of file +endif() + +# This is the latest package provided on CPM repo, but does not seem to work + +#CPMAddPackage( +# NAME nlohmann_json +# VERSION 3.9.1 +# OPTIONS +# "JSON_BuildTests OFF" +#) \ No newline at end of file diff --git a/clients/cpp/include/extreme_carpaccio_client/ExtremeCarpaccioClient.hpp b/clients/cpp/include/extreme_carpaccio_client/ExtremeCarpaccioClient.hpp index dde16240..f78aab11 100644 --- a/clients/cpp/include/extreme_carpaccio_client/ExtremeCarpaccioClient.hpp +++ b/clients/cpp/include/extreme_carpaccio_client/ExtremeCarpaccioClient.hpp @@ -3,9 +3,7 @@ #include -namespace kata { -namespace bowling_game { - EXTREME_CARPACCIO_CLIENT_API int bowlingScore(const std::vector & rolls); +namespace extreme_carpaccio_client { + EXTREME_CARPACCIO_CLIENT_API int dummy(); -} // namespace bowling_game -} // namespace kata +} // namespace extreme_carpaccio_client diff --git a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp index 48512d26..6e627783 100644 --- a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp +++ b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp @@ -4,48 +4,13 @@ #include #include -namespace kata { -namespace bowling_game { +namespace extreme_carpaccio_client { -const size_t TOTAL_PINS = 10; -const size_t TOTAL_FRAMES = 10; - -static bool isSpare(const std::vector & rolls, size_t frameIndex) -{ - return rolls[frameIndex] + rolls[frameIndex + 1] == TOTAL_PINS; -} - -static bool isStrike(const std::vector& rolls, size_t frameIndex) -{ - return rolls[frameIndex] == TOTAL_PINS; -} - -int bowlingScore(const std::vector & rolls) -{ - int score = 0; - size_t frameIndex = 0; - - for(size_t frame = 0; frame < TOTAL_FRAMES; ++frame) + int dummy() { - if(isStrike(rolls, frameIndex)) - { - score += TOTAL_PINS + rolls[frameIndex+1] + rolls[frameIndex+2]; - frameIndex++; - } - else if (isSpare(rolls, frameIndex)) - { - score += TOTAL_PINS + rolls[frameIndex+2]; - frameIndex += 2; - } - else - { - score += rolls[frameIndex] + rolls[frameIndex + 1]; - frameIndex += 2; - } + return 0; } - return score; -} -} // namespace bowling_game -} // namespace kata +} // namespace extreme_carpaccio_client + diff --git a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp index 72de4a57..80b6146b 100644 --- a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp +++ b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp @@ -5,109 +5,32 @@ #include -using namespace kata::bowling_game; +using namespace extreme_carpaccio_client; -TEST(BowlingGame, acceptance_test) +TEST(ExtremeCarpaccioClient, should_handle_feedback) { - EXPECT_EQ(133, bowlingScore(std::vector{1, 4, 4, 5, 6, 4, 5, 5, 10, 0, 1, 7, 3, 6, 4, 10, 2, 8, 6})); + EXPECT_EQ(1, 1); } -TEST(BowlingGame, one_pin_at_first) +TEST(ExtremeCarpaccioClient, should_handle_order) { - EXPECT_EQ(1, bowlingScore(std::vector{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})); + EXPECT_EQ(1, 1); } -TEST(BowlingGame, gutter_game) -{ - EXPECT_EQ(0, bowlingScore(std::vector{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})); -} - -TEST(BowlingGame, several_pins_at_first) -{ - EXPECT_EQ(6, bowlingScore(std::vector{6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})); -} - -TEST(BowlingGame, several_pins_at_second_roll) -{ - EXPECT_EQ(5, bowlingScore(std::vector{0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})); -} - -TEST(BowlingGame, several_pins_at_first_2_rolls) -{ - EXPECT_EQ(8, bowlingScore(std::vector{3, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})); -} - -TEST(BowlingGame, several_pins_at_last_rolls) -{ - EXPECT_EQ(7, bowlingScore(std::vector{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7})); -} +//it('should handle feedback', function(done) { +// var feedback = request('http://' + conf.host + ':' + conf.port + '/feedback', function(error, response) { +// expect(response.statusCode).toBe(204); +// done(); +// }); +// feedback.write('{type: "INFO", content: "this is my precious feedback"}'); +//}); +// +//it('should handle order', function(done) { +// var order = request('http://' + conf.host + ':' + conf.port + '/order', function(error, response, body) { +// expect(response.statusCode).toBe(200); +// expect(body).toBe('{total:0}'); +// done(); +// }); +// order.write('{prices: [], quantities: [], country: "DE", reduction: "STANDARD"}'); +//}); -TEST(BowlingGame, several_pins_at_first_3_rolls) -{ - EXPECT_EQ(9, bowlingScore(std::vector{1, 3, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})); -} - -TEST(BowlingGame, 3_pins_at_all_rolls) -{ - EXPECT_EQ(60, bowlingScore(std::vector{3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3})); -} - -TEST(BowlingGame, one_spare_at_beginning) -{ - EXPECT_EQ(18, bowlingScore(std::vector{6, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})); -} - -TEST(BowlingGame, another_spare_at_beginning) -{ - EXPECT_EQ(16, bowlingScore(std::vector{5, 5, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})); -} - -TEST(BowlingGame, spare_at_frame_2) -{ - EXPECT_EQ(14, bowlingScore(std::vector{0, 0, 3, 7, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})); -} - -TEST(BowlingGame, spare_at_frame_3) -{ - EXPECT_EQ(24, bowlingScore(std::vector{0, 0, 0, 0, 7, 3, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})); -} - -TEST(BowlingGame, spare_at_last_frame) -{ - EXPECT_EQ(13, bowlingScore(std::vector{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 4, 3})); -} - -TEST(BowlingGame, 5_pins_at_all_rolls) -{ - EXPECT_EQ(150, bowlingScore(std::vector{5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5})); -} - -TEST(BowlingGame, fake_spare_between_first_2_frames) -{ - EXPECT_EQ(11, bowlingScore(std::vector{0, 5, 5, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})); -} - -TEST(BowlingGame, one_strike_at_beginning) -{ - EXPECT_EQ(20, bowlingScore(std::vector{10, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})); -} - -TEST(BowlingGame, another_strike_at_beginning) -{ - EXPECT_EQ(18, bowlingScore(std::vector{10, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})); -} - -TEST(BowlingGame, one_strike_at_frame_2) -{ - EXPECT_EQ(14, bowlingScore(std::vector{0, 0, 10, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})); -} - -TEST(BowlingGame, one_strike_at_last_frame) -{ - EXPECT_EQ(17, bowlingScore(std::vector{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 3, 4})); -} - -TEST(BowlingGame, perfect_game) -{ - EXPECT_EQ(300, bowlingScore(std::vector(12, 10))); -} From 337a8d7571bb45a61ca4542336bc83678de5607f Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 27 May 2021 17:03:59 +0200 Subject: [PATCH 003/125] Retrospective --- clients/cpp/Retrospective.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 clients/cpp/Retrospective.md diff --git a/clients/cpp/Retrospective.md b/clients/cpp/Retrospective.md new file mode 100644 index 00000000..4e195cdb --- /dev/null +++ b/clients/cpp/Retrospective.md @@ -0,0 +1,25 @@ +# RETROSPECTIVE + +05/27/2021 + +## What did we do ? +- We did some cmake and CPM +- We wanted to build a extreme carpaccio client in cpp +- We have all dependencies to create an answer to server +- We updated CPM to latest version +- We made a copy of Bowling game kata to have all cmake config ready +- We debugged requests format using JS version of carpaccio + + +## What did we learn ? +- Patrice learnt on client/server problematic and REST requests + + +## Puzzle +- Dependencies handling in cpp is sport ! +- We have the boost example of GET, will it work with POST ? +- Can we use boost to build the server ? + +## Decide +- We miss some libraries in boost cmake so we need to add tham to build simple http client with boost +- We will add a Jira ticket to continue working on that \ No newline at end of file From ee227b3cbdd7bbbcba953fb0ab5c0d9a91c4fb8e Mon Sep 17 00:00:00 2001 From: Damien Menanteau Date: Thu, 27 May 2021 17:14:40 +0200 Subject: [PATCH 004/125] Remove FindCurl.cmake and FindHttpClient.cmake --- clients/cpp/cmake/FindCurl.cmake | 7 ------- clients/cpp/cmake/FindHttpClient.cmake | 8 -------- 2 files changed, 15 deletions(-) delete mode 100644 clients/cpp/cmake/FindCurl.cmake delete mode 100644 clients/cpp/cmake/FindHttpClient.cmake diff --git a/clients/cpp/cmake/FindCurl.cmake b/clients/cpp/cmake/FindCurl.cmake deleted file mode 100644 index 06f98d54..00000000 --- a/clients/cpp/cmake/FindCurl.cmake +++ /dev/null @@ -1,7 +0,0 @@ -# Fetch googletest - -CPMFindPackage( - NAME HTTPClient - GITHUB_REPOSITORY embeddedmz/httpclient-cpp - GIT_TAG master -) \ No newline at end of file diff --git a/clients/cpp/cmake/FindHttpClient.cmake b/clients/cpp/cmake/FindHttpClient.cmake deleted file mode 100644 index 739cfe0d..00000000 --- a/clients/cpp/cmake/FindHttpClient.cmake +++ /dev/null @@ -1,8 +0,0 @@ -# Fetch googletest - -CPMFindPackage( - NAME googletest - GITHUB_REPOSITORY google/googletest - GIT_TAG master - OPTIONS "INSTALL_GTEST OFF" "gtest_force_shared_crt" "BUILD_GMOCK OFF" -) \ No newline at end of file From debc3652b784e23b53f0040a0757a55b0dccf398 Mon Sep 17 00:00:00 2001 From: Damien Menanteau Date: Fri, 28 May 2021 12:47:40 +0200 Subject: [PATCH 005/125] Upgrade nlhmann_json to latest version (3.9.1) --- clients/cpp/cmake/FindNlohmannJson.cmake | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/clients/cpp/cmake/FindNlohmannJson.cmake b/clients/cpp/cmake/FindNlohmannJson.cmake index 7e279ad7..022cd094 100644 --- a/clients/cpp/cmake/FindNlohmannJson.cmake +++ b/clients/cpp/cmake/FindNlohmannJson.cmake @@ -2,22 +2,14 @@ CPMFindPackage( NAME nlohmann_json - VERSION 3.6.1 + VERSION 3.9.1 # the git repo is incredibly large, so we download the archived include directory - URL https://github.com/nlohmann/json/releases/download/v3.6.1/include.zip - URL_HASH SHA256=69cc88207ce91347ea530b227ff0776db82dcb8de6704e1a3d74f4841bc651cf + URL https://github.com/nlohmann/json/releases/download/v3.9.1/include.zip + URL_HASH SHA256=6bea5877b1541d353bd77bdfbdb2696333ae5ed8f9e8cc22df657192218cad91 + OPTIONS "JSON_BuildTests OFF" ) if (nlohmann_json_ADDED) add_library(nlohmann_json INTERFACE IMPORTED) target_include_directories(nlohmann_json INTERFACE ${nlohmann_json_SOURCE_DIR}) endif() - -# This is the latest package provided on CPM repo, but does not seem to work - -#CPMAddPackage( -# NAME nlohmann_json -# VERSION 3.9.1 -# OPTIONS -# "JSON_BuildTests OFF" -#) \ No newline at end of file From 67444abf6e7a8042ee34e21f7cf5316a2fbb935b Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 3 Jun 2021 15:17:18 +0200 Subject: [PATCH 006/125] Fix boost dependency --- clients/cpp/CMakeLists.txt | 3 ++- clients/cpp/TODOLIST.md | 4 +++- clients/cpp/test/ExtremeCarpaccioClientTest.cpp | 2 ++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/clients/cpp/CMakeLists.txt b/clients/cpp/CMakeLists.txt index c0300930..d2f1acd6 100644 --- a/clients/cpp/CMakeLists.txt +++ b/clients/cpp/CMakeLists.txt @@ -60,7 +60,8 @@ target_sources(Extreme-Carpaccio-Client-test target_link_libraries(Extreme-Carpaccio-Client-test PRIVATE Extreme-Carpaccio-Client-shared - gtest_main) + gtest_main + Boost::boost) add_test(NAME ctest-Extreme-Carpaccio-Client COMMAND Extreme-Carpaccio-Client-test) diff --git a/clients/cpp/TODOLIST.md b/clients/cpp/TODOLIST.md index 6c001ad7..8235b91a 100644 --- a/clients/cpp/TODOLIST.md +++ b/clients/cpp/TODOLIST.md @@ -4,4 +4,6 @@ ## PARKING - [ ] Clean gitignore file in cpp -- [ ] Ajouter dans le cmake le Json en thirdparty pour la soluation VS \ No newline at end of file +- [ ] Ajouter dans le cmake le Json en thirdparty pour la soluation VS +- [ ] Add dependencies on sub boost headers only libraries (beast), instead on depending on full boost +- [ ] Fix that : Failed to find all ICU components (missing: ICU_INCLUDE_DIR _ICU_REQUIRED_LIBS_FOUND) \ No newline at end of file diff --git a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp index 80b6146b..ef3b30ac 100644 --- a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp +++ b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp @@ -1,6 +1,8 @@ #include +#include + #include #include From 6683990ef1926de0078c40fb3f372819fd0e948d Mon Sep 17 00:00:00 2001 From: Damien Menanteau Date: Thu, 3 Jun 2021 15:44:30 +0200 Subject: [PATCH 007/125] Add raw HTTP call --- .../cpp/test/ExtremeCarpaccioClientTest.cpp | 66 ++++++++++++++++++- 1 file changed, 64 insertions(+), 2 deletions(-) diff --git a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp index ef3b30ac..df421196 100644 --- a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp +++ b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp @@ -1,16 +1,78 @@ #include -#include - #include #include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace beast = boost::beast; // from +namespace http = beast::http; // from +namespace net = boost::asio; // from +using tcp = net::ip::tcp; // from + + using namespace extreme_carpaccio_client; TEST(ExtremeCarpaccioClient, should_handle_feedback) { + + std::string host = "localhost"; + std::string port = "8081"; + std::string target = "/feedback"; + int version = 11; + + net::io_context ioc; + + // These objects perform our I/O + tcp::resolver resolver(ioc); + beast::tcp_stream stream(ioc); + + // Look up the domain name + auto const results = resolver.resolve(host, port); + + // Make the connection on the IP address we get from a lookup + stream.connect(results); + + // Set up an HTTP GET request message + http::request req{ http::verb::post, target, version }; + req.set(http::field::host, host); + req.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING); + + // Send the HTTP request to the remote host + http::write(stream, req); + + // This buffer is used for reading and must be persisted + beast::flat_buffer buffer; + + // Declare a container to hold the response + http::response res; + + // Receive the HTTP response + http::read(stream, buffer, res); + + // Write the message to standard out + std::cout << res << std::endl; + + // Gracefully close the socket + beast::error_code ec; + stream.socket().shutdown(tcp::socket::shutdown_both, ec); + + // not_connected happens sometimes + // so don't bother reporting it. + // + if (ec && ec != beast::errc::not_connected) + throw beast::system_error{ ec }; + + EXPECT_EQ(1, 1); } From 32720dbca5c4ea818668fa6ae1b7d1eef82eab43 Mon Sep 17 00:00:00 2001 From: NADIF Antoine Date: Thu, 3 Jun 2021 16:02:09 +0200 Subject: [PATCH 008/125] Add empty server shell for the Extreme Carpaccio Client (server) --- clients/cpp/CMakeLists.txt | 2 ++ .../ExtremeCarpaccioClient.hpp | 2 +- .../ExtremeCarpaccioClient.cpp | 35 ++++++++++++++++--- clients/cpp/src/main.cpp | 3 +- 4 files changed, 36 insertions(+), 6 deletions(-) diff --git a/clients/cpp/CMakeLists.txt b/clients/cpp/CMakeLists.txt index d2f1acd6..04437b01 100644 --- a/clients/cpp/CMakeLists.txt +++ b/clients/cpp/CMakeLists.txt @@ -37,6 +37,8 @@ target_include_directories(Extreme-Carpaccio-Client-shared ${CMAKE_CURRENT_SOURCE_DIR}/include ) +target_link_libraries(Extreme-Carpaccio-Client-shared PUBLIC Boost::boost) + # Client executable add_executable(Extreme-Carpaccio-Client) diff --git a/clients/cpp/include/extreme_carpaccio_client/ExtremeCarpaccioClient.hpp b/clients/cpp/include/extreme_carpaccio_client/ExtremeCarpaccioClient.hpp index f78aab11..f1eb0197 100644 --- a/clients/cpp/include/extreme_carpaccio_client/ExtremeCarpaccioClient.hpp +++ b/clients/cpp/include/extreme_carpaccio_client/ExtremeCarpaccioClient.hpp @@ -4,6 +4,6 @@ #include namespace extreme_carpaccio_client { - EXTREME_CARPACCIO_CLIENT_API int dummy(); + EXTREME_CARPACCIO_CLIENT_API int launchServer(); } // namespace extreme_carpaccio_client diff --git a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp index 6e627783..effb7436 100644 --- a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp +++ b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp @@ -1,14 +1,41 @@ #include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace ip = boost::asio::ip; // from +using tcp = boost::asio::ip::tcp; // from +namespace http = boost::beast::http; // from namespace extreme_carpaccio_client { - int dummy() + int launchServer() { - return 0; + auto const address = boost::asio::ip::make_address("localhost"); + unsigned short port = static_cast(std::atoi("8081")); + std::string doc_root = "./feedback"; + int num_workers = std::atoi("1"); + bool spin = true; + + boost::asio::io_context ioc{ 1 }; + tcp::acceptor acceptor{ ioc, {address, port} }; + + + + return EXIT_SUCCESS; } diff --git a/clients/cpp/src/main.cpp b/clients/cpp/src/main.cpp index e6b9bb0f..279288ca 100644 --- a/clients/cpp/src/main.cpp +++ b/clients/cpp/src/main.cpp @@ -1,6 +1,7 @@ +#include int main() { - + extreme_carpaccio_client::launchServer(); } \ No newline at end of file From c4fed7eb70c4be7bf1c718a84d4ae55a3bc6a406 Mon Sep 17 00:00:00 2001 From: Philippe Bourgau Date: Fri, 4 Jun 2021 10:31:39 +0200 Subject: [PATCH 009/125] Update TODO list with a plan of things to do, in order to resume work smoothly --- clients/cpp/TODOLIST.md | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/clients/cpp/TODOLIST.md b/clients/cpp/TODOLIST.md index 8235b91a..01836946 100644 --- a/clients/cpp/TODOLIST.md +++ b/clients/cpp/TODOLIST.md @@ -1,9 +1,28 @@ # TO DO LIST - +## TODO +- [X] Write a test sending an http request + - [X] Deal with all the cmake arcane... +- [ ] Create a main exe that starts a server and answers OK to a GET /whatever, test it in the browser +- [ ] Update our test to check that this GET /whatever works well +- [ ] Deal with starting & stoping the server correctly in the test to avoid resource leaks +- [ ] Implement the POST /order command + - [ ] check what the request and answers should look like from the js versions + - [ ] write a test to POST /order with a proper request + - [ ] implement POST /order + - [ ] test our client with the real extreme carpaccio server + - [ ] make sure we can easily build a json response (and play the game) +- [ ] Implement the POST /feedback command + - [ ] check what the request, answers and behavior should look like from the js versions + - [ ] write a test to POST /feedback with a proper request + - [ ] implement POST /feedback + - [ ] test our client can receive feedback form the real extreme carpaccio server +- [ ] Add a configuration file for main options (ports and maybe others) + - [ ] check the js client to see what options are available + - [ ] create a config file of command line options to set these options ## PARKING - [ ] Clean gitignore file in cpp -- [ ] Ajouter dans le cmake le Json en thirdparty pour la soluation VS +- [ ] Ajouter dans le cmake le Json en thirdparty pour la solution VS - [ ] Add dependencies on sub boost headers only libraries (beast), instead on depending on full boost - [ ] Fix that : Failed to find all ICU components (missing: ICU_INCLUDE_DIR _ICU_REQUIRED_LIBS_FOUND) \ No newline at end of file From 1f85d1f7989ae7189c26561693ee57b684e4f261 Mon Sep 17 00:00:00 2001 From: NADIF Antoine Date: Thu, 17 Jun 2021 15:27:26 +0200 Subject: [PATCH 010/125] Lay the ground work for the server, only minor details left to do. --- .../extreme_carpaccio_client/ExtremeCarpaccioClient.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp index effb7436..b7392e86 100644 --- a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp +++ b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp @@ -20,11 +20,16 @@ namespace ip = boost::asio::ip; // from using tcp = boost::asio::ip::tcp; // from namespace http = boost::beast::http; // from +static void start(tcp::acceptor& acceptor, const std::string& doc_root) +{ + +} + namespace extreme_carpaccio_client { int launchServer() { - auto const address = boost::asio::ip::make_address("localhost"); + auto const address = boost::asio::ip::make_address("127.0.0.1"); unsigned short port = static_cast(std::atoi("8081")); std::string doc_root = "./feedback"; int num_workers = std::atoi("1"); @@ -33,6 +38,8 @@ namespace extreme_carpaccio_client { boost::asio::io_context ioc{ 1 }; tcp::acceptor acceptor{ ioc, {address, port} }; + start(acceptor, doc_root); + return EXIT_SUCCESS; From 892ff3494bf43cbe9d08689f1d1efc971f4288b1 Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 17 Jun 2021 15:56:11 +0200 Subject: [PATCH 011/125] Almost done with the server... --- .../ExtremeCarpaccioClient.cpp | 84 ++++++++++++++++++- 1 file changed, 82 insertions(+), 2 deletions(-) diff --git a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp index b7392e86..5466ca12 100644 --- a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp +++ b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp @@ -20,11 +20,90 @@ namespace ip = boost::asio::ip; // from using tcp = boost::asio::ip::tcp; // from namespace http = boost::beast::http; // from -static void start(tcp::acceptor& acceptor, const std::string& doc_root) +class http_worker { +public: +http_worker(tcp::acceptor& acceptor, const std::string& doc_root): + m_acceptor(acceptor), m_doc_root(doc_root), m_socket(m_acceptor.get_executor().context()) +{ +} + +void send_bad_response( + http::status status, + std::string const& error) +{ + http::response string_response_; + + string_response_.result(status); + string_response_.keep_alive(false); + string_response_.set(http::field::server, "Beast"); + string_response_.set(http::field::content_type, "text/plain"); + string_response_.body() = error; + string_response_.prepare_payload(); + + http::response_serializer string_serializer(string_response_); + + http::async_write( + m_socket, + string_serializer, + [this](boost::beast::error_code ec, std::size_t) + { + m_socket.shutdown(tcp::socket::shutdown_send, ec); + accept(); + }); +} + + +void read_request() +{ + // On each read the parser needs to be destroyed and + // recreated. We store it in a boost::optional to + // achieve that. + // + // Arguments passed to the parser constructor are + // forwarded to the message object. A single argument + // is forwarded to the body constructor. + // + // We construct the dynamic body with a 1MB limit + // to prevent vulnerability to buffer attacks. + // + + http::request_parser parser; + + http::async_read( + m_socket, + m_buffer, + parser, + [this](boost::beast::error_code ec, std::size_t) + { + send_bad_response(http::status::bad_request, "Invalid request-method"); + }); +} + +void accept() +{ + m_acceptor.async_accept( + m_socket, + [this](boost::beast::error_code ec) + { + read_request(); + }); + +} +void start() +{ + accept(); } +private: + tcp::acceptor& m_acceptor; + const std::string& m_doc_root; + tcp::socket m_socket; + boost::beast::flat_static_buffer<8192> m_buffer; +}; + + namespace extreme_carpaccio_client { int launchServer() @@ -38,7 +117,8 @@ namespace extreme_carpaccio_client { boost::asio::io_context ioc{ 1 }; tcp::acceptor acceptor{ ioc, {address, port} }; - start(acceptor, doc_root); + http_worker worker(acceptor, doc_root); + worker.start(); From 19cd41967d007933a77bdf7f66bffa14bcfd6d66 Mon Sep 17 00:00:00 2001 From: NADIF Antoine Date: Thu, 17 Jun 2021 16:42:37 +0200 Subject: [PATCH 012/125] Make the server send a bad request on any http query. --- .../ExtremeCarpaccioClient.cpp | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp index 5466ca12..1c795cd1 100644 --- a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp +++ b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp @@ -23,8 +23,10 @@ namespace http = boost::beast::http; // from class http_worker { public: -http_worker(tcp::acceptor& acceptor, const std::string& doc_root): - m_acceptor(acceptor), m_doc_root(doc_root), m_socket(m_acceptor.get_executor().context()) +http_worker(tcp::acceptor& acceptor, const std::string& doc_root) + : m_acceptor(acceptor) + , m_doc_root(doc_root) + , m_socket(m_acceptor.get_executor()) { } @@ -68,16 +70,16 @@ void read_request() // to prevent vulnerability to buffer attacks. // - http::request_parser parser; + //http::request_parser parser(std::piecewise_construct, std::make_tuple()); - http::async_read( - m_socket, - m_buffer, - parser, - [this](boost::beast::error_code ec, std::size_t) - { + //http::async_read( + // m_socket, + // m_buffer, + // parser, + // [this](boost::beast::error_code ec, std::size_t) + // { send_bad_response(http::status::bad_request, "Invalid request-method"); - }); + //}); } void accept() @@ -111,8 +113,8 @@ namespace extreme_carpaccio_client { auto const address = boost::asio::ip::make_address("127.0.0.1"); unsigned short port = static_cast(std::atoi("8081")); std::string doc_root = "./feedback"; - int num_workers = std::atoi("1"); - bool spin = true; + //int num_workers = std::atoi("1"); + //bool spin = true; boost::asio::io_context ioc{ 1 }; tcp::acceptor acceptor{ ioc, {address, port} }; @@ -120,7 +122,7 @@ namespace extreme_carpaccio_client { http_worker worker(acceptor, doc_root); worker.start(); - + ioc.run(); return EXIT_SUCCESS; } From e8b96b55ec624c44c4379278ee745aef0a4b0ac1 Mon Sep 17 00:00:00 2001 From: NADIF Antoine Date: Thu, 15 Jul 2021 11:44:11 +0200 Subject: [PATCH 013/125] Integrate Boost Beast fast server example as is to have a starting point. --- .../ExtremeCarpaccioClient.cpp | 317 ++++++++++++++---- 1 file changed, 246 insertions(+), 71 deletions(-) diff --git a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp index 1c795cd1..bfbacc0f 100644 --- a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp +++ b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp @@ -5,7 +5,6 @@ #include #include #include -#include #include #include #include @@ -14,98 +13,274 @@ #include #include -#include +namespace beast = boost::beast; // from +namespace http = beast::http; // from +namespace net = boost::asio; // from +using tcp = boost::asio::ip::tcp; // from -namespace ip = boost::asio::ip; // from -using tcp = boost::asio::ip::tcp; // from -namespace http = boost::beast::http; // from +// Return a reasonable mime type based on the extension of a file. +beast::string_view +mime_type(beast::string_view path) +{ + using beast::iequals; + auto const ext = [&path] + { + auto const pos = path.rfind("."); + if (pos == beast::string_view::npos) + return beast::string_view{}; + return path.substr(pos); + }(); + if (iequals(ext, ".htm")) return "text/html"; + if (iequals(ext, ".html")) return "text/html"; + if (iequals(ext, ".php")) return "text/html"; + if (iequals(ext, ".css")) return "text/css"; + if (iequals(ext, ".txt")) return "text/plain"; + if (iequals(ext, ".js")) return "application/javascript"; + if (iequals(ext, ".json")) return "application/json"; + if (iequals(ext, ".xml")) return "application/xml"; + if (iequals(ext, ".swf")) return "application/x-shockwave-flash"; + if (iequals(ext, ".flv")) return "video/x-flv"; + if (iequals(ext, ".png")) return "image/png"; + if (iequals(ext, ".jpe")) return "image/jpeg"; + if (iequals(ext, ".jpeg")) return "image/jpeg"; + if (iequals(ext, ".jpg")) return "image/jpeg"; + if (iequals(ext, ".gif")) return "image/gif"; + if (iequals(ext, ".bmp")) return "image/bmp"; + if (iequals(ext, ".ico")) return "image/vnd.microsoft.icon"; + if (iequals(ext, ".tiff")) return "image/tiff"; + if (iequals(ext, ".tif")) return "image/tiff"; + if (iequals(ext, ".svg")) return "image/svg+xml"; + if (iequals(ext, ".svgz")) return "image/svg+xml"; + return "application/text"; +} class http_worker { public: -http_worker(tcp::acceptor& acceptor, const std::string& doc_root) - : m_acceptor(acceptor) - , m_doc_root(doc_root) - , m_socket(m_acceptor.get_executor()) -{ -} + http_worker(http_worker const&) = delete; + http_worker& operator=(http_worker const&) = delete; -void send_bad_response( - http::status status, - std::string const& error) -{ - http::response string_response_; + http_worker(tcp::acceptor& acceptor, const std::string& doc_root) : + acceptor_(acceptor), + doc_root_(doc_root) + { + } + + void start() + { + accept(); + check_deadline(); + } + +private: + using alloc_t = std::allocator; + //using request_body_t = http::basic_dynamic_body>; + using request_body_t = http::string_body; + + // The acceptor used to listen for incoming connections. + tcp::acceptor& acceptor_; + + // The path to the root of the document directory. + std::string doc_root_; + + // The socket for the currently connected client. + tcp::socket socket_{ acceptor_.get_executor() }; - string_response_.result(status); - string_response_.keep_alive(false); - string_response_.set(http::field::server, "Beast"); - string_response_.set(http::field::content_type, "text/plain"); - string_response_.body() = error; - string_response_.prepare_payload(); + // The buffer for performing reads + beast::flat_static_buffer<8192> buffer_; - http::response_serializer string_serializer(string_response_); + // The allocator used for the fields in the request and reply. + alloc_t alloc_; - http::async_write( - m_socket, - string_serializer, - [this](boost::beast::error_code ec, std::size_t) + // The parser for reading the requests + boost::optional> parser_; + + // The timer putting a time limit on requests. + net::steady_timer request_deadline_{ + acceptor_.get_executor(), (std::chrono::steady_clock::time_point::max)() }; + + // The string-based response message. + boost::optional>> string_response_; + + // The file-based response message. + boost::optional>> file_response_; + + void accept() + { + // Clean up any previous connection. + beast::error_code ec; + socket_.close(ec); + buffer_.consume(buffer_.size()); + + acceptor_.async_accept( + socket_, + [this](beast::error_code ec) + { + if (ec) + { + accept(); + } + else + { + // Request must be fully processed within 60 seconds. + request_deadline_.expires_after( + std::chrono::seconds(60)); + + read_request(); + } + }); + } + + void read_request() + { + // On each read the parser needs to be destroyed and + // recreated. We store it in a boost::optional to + // achieve that. + // + // Arguments passed to the parser constructor are + // forwarded to the message object. A single argument + // is forwarded to the body constructor. + // + // We construct the dynamic body with a 1MB limit + // to prevent vulnerability to buffer attacks. + // + parser_.emplace( + std::piecewise_construct, + std::make_tuple(), + std::make_tuple(alloc_)); + + http::async_read( + socket_, + buffer_, + *parser_, + [this](beast::error_code ec, std::size_t) { - m_socket.shutdown(tcp::socket::shutdown_send, ec); + if (ec) + accept(); + else + process_request(parser_->get()); + }); + } + + void process_request(http::request> const& req) + { + switch (req.method()) + { + case http::verb::get: + send_file(req.target()); + break; + + default: + // We return responses indicating an error if + // we do not recognize the request method. + send_bad_response( + http::status::bad_request, + "Invalid request-method '" + std::string(req.method_string()) + "'\r\n"); + break; + } + } + + void send_bad_response( + http::status status, + std::string const& error) + { + string_response_.emplace( + std::piecewise_construct, + std::make_tuple(), + std::make_tuple(alloc_)); + + string_response_->result(status); + string_response_->keep_alive(false); + string_response_->set(http::field::server, "Beast"); + string_response_->set(http::field::content_type, "text/plain"); + string_response_->body() = error; + string_response_->prepare_payload(); + + http::async_write( + socket_, + *string_response_, + [this](beast::error_code ec, std::size_t) + { + socket_.shutdown(tcp::socket::shutdown_send, ec); + string_response_.reset(); accept(); }); -} + } + void send_file(beast::string_view target) + { + // Request path must be absolute and not contain "..". + if (target.empty() || target[0] != '/' || target.find("..") != std::string::npos) + { + send_bad_response( + http::status::not_found, + "File not found\r\n"); + return; + } -void read_request() -{ - // On each read the parser needs to be destroyed and - // recreated. We store it in a boost::optional to - // achieve that. - // - // Arguments passed to the parser constructor are - // forwarded to the message object. A single argument - // is forwarded to the body constructor. - // - // We construct the dynamic body with a 1MB limit - // to prevent vulnerability to buffer attacks. - // - - //http::request_parser parser(std::piecewise_construct, std::make_tuple()); - - //http::async_read( - // m_socket, - // m_buffer, - // parser, - // [this](boost::beast::error_code ec, std::size_t) - // { - send_bad_response(http::status::bad_request, "Invalid request-method"); - //}); -} + std::string full_path = doc_root_; + full_path.append( + target.data(), + target.size()); -void accept() -{ - m_acceptor.async_accept( - m_socket, - [this](boost::beast::error_code ec) + http::file_body::value_type file; + beast::error_code ec; + file.open( + full_path.c_str(), + beast::file_mode::read, + ec); + if (ec) { - read_request(); + send_bad_response( + http::status::not_found, + "File not found\r\n"); + return; + } + + file_response_.emplace( + std::piecewise_construct, + std::make_tuple(), + std::make_tuple(alloc_)); + + file_response_->result(http::status::ok); + file_response_->keep_alive(false); + file_response_->set(http::field::server, "Beast"); + file_response_->set(http::field::content_type, mime_type(std::string(target))); + file_response_->body() = std::move(file); + file_response_->prepare_payload(); + + http::async_write( + socket_, + *file_response_, + [this](beast::error_code ec, std::size_t) + { + socket_.shutdown(tcp::socket::shutdown_send, ec); + file_response_.reset(); + accept(); }); + } -} + void check_deadline() + { + // The deadline may have moved, so check it has really passed. + if (request_deadline_.expiry() <= std::chrono::steady_clock::now()) + { + // Close socket to cancel any outstanding operation. + socket_.close(); -void start() -{ - accept(); -} + // Sleep indefinitely until we're given a new deadline. + request_deadline_.expires_at( + (std::chrono::steady_clock::time_point::max)()); + } -private: - tcp::acceptor& m_acceptor; - const std::string& m_doc_root; - tcp::socket m_socket; - boost::beast::flat_static_buffer<8192> m_buffer; + request_deadline_.async_wait( + [this](beast::error_code) + { + check_deadline(); + }); + } }; - namespace extreme_carpaccio_client { int launchServer() From 1446ed3a6d748eabbdbef6581e2f66c430523a33 Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 15 Jul 2021 17:41:37 +0200 Subject: [PATCH 014/125] Retro + update on todo --- clients/cpp/Retrospective.md | 14 ++++++++++++-- clients/cpp/TODOLIST.md | 5 +++-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/clients/cpp/Retrospective.md b/clients/cpp/Retrospective.md index 4e195cdb..35237674 100644 --- a/clients/cpp/Retrospective.md +++ b/clients/cpp/Retrospective.md @@ -1,6 +1,7 @@ # RETROSPECTIVE 05/27/2021 +07/15/2021 ## What did we do ? - We did some cmake and CPM @@ -9,17 +10,26 @@ - We updated CPM to latest version - We made a copy of Bowling game kata to have all cmake config ready - We debugged requests format using JS version of carpaccio +07/15/2021 +- We changed our approach, we chose to get the full example code and tested it successfully +- We change the allocator by using the default allocator, and it worked ## What did we learn ? - Patrice learnt on client/server problematic and REST requests - +07/15/2021 +- We learnt that folder and file need to exist to be able to retrieve them from the server +- Starting with something that works and try to refactoring seems to be a good solution ## Puzzle - Dependencies handling in cpp is sport ! - We have the boost example of GET, will it work with POST ? - Can we use boost to build the server ? +07/15/2021 +- boost beast is a bit tricky to understand and troubleshoot +- Example of server using boost library is not real good c++ !! ## Decide - We miss some libraries in boost cmake so we need to add tham to build simple http client with boost -- We will add a Jira ticket to continue working on that \ No newline at end of file +- We will add a Jira ticket to continue working on that +- 07/15/2021 \ No newline at end of file diff --git a/clients/cpp/TODOLIST.md b/clients/cpp/TODOLIST.md index 01836946..7392a448 100644 --- a/clients/cpp/TODOLIST.md +++ b/clients/cpp/TODOLIST.md @@ -3,8 +3,9 @@ ## TODO - [X] Write a test sending an http request - [X] Deal with all the cmake arcane... -- [ ] Create a main exe that starts a server and answers OK to a GET /whatever, test it in the browser -- [ ] Update our test to check that this GET /whatever works well +- [X] Create a main exe that starts a server +- [X] Manual test that it can display a bmp, test it in the browser +- [ ] Update our test to check that client can get a file not found from the server - [ ] Deal with starting & stoping the server correctly in the test to avoid resource leaks - [ ] Implement the POST /order command - [ ] check what the request and answers should look like from the js versions From 7c390382947976d6fff152dd7d28ba8130a45c43 Mon Sep 17 00:00:00 2001 From: Damien Menanteau Date: Thu, 2 Sep 2021 14:45:24 +0200 Subject: [PATCH 015/125] Working... --- clients/cpp/pull-push.sh | 33 +++++++++++++++++++++++++++++++++ clients/cpp/watch.sh | 27 +++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 clients/cpp/pull-push.sh create mode 100644 clients/cpp/watch.sh diff --git a/clients/cpp/pull-push.sh b/clients/cpp/pull-push.sh new file mode 100644 index 00000000..4be0b677 --- /dev/null +++ b/clients/cpp/pull-push.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env sh +# +# Copyright (c) 2021 Murex +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +# Pulls and pushes the current git branch. +# +# Use it to quickly switch driver in a remote mob or randori + +CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD) +export CURRENT_BRANCH + +git pull --no-recurse-submodules origin "${CURRENT_BRANCH}" +git add . +git commit -m 'Working...' +git push --no-recurse-submodules origin "${CURRENT_BRANCH}" diff --git a/clients/cpp/watch.sh b/clients/cpp/watch.sh new file mode 100644 index 00000000..f98c9b0d --- /dev/null +++ b/clients/cpp/watch.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env sh +# +# Copyright (c) 2021 Murex +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +cd "$(dirname -- "$0")" || exit + +while true; do + ./pull-push.sh +done From d3282d4b09db13aa730541e587dbb33c239df317 Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 2 Sep 2021 14:51:38 +0200 Subject: [PATCH 016/125] Thread --- clients/cpp/test/ExtremeCarpaccioClientTest.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp index df421196..d4e26470 100644 --- a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp +++ b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp @@ -13,6 +13,7 @@ #include #include #include +#include namespace beast = boost::beast; // from namespace http = beast::http; // from @@ -24,6 +25,7 @@ using namespace extreme_carpaccio_client; TEST(ExtremeCarpaccioClient, should_handle_feedback) { + std::thread thread(extreme_carpaccio_client::launchServer); std::string host = "localhost"; std::string port = "8081"; From 0b283000717679aa8c6974caf8ca50e0e242b2da Mon Sep 17 00:00:00 2001 From: Philippe Bourgau Date: Thu, 2 Sep 2021 15:43:37 +0200 Subject: [PATCH 017/125] thread detach --- clients/cpp/test/ExtremeCarpaccioClientTest.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp index d4e26470..af815a72 100644 --- a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp +++ b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp @@ -26,6 +26,7 @@ using namespace extreme_carpaccio_client; TEST(ExtremeCarpaccioClient, should_handle_feedback) { std::thread thread(extreme_carpaccio_client::launchServer); + std::this_thread::sleep_for(std::chrono::seconds(5)); std::string host = "localhost"; std::string port = "8081"; @@ -76,6 +77,7 @@ TEST(ExtremeCarpaccioClient, should_handle_feedback) EXPECT_EQ(1, 1); + thread.detach(); } TEST(ExtremeCarpaccioClient, should_handle_order) From 0617e05a070e891fc582707209a1b033ffbb31c9 Mon Sep 17 00:00:00 2001 From: Damien Menanteau Date: Thu, 2 Sep 2021 15:45:10 +0200 Subject: [PATCH 018/125] Add watch.sh --- clients/cpp/pull-push.sh | 33 +++++++++++++++++++++++++++++++++ clients/cpp/watch.sh | 27 +++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 clients/cpp/pull-push.sh create mode 100644 clients/cpp/watch.sh diff --git a/clients/cpp/pull-push.sh b/clients/cpp/pull-push.sh new file mode 100644 index 00000000..4be0b677 --- /dev/null +++ b/clients/cpp/pull-push.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env sh +# +# Copyright (c) 2021 Murex +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +# Pulls and pushes the current git branch. +# +# Use it to quickly switch driver in a remote mob or randori + +CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD) +export CURRENT_BRANCH + +git pull --no-recurse-submodules origin "${CURRENT_BRANCH}" +git add . +git commit -m 'Working...' +git push --no-recurse-submodules origin "${CURRENT_BRANCH}" diff --git a/clients/cpp/watch.sh b/clients/cpp/watch.sh new file mode 100644 index 00000000..f98c9b0d --- /dev/null +++ b/clients/cpp/watch.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env sh +# +# Copyright (c) 2021 Murex +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +cd "$(dirname -- "$0")" || exit + +while true; do + ./pull-push.sh +done From 4ee3bf4a890dbfa015016e0b8f9b4dbad0e1ab66 Mon Sep 17 00:00:00 2001 From: Damien Menanteau Date: Thu, 2 Sep 2021 15:50:56 +0200 Subject: [PATCH 019/125] Working... --- .../src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp index bfbacc0f..61db5f3f 100644 --- a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp +++ b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp @@ -297,7 +297,8 @@ namespace extreme_carpaccio_client { http_worker worker(acceptor, doc_root); worker.start(); - ioc.run(); + // TODO For tests. Should handle multiple requests later + ioc.run_one(); return EXIT_SUCCESS; } From 2e9a5ed24bc634a618a871fdc1f6496a4627b93f Mon Sep 17 00:00:00 2001 From: Damien Menanteau Date: Thu, 2 Sep 2021 15:51:19 +0200 Subject: [PATCH 020/125] Working... --- clients/cpp/test/ExtremeCarpaccioClientTest.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp index af815a72..4ae8913f 100644 --- a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp +++ b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp @@ -75,9 +75,8 @@ TEST(ExtremeCarpaccioClient, should_handle_feedback) if (ec && ec != beast::errc::not_connected) throw beast::system_error{ ec }; - EXPECT_EQ(1, 1); - thread.detach(); + thread.join(); } TEST(ExtremeCarpaccioClient, should_handle_order) From 5483f0fc36bf0775ddaf281312a80d1f640bdcf9 Mon Sep 17 00:00:00 2001 From: Damien Menanteau Date: Thu, 2 Sep 2021 15:52:54 +0200 Subject: [PATCH 021/125] Working... --- clients/cpp/test/ExtremeCarpaccioClientTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp index 4ae8913f..1d831947 100644 --- a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp +++ b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp @@ -26,7 +26,7 @@ using namespace extreme_carpaccio_client; TEST(ExtremeCarpaccioClient, should_handle_feedback) { std::thread thread(extreme_carpaccio_client::launchServer); - std::this_thread::sleep_for(std::chrono::seconds(5)); + std::this_thread::sleep_for(std::chrono::seconds(1)); std::string host = "localhost"; std::string port = "8081"; From cf6ced00e0b5ca2eb426d7523ed8aed70dcc20c4 Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 2 Sep 2021 15:53:43 +0200 Subject: [PATCH 022/125] Working... --- clients/cpp/test/ExtremeCarpaccioClientTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp index 1d831947..cf93c3d8 100644 --- a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp +++ b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp @@ -46,7 +46,7 @@ TEST(ExtremeCarpaccioClient, should_handle_feedback) stream.connect(results); // Set up an HTTP GET request message - http::request req{ http::verb::post, target, version }; + http::request req{ http::verb::get, target, version }; req.set(http::field::host, host); req.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING); From 8e7a25ae7042a4e01436bd35214628e0882496fe Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 2 Sep 2021 15:54:00 +0200 Subject: [PATCH 023/125] Working... --- clients/cpp/test/ExtremeCarpaccioClientTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp index cf93c3d8..a473ee62 100644 --- a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp +++ b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp @@ -30,7 +30,7 @@ TEST(ExtremeCarpaccioClient, should_handle_feedback) std::string host = "localhost"; std::string port = "8081"; - std::string target = "/feedback"; + std::string target = "/toto.png"; int version = 11; net::io_context ioc; From fe1349930b28d98ff5abde0b4c1f6c4c8361e915 Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 2 Sep 2021 15:56:18 +0200 Subject: [PATCH 024/125] Working... --- .../cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp index 61db5f3f..c548d3b1 100644 --- a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp +++ b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp @@ -298,7 +298,7 @@ namespace extreme_carpaccio_client { worker.start(); // TODO For tests. Should handle multiple requests later - ioc.run_one(); + ioc.run(); return EXIT_SUCCESS; } From 3d89a8eb9d64601e0e9d7aab92f016116b0960b8 Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 2 Sep 2021 15:56:33 +0200 Subject: [PATCH 025/125] Working... --- clients/cpp/test/ExtremeCarpaccioClientTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp index a473ee62..2d9ee0a1 100644 --- a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp +++ b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp @@ -26,7 +26,7 @@ using namespace extreme_carpaccio_client; TEST(ExtremeCarpaccioClient, should_handle_feedback) { std::thread thread(extreme_carpaccio_client::launchServer); - std::this_thread::sleep_for(std::chrono::seconds(1)); + std::this_thread::sleep_for(std::chrono::seconds(5)); std::string host = "localhost"; std::string port = "8081"; From 575bbb3a19b313f713f0679ef6f88cdb0fdbf02a Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 2 Sep 2021 15:56:36 +0200 Subject: [PATCH 026/125] Working... --- clients/cpp/test/ExtremeCarpaccioClientTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp index 2d9ee0a1..ece5c7e1 100644 --- a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp +++ b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp @@ -76,7 +76,7 @@ TEST(ExtremeCarpaccioClient, should_handle_feedback) throw beast::system_error{ ec }; EXPECT_EQ(1, 1); - thread.join(); + thread.detach(); } TEST(ExtremeCarpaccioClient, should_handle_order) From ebe258305168f883298c51bda0a428d74d8ac435 Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 2 Sep 2021 15:58:29 +0200 Subject: [PATCH 027/125] Working... --- clients/cpp/test/ExtremeCarpaccioClientTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp index ece5c7e1..fadc6428 100644 --- a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp +++ b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp @@ -63,7 +63,7 @@ TEST(ExtremeCarpaccioClient, should_handle_feedback) http::read(stream, buffer, res); // Write the message to standard out - std::cout << res << std::endl; + std::cout << "Result : " << res << std::endl; // Gracefully close the socket beast::error_code ec; From 65c421472bfb5f73cf9d142beb5a8010843d6fd9 Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 2 Sep 2021 16:10:03 +0200 Subject: [PATCH 028/125] toto.png --- clients/cpp/build/feedback/toto.png | Bin 0 -> 692 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 clients/cpp/build/feedback/toto.png diff --git a/clients/cpp/build/feedback/toto.png b/clients/cpp/build/feedback/toto.png new file mode 100644 index 0000000000000000000000000000000000000000..db9458dc18b7101d73391627c16b1465967e812c GIT binary patch literal 692 zcmV;l0!#ggP)AnxkT)#)2+X)5Z~Bsn&iO*hGc2*IsA{8buD^!_MqxT-G0?6h``KX zO%6|7s`!@*VfbiAygSgHiL*;dFe%3Sd&gCLQ9VzxmXVq+t)d7Am_bBAFc){+y4&_c zMfL*9hoz)ei%mis3{?k}e21p@Nwm3Gx-^BQUxC4DwrFOPPl5q}KUQcXY=sIa05s*} z?=tpR{rWcMr0!iA>YmSdKIUG#J+IH*HVfrZwzPR(TXyV&^!aiI^#V*JiIGl?j(HB? zAth-)H@ko| z>cnkZ{hFo8SZ7Vw#DyOgW`IbNWDvs~)REp}5^)Bm2lZ~aUbed8 aj(rR89Vz20`UpG#0000 Date: Thu, 2 Sep 2021 16:11:58 +0200 Subject: [PATCH 029/125] Working... --- clients/cpp/test/ExtremeCarpaccioClientTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp index fadc6428..daeda047 100644 --- a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp +++ b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp @@ -63,7 +63,7 @@ TEST(ExtremeCarpaccioClient, should_handle_feedback) http::read(stream, buffer, res); // Write the message to standard out - std::cout << "Result : " << res << std::endl; + std::cout << "Response" << std::endl << res << std::endl; // Gracefully close the socket beast::error_code ec; From df7ce6c9c78a4e5b453c5cb9d5dc8b2c519a62a1 Mon Sep 17 00:00:00 2001 From: Damien Menanteau Date: Thu, 2 Sep 2021 16:14:07 +0200 Subject: [PATCH 030/125] Working... --- clients/cpp/test/ExtremeCarpaccioClientTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp index daeda047..ef6b5b85 100644 --- a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp +++ b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp @@ -26,7 +26,7 @@ using namespace extreme_carpaccio_client; TEST(ExtremeCarpaccioClient, should_handle_feedback) { std::thread thread(extreme_carpaccio_client::launchServer); - std::this_thread::sleep_for(std::chrono::seconds(5)); + std::this_thread::sleep_for(std::chrono::seconds(1)); std::string host = "localhost"; std::string port = "8081"; From 34cf592c61760cca3877c15afe800e64e1990701 Mon Sep 17 00:00:00 2001 From: Damien Menanteau Date: Thu, 2 Sep 2021 16:18:40 +0200 Subject: [PATCH 031/125] Working... --- clients/cpp/test/ExtremeCarpaccioClientTest.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp index ef6b5b85..0c2660fa 100644 --- a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp +++ b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp @@ -75,11 +75,11 @@ TEST(ExtremeCarpaccioClient, should_handle_feedback) if (ec && ec != beast::errc::not_connected) throw beast::system_error{ ec }; - EXPECT_EQ(1, 1); + EXPECT_EQ(http::status::ok, res.result); thread.detach(); } -TEST(ExtremeCarpaccioClient, should_handle_order) +TEST(ExtremeCarpaccioClient, DISABLED_should_handle_order) { EXPECT_EQ(1, 1); } From 0b1d6fa52efb2ad76ea48675fd0c8bee4924ee1f Mon Sep 17 00:00:00 2001 From: Damien Menanteau Date: Thu, 2 Sep 2021 16:19:23 +0200 Subject: [PATCH 032/125] Working... --- clients/cpp/test/ExtremeCarpaccioClientTest.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp index 0c2660fa..abb7eb6d 100644 --- a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp +++ b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp @@ -61,9 +61,10 @@ TEST(ExtremeCarpaccioClient, should_handle_feedback) // Receive the HTTP response http::read(stream, buffer, res); + EXPECT_EQ(http::status::ok, res.result()); // Write the message to standard out - std::cout << "Response" << std::endl << res << std::endl; + //std::cout << "Response" << std::endl << res << std::endl; // Gracefully close the socket beast::error_code ec; @@ -75,7 +76,6 @@ TEST(ExtremeCarpaccioClient, should_handle_feedback) if (ec && ec != beast::errc::not_connected) throw beast::system_error{ ec }; - EXPECT_EQ(http::status::ok, res.result); thread.detach(); } From b7d3c62f1378c59859e7b6920609ebbdd45ef97e Mon Sep 17 00:00:00 2001 From: Damien Menanteau Date: Thu, 2 Sep 2021 16:20:42 +0200 Subject: [PATCH 033/125] Working... --- clients/cpp/test/ExtremeCarpaccioClientTest.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp index abb7eb6d..9917785b 100644 --- a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp +++ b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp @@ -61,10 +61,11 @@ TEST(ExtremeCarpaccioClient, should_handle_feedback) // Receive the HTTP response http::read(stream, buffer, res); - EXPECT_EQ(http::status::ok, res.result()); + // Write the message to standard out - //std::cout << "Response" << std::endl << res << std::endl; + std::cout << "Response" << std::endl << res << std::endl; + EXPECT_EQ(http::status::ok, res.result()); // Gracefully close the socket beast::error_code ec; From ae6209196a148c1327ba9f168ee9a78690d2880d Mon Sep 17 00:00:00 2001 From: Damien Menanteau Date: Thu, 2 Sep 2021 16:22:55 +0200 Subject: [PATCH 034/125] Working... --- clients/cpp/test/ExtremeCarpaccioClientTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp index 9917785b..fa4615e2 100644 --- a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp +++ b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp @@ -26,7 +26,7 @@ using namespace extreme_carpaccio_client; TEST(ExtremeCarpaccioClient, should_handle_feedback) { std::thread thread(extreme_carpaccio_client::launchServer); - std::this_thread::sleep_for(std::chrono::seconds(1)); + std::this_thread::sleep_for(std::chrono::seconds(5)); std::string host = "localhost"; std::string port = "8081"; From 81f3c52fbc3fc4f5134cbf9515c2bca0707103c5 Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 2 Sep 2021 16:25:16 +0200 Subject: [PATCH 035/125] Working... --- clients/cpp/test/ExtremeCarpaccioClientTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp index fa4615e2..9917785b 100644 --- a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp +++ b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp @@ -26,7 +26,7 @@ using namespace extreme_carpaccio_client; TEST(ExtremeCarpaccioClient, should_handle_feedback) { std::thread thread(extreme_carpaccio_client::launchServer); - std::this_thread::sleep_for(std::chrono::seconds(5)); + std::this_thread::sleep_for(std::chrono::seconds(1)); std::string host = "localhost"; std::string port = "8081"; From 79f7e61de05bae4d632690c324e853a46c3498f4 Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 2 Sep 2021 16:25:57 +0200 Subject: [PATCH 036/125] Working... --- .../cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp index c548d3b1..61db5f3f 100644 --- a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp +++ b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp @@ -298,7 +298,7 @@ namespace extreme_carpaccio_client { worker.start(); // TODO For tests. Should handle multiple requests later - ioc.run(); + ioc.run_one(); return EXIT_SUCCESS; } From 531b9ebbcc96152462a8aec3b73b4272c2395e3a Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 2 Sep 2021 16:26:47 +0200 Subject: [PATCH 037/125] Working... --- .../cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp index 61db5f3f..c548d3b1 100644 --- a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp +++ b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp @@ -298,7 +298,7 @@ namespace extreme_carpaccio_client { worker.start(); // TODO For tests. Should handle multiple requests later - ioc.run_one(); + ioc.run(); return EXIT_SUCCESS; } From 0858e04d8d520c5453c05904e980c68c04b58422 Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 2 Sep 2021 16:29:01 +0200 Subject: [PATCH 038/125] Working... --- .../cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp index c548d3b1..61db5f3f 100644 --- a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp +++ b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp @@ -298,7 +298,7 @@ namespace extreme_carpaccio_client { worker.start(); // TODO For tests. Should handle multiple requests later - ioc.run(); + ioc.run_one(); return EXIT_SUCCESS; } From 4656739101c3b30bedf016050799f9abf04e3406 Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 2 Sep 2021 16:31:11 +0200 Subject: [PATCH 039/125] Working... --- .../cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp index 61db5f3f..c548d3b1 100644 --- a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp +++ b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp @@ -298,7 +298,7 @@ namespace extreme_carpaccio_client { worker.start(); // TODO For tests. Should handle multiple requests later - ioc.run_one(); + ioc.run(); return EXIT_SUCCESS; } From 6cef913ba671804457a4ea83d04a0f7c99a87cca Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 2 Sep 2021 16:32:55 +0200 Subject: [PATCH 040/125] Working... --- .../cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp index c548d3b1..2e979860 100644 --- a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp +++ b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp @@ -283,7 +283,7 @@ class http_worker namespace extreme_carpaccio_client { - int launchServer() + boost::asio::io_context launchServer() { auto const address = boost::asio::ip::make_address("127.0.0.1"); unsigned short port = static_cast(std::atoi("8081")); From 41c9b627ff9b50742847b8f9bf3c9533dddd6db5 Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 2 Sep 2021 16:33:01 +0200 Subject: [PATCH 041/125] Working... --- .../cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp index 2e979860..1c449762 100644 --- a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp +++ b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp @@ -300,7 +300,7 @@ namespace extreme_carpaccio_client { // TODO For tests. Should handle multiple requests later ioc.run(); - return EXIT_SUCCESS; + return ioc; } From 9901c6651388d0d507efe2132428a8648de4d70b Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 2 Sep 2021 16:33:58 +0200 Subject: [PATCH 042/125] Working... --- .../src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp index 1c449762..c548d3b1 100644 --- a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp +++ b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp @@ -283,7 +283,7 @@ class http_worker namespace extreme_carpaccio_client { - boost::asio::io_context launchServer() + int launchServer() { auto const address = boost::asio::ip::make_address("127.0.0.1"); unsigned short port = static_cast(std::atoi("8081")); @@ -300,7 +300,7 @@ namespace extreme_carpaccio_client { // TODO For tests. Should handle multiple requests later ioc.run(); - return ioc; + return EXIT_SUCCESS; } From 228fd9612f6e9981625a5edfd1a8f5941c0de940 Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 2 Sep 2021 16:35:23 +0200 Subject: [PATCH 043/125] Working... --- .../src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp index c548d3b1..b32356a0 100644 --- a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp +++ b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp @@ -283,6 +283,11 @@ class http_worker namespace extreme_carpaccio_client { + class CarpaccioServer + { + + }; + int launchServer() { auto const address = boost::asio::ip::make_address("127.0.0.1"); From f6593d083f0eb3ff07a89882f02db78b024101e5 Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 2 Sep 2021 16:35:38 +0200 Subject: [PATCH 044/125] Working... --- .../cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp index b32356a0..56d95f26 100644 --- a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp +++ b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp @@ -286,6 +286,7 @@ namespace extreme_carpaccio_client { class CarpaccioServer { + boost::asio::io_context ioc; }; int launchServer() From e5a1c351811daed2370b3381d1a708352cc3f810 Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 2 Sep 2021 16:36:11 +0200 Subject: [PATCH 045/125] Working... --- .../src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp index 56d95f26..861f56cd 100644 --- a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp +++ b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp @@ -286,7 +286,10 @@ namespace extreme_carpaccio_client { class CarpaccioServer { + boost::asio::io_context ioc; + tcp::acceptor acceptor; + http_worker worker }; int launchServer() From 5e97c7ece22e0f818b28acc0225c2291d5229a8d Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 2 Sep 2021 16:36:18 +0200 Subject: [PATCH 046/125] Working... --- .../cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp index 861f56cd..2f583f95 100644 --- a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp +++ b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp @@ -286,7 +286,7 @@ namespace extreme_carpaccio_client { class CarpaccioServer { - + private: boost::asio::io_context ioc; tcp::acceptor acceptor; http_worker worker From 8111257bf53eff03b2a2eee83aa75ef5e4f18d63 Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 2 Sep 2021 16:36:22 +0200 Subject: [PATCH 047/125] Working... --- .../cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp index 2f583f95..0a52e917 100644 --- a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp +++ b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp @@ -285,6 +285,7 @@ namespace extreme_carpaccio_client { class CarpaccioServer { + public: private: boost::asio::io_context ioc; From 7092c5ee9b9eb49ce0938972587afb052a56be45 Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 2 Sep 2021 16:36:29 +0200 Subject: [PATCH 048/125] Working... --- .../cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp index 0a52e917..ec29fec9 100644 --- a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp +++ b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp @@ -286,6 +286,7 @@ namespace extreme_carpaccio_client { class CarpaccioServer { public: + CarpaccioServer(); private: boost::asio::io_context ioc; From 53d3ffc5aa90c8f3756935c08d4a12f460f68281 Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 2 Sep 2021 16:36:55 +0200 Subject: [PATCH 049/125] Working... --- .../cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp index ec29fec9..d4bef0b0 100644 --- a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp +++ b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp @@ -287,6 +287,7 @@ namespace extreme_carpaccio_client { { public: CarpaccioServer(); + void start(); private: boost::asio::io_context ioc; From cbd0b0d4690f2ee95638bd1964275fb06030778d Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 2 Sep 2021 16:36:58 +0200 Subject: [PATCH 050/125] Working... --- .../cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp index d4bef0b0..b5682401 100644 --- a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp +++ b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp @@ -288,6 +288,7 @@ namespace extreme_carpaccio_client { public: CarpaccioServer(); void start(); + void stop(); private: boost::asio::io_context ioc; From a5cd349ac26462cc6f3e06dadae648af9d1ee45b Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 2 Sep 2021 16:37:20 +0200 Subject: [PATCH 051/125] Working... --- .../src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp index b5682401..6d65a163 100644 --- a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp +++ b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp @@ -296,6 +296,11 @@ namespace extreme_carpaccio_client { http_worker worker }; + CarpaccioServer::CarpaccioServer() + { + + } + int launchServer() { auto const address = boost::asio::ip::make_address("127.0.0.1"); From 41b70ac8bf3736427673ffc138ca40407d7d5c1c Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 2 Sep 2021 16:37:51 +0200 Subject: [PATCH 052/125] Working... --- .../ExtremeCarpaccioClient.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp index 6d65a163..b23f0391 100644 --- a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp +++ b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp @@ -301,6 +301,16 @@ namespace extreme_carpaccio_client { } + void CarpaccioServer::start() + { + + } + + void CarpaccioServer::stop() + { + + } + int launchServer() { auto const address = boost::asio::ip::make_address("127.0.0.1"); From 3459b0fe543295307e7ea22eb9d349d9b0c1420a Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 2 Sep 2021 16:38:03 +0200 Subject: [PATCH 053/125] Working... --- .../cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp index b23f0391..bb2804d6 100644 --- a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp +++ b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp @@ -293,7 +293,7 @@ namespace extreme_carpaccio_client { private: boost::asio::io_context ioc; tcp::acceptor acceptor; - http_worker worker + http_worker worker; }; CarpaccioServer::CarpaccioServer() From 8b81f1876089a1b6c3076e7703a2c9084a3ec70a Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 2 Sep 2021 16:41:03 +0200 Subject: [PATCH 054/125] Working... --- clients/cpp/Retrospective.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/clients/cpp/Retrospective.md b/clients/cpp/Retrospective.md index 35237674..f58cd255 100644 --- a/clients/cpp/Retrospective.md +++ b/clients/cpp/Retrospective.md @@ -2,6 +2,7 @@ 05/27/2021 07/15/2021 +09/02/2021 ## What did we do ? - We did some cmake and CPM @@ -13,13 +14,15 @@ 07/15/2021 - We changed our approach, we chose to get the full example code and tested it successfully - We change the allocator by using the default allocator, and it worked - +09/02/2021 +- We built a test on the client using a get request ## What did we learn ? - Patrice learnt on client/server problematic and REST requests 07/15/2021 - We learnt that folder and file need to exist to be able to retrieve them from the server - Starting with something that works and try to refactoring seems to be a good solution +09/02/2021 ## Puzzle - Dependencies handling in cpp is sport ! @@ -28,8 +31,10 @@ 07/15/2021 - boost beast is a bit tricky to understand and troubleshoot - Example of server using boost library is not real good c++ !! +09/02/2021 ## Decide - We miss some libraries in boost cmake so we need to add tham to build simple http client with boost - We will add a Jira ticket to continue working on that -- 07/15/2021 \ No newline at end of file +- 07/15/2021 +09/02/2021 From f05d8cb458e6612a2984d9cf67c0a8812d558127 Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 2 Sep 2021 16:41:33 +0200 Subject: [PATCH 055/125] Working... --- clients/cpp/Retrospective.md | 1 + 1 file changed, 1 insertion(+) diff --git a/clients/cpp/Retrospective.md b/clients/cpp/Retrospective.md index f58cd255..4543c687 100644 --- a/clients/cpp/Retrospective.md +++ b/clients/cpp/Retrospective.md @@ -16,6 +16,7 @@ - We change the allocator by using the default allocator, and it worked 09/02/2021 - We built a test on the client using a get request +- We started to create class structure of server ## What did we learn ? - Patrice learnt on client/server problematic and REST requests From f7ae417bf4395dba1ffa886a6f760836e84ceba6 Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 2 Sep 2021 16:41:47 +0200 Subject: [PATCH 056/125] Working... --- clients/cpp/Retrospective.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clients/cpp/Retrospective.md b/clients/cpp/Retrospective.md index 4543c687..68d23f57 100644 --- a/clients/cpp/Retrospective.md +++ b/clients/cpp/Retrospective.md @@ -15,7 +15,7 @@ - We changed our approach, we chose to get the full example code and tested it successfully - We change the allocator by using the default allocator, and it worked 09/02/2021 -- We built a test on the client using a get request +- We built a test on the clients http server using a get request - We started to create class structure of server ## What did we learn ? From f2a84be17a2c409ec44363c5243835774b53a391 Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 2 Sep 2021 16:41:50 +0200 Subject: [PATCH 057/125] Working... --- clients/cpp/Retrospective.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clients/cpp/Retrospective.md b/clients/cpp/Retrospective.md index 68d23f57..0eb4fcb9 100644 --- a/clients/cpp/Retrospective.md +++ b/clients/cpp/Retrospective.md @@ -15,7 +15,7 @@ - We changed our approach, we chose to get the full example code and tested it successfully - We change the allocator by using the default allocator, and it worked 09/02/2021 -- We built a test on the clients http server using a get request +- We built a test on the client's http server using a get request - We started to create class structure of server ## What did we learn ? From 6d3092f353becb0533fd9d3279ec6b4e5f518714 Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 2 Sep 2021 16:42:02 +0200 Subject: [PATCH 058/125] Working... --- clients/cpp/Retrospective.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clients/cpp/Retrospective.md b/clients/cpp/Retrospective.md index 0eb4fcb9..0b2fe890 100644 --- a/clients/cpp/Retrospective.md +++ b/clients/cpp/Retrospective.md @@ -16,7 +16,7 @@ - We change the allocator by using the default allocator, and it worked 09/02/2021 - We built a test on the client's http server using a get request -- We started to create class structure of server +- We started to create class structure of server to host ioc ## What did we learn ? - Patrice learnt on client/server problematic and REST requests From ae9357d5ede41acd44af1c6b9699445d2cc89bc2 Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 2 Sep 2021 16:42:14 +0200 Subject: [PATCH 059/125] Working... --- clients/cpp/Retrospective.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clients/cpp/Retrospective.md b/clients/cpp/Retrospective.md index 0b2fe890..6f84d90d 100644 --- a/clients/cpp/Retrospective.md +++ b/clients/cpp/Retrospective.md @@ -16,7 +16,7 @@ - We change the allocator by using the default allocator, and it worked 09/02/2021 - We built a test on the client's http server using a get request -- We started to create class structure of server to host ioc +- We started to create class structure of server to host ioc, so that we can call start/stop on it ## What did we learn ? - Patrice learnt on client/server problematic and REST requests From 01ec72aaae969313337e440ef2aa5d4961dd3714 Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 2 Sep 2021 16:42:43 +0200 Subject: [PATCH 060/125] Working... --- clients/cpp/Retrospective.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/clients/cpp/Retrospective.md b/clients/cpp/Retrospective.md index 6f84d90d..58f65753 100644 --- a/clients/cpp/Retrospective.md +++ b/clients/cpp/Retrospective.md @@ -17,6 +17,7 @@ 09/02/2021 - We built a test on the client's http server using a get request - We started to create class structure of server to host ioc, so that we can call start/stop on it +- ## What did we learn ? - Patrice learnt on client/server problematic and REST requests @@ -33,6 +34,7 @@ - boost beast is a bit tricky to understand and troubleshoot - Example of server using boost library is not real good c++ !! 09/02/2021 +- We had some issues with threads ## Decide - We miss some libraries in boost cmake so we need to add tham to build simple http client with boost From 76164f8137967d444e7aeb97297edc332f8ab942 Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 2 Sep 2021 16:43:41 +0200 Subject: [PATCH 061/125] Working... --- clients/cpp/Retrospective.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clients/cpp/Retrospective.md b/clients/cpp/Retrospective.md index 58f65753..78a21bf0 100644 --- a/clients/cpp/Retrospective.md +++ b/clients/cpp/Retrospective.md @@ -34,7 +34,7 @@ - boost beast is a bit tricky to understand and troubleshoot - Example of server using boost library is not real good c++ !! 09/02/2021 -- We had some issues with threads +- We had some issues with threads. How can we stop server in a clean way ? How can we remove sleep ? ## Decide - We miss some libraries in boost cmake so we need to add tham to build simple http client with boost From 35775daedaff6760cdcc0f8247ec9ac8ca344331 Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 2 Sep 2021 16:44:45 +0200 Subject: [PATCH 062/125] Working... --- clients/cpp/Retrospective.md | 1 + 1 file changed, 1 insertion(+) diff --git a/clients/cpp/Retrospective.md b/clients/cpp/Retrospective.md index 78a21bf0..8994ad86 100644 --- a/clients/cpp/Retrospective.md +++ b/clients/cpp/Retrospective.md @@ -25,6 +25,7 @@ - We learnt that folder and file need to exist to be able to retrieve them from the server - Starting with something that works and try to refactoring seems to be a good solution 09/02/2021 +- We learnt how to build a thread in c++, we learnt about thread joining ## Puzzle - Dependencies handling in cpp is sport ! From 7095c04c146de6dad5e67cc5970927148ac38a69 Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 2 Sep 2021 16:45:41 +0200 Subject: [PATCH 063/125] Working... --- clients/cpp/Retrospective.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/clients/cpp/Retrospective.md b/clients/cpp/Retrospective.md index 8994ad86..9b390e30 100644 --- a/clients/cpp/Retrospective.md +++ b/clients/cpp/Retrospective.md @@ -36,6 +36,8 @@ - Example of server using boost library is not real good c++ !! 09/02/2021 - We had some issues with threads. How can we stop server in a clean way ? How can we remove sleep ? +- It takes time to build this C++ implementation of Extreme Carpaccio client + ## Decide - We miss some libraries in boost cmake so we need to add tham to build simple http client with boost From 9552e741f6696348e001d41493feec8d5b20b395 Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 2 Sep 2021 16:46:45 +0200 Subject: [PATCH 064/125] Working... --- clients/cpp/Retrospective.md | 1 + 1 file changed, 1 insertion(+) diff --git a/clients/cpp/Retrospective.md b/clients/cpp/Retrospective.md index 9b390e30..4a857a0f 100644 --- a/clients/cpp/Retrospective.md +++ b/clients/cpp/Retrospective.md @@ -37,6 +37,7 @@ 09/02/2021 - We had some issues with threads. How can we stop server in a clean way ? How can we remove sleep ? - It takes time to build this C++ implementation of Extreme Carpaccio client +- It's not trivial to build http server in c++ ## Decide From a951a0c4887c33c47892e07ae31c70c9e1769ee7 Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 2 Sep 2021 16:47:50 +0200 Subject: [PATCH 065/125] Working... --- clients/cpp/Retrospective.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clients/cpp/Retrospective.md b/clients/cpp/Retrospective.md index 4a857a0f..3af84ab7 100644 --- a/clients/cpp/Retrospective.md +++ b/clients/cpp/Retrospective.md @@ -37,7 +37,7 @@ 09/02/2021 - We had some issues with threads. How can we stop server in a clean way ? How can we remove sleep ? - It takes time to build this C++ implementation of Extreme Carpaccio client -- It's not trivial to build http server in c++ +- It's not trivial to build http server in c++, and we are still not handling requests of the extreme carpaccio ## Decide From 85d8fcf068308f2cefa7ed0eacc429ee9076050e Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 2 Sep 2021 16:47:54 +0200 Subject: [PATCH 066/125] Working... --- clients/cpp/Retrospective.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clients/cpp/Retrospective.md b/clients/cpp/Retrospective.md index 3af84ab7..3ce0e4d9 100644 --- a/clients/cpp/Retrospective.md +++ b/clients/cpp/Retrospective.md @@ -37,7 +37,7 @@ 09/02/2021 - We had some issues with threads. How can we stop server in a clean way ? How can we remove sleep ? - It takes time to build this C++ implementation of Extreme Carpaccio client -- It's not trivial to build http server in c++, and we are still not handling requests of the extreme carpaccio +- It's not trivial to build http server in c++, and we are still not handling requests of the extreme carpaccio game ## Decide From 2ca6f2d1093d5ddb1258136b02965daf4560cd21 Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 2 Sep 2021 16:49:20 +0200 Subject: [PATCH 067/125] Working... --- clients/cpp/Retrospective.md | 1 + 1 file changed, 1 insertion(+) diff --git a/clients/cpp/Retrospective.md b/clients/cpp/Retrospective.md index 3ce0e4d9..c5cf25e2 100644 --- a/clients/cpp/Retrospective.md +++ b/clients/cpp/Retrospective.md @@ -45,3 +45,4 @@ - We will add a Jira ticket to continue working on that - 07/15/2021 09/02/2021 +- Option 1 : We can check what is the feedback from Morrigan on Extreme Carpaccio, and if we get good feedback, we continue investigating on c++ version \ No newline at end of file From 9d3ad06497bbbfac59620dd6e28f92770528fe77 Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 2 Sep 2021 16:51:50 +0200 Subject: [PATCH 068/125] Working... --- clients/cpp/TODOLIST.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clients/cpp/TODOLIST.md b/clients/cpp/TODOLIST.md index 7392a448..30b65e1a 100644 --- a/clients/cpp/TODOLIST.md +++ b/clients/cpp/TODOLIST.md @@ -5,7 +5,7 @@ - [X] Deal with all the cmake arcane... - [X] Create a main exe that starts a server - [X] Manual test that it can display a bmp, test it in the browser -- [ ] Update our test to check that client can get a file not found from the server +- [ ] Update our test to check that client can get a file from the server - [ ] Deal with starting & stoping the server correctly in the test to avoid resource leaks - [ ] Implement the POST /order command - [ ] check what the request and answers should look like from the js versions From a2b81bdc4ba7233706ab10850132bd4bc618ec37 Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 2 Sep 2021 16:51:52 +0200 Subject: [PATCH 069/125] Working... --- clients/cpp/TODOLIST.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clients/cpp/TODOLIST.md b/clients/cpp/TODOLIST.md index 30b65e1a..6626c707 100644 --- a/clients/cpp/TODOLIST.md +++ b/clients/cpp/TODOLIST.md @@ -5,7 +5,7 @@ - [X] Deal with all the cmake arcane... - [X] Create a main exe that starts a server - [X] Manual test that it can display a bmp, test it in the browser -- [ ] Update our test to check that client can get a file from the server +- [X] Update our test to check that client can get a file from the server - [ ] Deal with starting & stoping the server correctly in the test to avoid resource leaks - [ ] Implement the POST /order command - [ ] check what the request and answers should look like from the js versions From 120c9418f3aedd4a150d37325118761991fd7763 Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 2 Sep 2021 16:53:28 +0200 Subject: [PATCH 070/125] Working... --- clients/cpp/TODOLIST.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clients/cpp/TODOLIST.md b/clients/cpp/TODOLIST.md index 6626c707..f515b63e 100644 --- a/clients/cpp/TODOLIST.md +++ b/clients/cpp/TODOLIST.md @@ -6,7 +6,7 @@ - [X] Create a main exe that starts a server - [X] Manual test that it can display a bmp, test it in the browser - [X] Update our test to check that client can get a file from the server -- [ ] Deal with starting & stoping the server correctly in the test to avoid resource leaks +- [ ] Deal with starting & stopping the server correctly in the test to avoid resource leaks - [ ] Implement the POST /order command - [ ] check what the request and answers should look like from the js versions - [ ] write a test to POST /order with a proper request From 5071536d25586edcca3c5ab501b9522f66b27483 Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 23 Sep 2021 19:51:36 +0200 Subject: [PATCH 071/125] Adding a CarpaccioServer class with start and stop --- .../ExtremeCarpaccioClient.hpp | 78 +++- .../ExtremeCarpaccioClient.cpp | 410 ++++++++---------- 2 files changed, 252 insertions(+), 236 deletions(-) diff --git a/clients/cpp/include/extreme_carpaccio_client/ExtremeCarpaccioClient.hpp b/clients/cpp/include/extreme_carpaccio_client/ExtremeCarpaccioClient.hpp index f1eb0197..dddccd26 100644 --- a/clients/cpp/include/extreme_carpaccio_client/ExtremeCarpaccioClient.hpp +++ b/clients/cpp/include/extreme_carpaccio_client/ExtremeCarpaccioClient.hpp @@ -1,9 +1,85 @@ +#include +#include +#include +#include #include #include namespace extreme_carpaccio_client { - EXTREME_CARPACCIO_CLIENT_API int launchServer(); + +class http_worker +{ +public: + http_worker(http_worker const&) = delete; + http_worker& operator=(http_worker const&) = delete; + + http_worker(boost::asio::ip::tcp::acceptor& acceptor, const std::string& doc_root); + + void start(); + +private: + using alloc_t = std::allocator; + //using request_body_t = http::basic_dynamic_body>; + using request_body_t = boost::beast::http::string_body; + + // The acceptor used to listen for incoming connections. + boost::asio::ip::tcp::acceptor& acceptor_; + + // The path to the root of the document directory. + std::string doc_root_; + + // The socket for the currently connected client. + boost::asio::ip::tcp::socket socket_{ acceptor_.get_executor() }; + + // The buffer for performing reads + boost::beast::flat_static_buffer<8192> buffer_; + + // The allocator used for the fields in the request and reply. + alloc_t alloc_; + + // The parser for reading the requests + boost::optional> parser_; + + // The timer putting a time limit on requests. + boost::asio::steady_timer request_deadline_{ + acceptor_.get_executor(), (std::chrono::steady_clock::time_point::max)() }; + + // The string-based response message. + boost::optional>> string_response_; + + // The file-based response message. + boost::optional>> file_response_; + + void accept(); + + void read_request(); + + void process_request(boost::beast::http::request> const& req); + + void send_bad_response( + boost::beast::http::status status, + std::string const& error); + + void send_file(boost::beast::string_view target); + + void check_deadline(); +}; + +class CarpaccioServer +{ +public: + CarpaccioServer(); + void start(); + void stop(); + +private: + boost::asio::io_context ioc; + boost::asio::ip::tcp::acceptor acceptor; + http_worker worker; +}; + +EXTREME_CARPACCIO_CLIENT_API int launchServer(); } // namespace extreme_carpaccio_client diff --git a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp index bb2804d6..ad8e7a6a 100644 --- a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp +++ b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp @@ -54,280 +54,220 @@ mime_type(beast::string_view path) return "application/text"; } -class http_worker -{ -public: - http_worker(http_worker const&) = delete; - http_worker& operator=(http_worker const&) = delete; - - http_worker(tcp::acceptor& acceptor, const std::string& doc_root) : - acceptor_(acceptor), - doc_root_(doc_root) - { - } - - void start() - { - accept(); - check_deadline(); - } - -private: - using alloc_t = std::allocator; - //using request_body_t = http::basic_dynamic_body>; - using request_body_t = http::string_body; - // The acceptor used to listen for incoming connections. - tcp::acceptor& acceptor_; - - // The path to the root of the document directory. - std::string doc_root_; - - // The socket for the currently connected client. - tcp::socket socket_{ acceptor_.get_executor() }; - - // The buffer for performing reads - beast::flat_static_buffer<8192> buffer_; - - // The allocator used for the fields in the request and reply. - alloc_t alloc_; - - // The parser for reading the requests - boost::optional> parser_; - - // The timer putting a time limit on requests. - net::steady_timer request_deadline_{ - acceptor_.get_executor(), (std::chrono::steady_clock::time_point::max)() }; +namespace extreme_carpaccio_client { - // The string-based response message. - boost::optional>> string_response_; + http_worker::http_worker(tcp::acceptor& acceptor, const std::string& doc_root) : + acceptor_(acceptor), + doc_root_(doc_root) +{ +} - // The file-based response message. - boost::optional>> file_response_; +void http_worker::start() +{ + accept(); + check_deadline(); +} - void accept() +void http_worker::accept() +{ + // Clean up any previous connection. + beast::error_code ec; + socket_.close(ec); + buffer_.consume(buffer_.size()); + + acceptor_.async_accept( + socket_, + [this](beast::error_code ec) { - // Clean up any previous connection. - beast::error_code ec; - socket_.close(ec); - buffer_.consume(buffer_.size()); - - acceptor_.async_accept( - socket_, - [this](beast::error_code ec) + if (ec) { - if (ec) - { - accept(); - } - else - { - // Request must be fully processed within 60 seconds. - request_deadline_.expires_after( - std::chrono::seconds(60)); - - read_request(); - } - }); - } - - void read_request() - { - // On each read the parser needs to be destroyed and - // recreated. We store it in a boost::optional to - // achieve that. - // - // Arguments passed to the parser constructor are - // forwarded to the message object. A single argument - // is forwarded to the body constructor. - // - // We construct the dynamic body with a 1MB limit - // to prevent vulnerability to buffer attacks. - // - parser_.emplace( - std::piecewise_construct, - std::make_tuple(), - std::make_tuple(alloc_)); - - http::async_read( - socket_, - buffer_, - *parser_, - [this](beast::error_code ec, std::size_t) + accept(); + } + else { - if (ec) - accept(); - else - process_request(parser_->get()); - }); - } + // Request must be fully processed within 60 seconds. + request_deadline_.expires_after( + std::chrono::seconds(60)); - void process_request(http::request> const& req) - { - switch (req.method()) - { - case http::verb::get: - send_file(req.target()); - break; - - default: - // We return responses indicating an error if - // we do not recognize the request method. - send_bad_response( - http::status::bad_request, - "Invalid request-method '" + std::string(req.method_string()) + "'\r\n"); - break; + read_request(); } - } + }); +} - void send_bad_response( - http::status status, - std::string const& error) +void http_worker::read_request() +{ + // On each read the parser needs to be destroyed and + // recreated. We store it in a boost::optional to + // achieve that. + // + // Arguments passed to the parser constructor are + // forwarded to the message object. A single argument + // is forwarded to the body constructor. + // + // We construct the dynamic body with a 1MB limit + // to prevent vulnerability to buffer attacks. + // + parser_.emplace( + std::piecewise_construct, + std::make_tuple(), + std::make_tuple(alloc_)); + + http::async_read( + socket_, + buffer_, + *parser_, + [this](beast::error_code ec, std::size_t) { - string_response_.emplace( - std::piecewise_construct, - std::make_tuple(), - std::make_tuple(alloc_)); - - string_response_->result(status); - string_response_->keep_alive(false); - string_response_->set(http::field::server, "Beast"); - string_response_->set(http::field::content_type, "text/plain"); - string_response_->body() = error; - string_response_->prepare_payload(); - - http::async_write( - socket_, - *string_response_, - [this](beast::error_code ec, std::size_t) - { - socket_.shutdown(tcp::socket::shutdown_send, ec); - string_response_.reset(); + if (ec) accept(); - }); + else + process_request(parser_->get()); + }); +} + +void http_worker::process_request(http::request> const& req) +{ + switch (req.method()) + { + case http::verb::get: + send_file(req.target()); + break; + + default: + // We return responses indicating an error if + // we do not recognize the request method. + send_bad_response( + http::status::bad_request, + "Invalid request-method '" + std::string(req.method_string()) + "'\r\n"); + break; } +} - void send_file(beast::string_view target) +void http_worker::send_bad_response( + http::status status, + std::string const& error) +{ + string_response_.emplace( + std::piecewise_construct, + std::make_tuple(), + std::make_tuple(alloc_)); + + string_response_->result(status); + string_response_->keep_alive(false); + string_response_->set(http::field::server, "Beast"); + string_response_->set(http::field::content_type, "text/plain"); + string_response_->body() = error; + string_response_->prepare_payload(); + + http::async_write( + socket_, + *string_response_, + [this](beast::error_code ec, std::size_t) { - // Request path must be absolute and not contain "..". - if (target.empty() || target[0] != '/' || target.find("..") != std::string::npos) - { - send_bad_response( - http::status::not_found, - "File not found\r\n"); - return; - } + socket_.shutdown(tcp::socket::shutdown_send, ec); + string_response_.reset(); + accept(); + }); +} - std::string full_path = doc_root_; - full_path.append( - target.data(), - target.size()); - - http::file_body::value_type file; - beast::error_code ec; - file.open( - full_path.c_str(), - beast::file_mode::read, - ec); - if (ec) - { - send_bad_response( - http::status::not_found, - "File not found\r\n"); - return; - } +void http_worker::send_file(beast::string_view target) +{ + // Request path must be absolute and not contain "..". + if (target.empty() || target[0] != '/' || target.find("..") != std::string::npos) + { + send_bad_response( + http::status::not_found, + "File not found\r\n"); + return; + } - file_response_.emplace( - std::piecewise_construct, - std::make_tuple(), - std::make_tuple(alloc_)); - - file_response_->result(http::status::ok); - file_response_->keep_alive(false); - file_response_->set(http::field::server, "Beast"); - file_response_->set(http::field::content_type, mime_type(std::string(target))); - file_response_->body() = std::move(file); - file_response_->prepare_payload(); - - http::async_write( - socket_, - *file_response_, - [this](beast::error_code ec, std::size_t) - { - socket_.shutdown(tcp::socket::shutdown_send, ec); - file_response_.reset(); - accept(); - }); + std::string full_path = doc_root_; + full_path.append( + target.data(), + target.size()); + + http::file_body::value_type file; + beast::error_code ec; + file.open( + full_path.c_str(), + beast::file_mode::read, + ec); + if (ec) + { + send_bad_response( + http::status::not_found, + "File not found\r\n"); + return; } - void check_deadline() + file_response_.emplace( + std::piecewise_construct, + std::make_tuple(), + std::make_tuple(alloc_)); + + file_response_->result(http::status::ok); + file_response_->keep_alive(false); + file_response_->set(http::field::server, "Beast"); + file_response_->set(http::field::content_type, mime_type(std::string(target))); + file_response_->body() = std::move(file); + file_response_->prepare_payload(); + + http::async_write( + socket_, + *file_response_, + [this](beast::error_code ec, std::size_t) { - // The deadline may have moved, so check it has really passed. - if (request_deadline_.expiry() <= std::chrono::steady_clock::now()) - { - // Close socket to cancel any outstanding operation. - socket_.close(); + socket_.shutdown(tcp::socket::shutdown_send, ec); + file_response_.reset(); + accept(); + }); +} - // Sleep indefinitely until we're given a new deadline. - request_deadline_.expires_at( - (std::chrono::steady_clock::time_point::max)()); - } +void http_worker::check_deadline() +{ + // The deadline may have moved, so check it has really passed. + if (request_deadline_.expiry() <= std::chrono::steady_clock::now()) + { + // Close socket to cancel any outstanding operation. + socket_.close(); - request_deadline_.async_wait( - [this](beast::error_code) - { - check_deadline(); - }); + // Sleep indefinitely until we're given a new deadline. + request_deadline_.expires_at( + (std::chrono::steady_clock::time_point::max)()); } -}; - -namespace extreme_carpaccio_client { - class CarpaccioServer - { - public: - CarpaccioServer(); - void start(); - void stop(); - - private: - boost::asio::io_context ioc; - tcp::acceptor acceptor; - http_worker worker; - }; - - CarpaccioServer::CarpaccioServer() + request_deadline_.async_wait( + [this](beast::error_code) { + check_deadline(); + }); +} + CarpaccioServer::CarpaccioServer() : + ioc(1), + acceptor(ioc, {boost::asio::ip::make_address("127.0.0.1"), static_cast(std::atoi("8081"))} ), + worker(acceptor, "./feedback") + { + } void CarpaccioServer::start() { - + worker.start(); + ioc.run(); } void CarpaccioServer::stop() { - + ioc.stop(); } int launchServer() { - auto const address = boost::asio::ip::make_address("127.0.0.1"); - unsigned short port = static_cast(std::atoi("8081")); - std::string doc_root = "./feedback"; - //int num_workers = std::atoi("1"); - //bool spin = true; - - boost::asio::io_context ioc{ 1 }; - tcp::acceptor acceptor{ ioc, {address, port} }; - - http_worker worker(acceptor, doc_root); - worker.start(); - - // TODO For tests. Should handle multiple requests later - ioc.run(); + CarpaccioServer server; + server.start(); return EXIT_SUCCESS; } From b641de2cef3d5005708a5de665f8d31fef0b5bf4 Mon Sep 17 00:00:00 2001 From: NADIF Antoine Date: Thu, 14 Oct 2021 15:42:21 +0200 Subject: [PATCH 072/125] Cosmetic fix --- clients/cpp/CMakeLists.txt | 3 ++- clients/cpp/build/feedback/toto.png | Bin 692 -> 0 bytes 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/clients/cpp/CMakeLists.txt b/clients/cpp/CMakeLists.txt index 04437b01..b5836ef6 100644 --- a/clients/cpp/CMakeLists.txt +++ b/clients/cpp/CMakeLists.txt @@ -70,7 +70,8 @@ add_test(NAME ctest-Extreme-Carpaccio-Client COMMAND Extreme-Carpaccio-Client-te #Globals add_custom_target(Docs SOURCES - ../README.md) + ${CMAKE_CURRENT_SOURCE_DIR}/TODOLIST.md + ${CMAKE_CURRENT_SOURCE_DIR}/../README.md) set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT Extreme-Carpaccio-Client-test) set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY XCODE_STARTUP_PROJECT Extreme-Carpaccio-Client-test) diff --git a/clients/cpp/build/feedback/toto.png b/clients/cpp/build/feedback/toto.png index db9458dc18b7101d73391627c16b1465967e812c..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 GIT binary patch literal 0 HcmV?d00001 literal 692 zcmV;l0!#ggP)AnxkT)#)2+X)5Z~Bsn&iO*hGc2*IsA{8buD^!_MqxT-G0?6h``KX zO%6|7s`!@*VfbiAygSgHiL*;dFe%3Sd&gCLQ9VzxmXVq+t)d7Am_bBAFc){+y4&_c zMfL*9hoz)ei%mis3{?k}e21p@Nwm3Gx-^BQUxC4DwrFOPPl5q}KUQcXY=sIa05s*} z?=tpR{rWcMr0!iA>YmSdKIUG#J+IH*HVfrZwzPR(TXyV&^!aiI^#V*JiIGl?j(HB? zAth-)H@ko| z>cnkZ{hFo8SZ7Vw#DyOgW`IbNWDvs~)REp}5^)Bm2lZ~aUbed8 aj(rR89Vz20`UpG#0000 Date: Thu, 14 Oct 2021 16:05:30 +0200 Subject: [PATCH 073/125] Use server start/stop instead of launchServer. --- .../extreme_carpaccio_client/ExtremeCarpaccioClient.hpp | 4 ++-- clients/cpp/test/ExtremeCarpaccioClientTest.cpp | 9 ++++++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/clients/cpp/include/extreme_carpaccio_client/ExtremeCarpaccioClient.hpp b/clients/cpp/include/extreme_carpaccio_client/ExtremeCarpaccioClient.hpp index dddccd26..d8de7546 100644 --- a/clients/cpp/include/extreme_carpaccio_client/ExtremeCarpaccioClient.hpp +++ b/clients/cpp/include/extreme_carpaccio_client/ExtremeCarpaccioClient.hpp @@ -1,7 +1,7 @@ +#include #include #include #include -#include #include @@ -67,7 +67,7 @@ class http_worker void check_deadline(); }; -class CarpaccioServer +class EXTREME_CARPACCIO_CLIENT_API CarpaccioServer { public: CarpaccioServer(); diff --git a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp index 9917785b..6645cb04 100644 --- a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp +++ b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp @@ -5,11 +5,11 @@ #include +#include +#include #include #include #include -#include -#include #include #include #include @@ -25,7 +25,8 @@ using namespace extreme_carpaccio_client; TEST(ExtremeCarpaccioClient, should_handle_feedback) { - std::thread thread(extreme_carpaccio_client::launchServer); + CarpaccioServer server; + std::thread thread(&CarpaccioServer::start, &server); std::this_thread::sleep_for(std::chrono::seconds(1)); std::string host = "localhost"; @@ -67,6 +68,8 @@ TEST(ExtremeCarpaccioClient, should_handle_feedback) std::cout << "Response" << std::endl << res << std::endl; EXPECT_EQ(http::status::ok, res.result()); + server.stop(); + // Gracefully close the socket beast::error_code ec; stream.socket().shutdown(tcp::socket::shutdown_both, ec); From 4510134d7de510697a4bf087bfe80748d5811a60 Mon Sep 17 00:00:00 2001 From: NADIF Antoine Date: Thu, 14 Oct 2021 16:13:06 +0200 Subject: [PATCH 074/125] Avoid resource leak. --- clients/cpp/TODOLIST.md | 2 +- .../ExtremeCarpaccioClient.hpp | 4 +--- .../ExtremeCarpaccioClient.cpp | 17 ++++------------- clients/cpp/src/main.cpp | 5 +++-- clients/cpp/test/ExtremeCarpaccioClientTest.cpp | 2 +- 5 files changed, 10 insertions(+), 20 deletions(-) diff --git a/clients/cpp/TODOLIST.md b/clients/cpp/TODOLIST.md index f515b63e..3d1c7e9a 100644 --- a/clients/cpp/TODOLIST.md +++ b/clients/cpp/TODOLIST.md @@ -6,7 +6,7 @@ - [X] Create a main exe that starts a server - [X] Manual test that it can display a bmp, test it in the browser - [X] Update our test to check that client can get a file from the server -- [ ] Deal with starting & stopping the server correctly in the test to avoid resource leaks +- [X] Deal with starting & stopping the server correctly in the test to avoid resource leaks - [ ] Implement the POST /order command - [ ] check what the request and answers should look like from the js versions - [ ] write a test to POST /order with a proper request diff --git a/clients/cpp/include/extreme_carpaccio_client/ExtremeCarpaccioClient.hpp b/clients/cpp/include/extreme_carpaccio_client/ExtremeCarpaccioClient.hpp index d8de7546..b5247557 100644 --- a/clients/cpp/include/extreme_carpaccio_client/ExtremeCarpaccioClient.hpp +++ b/clients/cpp/include/extreme_carpaccio_client/ExtremeCarpaccioClient.hpp @@ -70,7 +70,7 @@ class http_worker class EXTREME_CARPACCIO_CLIENT_API CarpaccioServer { public: - CarpaccioServer(); + CarpaccioServer(unsigned short port); void start(); void stop(); @@ -80,6 +80,4 @@ class EXTREME_CARPACCIO_CLIENT_API CarpaccioServer http_worker worker; }; -EXTREME_CARPACCIO_CLIENT_API int launchServer(); - } // namespace extreme_carpaccio_client diff --git a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp index ad8e7a6a..212fe7b0 100644 --- a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp +++ b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp @@ -1,10 +1,10 @@ #include +#include #include #include #include -#include #include #include #include @@ -244,9 +244,9 @@ void http_worker::check_deadline() }); } - CarpaccioServer::CarpaccioServer() : - ioc(1), - acceptor(ioc, {boost::asio::ip::make_address("127.0.0.1"), static_cast(std::atoi("8081"))} ), + CarpaccioServer::CarpaccioServer(unsigned short port) + : ioc(1) + , acceptor(ioc, {boost::asio::ip::make_address("127.0.0.1"), port } ), worker(acceptor, "./feedback") { @@ -263,14 +263,5 @@ void http_worker::check_deadline() ioc.stop(); } - int launchServer() - { - CarpaccioServer server; - - server.start(); - return EXIT_SUCCESS; - } - - } // namespace extreme_carpaccio_client diff --git a/clients/cpp/src/main.cpp b/clients/cpp/src/main.cpp index 279288ca..c5af6024 100644 --- a/clients/cpp/src/main.cpp +++ b/clients/cpp/src/main.cpp @@ -3,5 +3,6 @@ int main() { - extreme_carpaccio_client::launchServer(); -} \ No newline at end of file + extreme_carpaccio_client::CarpaccioServer server(8081); + server.start(); +} diff --git a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp index 6645cb04..d5b31141 100644 --- a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp +++ b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp @@ -25,7 +25,7 @@ using namespace extreme_carpaccio_client; TEST(ExtremeCarpaccioClient, should_handle_feedback) { - CarpaccioServer server; + CarpaccioServer server(8081); std::thread thread(&CarpaccioServer::start, &server); std::this_thread::sleep_for(std::chrono::seconds(1)); From 53306f5935dac5e42941f594bdfa9f3a36ad4ea2 Mon Sep 17 00:00:00 2001 From: NADIF Antoine Date: Thu, 14 Oct 2021 16:41:40 +0200 Subject: [PATCH 075/125] Factorize stream creation, management, destruction in a separate class. --- .../ExtremeCarpaccioClient.hpp | 16 ++++++ .../ExtremeCarpaccioClient.cpp | 39 +++++++++++++++ .../cpp/test/ExtremeCarpaccioClientTest.cpp | 50 +++++++------------ 3 files changed, 72 insertions(+), 33 deletions(-) diff --git a/clients/cpp/include/extreme_carpaccio_client/ExtremeCarpaccioClient.hpp b/clients/cpp/include/extreme_carpaccio_client/ExtremeCarpaccioClient.hpp index b5247557..4d2a3eab 100644 --- a/clients/cpp/include/extreme_carpaccio_client/ExtremeCarpaccioClient.hpp +++ b/clients/cpp/include/extreme_carpaccio_client/ExtremeCarpaccioClient.hpp @@ -80,4 +80,20 @@ class EXTREME_CARPACCIO_CLIENT_API CarpaccioServer http_worker worker; }; +class EXTREME_CARPACCIO_CLIENT_API CarpaccioStream +{ +public: + CarpaccioStream(const std::string & host, unsigned short port); + ~CarpaccioStream(); + + boost::beast::http::response read(boost::beast::flat_buffer&); + void write(const boost::beast::http::request & request); + +private: + boost::asio::io_context m_ioContext; + boost::asio::ip::tcp::resolver m_resolver; + boost::asio::ip::tcp::resolver::results_type m_resolverResults; + boost::beast::tcp_stream m_stream; +}; + } // namespace extreme_carpaccio_client diff --git a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp index 212fe7b0..fc81260f 100644 --- a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp +++ b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp @@ -262,6 +262,45 @@ void http_worker::check_deadline() { ioc.stop(); } + + CarpaccioStream::CarpaccioStream(const std::string & host, unsigned short port) + : m_ioContext() + , m_resolver(m_ioContext) // These objects perform our I/O + , m_resolverResults(m_resolver.resolve(host, std::to_string(port))) // Look up the domain name + , m_stream(m_ioContext) + { + // Make the connection on the IP address we get from a lookup + m_stream.connect(m_resolverResults); + } + + CarpaccioStream::~CarpaccioStream() + { + // Gracefully close the socket + beast::error_code ec; + m_stream.socket().shutdown(tcp::socket::shutdown_both, ec); + + //// not_connected happens sometimes + //// so don't bother reporting it. + //if (ec && ec != beast::errc::not_connected) + // throw beast::system_error{ ec }; + } + + http::response CarpaccioStream::read(beast::flat_buffer & buffer) + { + // Declare a container to hold the response + http::response response; + + // Receive the HTTP response + http::read(m_stream, buffer, response); + + return response; + } + + void CarpaccioStream::write(const http::request & request) + { + // Send the HTTP request to the remote host + http::write(m_stream, request); + } } // namespace extreme_carpaccio_client diff --git a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp index d5b31141..5edc37fc 100644 --- a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp +++ b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp @@ -23,69 +23,53 @@ using tcp = net::ip::tcp; // from using namespace extreme_carpaccio_client; +const char serverHost[] = "localhost"; +const unsigned short serverPort = 8081; +const int version = 11; + TEST(ExtremeCarpaccioClient, should_handle_feedback) { CarpaccioServer server(8081); std::thread thread(&CarpaccioServer::start, &server); std::this_thread::sleep_for(std::chrono::seconds(1)); - std::string host = "localhost"; - std::string port = "8081"; - std::string target = "/toto.png"; - int version = 11; - - net::io_context ioc; - - // These objects perform our I/O - tcp::resolver resolver(ioc); - beast::tcp_stream stream(ioc); + CarpaccioStream stream(serverHost, serverPort); - // Look up the domain name - auto const results = resolver.resolve(host, port); - - // Make the connection on the IP address we get from a lookup - stream.connect(results); + std::string target = "/toto.png"; // Set up an HTTP GET request message http::request req{ http::verb::get, target, version }; - req.set(http::field::host, host); + req.set(http::field::host, serverHost); req.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING); // Send the HTTP request to the remote host - http::write(stream, req); + stream.write(req); // This buffer is used for reading and must be persisted beast::flat_buffer buffer; - // Declare a container to hold the response - http::response res; - // Receive the HTTP response - http::read(stream, buffer, res); + auto res = stream.read(buffer); - // Write the message to standard out std::cout << "Response" << std::endl << res << std::endl; EXPECT_EQ(http::status::ok, res.result()); server.stop(); - // Gracefully close the socket - beast::error_code ec; - stream.socket().shutdown(tcp::socket::shutdown_both, ec); - - // not_connected happens sometimes - // so don't bother reporting it. - // - if (ec && ec != beast::errc::not_connected) - throw beast::system_error{ ec }; - thread.detach(); } -TEST(ExtremeCarpaccioClient, DISABLED_should_handle_order) +TEST(ExtremeCarpaccioClient, should_handle_order) { + CarpaccioServer server(serverPort); + std::thread thread(&CarpaccioServer::start, &server); + std::this_thread::sleep_for(std::chrono::seconds(1)); + EXPECT_EQ(1, 1); + + server.stop(); + thread.detach(); } //it('should handle feedback', function(done) { From f1ce572d9f9c06abb190cb3eeb3a15adefbb805c Mon Sep 17 00:00:00 2001 From: NADIF Antoine Date: Thu, 14 Oct 2021 16:47:20 +0200 Subject: [PATCH 076/125] Factorize request creation. --- .../ExtremeCarpaccioClient.hpp | 3 ++- .../ExtremeCarpaccioClient.cpp | 12 ++++++++++-- clients/cpp/test/ExtremeCarpaccioClientTest.cpp | 8 +------- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/clients/cpp/include/extreme_carpaccio_client/ExtremeCarpaccioClient.hpp b/clients/cpp/include/extreme_carpaccio_client/ExtremeCarpaccioClient.hpp index 4d2a3eab..99d37a39 100644 --- a/clients/cpp/include/extreme_carpaccio_client/ExtremeCarpaccioClient.hpp +++ b/clients/cpp/include/extreme_carpaccio_client/ExtremeCarpaccioClient.hpp @@ -87,9 +87,10 @@ class EXTREME_CARPACCIO_CLIENT_API CarpaccioStream ~CarpaccioStream(); boost::beast::http::response read(boost::beast::flat_buffer&); - void write(const boost::beast::http::request & request); + void write(boost::beast::http::verb requestType, const std::string & target); private: + std::string m_serverHost; boost::asio::io_context m_ioContext; boost::asio::ip::tcp::resolver m_resolver; boost::asio::ip::tcp::resolver::results_type m_resolverResults; diff --git a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp index fc81260f..ce9ac7a6 100644 --- a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp +++ b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp @@ -18,6 +18,8 @@ namespace http = beast::http; // from namespace net = boost::asio; // from using tcp = boost::asio::ip::tcp; // from +const int version = 11; + // Return a reasonable mime type based on the extension of a file. beast::string_view mime_type(beast::string_view path) @@ -264,7 +266,8 @@ void http_worker::check_deadline() } CarpaccioStream::CarpaccioStream(const std::string & host, unsigned short port) - : m_ioContext() + : m_serverHost(host) + , m_ioContext() , m_resolver(m_ioContext) // These objects perform our I/O , m_resolverResults(m_resolver.resolve(host, std::to_string(port))) // Look up the domain name , m_stream(m_ioContext) @@ -296,8 +299,13 @@ void http_worker::check_deadline() return response; } - void CarpaccioStream::write(const http::request & request) + void CarpaccioStream::write(boost::beast::http::verb requestType, const std::string & target) { + // Set up an HTTP GET request message + http::request request{ requestType, target, version }; + request.set(http::field::host, m_serverHost); + request.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING); + // Send the HTTP request to the remote host http::write(m_stream, request); } diff --git a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp index 5edc37fc..fa6263f1 100644 --- a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp +++ b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp @@ -25,7 +25,6 @@ using namespace extreme_carpaccio_client; const char serverHost[] = "localhost"; const unsigned short serverPort = 8081; -const int version = 11; TEST(ExtremeCarpaccioClient, should_handle_feedback) { @@ -37,13 +36,8 @@ TEST(ExtremeCarpaccioClient, should_handle_feedback) std::string target = "/toto.png"; - // Set up an HTTP GET request message - http::request req{ http::verb::get, target, version }; - req.set(http::field::host, serverHost); - req.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING); - // Send the HTTP request to the remote host - stream.write(req); + stream.write(http::verb::get, target); // This buffer is used for reading and must be persisted beast::flat_buffer buffer; From 745be6474dade8aa7a3859b354f2f2fadd68699e Mon Sep 17 00:00:00 2001 From: NADIF Antoine Date: Thu, 14 Oct 2021 16:52:38 +0200 Subject: [PATCH 077/125] Retrospective --- clients/cpp/CMakeLists.txt | 1 + clients/cpp/Retrospective.md | 11 ++++++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/clients/cpp/CMakeLists.txt b/clients/cpp/CMakeLists.txt index b5836ef6..b32cc9e7 100644 --- a/clients/cpp/CMakeLists.txt +++ b/clients/cpp/CMakeLists.txt @@ -70,6 +70,7 @@ add_test(NAME ctest-Extreme-Carpaccio-Client COMMAND Extreme-Carpaccio-Client-te #Globals add_custom_target(Docs SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/Retrospective.md ${CMAKE_CURRENT_SOURCE_DIR}/TODOLIST.md ${CMAKE_CURRENT_SOURCE_DIR}/../README.md) diff --git a/clients/cpp/Retrospective.md b/clients/cpp/Retrospective.md index c5cf25e2..a187c8b2 100644 --- a/clients/cpp/Retrospective.md +++ b/clients/cpp/Retrospective.md @@ -3,6 +3,7 @@ 05/27/2021 07/15/2021 09/02/2021 +10/14/2021 ## What did we do ? - We did some cmake and CPM @@ -17,7 +18,8 @@ 09/02/2021 - We built a test on the client's http server using a get request - We started to create class structure of server to host ioc, so that we can call start/stop on it -- +10/14/2021 +- We refactored the Carpaccio Server and the Stream to simplify the tests ## What did we learn ? - Patrice learnt on client/server problematic and REST requests @@ -26,7 +28,8 @@ - Starting with something that works and try to refactoring seems to be a good solution 09/02/2021 - We learnt how to build a thread in c++, we learnt about thread joining - +10/14/2021 +- We learnt that we could create a thread with a class member function ## Puzzle - Dependencies handling in cpp is sport ! - We have the boost example of GET, will it work with POST ? @@ -38,7 +41,9 @@ - We had some issues with threads. How can we stop server in a clean way ? How can we remove sleep ? - It takes time to build this C++ implementation of Extreme Carpaccio client - It's not trivial to build http server in c++, and we are still not handling requests of the extreme carpaccio game - +10/14/2021 +- Be careful about relative paths in CMakeLists.txt +- Never commit anything inside the build directory! ## Decide - We miss some libraries in boost cmake so we need to add tham to build simple http client with boost From f44b52dc248c18529d76480b162b589c5589352e Mon Sep 17 00:00:00 2001 From: NADIF Antoine Date: Thu, 14 Oct 2021 16:56:14 +0200 Subject: [PATCH 078/125] Factorize the main test code. --- .../cpp/test/ExtremeCarpaccioClientTest.cpp | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp index fa6263f1..d3a5f0f5 100644 --- a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp +++ b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp @@ -26,7 +26,7 @@ using namespace extreme_carpaccio_client; const char serverHost[] = "localhost"; const unsigned short serverPort = 8081; -TEST(ExtremeCarpaccioClient, should_handle_feedback) +static http::response generateServerResponse(boost::beast::http::verb requestType, const std::string & target) { CarpaccioServer server(8081); std::thread thread(&CarpaccioServer::start, &server); @@ -34,8 +34,6 @@ TEST(ExtremeCarpaccioClient, should_handle_feedback) CarpaccioStream stream(serverHost, serverPort); - std::string target = "/toto.png"; - // Send the HTTP request to the remote host stream.write(http::verb::get, target); @@ -44,14 +42,24 @@ TEST(ExtremeCarpaccioClient, should_handle_feedback) // Receive the HTTP response auto res = stream.read(buffer); - - // Write the message to standard out - std::cout << "Response" << std::endl << res << std::endl; - EXPECT_EQ(http::status::ok, res.result()); server.stop(); thread.detach(); + + return res; +} + +TEST(ExtremeCarpaccioClient, should_handle_feedback) +{ + std::string target = "/toto.png"; + + // Receive the HTTP response + auto res = generateServerResponse(http::verb::get, target); + + // Write the message to standard out + std::cout << "Response" << std::endl << res << std::endl; + EXPECT_EQ(http::status::ok, res.result()); } TEST(ExtremeCarpaccioClient, should_handle_order) From 52e3c9fc66276629892376737267c6dd29b3a9d4 Mon Sep 17 00:00:00 2001 From: NADIF Antoine Date: Thu, 21 Oct 2021 14:32:07 +0200 Subject: [PATCH 079/125] Use the request type parameter instead of a hardcoded get. --- clients/cpp/test/ExtremeCarpaccioClientTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp index d3a5f0f5..2f88017c 100644 --- a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp +++ b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp @@ -35,7 +35,7 @@ static http::response generateServerResponse(boost::beast::h CarpaccioStream stream(serverHost, serverPort); // Send the HTTP request to the remote host - stream.write(http::verb::get, target); + stream.write(requestType, target); // This buffer is used for reading and must be persisted beast::flat_buffer buffer; From 5c158104f4685ceeb8a34a458932b68b1fdb6503 Mon Sep 17 00:00:00 2001 From: NADIF Antoine Date: Thu, 21 Oct 2021 15:38:21 +0200 Subject: [PATCH 080/125] Handle order requests and default response. --- .../ExtremeCarpaccioClient.hpp | 6 +- .../ExtremeCarpaccioClient.cpp | 127 ++++-------------- .../cpp/test/ExtremeCarpaccioClientTest.cpp | 22 +-- 3 files changed, 38 insertions(+), 117 deletions(-) diff --git a/clients/cpp/include/extreme_carpaccio_client/ExtremeCarpaccioClient.hpp b/clients/cpp/include/extreme_carpaccio_client/ExtremeCarpaccioClient.hpp index 99d37a39..f71ed597 100644 --- a/clients/cpp/include/extreme_carpaccio_client/ExtremeCarpaccioClient.hpp +++ b/clients/cpp/include/extreme_carpaccio_client/ExtremeCarpaccioClient.hpp @@ -62,9 +62,9 @@ class http_worker boost::beast::http::status status, std::string const& error); - void send_file(boost::beast::string_view target); - void check_deadline(); + + bool handleRequest(boost::beast::http::verb requestType, const std::string & target, const std::string & contentType, const std::string & body); }; class EXTREME_CARPACCIO_CLIENT_API CarpaccioServer @@ -87,7 +87,7 @@ class EXTREME_CARPACCIO_CLIENT_API CarpaccioStream ~CarpaccioStream(); boost::beast::http::response read(boost::beast::flat_buffer&); - void write(boost::beast::http::verb requestType, const std::string & target); + void write(boost::beast::http::verb requestType, const std::string & target, const std::string & contentType, const std::string & body); private: std::string m_serverHost; diff --git a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp index ce9ac7a6..322c5859 100644 --- a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp +++ b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp @@ -20,43 +20,6 @@ using tcp = boost::asio::ip::tcp; // from const int version = 11; -// Return a reasonable mime type based on the extension of a file. -beast::string_view -mime_type(beast::string_view path) -{ - using beast::iequals; - auto const ext = [&path] - { - auto const pos = path.rfind("."); - if (pos == beast::string_view::npos) - return beast::string_view{}; - return path.substr(pos); - }(); - if (iequals(ext, ".htm")) return "text/html"; - if (iequals(ext, ".html")) return "text/html"; - if (iequals(ext, ".php")) return "text/html"; - if (iequals(ext, ".css")) return "text/css"; - if (iequals(ext, ".txt")) return "text/plain"; - if (iequals(ext, ".js")) return "application/javascript"; - if (iequals(ext, ".json")) return "application/json"; - if (iequals(ext, ".xml")) return "application/xml"; - if (iequals(ext, ".swf")) return "application/x-shockwave-flash"; - if (iequals(ext, ".flv")) return "video/x-flv"; - if (iequals(ext, ".png")) return "image/png"; - if (iequals(ext, ".jpe")) return "image/jpeg"; - if (iequals(ext, ".jpeg")) return "image/jpeg"; - if (iequals(ext, ".jpg")) return "image/jpeg"; - if (iequals(ext, ".gif")) return "image/gif"; - if (iequals(ext, ".bmp")) return "image/bmp"; - if (iequals(ext, ".ico")) return "image/vnd.microsoft.icon"; - if (iequals(ext, ".tiff")) return "image/tiff"; - if (iequals(ext, ".tif")) return "image/tiff"; - if (iequals(ext, ".svg")) return "image/svg+xml"; - if (iequals(ext, ".svgz")) return "image/svg+xml"; - return "application/text"; -} - - namespace extreme_carpaccio_client { http_worker::http_worker(tcp::acceptor& acceptor, const std::string& doc_root) : @@ -128,21 +91,30 @@ void http_worker::read_request() }); } +bool http_worker::handleRequest(http::verb requestType, const std::string & target, const std::string & contentType, const std::string & body) +{ + bool error = true; + + if (requestType == http::verb::post && contentType == "application/json") + { + if (target == "/order") + { + send_bad_response(http::status::ok, "OUAIS !\r\n"); + error = false; + } + } + + return error; +} + void http_worker::process_request(http::request> const& req) { - switch (req.method()) + const std::string contentType = req[http::field::content_type].to_string(); + const std::string body = req[http::field::body].to_string(); + + if (this->handleRequest(req.method(), req.target().to_string(), contentType, body)) { - case http::verb::get: - send_file(req.target()); - break; - - default: - // We return responses indicating an error if - // we do not recognize the request method. - send_bad_response( - http::status::bad_request, - "Invalid request-method '" + std::string(req.method_string()) + "'\r\n"); - break; + this->send_bad_response(http::status::not_found, "HTTP code 404\r\n"); } } @@ -173,59 +145,6 @@ void http_worker::send_bad_response( }); } -void http_worker::send_file(beast::string_view target) -{ - // Request path must be absolute and not contain "..". - if (target.empty() || target[0] != '/' || target.find("..") != std::string::npos) - { - send_bad_response( - http::status::not_found, - "File not found\r\n"); - return; - } - - std::string full_path = doc_root_; - full_path.append( - target.data(), - target.size()); - - http::file_body::value_type file; - beast::error_code ec; - file.open( - full_path.c_str(), - beast::file_mode::read, - ec); - if (ec) - { - send_bad_response( - http::status::not_found, - "File not found\r\n"); - return; - } - - file_response_.emplace( - std::piecewise_construct, - std::make_tuple(), - std::make_tuple(alloc_)); - - file_response_->result(http::status::ok); - file_response_->keep_alive(false); - file_response_->set(http::field::server, "Beast"); - file_response_->set(http::field::content_type, mime_type(std::string(target))); - file_response_->body() = std::move(file); - file_response_->prepare_payload(); - - http::async_write( - socket_, - *file_response_, - [this](beast::error_code ec, std::size_t) - { - socket_.shutdown(tcp::socket::shutdown_send, ec); - file_response_.reset(); - accept(); - }); -} - void http_worker::check_deadline() { // The deadline may have moved, so check it has really passed. @@ -299,12 +218,14 @@ void http_worker::check_deadline() return response; } - void CarpaccioStream::write(boost::beast::http::verb requestType, const std::string & target) + void CarpaccioStream::write(boost::beast::http::verb requestType, const std::string & target, const std::string & contentType, const std::string & body) { // Set up an HTTP GET request message http::request request{ requestType, target, version }; request.set(http::field::host, m_serverHost); request.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING); + request.set(http::field::content_type, contentType); + request.set(http::field::body, body); // Send the HTTP request to the remote host http::write(m_stream, request); diff --git a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp index 2f88017c..7277ae20 100644 --- a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp +++ b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp @@ -26,7 +26,7 @@ using namespace extreme_carpaccio_client; const char serverHost[] = "localhost"; const unsigned short serverPort = 8081; -static http::response generateServerResponse(boost::beast::http::verb requestType, const std::string & target) +static http::response generateServerResponse(boost::beast::http::verb requestType, const std::string & target, const std::string & contentType = "", const std::string & body = "") { CarpaccioServer server(8081); std::thread thread(&CarpaccioServer::start, &server); @@ -35,7 +35,7 @@ static http::response generateServerResponse(boost::beast::h CarpaccioStream stream(serverHost, serverPort); // Send the HTTP request to the remote host - stream.write(requestType, target); + stream.write(requestType, target, contentType, body); // This buffer is used for reading and must be persisted beast::flat_buffer buffer; @@ -50,28 +50,28 @@ static http::response generateServerResponse(boost::beast::h return res; } -TEST(ExtremeCarpaccioClient, should_handle_feedback) +TEST(ExtremeCarpaccioClient, should_answer_404_to_incorrect_request) { - std::string target = "/toto.png"; + std::string target = "/je-suis-trop-fort"; // Receive the HTTP response auto res = generateServerResponse(http::verb::get, target); // Write the message to standard out std::cout << "Response" << std::endl << res << std::endl; - EXPECT_EQ(http::status::ok, res.result()); + EXPECT_EQ(http::status::not_found, res.result()); } TEST(ExtremeCarpaccioClient, should_handle_order) { - CarpaccioServer server(serverPort); - std::thread thread(&CarpaccioServer::start, &server); - std::this_thread::sleep_for(std::chrono::seconds(1)); + std::string target = "/order"; - EXPECT_EQ(1, 1); + // Receive the HTTP response + auto res = generateServerResponse(http::verb::post, target, "application/json", "{prices: [], quantities: [], country: \"DE\", reduction: \"STANDARD\"}"); - server.stop(); - thread.detach(); + // Write the message to standard out + std::cout << "Response" << std::endl << res << std::endl; + EXPECT_EQ(http::status::ok, res.result()); } //it('should handle feedback', function(done) { From 34829b2e1ff40d871b967d154fcfd00e721ce9c4 Mon Sep 17 00:00:00 2001 From: NADIF Antoine Date: Thu, 21 Oct 2021 15:41:32 +0200 Subject: [PATCH 081/125] Update TODO list with next objectives: manual test with actual carpaccio server and json read/write. --- clients/cpp/TODOLIST.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/clients/cpp/TODOLIST.md b/clients/cpp/TODOLIST.md index 3d1c7e9a..b06c28c1 100644 --- a/clients/cpp/TODOLIST.md +++ b/clients/cpp/TODOLIST.md @@ -8,9 +8,9 @@ - [X] Update our test to check that client can get a file from the server - [X] Deal with starting & stopping the server correctly in the test to avoid resource leaks - [ ] Implement the POST /order command - - [ ] check what the request and answers should look like from the js versions - - [ ] write a test to POST /order with a proper request - - [ ] implement POST /order + - [X] check what the request and answers should look like from the js versions + - [X] write a test to POST /order with a proper request + - [X] implement POST /order - [ ] test our client with the real extreme carpaccio server - [ ] make sure we can easily build a json response (and play the game) - [ ] Implement the POST /feedback command From 4da224d2454b1f3450614dc33d292bb0cbabb146 Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 4 Nov 2021 12:04:50 +0100 Subject: [PATCH 082/125] Update todolist : we tested our client http server with the real carpaccio server --- clients/cpp/TODOLIST.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clients/cpp/TODOLIST.md b/clients/cpp/TODOLIST.md index b06c28c1..ebadcf3a 100644 --- a/clients/cpp/TODOLIST.md +++ b/clients/cpp/TODOLIST.md @@ -11,7 +11,7 @@ - [X] check what the request and answers should look like from the js versions - [X] write a test to POST /order with a proper request - [X] implement POST /order - - [ ] test our client with the real extreme carpaccio server + - [X] test our client with the real extreme carpaccio server - [ ] make sure we can easily build a json response (and play the game) - [ ] Implement the POST /feedback command - [ ] check what the request, answers and behavior should look like from the js versions From 5dc9a69786a0ec876bcd441e4c899f88348d5462 Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 4 Nov 2021 15:55:35 +0100 Subject: [PATCH 083/125] Add dependency on nlohmann json library --- clients/cpp/CMakeLists.txt | 5 +++-- clients/cpp/cmake/FindNlohmannJson.cmake | 11 ++++++----- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/clients/cpp/CMakeLists.txt b/clients/cpp/CMakeLists.txt index b32cc9e7..c5cee4ef 100644 --- a/clients/cpp/CMakeLists.txt +++ b/clients/cpp/CMakeLists.txt @@ -37,7 +37,7 @@ target_include_directories(Extreme-Carpaccio-Client-shared ${CMAKE_CURRENT_SOURCE_DIR}/include ) -target_link_libraries(Extreme-Carpaccio-Client-shared PUBLIC Boost::boost) +target_link_libraries(Extreme-Carpaccio-Client-shared PUBLIC Boost::boost PRIVATE nlohmann_json) # Client executable add_executable(Extreme-Carpaccio-Client) @@ -63,7 +63,8 @@ target_link_libraries(Extreme-Carpaccio-Client-test PRIVATE Extreme-Carpaccio-Client-shared gtest_main - Boost::boost) + Boost::boost + nlohmann_json) add_test(NAME ctest-Extreme-Carpaccio-Client COMMAND Extreme-Carpaccio-Client-test) diff --git a/clients/cpp/cmake/FindNlohmannJson.cmake b/clients/cpp/cmake/FindNlohmannJson.cmake index 022cd094..78939bea 100644 --- a/clients/cpp/cmake/FindNlohmannJson.cmake +++ b/clients/cpp/cmake/FindNlohmannJson.cmake @@ -2,14 +2,15 @@ CPMFindPackage( NAME nlohmann_json - VERSION 3.9.1 + VERSION 3.6.1 # the git repo is incredibly large, so we download the archived include directory - URL https://github.com/nlohmann/json/releases/download/v3.9.1/include.zip - URL_HASH SHA256=6bea5877b1541d353bd77bdfbdb2696333ae5ed8f9e8cc22df657192218cad91 - OPTIONS "JSON_BuildTests OFF" + URL https://github.com/nlohmann/json/releases/download/v3.6.1/include.zip + URL_HASH SHA256=69cc88207ce91347ea530b227ff0776db82dcb8de6704e1a3d74f4841bc651cf ) if (nlohmann_json_ADDED) add_library(nlohmann_json INTERFACE IMPORTED) target_include_directories(nlohmann_json INTERFACE ${nlohmann_json_SOURCE_DIR}) -endif() +else() + message(FATAL_ERROR "nlohman json dependency not found") +endif() \ No newline at end of file From a179bcba47ec45d2895a88aa860c2efb0fcf063d Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 4 Nov 2021 15:56:51 +0100 Subject: [PATCH 084/125] Implement compute total amount + json parsing --- .../ExtremeCarpaccioClient.cpp | 20 ++++++++++++++++++- .../cpp/test/ExtremeCarpaccioClientTest.cpp | 20 ++++++++++++++----- 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp index 322c5859..f9ef9a40 100644 --- a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp +++ b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp @@ -12,6 +12,7 @@ #include #include #include +#include namespace beast = boost::beast; // from namespace http = beast::http; // from @@ -91,6 +92,11 @@ void http_worker::read_request() }); } +double computeTotalAmount() +{ + return 0.0; +} + bool http_worker::handleRequest(http::verb requestType, const std::string & target, const std::string & contentType, const std::string & body) { bool error = true; @@ -99,7 +105,19 @@ bool http_worker::handleRequest(http::verb requestType, const std::string & targ { if (target == "/order") { - send_bad_response(http::status::ok, "OUAIS !\r\n"); + try + { + auto requestJson = nlohmann::json::parse(body); + } + catch (nlohmann::json::exception& e) + { + return true; + } + + nlohmann::json totalAmountJson; + + totalAmountJson["total"] = computeTotalAmount(); + send_bad_response(http::status::ok, totalAmountJson.dump()); error = false; } } diff --git a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp index 7277ae20..c09376d1 100644 --- a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp +++ b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp @@ -14,6 +14,7 @@ #include #include #include +#include namespace beast = boost::beast; // from namespace http = beast::http; // from @@ -62,16 +63,25 @@ TEST(ExtremeCarpaccioClient, should_answer_404_to_incorrect_request) EXPECT_EQ(http::status::not_found, res.result()); } -TEST(ExtremeCarpaccioClient, should_handle_order) +TEST(ExtremeCarpaccioClient, should_return_valid_amount_on_order_request) { std::string target = "/order"; // Receive the HTTP response - auto res = generateServerResponse(http::verb::post, target, "application/json", "{prices: [], quantities: [], country: \"DE\", reduction: \"STANDARD\"}"); + auto res = generateServerResponse(http::verb::post, target, "application/json", "{\"prices\": [], \"quantities\": [], \"country\": \"DE\", \"reduction\": \"STANDARD\"}"); - // Write the message to standard out - std::cout << "Response" << std::endl << res << std::endl; - EXPECT_EQ(http::status::ok, res.result()); + ASSERT_EQ(http::status::ok, res.result()); + + auto totalAmountJson = nlohmann::json::parse(boost::beast::buffers_to_string(res.body().data())); + + EXPECT_NO_THROW(totalAmountJson["total"].get()); +} + +TEST(ExtremeCarpaccioClient, parsing_json) +{ + auto totalAmountJson = nlohmann::json::parse("{\"total\":0.0}"); + + EXPECT_EQ(totalAmountJson["total"].get(), 0.); } //it('should handle feedback', function(done) { From ede4d6a11b7dece2508fe1f8c86ec6eb0e7e3f78 Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 4 Nov 2021 15:57:03 +0100 Subject: [PATCH 085/125] Update of TODOLIST --- clients/cpp/TODOLIST.md | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/clients/cpp/TODOLIST.md b/clients/cpp/TODOLIST.md index ebadcf3a..67867ec9 100644 --- a/clients/cpp/TODOLIST.md +++ b/clients/cpp/TODOLIST.md @@ -12,7 +12,14 @@ - [X] write a test to POST /order with a proper request - [X] implement POST /order - [X] test our client with the real extreme carpaccio server - - [ ] make sure we can easily build a json response (and play the game) + - [ ] make sure we can parse the json order and build an order object + - [X] make sure we can parse the json order + - [ ] use correct field to pass the body of the request + - [ ] build an order object from the json (cf value_ field of the res object) + - [ ] Refactor handleRequest + - [X] Return total amount json + - [X] make sure we can easily build a json response (and play the game) + - [ ] By default return error 404 as answer to the request to be in line with other implementations - [ ] Implement the POST /feedback command - [ ] check what the request, answers and behavior should look like from the js versions - [ ] write a test to POST /feedback with a proper request @@ -26,4 +33,5 @@ - [ ] Clean gitignore file in cpp - [ ] Ajouter dans le cmake le Json en thirdparty pour la solution VS - [ ] Add dependencies on sub boost headers only libraries (beast), instead on depending on full boost -- [ ] Fix that : Failed to find all ICU components (missing: ICU_INCLUDE_DIR _ICU_REQUIRED_LIBS_FOUND) \ No newline at end of file +- [ ] Fix that : Failed to find all ICU components (missing: ICU_INCLUDE_DIR _ICU_REQUIRED_LIBS_FOUND) +- [ ] Upgrade nlohman json version \ No newline at end of file From 5e42d67fd351a44593a83202fdfa728e3478dac7 Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 4 Nov 2021 15:58:20 +0100 Subject: [PATCH 086/125] Remove test on json parsing --- clients/cpp/test/ExtremeCarpaccioClientTest.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp index c09376d1..e219184e 100644 --- a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp +++ b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp @@ -77,13 +77,6 @@ TEST(ExtremeCarpaccioClient, should_return_valid_amount_on_order_request) EXPECT_NO_THROW(totalAmountJson["total"].get()); } -TEST(ExtremeCarpaccioClient, parsing_json) -{ - auto totalAmountJson = nlohmann::json::parse("{\"total\":0.0}"); - - EXPECT_EQ(totalAmountJson["total"].get(), 0.); -} - //it('should handle feedback', function(done) { // var feedback = request('http://' + conf.host + ':' + conf.port + '/feedback', function(error, response) { // expect(response.statusCode).toBe(204); From 6c71f6428b6f7a58fff975bbbe69995991d03fda Mon Sep 17 00:00:00 2001 From: Mirna Date: Thu, 27 Jan 2022 17:36:22 +0100 Subject: [PATCH 087/125] Parse order --- clients/cpp/CMakeLists.txt | 4 ++-- clients/cpp/TODOLIST.md | 2 +- clients/cpp/cmake/FindGoogleTest.cmake | 2 +- .../ExtremeCarpaccioClient.hpp | 11 +++++++++++ .../ExtremeCarpaccioClient.cpp | 14 ++++++++++++++ clients/cpp/test/ExtremeCarpaccioClientTest.cpp | 15 +++++++++++++++ 6 files changed, 44 insertions(+), 4 deletions(-) diff --git a/clients/cpp/CMakeLists.txt b/clients/cpp/CMakeLists.txt index c5cee4ef..afdf2c69 100644 --- a/clients/cpp/CMakeLists.txt +++ b/clients/cpp/CMakeLists.txt @@ -62,7 +62,7 @@ target_sources(Extreme-Carpaccio-Client-test target_link_libraries(Extreme-Carpaccio-Client-test PRIVATE Extreme-Carpaccio-Client-shared - gtest_main + gmock_main Boost::boost nlohmann_json) @@ -83,6 +83,6 @@ set_property(TARGET Extreme-Carpaccio-Client-test PROPERTY FOLDER "ExtremeCarpac set_property(TARGET Extreme-Carpaccio-Client PROPERTY FOLDER "ExtremeCarpaccioClient") set_property(TARGET Docs PROPERTY FOLDER "ExtremeCarpaccioClient") -set_property(TARGET gtest gtest_main PROPERTY FOLDER "Third-Party/GoogleTest") +set_property(TARGET gtest gmock_main PROPERTY FOLDER "Third-Party/GoogleTest") set_property(GLOBAL PROPERTY PREDEFINED_TARGETS_FOLDER "CMake Generated") diff --git a/clients/cpp/TODOLIST.md b/clients/cpp/TODOLIST.md index 67867ec9..4f2fe25a 100644 --- a/clients/cpp/TODOLIST.md +++ b/clients/cpp/TODOLIST.md @@ -14,7 +14,7 @@ - [X] test our client with the real extreme carpaccio server - [ ] make sure we can parse the json order and build an order object - [X] make sure we can parse the json order - - [ ] use correct field to pass the body of the request + - [X] use correct field to pass the body of the request? - [ ] build an order object from the json (cf value_ field of the res object) - [ ] Refactor handleRequest - [X] Return total amount json diff --git a/clients/cpp/cmake/FindGoogleTest.cmake b/clients/cpp/cmake/FindGoogleTest.cmake index 727996b1..dad94cb3 100644 --- a/clients/cpp/cmake/FindGoogleTest.cmake +++ b/clients/cpp/cmake/FindGoogleTest.cmake @@ -5,5 +5,5 @@ CPMAddPackage( GITHUB_REPOSITORY google/googletest GIT_TAG release-1.10.0 VERSION 1.10.0 - OPTIONS "INSTALL_GTEST OFF" "gtest_force_shared_crt" "BUILD_GMOCK OFF" + OPTIONS "INSTALL_GTEST OFF" "gtest_force_shared_crt" "BUILD_GMOCK ON" ) diff --git a/clients/cpp/include/extreme_carpaccio_client/ExtremeCarpaccioClient.hpp b/clients/cpp/include/extreme_carpaccio_client/ExtremeCarpaccioClient.hpp index f71ed597..d73e2427 100644 --- a/clients/cpp/include/extreme_carpaccio_client/ExtremeCarpaccioClient.hpp +++ b/clients/cpp/include/extreme_carpaccio_client/ExtremeCarpaccioClient.hpp @@ -5,6 +5,7 @@ #include +#include #include namespace extreme_carpaccio_client { @@ -97,4 +98,14 @@ class EXTREME_CARPACCIO_CLIENT_API CarpaccioStream boost::beast::tcp_stream m_stream; }; +struct EXTREME_CARPACCIO_CLIENT_API Order +{ + std::vector quantities; + std::vector prices; + std::string country; + std::string reduction; +}; + +EXTREME_CARPACCIO_CLIENT_API Order parseOrder(const std::string& jsonOrder); + } // namespace extreme_carpaccio_client diff --git a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp index f9ef9a40..092efcf9 100644 --- a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp +++ b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp @@ -249,5 +249,19 @@ void http_worker::check_deadline() http::write(m_stream, request); } + EXTREME_CARPACCIO_CLIENT_API Order parseOrder(const std::string & jsonOrder) + { + Order order; + + auto parsedOrder = nlohmann::json::parse(jsonOrder); + + order.country = parsedOrder["country"].get(); + order.reduction = parsedOrder["reduction"].get(); + order.prices = parsedOrder["prices"].get>(); + order.quantities = parsedOrder["quantities"].get>(); + + return order; + } + } // namespace extreme_carpaccio_client diff --git a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp index e219184e..0ca7c756 100644 --- a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp +++ b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp @@ -1,6 +1,7 @@ #include +#include #include #include @@ -21,6 +22,7 @@ namespace http = beast::http; // from namespace net = boost::asio; // from using tcp = net::ip::tcp; // from +using testing::ElementsAre; using namespace extreme_carpaccio_client; @@ -77,6 +79,19 @@ TEST(ExtremeCarpaccioClient, should_return_valid_amount_on_order_request) EXPECT_NO_THROW(totalAmountJson["total"].get()); } +TEST(ExtremeCarpaccioClient, should_return_order_object_from_json_order) +{ + std::string orderRequest = "{\"prices\": [1,1.5], \"quantities\": [100, 200], \"country\": \"DE\", \"reduction\": \"STANDARD\"}"; + + Order order = parseOrder(orderRequest); + + EXPECT_EQ("DE", order.country); + EXPECT_EQ("STANDARD", order.reduction); + + EXPECT_THAT(order.prices, ElementsAre(1, 1.5)); + EXPECT_THAT(order.quantities, ElementsAre(100, 200)); +} + //it('should handle feedback', function(done) { // var feedback = request('http://' + conf.host + ':' + conf.port + '/feedback', function(error, response) { // expect(response.statusCode).toBe(204); From 413bd54c05a772b3194b2f5109fed30173b905ca Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 3 Feb 2022 15:36:05 +0100 Subject: [PATCH 088/125] Put Order in a specific file --- clients/cpp/CMakeLists.txt | 2 ++ clients/cpp/TODOLIST.md | 5 ++-- .../ExtremeCarpaccioClient.hpp | 11 --------- .../extreme_carpaccio_client/Order.hpp | 18 +++++++++++++++ .../ExtremeCarpaccioClient.cpp | 14 ----------- .../src/extreme_carpaccio_client/Order.cpp | 23 +++++++++++++++++++ .../cpp/test/ExtremeCarpaccioClientTest.cpp | 2 +- 7 files changed, 47 insertions(+), 28 deletions(-) create mode 100644 clients/cpp/include/extreme_carpaccio_client/Order.hpp create mode 100644 clients/cpp/src/extreme_carpaccio_client/Order.cpp diff --git a/clients/cpp/CMakeLists.txt b/clients/cpp/CMakeLists.txt index afdf2c69..ff40e926 100644 --- a/clients/cpp/CMakeLists.txt +++ b/clients/cpp/CMakeLists.txt @@ -25,9 +25,11 @@ target_compile_definitions(Extreme-Carpaccio-Client-shared PRIVATE EXTREME_CARPA target_sources(Extreme-Carpaccio-Client-shared PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/extreme_carpaccio_client/Order.cpp PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include/extreme_carpaccio_client/ExtremeCarpaccioClient.hpp ${CMAKE_CURRENT_SOURCE_DIR}/include/extreme_carpaccio_client/config.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/include/extreme_carpaccio_client/Order.hpp ) target_include_directories(Extreme-Carpaccio-Client-shared diff --git a/clients/cpp/TODOLIST.md b/clients/cpp/TODOLIST.md index 4f2fe25a..928f6a64 100644 --- a/clients/cpp/TODOLIST.md +++ b/clients/cpp/TODOLIST.md @@ -12,10 +12,11 @@ - [X] write a test to POST /order with a proper request - [X] implement POST /order - [X] test our client with the real extreme carpaccio server - - [ ] make sure we can parse the json order and build an order object + - [X] make sure we can parse the json order and build an order object - [X] make sure we can parse the json order - [X] use correct field to pass the body of the request? - - [ ] build an order object from the json (cf value_ field of the res object) + - [X] build an order object from the json (cf value_ field of the res object) + - [X] Put the order object in a specific file - [ ] Refactor handleRequest - [X] Return total amount json - [X] make sure we can easily build a json response (and play the game) diff --git a/clients/cpp/include/extreme_carpaccio_client/ExtremeCarpaccioClient.hpp b/clients/cpp/include/extreme_carpaccio_client/ExtremeCarpaccioClient.hpp index d73e2427..a224691f 100644 --- a/clients/cpp/include/extreme_carpaccio_client/ExtremeCarpaccioClient.hpp +++ b/clients/cpp/include/extreme_carpaccio_client/ExtremeCarpaccioClient.hpp @@ -6,7 +6,6 @@ #include #include -#include namespace extreme_carpaccio_client { @@ -98,14 +97,4 @@ class EXTREME_CARPACCIO_CLIENT_API CarpaccioStream boost::beast::tcp_stream m_stream; }; -struct EXTREME_CARPACCIO_CLIENT_API Order -{ - std::vector quantities; - std::vector prices; - std::string country; - std::string reduction; -}; - -EXTREME_CARPACCIO_CLIENT_API Order parseOrder(const std::string& jsonOrder); - } // namespace extreme_carpaccio_client diff --git a/clients/cpp/include/extreme_carpaccio_client/Order.hpp b/clients/cpp/include/extreme_carpaccio_client/Order.hpp new file mode 100644 index 00000000..62ed3e9f --- /dev/null +++ b/clients/cpp/include/extreme_carpaccio_client/Order.hpp @@ -0,0 +1,18 @@ +#include + +#include +#include + +namespace extreme_carpaccio_client { + +struct EXTREME_CARPACCIO_CLIENT_API Order +{ + std::vector quantities; + std::vector prices; + std::string country; + std::string reduction; +}; + +EXTREME_CARPACCIO_CLIENT_API Order parseOrder(const std::string& jsonOrder); + +} // namespace extreme_carpaccio_client diff --git a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp index 092efcf9..f9ef9a40 100644 --- a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp +++ b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp @@ -249,19 +249,5 @@ void http_worker::check_deadline() http::write(m_stream, request); } - EXTREME_CARPACCIO_CLIENT_API Order parseOrder(const std::string & jsonOrder) - { - Order order; - - auto parsedOrder = nlohmann::json::parse(jsonOrder); - - order.country = parsedOrder["country"].get(); - order.reduction = parsedOrder["reduction"].get(); - order.prices = parsedOrder["prices"].get>(); - order.quantities = parsedOrder["quantities"].get>(); - - return order; - } - } // namespace extreme_carpaccio_client diff --git a/clients/cpp/src/extreme_carpaccio_client/Order.cpp b/clients/cpp/src/extreme_carpaccio_client/Order.cpp new file mode 100644 index 00000000..51fdc1b2 --- /dev/null +++ b/clients/cpp/src/extreme_carpaccio_client/Order.cpp @@ -0,0 +1,23 @@ +#include + +#include + + +namespace extreme_carpaccio_client { + +EXTREME_CARPACCIO_CLIENT_API Order parseOrder(const std::string & jsonOrder) +{ + Order order; + + auto parsedOrder = nlohmann::json::parse(jsonOrder); + + order.country = parsedOrder["country"].get(); + order.reduction = parsedOrder["reduction"].get(); + order.prices = parsedOrder["prices"].get>(); + order.quantities = parsedOrder["quantities"].get>(); + + return order; +} + +} // namespace extreme_carpaccio_client + diff --git a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp index 0ca7c756..f27f693e 100644 --- a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp +++ b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp @@ -1,5 +1,5 @@ - #include +#include #include #include From 7633580e37d6f53f85f942f7265ee396b7785234 Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 3 Feb 2022 16:01:57 +0100 Subject: [PATCH 089/125] Use Order in computeTotalAmount --- clients/cpp/TODOLIST.md | 2 +- .../ExtremeCarpaccioClient.hpp | 4 +- .../ExtremeCarpaccioClient.cpp | 41 ++++++++----------- .../cpp/test/ExtremeCarpaccioClientTest.cpp | 13 ++++++ 4 files changed, 32 insertions(+), 28 deletions(-) diff --git a/clients/cpp/TODOLIST.md b/clients/cpp/TODOLIST.md index 928f6a64..320c9a92 100644 --- a/clients/cpp/TODOLIST.md +++ b/clients/cpp/TODOLIST.md @@ -17,7 +17,7 @@ - [X] use correct field to pass the body of the request? - [X] build an order object from the json (cf value_ field of the res object) - [X] Put the order object in a specific file - - [ ] Refactor handleRequest + - [X] Refactor handleRequest - [X] Return total amount json - [X] make sure we can easily build a json response (and play the game) - [ ] By default return error 404 as answer to the request to be in line with other implementations diff --git a/clients/cpp/include/extreme_carpaccio_client/ExtremeCarpaccioClient.hpp b/clients/cpp/include/extreme_carpaccio_client/ExtremeCarpaccioClient.hpp index a224691f..09d8e014 100644 --- a/clients/cpp/include/extreme_carpaccio_client/ExtremeCarpaccioClient.hpp +++ b/clients/cpp/include/extreme_carpaccio_client/ExtremeCarpaccioClient.hpp @@ -58,9 +58,7 @@ class http_worker void process_request(boost::beast::http::request> const& req); - void send_bad_response( - boost::beast::http::status status, - std::string const& error); + void send_response(boost::beast::http::status status, std::string const& body); void check_deadline(); diff --git a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp index f9ef9a40..ad474b07 100644 --- a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp +++ b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp @@ -1,5 +1,5 @@ - #include +#include #include #include @@ -92,37 +92,32 @@ void http_worker::read_request() }); } -double computeTotalAmount() +double computeTotalAmount(Order order) { - return 0.0; + double amount = 0.; + + for (int priceIndex = 0; priceIndex < order.prices.size(); ++priceIndex) + { + amount += order.prices[priceIndex] * order.quantities[priceIndex]; + } + return amount; } bool http_worker::handleRequest(http::verb requestType, const std::string & target, const std::string & contentType, const std::string & body) { - bool error = true; - if (requestType == http::verb::post && contentType == "application/json") { if (target == "/order") { - try - { - auto requestJson = nlohmann::json::parse(body); - } - catch (nlohmann::json::exception& e) - { - return true; - } - + Order order = parseOrder(body); nlohmann::json totalAmountJson; - totalAmountJson["total"] = computeTotalAmount(); - send_bad_response(http::status::ok, totalAmountJson.dump()); - error = false; + totalAmountJson["total"] = computeTotalAmount(order); + send_response(http::status::ok, totalAmountJson.dump()); + return false; } } - - return error; + return true; } void http_worker::process_request(http::request> const& req) @@ -132,13 +127,11 @@ void http_worker::process_request(http::requesthandleRequest(req.method(), req.target().to_string(), contentType, body)) { - this->send_bad_response(http::status::not_found, "HTTP code 404\r\n"); + this->send_response(http::status::not_found, "HTTP code 404\r\n"); } } -void http_worker::send_bad_response( - http::status status, - std::string const& error) +void http_worker::send_response(http::status status, std::string const& body) { string_response_.emplace( std::piecewise_construct, @@ -149,7 +142,7 @@ void http_worker::send_bad_response( string_response_->keep_alive(false); string_response_->set(http::field::server, "Beast"); string_response_->set(http::field::content_type, "text/plain"); - string_response_->body() = error; + string_response_->body() = body; string_response_->prepare_payload(); http::async_write( diff --git a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp index f27f693e..68a724ab 100644 --- a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp +++ b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp @@ -79,6 +79,19 @@ TEST(ExtremeCarpaccioClient, should_return_valid_amount_on_order_request) EXPECT_NO_THROW(totalAmountJson["total"].get()); } +TEST(ExtremeCarpaccioClient, should_return_amount_computed_with_prices_and_quantities_only) +{ + std::string target = "/order"; + + auto res = generateServerResponse(http::verb::post, target, "application/json", "{\"prices\": [1,1.5], \"quantities\": [100, 200], \"country\": \"DE\", \"reduction\": \"STANDARD\"}"); + + ASSERT_EQ(http::status::ok, res.result()); + + auto totalAmountJson = nlohmann::json::parse(boost::beast::buffers_to_string(res.body().data())); + + EXPECT_EQ(100 * 1 + 200 * 1.5, totalAmountJson["total"].get()); +} + TEST(ExtremeCarpaccioClient, should_return_order_object_from_json_order) { std::string orderRequest = "{\"prices\": [1,1.5], \"quantities\": [100, 200], \"country\": \"DE\", \"reduction\": \"STANDARD\"}"; From a1785ac9ddffa5a68455ef5d377d3e07d026fda5 Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 3 Feb 2022 18:15:39 +0100 Subject: [PATCH 090/125] Fill and read corretly the body of the request --- .../src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp index ad474b07..a36eb328 100644 --- a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp +++ b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp @@ -123,7 +123,7 @@ bool http_worker::handleRequest(http::verb requestType, const std::string & targ void http_worker::process_request(http::request> const& req) { const std::string contentType = req[http::field::content_type].to_string(); - const std::string body = req[http::field::body].to_string(); + const std::string body = req.body(); if (this->handleRequest(req.method(), req.target().to_string(), contentType, body)) { @@ -236,7 +236,8 @@ void http_worker::check_deadline() request.set(http::field::host, m_serverHost); request.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING); request.set(http::field::content_type, contentType); - request.set(http::field::body, body); + request.body() = body; + request.prepare_payload(); // Send the HTTP request to the remote host http::write(m_stream, request); From 8ab1c1fb2c2f26108aab5f3e75db84430a2c2af6 Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 3 Feb 2022 18:29:51 +0100 Subject: [PATCH 091/125] Handle POST feedback --- .../ExtremeCarpaccioClient.cpp | 24 ++++++++++++++ .../cpp/test/ExtremeCarpaccioClientTest.cpp | 32 +++++++++---------- 2 files changed, 40 insertions(+), 16 deletions(-) diff --git a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp index a36eb328..a63b88d7 100644 --- a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp +++ b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp @@ -103,6 +103,22 @@ double computeTotalAmount(Order order) return amount; } +struct Feedback +{ + std::string type; + std::string content; +}; + +static Feedback parseFeedback(const std::string& jsonFeedback) +{ + auto parsedFeedback = nlohmann::json::parse(jsonFeedback); + Feedback feedback = {}; + + feedback.type = parsedFeedback["type"].get(); + feedback.content = parsedFeedback["content"].get(); + return feedback; +} + bool http_worker::handleRequest(http::verb requestType, const std::string & target, const std::string & contentType, const std::string & body) { if (requestType == http::verb::post && contentType == "application/json") @@ -116,6 +132,14 @@ bool http_worker::handleRequest(http::verb requestType, const std::string & targ send_response(http::status::ok, totalAmountJson.dump()); return false; } + else if (target == "/feedback") + { + Feedback feedback = parseFeedback(body); + + std::cout << feedback.type << " : " << feedback.content << std::endl; + send_response(http::status::ok, "Feedback received"); + return false; + } } return true; } diff --git a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp index 68a724ab..5a19553a 100644 --- a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp +++ b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp @@ -4,6 +4,7 @@ #include #include +#include #include #include @@ -105,20 +106,19 @@ TEST(ExtremeCarpaccioClient, should_return_order_object_from_json_order) EXPECT_THAT(order.quantities, ElementsAre(100, 200)); } -//it('should handle feedback', function(done) { -// var feedback = request('http://' + conf.host + ':' + conf.port + '/feedback', function(error, response) { -// expect(response.statusCode).toBe(204); -// done(); -// }); -// feedback.write('{type: "INFO", content: "this is my precious feedback"}'); -//}); -// -//it('should handle order', function(done) { -// var order = request('http://' + conf.host + ':' + conf.port + '/order', function(error, response, body) { -// expect(response.statusCode).toBe(200); -// expect(body).toBe('{total:0}'); -// done(); -// }); -// order.write('{prices: [], quantities: [], country: "DE", reduction: "STANDARD"}'); -//}); +TEST(ExtremeCarpaccioClient, should_handle_post_feedback) +{ + std::string target = "/feedback"; + std::stringstream buffer; + // Save cout's buffer here + std::streambuf *sbuf = std::cout.rdbuf(); + // Redirect cout to our stringstream buffer + std::cout.rdbuf(buffer.rdbuf()); + + auto res = generateServerResponse(http::verb::post, target, "application/json", "{\"type\": \"ERROR\", \"content\": \"Field total in response is missing\"}"); + ASSERT_EQ(http::status::ok, res.result()); + ASSERT_EQ("ERROR : Field total in response is missing\n", buffer.str()); + // When done redirect cout to its old self + std::cout.rdbuf(sbuf); +} From c62df1a77d628b58cc4b9c856ced530f82116aad Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 3 Feb 2022 18:43:01 +0100 Subject: [PATCH 092/125] Update Todo list --- clients/cpp/TODOLIST.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/clients/cpp/TODOLIST.md b/clients/cpp/TODOLIST.md index 320c9a92..2746cf4e 100644 --- a/clients/cpp/TODOLIST.md +++ b/clients/cpp/TODOLIST.md @@ -21,11 +21,11 @@ - [X] Return total amount json - [X] make sure we can easily build a json response (and play the game) - [ ] By default return error 404 as answer to the request to be in line with other implementations -- [ ] Implement the POST /feedback command - - [ ] check what the request, answers and behavior should look like from the js versions - - [ ] write a test to POST /feedback with a proper request - - [ ] implement POST /feedback - - [ ] test our client can receive feedback form the real extreme carpaccio server +- [X] Implement the POST /feedback command + - [X] check what the request, answers and behavior should look like from the js versions + - [X] write a test to POST /feedback with a proper request + - [X] implement POST /feedback + - [X] test our client can receive feedback form the real extreme carpaccio server - [ ] Add a configuration file for main options (ports and maybe others) - [ ] check the js client to see what options are available - [ ] create a config file of command line options to set these options From 0478b2a5eea7356a01ad679dc3a325472d7125c1 Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 3 Feb 2022 18:47:31 +0100 Subject: [PATCH 093/125] Remove default implementation and send a 404 error --- clients/cpp/TODOLIST.md | 4 +-- .../ExtremeCarpaccioClient.cpp | 26 ++++++++----------- .../cpp/test/ExtremeCarpaccioClientTest.cpp | 4 +-- 3 files changed, 15 insertions(+), 19 deletions(-) diff --git a/clients/cpp/TODOLIST.md b/clients/cpp/TODOLIST.md index 2746cf4e..25a381da 100644 --- a/clients/cpp/TODOLIST.md +++ b/clients/cpp/TODOLIST.md @@ -7,7 +7,7 @@ - [X] Manual test that it can display a bmp, test it in the browser - [X] Update our test to check that client can get a file from the server - [X] Deal with starting & stopping the server correctly in the test to avoid resource leaks -- [ ] Implement the POST /order command +- [X] Implement the POST /order command - [X] check what the request and answers should look like from the js versions - [X] write a test to POST /order with a proper request - [X] implement POST /order @@ -20,7 +20,7 @@ - [X] Refactor handleRequest - [X] Return total amount json - [X] make sure we can easily build a json response (and play the game) - - [ ] By default return error 404 as answer to the request to be in line with other implementations + - [X] By default return error 404 as answer to the request to be in line with other implementations - [X] Implement the POST /feedback command - [X] check what the request, answers and behavior should look like from the js versions - [X] write a test to POST /feedback with a proper request diff --git a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp index a63b88d7..9c67281d 100644 --- a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp +++ b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp @@ -92,17 +92,6 @@ void http_worker::read_request() }); } -double computeTotalAmount(Order order) -{ - double amount = 0.; - - for (int priceIndex = 0; priceIndex < order.prices.size(); ++priceIndex) - { - amount += order.prices[priceIndex] * order.quantities[priceIndex]; - } - return amount; -} - struct Feedback { std::string type; @@ -119,6 +108,11 @@ static Feedback parseFeedback(const std::string& jsonFeedback) return feedback; } +double computeTotalAmount(Order /*order*/) +{ + return 0.; +} + bool http_worker::handleRequest(http::verb requestType, const std::string & target, const std::string & contentType, const std::string & body) { if (requestType == http::verb::post && contentType == "application/json") @@ -126,11 +120,13 @@ bool http_worker::handleRequest(http::verb requestType, const std::string & targ if (target == "/order") { Order order = parseOrder(body); - nlohmann::json totalAmountJson; + + //TO IMPLEMENT + //nlohmann::json totalAmountJson; - totalAmountJson["total"] = computeTotalAmount(order); - send_response(http::status::ok, totalAmountJson.dump()); - return false; + //totalAmountJson["total"] = computeTotalAmount(order); + //send_response(http::status::ok, totalAmountJson.dump()); + return true; } else if (target == "/feedback") { diff --git a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp index 5a19553a..201dfe41 100644 --- a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp +++ b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp @@ -66,7 +66,7 @@ TEST(ExtremeCarpaccioClient, should_answer_404_to_incorrect_request) EXPECT_EQ(http::status::not_found, res.result()); } -TEST(ExtremeCarpaccioClient, should_return_valid_amount_on_order_request) +TEST(ExtremeCarpaccioClient, DISABLED_should_return_valid_amount_on_order_request) { std::string target = "/order"; @@ -80,7 +80,7 @@ TEST(ExtremeCarpaccioClient, should_return_valid_amount_on_order_request) EXPECT_NO_THROW(totalAmountJson["total"].get()); } -TEST(ExtremeCarpaccioClient, should_return_amount_computed_with_prices_and_quantities_only) +TEST(ExtremeCarpaccioClient, DISABLED_should_return_amount_computed_with_prices_and_quantities_only) { std::string target = "/order"; From 37bd87696431fb5042adabbfd2fb239f856f1121 Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 17 Feb 2022 19:04:37 +0100 Subject: [PATCH 094/125] Enrich TODOLIST following demo feedbacks. --- clients/cpp/TODOLIST.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/clients/cpp/TODOLIST.md b/clients/cpp/TODOLIST.md index 25a381da..0ba14b52 100644 --- a/clients/cpp/TODOLIST.md +++ b/clients/cpp/TODOLIST.md @@ -26,10 +26,12 @@ - [X] write a test to POST /feedback with a proper request - [X] implement POST /feedback - [X] test our client can receive feedback form the real extreme carpaccio server -- [ ] Add a configuration file for main options (ports and maybe others) +- [] Add a configuration file for main options (ports and maybe others) - [ ] check the js client to see what options are available - [ ] create a config file of command line options to set these options - +- [] Move in a dedicated file the request handling part of the client code +- [] Find a way to test code while the client is running (copy dll, use a static library, edit and continue ???) +- [] Use a different port number for tests ## PARKING - [ ] Clean gitignore file in cpp - [ ] Ajouter dans le cmake le Json en thirdparty pour la solution VS From 69b76214a0f8fcb6dab356d9854c44f7dfd1d09a Mon Sep 17 00:00:00 2001 From: pdalesme Date: Tue, 29 Mar 2022 08:11:15 +0200 Subject: [PATCH 095/125] Add actions following session on extreme carpaccio using c++ client --- clients/cpp/TODOLIST.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/clients/cpp/TODOLIST.md b/clients/cpp/TODOLIST.md index 0ba14b52..342eaba6 100644 --- a/clients/cpp/TODOLIST.md +++ b/clients/cpp/TODOLIST.md @@ -29,6 +29,13 @@ - [] Add a configuration file for main options (ports and maybe others) - [ ] check the js client to see what options are available - [ ] create a config file of command line options to set these options +- [ ] Feedbacks from the session on extreme carpaccio with C++ client + - [ ] Display the order description in the code handling the order to have it in the console + - [ ] We need to initialize the http server with the hostname of the user launching it + - [ ] Tests crashed when Mirna launched them on their machine + - [ ] We need a specific test target for functional tests + - [ ] Add guards in header files + - [ ] Copying dll and binary to another directory was not easy - [] Move in a dedicated file the request handling part of the client code - [] Find a way to test code while the client is running (copy dll, use a static library, edit and continue ???) - [] Use a different port number for tests From c9c6099e674d9d3e74671d10ff08770ce4ef397c Mon Sep 17 00:00:00 2001 From: Damien Menanteau Date: Thu, 7 Apr 2022 15:21:11 +0200 Subject: [PATCH 096/125] Add trace on orders receival --- clients/cpp/TODOLIST.md | 10 ++-- .../extreme_carpaccio_client/Order.hpp | 1 + .../ExtremeCarpaccioClient.cpp | 3 +- .../src/extreme_carpaccio_client/Order.cpp | 52 ++++++++++++++----- .../cpp/test/ExtremeCarpaccioClientTest.cpp | 17 ++++++ 5 files changed, 64 insertions(+), 19 deletions(-) diff --git a/clients/cpp/TODOLIST.md b/clients/cpp/TODOLIST.md index 342eaba6..dd494cca 100644 --- a/clients/cpp/TODOLIST.md +++ b/clients/cpp/TODOLIST.md @@ -26,19 +26,19 @@ - [X] write a test to POST /feedback with a proper request - [X] implement POST /feedback - [X] test our client can receive feedback form the real extreme carpaccio server -- [] Add a configuration file for main options (ports and maybe others) +- [ ] Add a configuration file for main options (ports and maybe others) - [ ] check the js client to see what options are available - [ ] create a config file of command line options to set these options - [ ] Feedbacks from the session on extreme carpaccio with C++ client - - [ ] Display the order description in the code handling the order to have it in the console + - [x] Display the order description in the code handling the order to have it in the console - [ ] We need to initialize the http server with the hostname of the user launching it - [ ] Tests crashed when Mirna launched them on their machine - [ ] We need a specific test target for functional tests - [ ] Add guards in header files - [ ] Copying dll and binary to another directory was not easy -- [] Move in a dedicated file the request handling part of the client code -- [] Find a way to test code while the client is running (copy dll, use a static library, edit and continue ???) -- [] Use a different port number for tests +- [ ] Move in a dedicated file the request handling part of the client code +- [ ] Find a way to test code while the client is running (copy dll, use a static library, edit and continue ???) +- [ ] Use a different port number for tests ## PARKING - [ ] Clean gitignore file in cpp - [ ] Ajouter dans le cmake le Json en thirdparty pour la solution VS diff --git a/clients/cpp/include/extreme_carpaccio_client/Order.hpp b/clients/cpp/include/extreme_carpaccio_client/Order.hpp index 62ed3e9f..ef8d3f54 100644 --- a/clients/cpp/include/extreme_carpaccio_client/Order.hpp +++ b/clients/cpp/include/extreme_carpaccio_client/Order.hpp @@ -14,5 +14,6 @@ struct EXTREME_CARPACCIO_CLIENT_API Order }; EXTREME_CARPACCIO_CLIENT_API Order parseOrder(const std::string& jsonOrder); +EXTREME_CARPACCIO_CLIENT_API std::ostream& operator<< (std::ostream& stream, const Order& order); } // namespace extreme_carpaccio_client diff --git a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp index 9c67281d..ef2caa4c 100644 --- a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp +++ b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp @@ -120,7 +120,8 @@ bool http_worker::handleRequest(http::verb requestType, const std::string & targ if (target == "/order") { Order order = parseOrder(body); - + std::cout << "Order received: " << order << std::endl; + //TO IMPLEMENT //nlohmann::json totalAmountJson; diff --git a/clients/cpp/src/extreme_carpaccio_client/Order.cpp b/clients/cpp/src/extreme_carpaccio_client/Order.cpp index 51fdc1b2..fede83d7 100644 --- a/clients/cpp/src/extreme_carpaccio_client/Order.cpp +++ b/clients/cpp/src/extreme_carpaccio_client/Order.cpp @@ -5,19 +5,45 @@ namespace extreme_carpaccio_client { -EXTREME_CARPACCIO_CLIENT_API Order parseOrder(const std::string & jsonOrder) -{ - Order order; - - auto parsedOrder = nlohmann::json::parse(jsonOrder); - - order.country = parsedOrder["country"].get(); - order.reduction = parsedOrder["reduction"].get(); - order.prices = parsedOrder["prices"].get>(); - order.quantities = parsedOrder["quantities"].get>(); - - return order; -} + Order parseOrder(const std::string& jsonOrder) + { + Order order; + + auto parsedOrder = nlohmann::json::parse(jsonOrder); + + order.country = parsedOrder["country"].get(); + order.reduction = parsedOrder["reduction"].get(); + order.prices = parsedOrder["prices"].get>(); + order.quantities = parsedOrder["quantities"].get>(); + + return order; + } + + template static std::ostream& operator<< (std::ostream& stream, const std::vector& v) + { + stream << "{"; + for (std::size_t i = 0; i < v.size(); ++i) + { + if (i > 0) + { + stream << ","; + } + stream << v[i]; + } + stream << '}'; + return stream; + } + + std::ostream& operator<< (std::ostream& stream, const Order& order) + { + stream << "Order{" << + "prices=" << order.prices << + ", quantities=" << order.quantities << + ", country='" << order.country + '\'' << + ", reduction='" << order.reduction << '\'' << + '}'; + return stream; + } } // namespace extreme_carpaccio_client diff --git a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp index 201dfe41..687be064 100644 --- a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp +++ b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp @@ -122,3 +122,20 @@ TEST(ExtremeCarpaccioClient, should_handle_post_feedback) // When done redirect cout to its old self std::cout.rdbuf(sbuf); } + +TEST(ExtremeCarpaccioClient, should_trace_order_description) +{ + std::string target = "/order"; + std::stringstream buffer; + // Save cout's buffer here + std::streambuf* sbuf = std::cout.rdbuf(); + // Redirect cout to our stringstream buffer + std::cout.rdbuf(buffer.rdbuf()); + + auto res = generateServerResponse(http::verb::post, target, "application/json", "{\"prices\": [1,1.5], \"quantities\": [100, 200], \"country\": \"DE\", \"reduction\": \"STANDARD\"}"); + + //ASSERT_EQ(http::status::ok, res.result()); + ASSERT_EQ("Order received: Order{prices={1,1.5}, quantities={100,200}, country='DE', reduction='STANDARD'}\n", buffer.str()); + // When done redirect cout to its old self + std::cout.rdbuf(sbuf); +} \ No newline at end of file From a2ff8abf5e08aca1ee3d19625cdb3d9be5cc18a4 Mon Sep 17 00:00:00 2001 From: Ahmad Atwi Date: Thu, 7 Apr 2022 16:00:49 +0200 Subject: [PATCH 097/125] Extract a constant for the HTTP Server IP and Port number --- clients/cpp/CMakeLists.txt | 1 + clients/cpp/TODOLIST.md | 2 +- .../extreme_carpaccio_client/ExtremeCarpaccioClient.hpp | 1 + .../extreme_carpaccio_client/ExtremeCarpaccioClient.cpp | 8 +++++++- clients/cpp/src/extreme_carpaccio_client/HTTPConfig.hpp | 7 +++++++ clients/cpp/src/main.cpp | 2 +- 6 files changed, 18 insertions(+), 3 deletions(-) create mode 100644 clients/cpp/src/extreme_carpaccio_client/HTTPConfig.hpp diff --git a/clients/cpp/CMakeLists.txt b/clients/cpp/CMakeLists.txt index ff40e926..e077824c 100644 --- a/clients/cpp/CMakeLists.txt +++ b/clients/cpp/CMakeLists.txt @@ -26,6 +26,7 @@ target_sources(Extreme-Carpaccio-Client-shared PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/extreme_carpaccio_client/Order.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/extreme_carpaccio_client/HTTPConfig.hpp PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include/extreme_carpaccio_client/ExtremeCarpaccioClient.hpp ${CMAKE_CURRENT_SOURCE_DIR}/include/extreme_carpaccio_client/config.hpp diff --git a/clients/cpp/TODOLIST.md b/clients/cpp/TODOLIST.md index dd494cca..7cccd297 100644 --- a/clients/cpp/TODOLIST.md +++ b/clients/cpp/TODOLIST.md @@ -31,7 +31,7 @@ - [ ] create a config file of command line options to set these options - [ ] Feedbacks from the session on extreme carpaccio with C++ client - [x] Display the order description in the code handling the order to have it in the console - - [ ] We need to initialize the http server with the hostname of the user launching it + - [X] We need to initialize the http server with the hostname of the user launching it - [ ] Tests crashed when Mirna launched them on their machine - [ ] We need a specific test target for functional tests - [ ] Add guards in header files diff --git a/clients/cpp/include/extreme_carpaccio_client/ExtremeCarpaccioClient.hpp b/clients/cpp/include/extreme_carpaccio_client/ExtremeCarpaccioClient.hpp index 09d8e014..be58c250 100644 --- a/clients/cpp/include/extreme_carpaccio_client/ExtremeCarpaccioClient.hpp +++ b/clients/cpp/include/extreme_carpaccio_client/ExtremeCarpaccioClient.hpp @@ -69,6 +69,7 @@ class EXTREME_CARPACCIO_CLIENT_API CarpaccioServer { public: CarpaccioServer(unsigned short port); + CarpaccioServer(); void start(); void stop(); diff --git a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp index ef2caa4c..dd5b01bc 100644 --- a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp +++ b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -197,9 +198,14 @@ void http_worker::check_deadline() }); } + CarpaccioServer::CarpaccioServer() : CarpaccioServer(HTTP_SERVER_PORT) + { + + } + CarpaccioServer::CarpaccioServer(unsigned short port) : ioc(1) - , acceptor(ioc, {boost::asio::ip::make_address("127.0.0.1"), port } ), + , acceptor(ioc, {boost::asio::ip::make_address(HTTP_SERVER_IP), port } ), worker(acceptor, "./feedback") { diff --git a/clients/cpp/src/extreme_carpaccio_client/HTTPConfig.hpp b/clients/cpp/src/extreme_carpaccio_client/HTTPConfig.hpp new file mode 100644 index 00000000..67373e85 --- /dev/null +++ b/clients/cpp/src/extreme_carpaccio_client/HTTPConfig.hpp @@ -0,0 +1,7 @@ +#ifndef EXTREME_CARPACCIO_CLIENT_HTTPCONFIG_HPP +#define EXTREME_CARPACCIO_CLIENT_HTTPCONFIG_HPP + +#define HTTP_SERVER_IP "127.0.0.1" +#define HTTP_SERVER_PORT 8081 + +#endif // EXTREME_CARPACCIO_CLIENT_HTTPCONFIG_HPP \ No newline at end of file diff --git a/clients/cpp/src/main.cpp b/clients/cpp/src/main.cpp index c5af6024..314c6b4e 100644 --- a/clients/cpp/src/main.cpp +++ b/clients/cpp/src/main.cpp @@ -3,6 +3,6 @@ int main() { - extreme_carpaccio_client::CarpaccioServer server(8081); + extreme_carpaccio_client::CarpaccioServer server; server.start(); } From aba5c265ac9bb22b25fea3697930a4dfed627f55 Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 14 Apr 2022 14:41:59 +0200 Subject: [PATCH 098/125] Adding a new target + update TODO --- clients/cpp/CMakeLists.txt | 24 ++++++++++++++++++++++++ clients/cpp/TODOLIST.md | 4 ++-- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/clients/cpp/CMakeLists.txt b/clients/cpp/CMakeLists.txt index e077824c..968686a0 100644 --- a/clients/cpp/CMakeLists.txt +++ b/clients/cpp/CMakeLists.txt @@ -17,6 +17,30 @@ include(cmake/FindGoogleTest.cmake) include(cmake/FindNlohmannJson.cmake) include(cmake/FindBoost.cmake) +#Functional library to be modified by trainees +add_library(Extreme-Carpaccio-Order-Management-shared SHARED) + +target_compile_definitions(Extreme-Carpaccio-Order-Management-shared PRIVATE EXTREME_CARPACCIO_ORDER_MANAGEMENT_EXPORTS) + +target_sources(Extreme-Carpaccio-Order-Management-shared + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/src/extreme_carpaccio_order_management/OrderParsing.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/extreme_carpaccio_order_management/TotalAmount.cpp + PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/include/extreme_carpaccio_order_management/OrderParsing.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/include/extreme_carpaccio_order_management/TotalAmount.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/include/extreme_carpaccio_order_management/config.hpp +) + +target_include_directories(Extreme-Carpaccio-Order-Management-shared + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/src + PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/include +) + +target_link_libraries(Extreme-Carpaccio-Order-Management-shared PUBLIC Boost::boost PRIVATE nlohmann_json) + #Shared library add_library(Extreme-Carpaccio-Client-shared SHARED) diff --git a/clients/cpp/TODOLIST.md b/clients/cpp/TODOLIST.md index 7cccd297..4772ff66 100644 --- a/clients/cpp/TODOLIST.md +++ b/clients/cpp/TODOLIST.md @@ -32,7 +32,6 @@ - [ ] Feedbacks from the session on extreme carpaccio with C++ client - [x] Display the order description in the code handling the order to have it in the console - [X] We need to initialize the http server with the hostname of the user launching it - - [ ] Tests crashed when Mirna launched them on their machine - [ ] We need a specific test target for functional tests - [ ] Add guards in header files - [ ] Copying dll and binary to another directory was not easy @@ -44,4 +43,5 @@ - [ ] Ajouter dans le cmake le Json en thirdparty pour la solution VS - [ ] Add dependencies on sub boost headers only libraries (beast), instead on depending on full boost - [ ] Fix that : Failed to find all ICU components (missing: ICU_INCLUDE_DIR _ICU_REQUIRED_LIBS_FOUND) -- [ ] Upgrade nlohman json version \ No newline at end of file +- [ ] Upgrade nlohman json version +- [ ] Tests crashed when Mirna launched them on their machine \ No newline at end of file From b5c57e3e446a32b33da86d7bc9ab0764cce648ff Mon Sep 17 00:00:00 2001 From: NADIF Antoine Date: Thu, 14 Apr 2022 15:34:20 +0200 Subject: [PATCH 099/125] Add new library for participants to modify during the Kata. --- clients/cpp/CMakeLists.txt | 34 +++---------- clients/cpp/OrderManagement/CMakeLists.txt | 28 +++++++++++ .../order_management/Order.hpp | 27 ++++++++++ .../order_management/OrderParsing.hpp | 18 +++++++ .../order_management/TotalAmount.hpp | 0 .../order_management/config.hpp | 14 ++++++ .../order_management/Order.cpp | 36 ++++++++++++++ .../order_management/OrderParsing.cpp | 25 ++++++++++ .../order_management/TotalAmount.cpp | 0 .../extreme_carpaccio_client/Order.hpp | 19 ------- .../ExtremeCarpaccioClient.cpp | 9 ++-- .../src/extreme_carpaccio_client/Order.cpp | 49 ------------------- .../cpp/test/ExtremeCarpaccioClientTest.cpp | 5 +- 13 files changed, 165 insertions(+), 99 deletions(-) create mode 100644 clients/cpp/OrderManagement/CMakeLists.txt create mode 100644 clients/cpp/OrderManagement/includes/extreme_carpaccio/order_management/Order.hpp create mode 100644 clients/cpp/OrderManagement/includes/extreme_carpaccio/order_management/OrderParsing.hpp create mode 100644 clients/cpp/OrderManagement/includes/extreme_carpaccio/order_management/TotalAmount.hpp create mode 100644 clients/cpp/OrderManagement/includes/extreme_carpaccio/order_management/config.hpp create mode 100644 clients/cpp/OrderManagement/sources/extreme_carpaccio/order_management/Order.cpp create mode 100644 clients/cpp/OrderManagement/sources/extreme_carpaccio/order_management/OrderParsing.cpp create mode 100644 clients/cpp/OrderManagement/sources/extreme_carpaccio/order_management/TotalAmount.cpp delete mode 100644 clients/cpp/include/extreme_carpaccio_client/Order.hpp delete mode 100644 clients/cpp/src/extreme_carpaccio_client/Order.cpp diff --git a/clients/cpp/CMakeLists.txt b/clients/cpp/CMakeLists.txt index 968686a0..beedd2a7 100644 --- a/clients/cpp/CMakeLists.txt +++ b/clients/cpp/CMakeLists.txt @@ -17,29 +17,7 @@ include(cmake/FindGoogleTest.cmake) include(cmake/FindNlohmannJson.cmake) include(cmake/FindBoost.cmake) -#Functional library to be modified by trainees -add_library(Extreme-Carpaccio-Order-Management-shared SHARED) - -target_compile_definitions(Extreme-Carpaccio-Order-Management-shared PRIVATE EXTREME_CARPACCIO_ORDER_MANAGEMENT_EXPORTS) - -target_sources(Extreme-Carpaccio-Order-Management-shared - PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/src/extreme_carpaccio_order_management/OrderParsing.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/extreme_carpaccio_order_management/TotalAmount.cpp - PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}/include/extreme_carpaccio_order_management/OrderParsing.hpp - ${CMAKE_CURRENT_SOURCE_DIR}/include/extreme_carpaccio_order_management/TotalAmount.hpp - ${CMAKE_CURRENT_SOURCE_DIR}/include/extreme_carpaccio_order_management/config.hpp -) - -target_include_directories(Extreme-Carpaccio-Order-Management-shared - PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/src - PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}/include -) - -target_link_libraries(Extreme-Carpaccio-Order-Management-shared PUBLIC Boost::boost PRIVATE nlohmann_json) +add_subdirectory(OrderManagement) #Shared library add_library(Extreme-Carpaccio-Client-shared SHARED) @@ -49,12 +27,10 @@ target_compile_definitions(Extreme-Carpaccio-Client-shared PRIVATE EXTREME_CARPA target_sources(Extreme-Carpaccio-Client-shared PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/extreme_carpaccio_client/Order.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/extreme_carpaccio_client/HTTPConfig.hpp PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include/extreme_carpaccio_client/ExtremeCarpaccioClient.hpp ${CMAKE_CURRENT_SOURCE_DIR}/include/extreme_carpaccio_client/config.hpp - ${CMAKE_CURRENT_SOURCE_DIR}/include/extreme_carpaccio_client/Order.hpp ) target_include_directories(Extreme-Carpaccio-Client-shared @@ -64,7 +40,13 @@ target_include_directories(Extreme-Carpaccio-Client-shared ${CMAKE_CURRENT_SOURCE_DIR}/include ) -target_link_libraries(Extreme-Carpaccio-Client-shared PUBLIC Boost::boost PRIVATE nlohmann_json) +target_link_libraries(Extreme-Carpaccio-Client-shared + PRIVATE + nlohmann_json + PUBLIC + Boost::boost + Extreme-Carpaccio-Order-Management-shared +) # Client executable add_executable(Extreme-Carpaccio-Client) diff --git a/clients/cpp/OrderManagement/CMakeLists.txt b/clients/cpp/OrderManagement/CMakeLists.txt new file mode 100644 index 00000000..38345139 --- /dev/null +++ b/clients/cpp/OrderManagement/CMakeLists.txt @@ -0,0 +1,28 @@ + +#Functional library to be modified by participants +add_library(Extreme-Carpaccio-Order-Management-shared SHARED) + +target_compile_definitions(Extreme-Carpaccio-Order-Management-shared PRIVATE EXTREME_CARPACCIO_ORDER_MANAGEMENT_EXPORTS) + +target_sources(Extreme-Carpaccio-Order-Management-shared + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/sources/extreme_carpaccio/order_management/OrderParsing.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/sources/extreme_carpaccio/order_management/Order.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/sources/extreme_carpaccio/order_management/TotalAmount.cpp + PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/includes/extreme_carpaccio/order_management/Order.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/includes/extreme_carpaccio/order_management/OrderParsing.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/includes/extreme_carpaccio/order_management/TotalAmount.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/includes/extreme_carpaccio/order_management/config.hpp +) + +target_include_directories(Extreme-Carpaccio-Order-Management-shared + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/sources + PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/includes +) + +target_link_libraries(Extreme-Carpaccio-Order-Management-shared PUBLIC Boost::boost PRIVATE nlohmann_json) + +set_property(TARGET Extreme-Carpaccio-Order-Management-shared PROPERTY FOLDER "OrderManagement") diff --git a/clients/cpp/OrderManagement/includes/extreme_carpaccio/order_management/Order.hpp b/clients/cpp/OrderManagement/includes/extreme_carpaccio/order_management/Order.hpp new file mode 100644 index 00000000..bd056def --- /dev/null +++ b/clients/cpp/OrderManagement/includes/extreme_carpaccio/order_management/Order.hpp @@ -0,0 +1,27 @@ + +#ifndef EXTREME_CARPACCIO_ORDER_MANAGEMENT_ORDER_HPP +#define EXTREME_CARPACCIO_ORDER_MANAGEMENT_ORDER_HPP + +#include + +#include +#include +#include + +namespace extreme_carpaccio { +namespace order_management { + +struct EXTREME_CARPACCIO_ORDER_MANAGEMENT_API Order +{ + std::vector quantities; + std::vector prices; + std::string country; + std::string reduction; +}; + +EXTREME_CARPACCIO_ORDER_MANAGEMENT_API std::ostream& operator<< (std::ostream& stream, const Order& order); + +} // namespace order_management +} // namespace extreme_carpaccio + +#endif // EXTREME_CARPACCIO_ORDER_MANAGEMENT_ORDER_HPP \ No newline at end of file diff --git a/clients/cpp/OrderManagement/includes/extreme_carpaccio/order_management/OrderParsing.hpp b/clients/cpp/OrderManagement/includes/extreme_carpaccio/order_management/OrderParsing.hpp new file mode 100644 index 00000000..8470057b --- /dev/null +++ b/clients/cpp/OrderManagement/includes/extreme_carpaccio/order_management/OrderParsing.hpp @@ -0,0 +1,18 @@ + +#ifndef EXTREME_CARPACCIO_ORDER_MANAGEMENT_ORDERPARSING_HPP +#define EXTREME_CARPACCIO_ORDER_MANAGEMENT_ORDERPARSING_HPP + +#include +#include + +#include + +namespace extreme_carpaccio { +namespace order_management { + +EXTREME_CARPACCIO_ORDER_MANAGEMENT_API Order parseOrder(const std::string& jsonOrder); + +} // namespace order_management +} // namespace extreme_carpaccio + +#endif // EXTREME_CARPACCIO_ORDER_MANAGEMENT_ORDERPARSING_HPP \ No newline at end of file diff --git a/clients/cpp/OrderManagement/includes/extreme_carpaccio/order_management/TotalAmount.hpp b/clients/cpp/OrderManagement/includes/extreme_carpaccio/order_management/TotalAmount.hpp new file mode 100644 index 00000000..e69de29b diff --git a/clients/cpp/OrderManagement/includes/extreme_carpaccio/order_management/config.hpp b/clients/cpp/OrderManagement/includes/extreme_carpaccio/order_management/config.hpp new file mode 100644 index 00000000..da49c655 --- /dev/null +++ b/clients/cpp/OrderManagement/includes/extreme_carpaccio/order_management/config.hpp @@ -0,0 +1,14 @@ +#ifndef EXTREME_CARPACCIO_ORDER_MANAGEMENT_CONFIG +#define EXTREME_CARPACCIO_ORDER_MANAGEMENT_CONFIG + +#ifdef _MSC_VER +#ifdef EXTREME_CARPACCIO_ORDER_MANAGEMENT_EXPORTS +#define EXTREME_CARPACCIO_ORDER_MANAGEMENT_API __declspec(dllexport) +#else +#define EXTREME_CARPACCIO_ORDER_MANAGEMENT_API __declspec(dllimport) +#endif +#else +#define EXTREME_CARPACCIO_ORDER_MANAGEMENT_API +#endif + +#endif // EXTREME_CARPACCIO_ORDER_MANAGEMENT_CONFIG diff --git a/clients/cpp/OrderManagement/sources/extreme_carpaccio/order_management/Order.cpp b/clients/cpp/OrderManagement/sources/extreme_carpaccio/order_management/Order.cpp new file mode 100644 index 00000000..e7940701 --- /dev/null +++ b/clients/cpp/OrderManagement/sources/extreme_carpaccio/order_management/Order.cpp @@ -0,0 +1,36 @@ +#include + +#include + +namespace extreme_carpaccio { +namespace order_management { + +template +static std::ostream& operator<< (std::ostream& stream, const std::vector& v) +{ + stream << "{"; + for (std::size_t i = 0; i < v.size(); ++i) + { + if (i > 0) + { + stream << ","; + } + stream << v[i]; + } + stream << '}'; + return stream; +} + +std::ostream& operator<< (std::ostream& stream, const Order& order) +{ + stream << "Order{" << + "prices=" << order.prices << + ", quantities=" << order.quantities << + ", country='" << order.country + '\'' << + ", reduction='" << order.reduction << '\'' << + '}'; + return stream; +} + +} // namespace order_management +} // namespace extreme_carpaccio diff --git a/clients/cpp/OrderManagement/sources/extreme_carpaccio/order_management/OrderParsing.cpp b/clients/cpp/OrderManagement/sources/extreme_carpaccio/order_management/OrderParsing.cpp new file mode 100644 index 00000000..c270c0e5 --- /dev/null +++ b/clients/cpp/OrderManagement/sources/extreme_carpaccio/order_management/OrderParsing.cpp @@ -0,0 +1,25 @@ + +#include + +#include + + +namespace extreme_carpaccio { +namespace order_management { + +Order parseOrder(const std::string& jsonOrder) +{ + Order order; + + auto parsedOrder = nlohmann::json::parse(jsonOrder); + + order.country = parsedOrder["country"].get(); + order.reduction = parsedOrder["reduction"].get(); + order.prices = parsedOrder["prices"].get>(); + order.quantities = parsedOrder["quantities"].get>(); + + return order; +} + +} // namespace order_management +} // namespace extreme_carpaccio diff --git a/clients/cpp/OrderManagement/sources/extreme_carpaccio/order_management/TotalAmount.cpp b/clients/cpp/OrderManagement/sources/extreme_carpaccio/order_management/TotalAmount.cpp new file mode 100644 index 00000000..e69de29b diff --git a/clients/cpp/include/extreme_carpaccio_client/Order.hpp b/clients/cpp/include/extreme_carpaccio_client/Order.hpp deleted file mode 100644 index ef8d3f54..00000000 --- a/clients/cpp/include/extreme_carpaccio_client/Order.hpp +++ /dev/null @@ -1,19 +0,0 @@ -#include - -#include -#include - -namespace extreme_carpaccio_client { - -struct EXTREME_CARPACCIO_CLIENT_API Order -{ - std::vector quantities; - std::vector prices; - std::string country; - std::string reduction; -}; - -EXTREME_CARPACCIO_CLIENT_API Order parseOrder(const std::string& jsonOrder); -EXTREME_CARPACCIO_CLIENT_API std::ostream& operator<< (std::ostream& stream, const Order& order); - -} // namespace extreme_carpaccio_client diff --git a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp index dd5b01bc..8050b90d 100644 --- a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp +++ b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp @@ -1,7 +1,10 @@ #include -#include #include +#include +#include +#include + #include #include #include @@ -109,7 +112,7 @@ static Feedback parseFeedback(const std::string& jsonFeedback) return feedback; } -double computeTotalAmount(Order /*order*/) +double computeTotalAmount(extreme_carpaccio::order_management::Order /*order*/) { return 0.; } @@ -120,7 +123,7 @@ bool http_worker::handleRequest(http::verb requestType, const std::string & targ { if (target == "/order") { - Order order = parseOrder(body); + extreme_carpaccio::order_management::Order order = extreme_carpaccio::order_management::parseOrder(body); std::cout << "Order received: " << order << std::endl; //TO IMPLEMENT diff --git a/clients/cpp/src/extreme_carpaccio_client/Order.cpp b/clients/cpp/src/extreme_carpaccio_client/Order.cpp deleted file mode 100644 index fede83d7..00000000 --- a/clients/cpp/src/extreme_carpaccio_client/Order.cpp +++ /dev/null @@ -1,49 +0,0 @@ -#include - -#include - - -namespace extreme_carpaccio_client { - - Order parseOrder(const std::string& jsonOrder) - { - Order order; - - auto parsedOrder = nlohmann::json::parse(jsonOrder); - - order.country = parsedOrder["country"].get(); - order.reduction = parsedOrder["reduction"].get(); - order.prices = parsedOrder["prices"].get>(); - order.quantities = parsedOrder["quantities"].get>(); - - return order; - } - - template static std::ostream& operator<< (std::ostream& stream, const std::vector& v) - { - stream << "{"; - for (std::size_t i = 0; i < v.size(); ++i) - { - if (i > 0) - { - stream << ","; - } - stream << v[i]; - } - stream << '}'; - return stream; - } - - std::ostream& operator<< (std::ostream& stream, const Order& order) - { - stream << "Order{" << - "prices=" << order.prices << - ", quantities=" << order.quantities << - ", country='" << order.country + '\'' << - ", reduction='" << order.reduction << '\'' << - '}'; - return stream; - } - -} // namespace extreme_carpaccio_client - diff --git a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp index 687be064..c5383c58 100644 --- a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp +++ b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp @@ -1,5 +1,6 @@ #include -#include + +#include #include #include @@ -97,7 +98,7 @@ TEST(ExtremeCarpaccioClient, should_return_order_object_from_json_order) { std::string orderRequest = "{\"prices\": [1,1.5], \"quantities\": [100, 200], \"country\": \"DE\", \"reduction\": \"STANDARD\"}"; - Order order = parseOrder(orderRequest); + extreme_carpaccio::order_management::Order order = extreme_carpaccio::order_management::parseOrder(orderRequest); EXPECT_EQ("DE", order.country); EXPECT_EQ("STANDARD", order.reduction); From 5d4edeb92412a9160a68b5353b2b9e382c8d2f78 Mon Sep 17 00:00:00 2001 From: NADIF Antoine Date: Thu, 14 Apr 2022 16:00:43 +0200 Subject: [PATCH 100/125] Add new gtest project where participants will write tests for their library. --- clients/cpp/CMakeLists.txt | 2 +- clients/cpp/OrderManagement/CMakeLists.txt | 2 ++ .../order_management/TotalAmount.hpp | 19 ++++++++++++ .../order_management/TotalAmount.cpp | 13 ++++++++ .../cpp/OrderManagement/tests/CMakeLists.txt | 22 +++++++++++++ .../tests/sources/OrderParsingTests.cpp | 31 +++++++++++++++++++ .../tests/sources/TotalAmountTests.cpp | 20 ++++++++++++ .../ExtremeCarpaccioClient.cpp | 5 --- .../cpp/test/ExtremeCarpaccioClientTest.cpp | 13 -------- 9 files changed, 108 insertions(+), 19 deletions(-) create mode 100644 clients/cpp/OrderManagement/tests/CMakeLists.txt create mode 100644 clients/cpp/OrderManagement/tests/sources/OrderParsingTests.cpp create mode 100644 clients/cpp/OrderManagement/tests/sources/TotalAmountTests.cpp diff --git a/clients/cpp/CMakeLists.txt b/clients/cpp/CMakeLists.txt index beedd2a7..d134eb2f 100644 --- a/clients/cpp/CMakeLists.txt +++ b/clients/cpp/CMakeLists.txt @@ -92,6 +92,6 @@ set_property(TARGET Extreme-Carpaccio-Client-test PROPERTY FOLDER "ExtremeCarpac set_property(TARGET Extreme-Carpaccio-Client PROPERTY FOLDER "ExtremeCarpaccioClient") set_property(TARGET Docs PROPERTY FOLDER "ExtremeCarpaccioClient") -set_property(TARGET gtest gmock_main PROPERTY FOLDER "Third-Party/GoogleTest") +set_property(TARGET gtest gtest_main gmock gmock_main PROPERTY FOLDER "Third-Party/GoogleTest") set_property(GLOBAL PROPERTY PREDEFINED_TARGETS_FOLDER "CMake Generated") diff --git a/clients/cpp/OrderManagement/CMakeLists.txt b/clients/cpp/OrderManagement/CMakeLists.txt index 38345139..a6ad5188 100644 --- a/clients/cpp/OrderManagement/CMakeLists.txt +++ b/clients/cpp/OrderManagement/CMakeLists.txt @@ -26,3 +26,5 @@ target_include_directories(Extreme-Carpaccio-Order-Management-shared target_link_libraries(Extreme-Carpaccio-Order-Management-shared PUBLIC Boost::boost PRIVATE nlohmann_json) set_property(TARGET Extreme-Carpaccio-Order-Management-shared PROPERTY FOLDER "OrderManagement") + +add_subdirectory(tests) \ No newline at end of file diff --git a/clients/cpp/OrderManagement/includes/extreme_carpaccio/order_management/TotalAmount.hpp b/clients/cpp/OrderManagement/includes/extreme_carpaccio/order_management/TotalAmount.hpp index e69de29b..98f5d4f4 100644 --- a/clients/cpp/OrderManagement/includes/extreme_carpaccio/order_management/TotalAmount.hpp +++ b/clients/cpp/OrderManagement/includes/extreme_carpaccio/order_management/TotalAmount.hpp @@ -0,0 +1,19 @@ + +#ifndef EXTREME_CARPACCIO_ORDER_MANAGEMENT_TOTALAMOUNT_HPP +#define EXTREME_CARPACCIO_ORDER_MANAGEMENT_TOTALAMOUNT_HPP + +#include +#include + +#include + +namespace extreme_carpaccio { +namespace order_management { + +EXTREME_CARPACCIO_ORDER_MANAGEMENT_API double computeTotalAmount(const Order & order); + +} // namespace order_management +} // namespace extreme_carpaccio + +#endif // EXTREME_CARPACCIO_ORDER_MANAGEMENT_TOTALAMOUNT_HPP + diff --git a/clients/cpp/OrderManagement/sources/extreme_carpaccio/order_management/TotalAmount.cpp b/clients/cpp/OrderManagement/sources/extreme_carpaccio/order_management/TotalAmount.cpp index e69de29b..cc630d3e 100644 --- a/clients/cpp/OrderManagement/sources/extreme_carpaccio/order_management/TotalAmount.cpp +++ b/clients/cpp/OrderManagement/sources/extreme_carpaccio/order_management/TotalAmount.cpp @@ -0,0 +1,13 @@ + +#include + +namespace extreme_carpaccio { +namespace order_management { + +double computeTotalAmount(const Order & /*order*/) +{ + return 42.; +} + +} // namespace order_management +} // namespace extreme_carpaccio diff --git a/clients/cpp/OrderManagement/tests/CMakeLists.txt b/clients/cpp/OrderManagement/tests/CMakeLists.txt new file mode 100644 index 00000000..ed036c48 --- /dev/null +++ b/clients/cpp/OrderManagement/tests/CMakeLists.txt @@ -0,0 +1,22 @@ + +add_executable(Extreme-Carpaccio-Order-Management-tests) + +target_sources(Extreme-Carpaccio-Order-Management-tests + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/sources/OrderParsingTests.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/sources/TotalAmountTests.cpp +) + +target_include_directories(Extreme-Carpaccio-Order-Management-tests + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/sources +) + +target_link_libraries(Extreme-Carpaccio-Order-Management-tests + PRIVATE + Extreme-Carpaccio-Order-Management-shared + gmock_main) + +add_test(NAME ctest-Extreme-Carpaccio-Order-Management-tests COMMAND Extreme-Carpaccio-Order-Management-tests) + +set_property(TARGET Extreme-Carpaccio-Order-Management-tests PROPERTY FOLDER "OrderManagement") diff --git a/clients/cpp/OrderManagement/tests/sources/OrderParsingTests.cpp b/clients/cpp/OrderManagement/tests/sources/OrderParsingTests.cpp new file mode 100644 index 00000000..ce2f6d92 --- /dev/null +++ b/clients/cpp/OrderManagement/tests/sources/OrderParsingTests.cpp @@ -0,0 +1,31 @@ + +#include +#include + +#include +#include + +#include + +using namespace testing; + +namespace extreme_carpaccio { +namespace order_management { +namespace test { + +TEST(OrderParsing, should_return_order_object_from_json_order) +{ + std::string orderRequest = "{\"prices\": [1,1.5], \"quantities\": [100, 200], \"country\": \"DE\", \"reduction\": \"STANDARD\"}"; + + Order order = parseOrder(orderRequest); + + EXPECT_EQ("DE", order.country); + EXPECT_EQ("STANDARD", order.reduction); + + EXPECT_THAT(order.prices, ElementsAre(1, 1.5)); + EXPECT_THAT(order.quantities, ElementsAre(100, 200)); +} + +} // namespace tests +} // namespace order_management +} // namespace extreme_management diff --git a/clients/cpp/OrderManagement/tests/sources/TotalAmountTests.cpp b/clients/cpp/OrderManagement/tests/sources/TotalAmountTests.cpp new file mode 100644 index 00000000..fa5e89fd --- /dev/null +++ b/clients/cpp/OrderManagement/tests/sources/TotalAmountTests.cpp @@ -0,0 +1,20 @@ + +#include + +#include + +using namespace testing; + +namespace extreme_carpaccio { +namespace order_management { +namespace test { + +TEST(TotalAmount, dummy_test) +{ + Order order; + EXPECT_EQ(42., computeTotalAmount(order)); +} + +} // namespace tests +} // namespace order_management +} // namespace extreme_management diff --git a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp index 8050b90d..09aee242 100644 --- a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp +++ b/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp @@ -112,11 +112,6 @@ static Feedback parseFeedback(const std::string& jsonFeedback) return feedback; } -double computeTotalAmount(extreme_carpaccio::order_management::Order /*order*/) -{ - return 0.; -} - bool http_worker::handleRequest(http::verb requestType, const std::string & target, const std::string & contentType, const std::string & body) { if (requestType == http::verb::post && contentType == "application/json") diff --git a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp index c5383c58..ad9250be 100644 --- a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp +++ b/clients/cpp/test/ExtremeCarpaccioClientTest.cpp @@ -94,19 +94,6 @@ TEST(ExtremeCarpaccioClient, DISABLED_should_return_amount_computed_with_prices_ EXPECT_EQ(100 * 1 + 200 * 1.5, totalAmountJson["total"].get()); } -TEST(ExtremeCarpaccioClient, should_return_order_object_from_json_order) -{ - std::string orderRequest = "{\"prices\": [1,1.5], \"quantities\": [100, 200], \"country\": \"DE\", \"reduction\": \"STANDARD\"}"; - - extreme_carpaccio::order_management::Order order = extreme_carpaccio::order_management::parseOrder(orderRequest); - - EXPECT_EQ("DE", order.country); - EXPECT_EQ("STANDARD", order.reduction); - - EXPECT_THAT(order.prices, ElementsAre(1, 1.5)); - EXPECT_THAT(order.quantities, ElementsAre(100, 200)); -} - TEST(ExtremeCarpaccioClient, should_handle_post_feedback) { std::string target = "/feedback"; From 8e8980a59cf5a5d6c89b9ea6120b91e98eafd4ec Mon Sep 17 00:00:00 2001 From: NADIF Antoine Date: Thu, 14 Apr 2022 16:12:14 +0200 Subject: [PATCH 101/125] Change computeTotalAmount interface and provide an example test. --- .../extreme_carpaccio/order_management/TotalAmount.hpp | 8 ++++++-- .../extreme_carpaccio/order_management/TotalAmount.cpp | 7 +++++-- .../OrderManagement/tests/sources/TotalAmountTests.cpp | 10 ++++++++-- clients/cpp/TODOLIST.md | 6 ++++-- 4 files changed, 23 insertions(+), 8 deletions(-) diff --git a/clients/cpp/OrderManagement/includes/extreme_carpaccio/order_management/TotalAmount.hpp b/clients/cpp/OrderManagement/includes/extreme_carpaccio/order_management/TotalAmount.hpp index 98f5d4f4..dce164ab 100644 --- a/clients/cpp/OrderManagement/includes/extreme_carpaccio/order_management/TotalAmount.hpp +++ b/clients/cpp/OrderManagement/includes/extreme_carpaccio/order_management/TotalAmount.hpp @@ -3,14 +3,18 @@ #define EXTREME_CARPACCIO_ORDER_MANAGEMENT_TOTALAMOUNT_HPP #include -#include + +#include #include +#include namespace extreme_carpaccio { namespace order_management { -EXTREME_CARPACCIO_ORDER_MANAGEMENT_API double computeTotalAmount(const Order & order); +using TotalAmountResponse = std::pair; + +EXTREME_CARPACCIO_ORDER_MANAGEMENT_API TotalAmountResponse computeTotalAmount(const std::string & requestBody); } // namespace order_management } // namespace extreme_carpaccio diff --git a/clients/cpp/OrderManagement/sources/extreme_carpaccio/order_management/TotalAmount.cpp b/clients/cpp/OrderManagement/sources/extreme_carpaccio/order_management/TotalAmount.cpp index cc630d3e..6156d0e2 100644 --- a/clients/cpp/OrderManagement/sources/extreme_carpaccio/order_management/TotalAmount.cpp +++ b/clients/cpp/OrderManagement/sources/extreme_carpaccio/order_management/TotalAmount.cpp @@ -1,12 +1,15 @@ #include +namespace beast = boost::beast; +namespace http = beast::http; + namespace extreme_carpaccio { namespace order_management { -double computeTotalAmount(const Order & /*order*/) +TotalAmountResponse computeTotalAmount(const std::string & /*requestBody*/) { - return 42.; + return std::make_pair(http::status::not_found, 42.); } } // namespace order_management diff --git a/clients/cpp/OrderManagement/tests/sources/TotalAmountTests.cpp b/clients/cpp/OrderManagement/tests/sources/TotalAmountTests.cpp index fa5e89fd..1236db66 100644 --- a/clients/cpp/OrderManagement/tests/sources/TotalAmountTests.cpp +++ b/clients/cpp/OrderManagement/tests/sources/TotalAmountTests.cpp @@ -5,14 +5,20 @@ using namespace testing; +namespace beast = boost::beast; +namespace http = beast::http; + namespace extreme_carpaccio { namespace order_management { namespace test { TEST(TotalAmount, dummy_test) { - Order order; - EXPECT_EQ(42., computeTotalAmount(order)); + const std::string requestBody = "{\"prices\": [1,1.5], \"quantities\": [100, 200], \"country\": \"DE\", \"reduction\": \"STANDARD\"}"; + auto response = computeTotalAmount(requestBody); + + EXPECT_EQ(response.first, http::status::not_found); + EXPECT_EQ(response.second, 42.); } } // namespace tests diff --git a/clients/cpp/TODOLIST.md b/clients/cpp/TODOLIST.md index 4772ff66..2acb5023 100644 --- a/clients/cpp/TODOLIST.md +++ b/clients/cpp/TODOLIST.md @@ -32,10 +32,12 @@ - [ ] Feedbacks from the session on extreme carpaccio with C++ client - [x] Display the order description in the code handling the order to have it in the console - [X] We need to initialize the http server with the hostname of the user launching it - - [ ] We need a specific test target for functional tests + - [X] We need a specific test target for functional tests - [ ] Add guards in header files + - [ ] Finish target restructuring - [ ] Copying dll and binary to another directory was not easy -- [ ] Move in a dedicated file the request handling part of the client code +- [X] Move in a dedicated file the request handling part of the client code +- [ ] Use the computeTotalAmount in the client - [ ] Find a way to test code while the client is running (copy dll, use a static library, edit and continue ???) - [ ] Use a different port number for tests ## PARKING From f5f7a1d4f0440cc9a8b22d5f2c88f8f295af70fa Mon Sep 17 00:00:00 2001 From: NADIF Antoine Date: Fri, 15 Apr 2022 18:21:31 +0200 Subject: [PATCH 102/125] Reorganize the carpaccio client targets (library, tests, executable). --- clients/cpp/CMakeLists.txt | 70 ++----------------- clients/cpp/Client/CMakeLists.txt | 3 + clients/cpp/Client/executable/CMakeLists.txt | 23 ++++++ .../cpp/Client/executable/sources/main.cpp | 12 ++++ clients/cpp/Client/library/CMakeLists.txt | 47 +++++++++++++ .../extreme_carpaccio/client/Client.hpp} | 16 +++-- .../extreme_carpaccio/client}/config.hpp | 0 .../extreme_carpaccio/client/Client.cpp} | 13 ++-- .../extreme_carpaccio/client/HttpConfig.hpp} | 7 ++ .../cpp/Client/library/tests/CMakeLists.txt | 29 ++++++++ .../library/tests/sources/ClientTests.cpp} | 14 ++-- clients/cpp/OrderManagement/CMakeLists.txt | 45 ++++++++---- .../cpp/OrderManagement/tests/CMakeLists.txt | 29 +++++--- clients/cpp/build/feedback/toto.png | 0 clients/cpp/src/main.cpp | 8 --- 15 files changed, 203 insertions(+), 113 deletions(-) create mode 100644 clients/cpp/Client/CMakeLists.txt create mode 100644 clients/cpp/Client/executable/CMakeLists.txt create mode 100644 clients/cpp/Client/executable/sources/main.cpp create mode 100644 clients/cpp/Client/library/CMakeLists.txt rename clients/cpp/{include/extreme_carpaccio_client/ExtremeCarpaccioClient.hpp => Client/library/includes/extreme_carpaccio/client/Client.hpp} (91%) rename clients/cpp/{include/extreme_carpaccio_client => Client/library/includes/extreme_carpaccio/client}/config.hpp (100%) rename clients/cpp/{src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp => Client/library/sources/extreme_carpaccio/client/Client.cpp} (96%) rename clients/cpp/{src/extreme_carpaccio_client/HTTPConfig.hpp => Client/library/sources/extreme_carpaccio/client/HttpConfig.hpp} (66%) create mode 100644 clients/cpp/Client/library/tests/CMakeLists.txt rename clients/cpp/{test/ExtremeCarpaccioClientTest.cpp => Client/library/tests/sources/ClientTests.cpp} (95%) delete mode 100644 clients/cpp/build/feedback/toto.png delete mode 100644 clients/cpp/src/main.cpp diff --git a/clients/cpp/CMakeLists.txt b/clients/cpp/CMakeLists.txt index d134eb2f..eb6bde97 100644 --- a/clients/cpp/CMakeLists.txt +++ b/clients/cpp/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.19.3) -project(Extreme-Carpaccio-Client CXX) +project(Extreme-Carpaccio CXX) set(CMAKE_CXX_STANDARD 14) enable_testing() @@ -18,64 +18,7 @@ include(cmake/FindNlohmannJson.cmake) include(cmake/FindBoost.cmake) add_subdirectory(OrderManagement) - -#Shared library -add_library(Extreme-Carpaccio-Client-shared SHARED) - -target_compile_definitions(Extreme-Carpaccio-Client-shared PRIVATE EXTREME_CARPACCIO_CLIENT_EXPORTS) - -target_sources(Extreme-Carpaccio-Client-shared - PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/extreme_carpaccio_client/HTTPConfig.hpp - PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}/include/extreme_carpaccio_client/ExtremeCarpaccioClient.hpp - ${CMAKE_CURRENT_SOURCE_DIR}/include/extreme_carpaccio_client/config.hpp -) - -target_include_directories(Extreme-Carpaccio-Client-shared - PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/src - PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}/include -) - -target_link_libraries(Extreme-Carpaccio-Client-shared - PRIVATE - nlohmann_json - PUBLIC - Boost::boost - Extreme-Carpaccio-Order-Management-shared -) - -# Client executable -add_executable(Extreme-Carpaccio-Client) - -target_sources(Extreme-Carpaccio-Client - PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/src/main.cpp -) - -target_link_libraries(Extreme-Carpaccio-Client - PRIVATE - Extreme-Carpaccio-Client-shared) - -# Test executable -add_executable(Extreme-Carpaccio-Client-test) - -target_sources(Extreme-Carpaccio-Client-test - PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/test/ExtremeCarpaccioClientTest.cpp -) - -target_link_libraries(Extreme-Carpaccio-Client-test - PRIVATE - Extreme-Carpaccio-Client-shared - gmock_main - Boost::boost - nlohmann_json) - -add_test(NAME ctest-Extreme-Carpaccio-Client COMMAND Extreme-Carpaccio-Client-test) +add_subdirectory(Client) #Globals add_custom_target(Docs @@ -84,13 +27,8 @@ add_custom_target(Docs ${CMAKE_CURRENT_SOURCE_DIR}/TODOLIST.md ${CMAKE_CURRENT_SOURCE_DIR}/../README.md) -set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT Extreme-Carpaccio-Client-test) -set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY XCODE_STARTUP_PROJECT Extreme-Carpaccio-Client-test) - -set_property(TARGET Extreme-Carpaccio-Client-shared PROPERTY FOLDER "ExtremeCarpaccioClient") -set_property(TARGET Extreme-Carpaccio-Client-test PROPERTY FOLDER "ExtremeCarpaccioClient") -set_property(TARGET Extreme-Carpaccio-Client PROPERTY FOLDER "ExtremeCarpaccioClient") -set_property(TARGET Docs PROPERTY FOLDER "ExtremeCarpaccioClient") +set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT Order-Management-tests) +set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY XCODE_STARTUP_PROJECT Order-Management-tests) set_property(TARGET gtest gtest_main gmock gmock_main PROPERTY FOLDER "Third-Party/GoogleTest") diff --git a/clients/cpp/Client/CMakeLists.txt b/clients/cpp/Client/CMakeLists.txt new file mode 100644 index 00000000..bf7a0e96 --- /dev/null +++ b/clients/cpp/Client/CMakeLists.txt @@ -0,0 +1,3 @@ + +add_subdirectory(executable) +add_subdirectory(library) diff --git a/clients/cpp/Client/executable/CMakeLists.txt b/clients/cpp/Client/executable/CMakeLists.txt new file mode 100644 index 00000000..fedaef10 --- /dev/null +++ b/clients/cpp/Client/executable/CMakeLists.txt @@ -0,0 +1,23 @@ + +add_executable(Client-exe) + +set(CLIENT_EXE_PRIVATE_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/sources/main.cpp +) + +target_sources(Client-exe + PRIVATE + ${CLIENT_EXE_PRIVATE_SOURCES} +) + +source_group( + TREE ${CMAKE_CURRENT_SOURCE_DIR} + FILES + ${CLIENT_EXE_PRIVATE_SOURCES} +) + +target_link_libraries(Client-exe + PRIVATE + Client-shared) + +set_property(TARGET Client-exe PROPERTY FOLDER "Client") diff --git a/clients/cpp/Client/executable/sources/main.cpp b/clients/cpp/Client/executable/sources/main.cpp new file mode 100644 index 00000000..8084f741 --- /dev/null +++ b/clients/cpp/Client/executable/sources/main.cpp @@ -0,0 +1,12 @@ + +#include + +#include + +int main() +{ + extreme_carpaccio::client::CarpaccioServer server; + server.start(); + + return EXIT_SUCCESS; +} diff --git a/clients/cpp/Client/library/CMakeLists.txt b/clients/cpp/Client/library/CMakeLists.txt new file mode 100644 index 00000000..6e0ad4ae --- /dev/null +++ b/clients/cpp/Client/library/CMakeLists.txt @@ -0,0 +1,47 @@ + +add_library(Client-shared SHARED) + +target_compile_definitions(Client-shared PRIVATE EXTREME_CARPACCIO_CLIENT_EXPORTS) + +set(CLIENT_SHARED_PRIVATE_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/sources/extreme_carpaccio/client/Client.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/sources/extreme_carpaccio/client/HttpConfig.hpp +) + +set(CLIENT_SHARED_PUBLIC_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/includes/extreme_carpaccio/client/Client.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/includes/extreme_carpaccio/client/config.hpp +) + +target_sources(Client-shared + PRIVATE + ${CLIENT_SHARED_PRIVATE_SOURCES} + PUBLIC + ${CLIENT_SHARED_PUBLIC_SOURCES} +) + +source_group( + TREE ${CMAKE_CURRENT_SOURCE_DIR} + FILES + ${CLIENT_SHARED_PRIVATE_SOURCES} + ${CLIENT_SHARED_PUBLIC_SOURCES} +) + +target_include_directories(Client-shared + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/sources + PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/includes +) + +target_link_libraries(Client-shared + PRIVATE + nlohmann_json + PUBLIC + Boost::boost + Order-Management-shared +) + +set_property(TARGET Client-shared PROPERTY FOLDER "Client") + +add_subdirectory(tests) diff --git a/clients/cpp/include/extreme_carpaccio_client/ExtremeCarpaccioClient.hpp b/clients/cpp/Client/library/includes/extreme_carpaccio/client/Client.hpp similarity index 91% rename from clients/cpp/include/extreme_carpaccio_client/ExtremeCarpaccioClient.hpp rename to clients/cpp/Client/library/includes/extreme_carpaccio/client/Client.hpp index be58c250..d93cfe29 100644 --- a/clients/cpp/include/extreme_carpaccio_client/ExtremeCarpaccioClient.hpp +++ b/clients/cpp/Client/library/includes/extreme_carpaccio/client/Client.hpp @@ -1,13 +1,18 @@ + +#ifndef EXTREME_CARPACCIO_CLIENT_CLIENT_HPP +#define EXTREME_CARPACCIO_CLIENT_CLIENT_HPP + +#include + #include #include #include #include -#include - #include -namespace extreme_carpaccio_client { +namespace extreme_carpaccio { +namespace client { class http_worker { @@ -96,4 +101,7 @@ class EXTREME_CARPACCIO_CLIENT_API CarpaccioStream boost::beast::tcp_stream m_stream; }; -} // namespace extreme_carpaccio_client +} // namespace client +} // namespace extreme_carpaccio + +#endif // EXTREME_CARPACCIO_CLIENT_CLIENT_HPP diff --git a/clients/cpp/include/extreme_carpaccio_client/config.hpp b/clients/cpp/Client/library/includes/extreme_carpaccio/client/config.hpp similarity index 100% rename from clients/cpp/include/extreme_carpaccio_client/config.hpp rename to clients/cpp/Client/library/includes/extreme_carpaccio/client/config.hpp diff --git a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp b/clients/cpp/Client/library/sources/extreme_carpaccio/client/Client.cpp similarity index 96% rename from clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp rename to clients/cpp/Client/library/sources/extreme_carpaccio/client/Client.cpp index 09aee242..a2846e5f 100644 --- a/clients/cpp/src/extreme_carpaccio_client/ExtremeCarpaccioClient.cpp +++ b/clients/cpp/Client/library/sources/extreme_carpaccio/client/Client.cpp @@ -1,5 +1,5 @@ -#include -#include +#include +#include #include #include @@ -25,9 +25,10 @@ using tcp = boost::asio::ip::tcp; // from const int version = 11; -namespace extreme_carpaccio_client { +namespace extreme_carpaccio { +namespace client { - http_worker::http_worker(tcp::acceptor& acceptor, const std::string& doc_root) : +http_worker::http_worker(tcp::acceptor& acceptor, const std::string& doc_root) : acceptor_(acceptor), doc_root_(doc_root) { @@ -268,5 +269,5 @@ void http_worker::check_deadline() http::write(m_stream, request); } -} // namespace extreme_carpaccio_client - +} // namespace client +} // namespace extreme_carpaccio diff --git a/clients/cpp/src/extreme_carpaccio_client/HTTPConfig.hpp b/clients/cpp/Client/library/sources/extreme_carpaccio/client/HttpConfig.hpp similarity index 66% rename from clients/cpp/src/extreme_carpaccio_client/HTTPConfig.hpp rename to clients/cpp/Client/library/sources/extreme_carpaccio/client/HttpConfig.hpp index 67373e85..26de681f 100644 --- a/clients/cpp/src/extreme_carpaccio_client/HTTPConfig.hpp +++ b/clients/cpp/Client/library/sources/extreme_carpaccio/client/HttpConfig.hpp @@ -1,7 +1,14 @@ + #ifndef EXTREME_CARPACCIO_CLIENT_HTTPCONFIG_HPP #define EXTREME_CARPACCIO_CLIENT_HTTPCONFIG_HPP #define HTTP_SERVER_IP "127.0.0.1" #define HTTP_SERVER_PORT 8081 +namespace extreme_carpaccio { +namespace client { + +} // namespace client +} // namespace extreme_carpaccio + #endif // EXTREME_CARPACCIO_CLIENT_HTTPCONFIG_HPP \ No newline at end of file diff --git a/clients/cpp/Client/library/tests/CMakeLists.txt b/clients/cpp/Client/library/tests/CMakeLists.txt new file mode 100644 index 00000000..55551802 --- /dev/null +++ b/clients/cpp/Client/library/tests/CMakeLists.txt @@ -0,0 +1,29 @@ + +add_executable(Client-tests) + +set(CLIENT_TESTS_PRIVATE_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/sources/ClientTests.cpp +) + +target_sources(Client-tests + PRIVATE + ${CLIENT_TESTS_PRIVATE_SOURCES} +) + +source_group( + TREE ${CMAKE_CURRENT_SOURCE_DIR} + FILES + ${CLIENT_TESTS_PRIVATE_SOURCES} +) + +target_link_libraries(Client-tests + PRIVATE + Client-shared + gmock_main + Boost::boost + nlohmann_json +) + +add_test(NAME ctest-Extreme-Carpaccio-Client-tests COMMAND Client-tests) + +set_property(TARGET Client-tests PROPERTY FOLDER "Client") diff --git a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp b/clients/cpp/Client/library/tests/sources/ClientTests.cpp similarity index 95% rename from clients/cpp/test/ExtremeCarpaccioClientTest.cpp rename to clients/cpp/Client/library/tests/sources/ClientTests.cpp index ad9250be..5498671f 100644 --- a/clients/cpp/test/ExtremeCarpaccioClientTest.cpp +++ b/clients/cpp/Client/library/tests/sources/ClientTests.cpp @@ -1,4 +1,4 @@ -#include +#include #include @@ -26,11 +26,13 @@ using tcp = net::ip::tcp; // from using testing::ElementsAre; -using namespace extreme_carpaccio_client; - const char serverHost[] = "localhost"; const unsigned short serverPort = 8081; +namespace extreme_carpaccio { +namespace client { +namespace test { + static http::response generateServerResponse(boost::beast::http::verb requestType, const std::string & target, const std::string & contentType = "", const std::string & body = "") { CarpaccioServer server(8081); @@ -126,4 +128,8 @@ TEST(ExtremeCarpaccioClient, should_trace_order_description) ASSERT_EQ("Order received: Order{prices={1,1.5}, quantities={100,200}, country='DE', reduction='STANDARD'}\n", buffer.str()); // When done redirect cout to its old self std::cout.rdbuf(sbuf); -} \ No newline at end of file +} + +} // namespace test +} // namespace client +} // namespace extreme_carpaccio diff --git a/clients/cpp/OrderManagement/CMakeLists.txt b/clients/cpp/OrderManagement/CMakeLists.txt index a6ad5188..0b5d6287 100644 --- a/clients/cpp/OrderManagement/CMakeLists.txt +++ b/clients/cpp/OrderManagement/CMakeLists.txt @@ -1,30 +1,45 @@ #Functional library to be modified by participants -add_library(Extreme-Carpaccio-Order-Management-shared SHARED) +add_library(Order-Management-shared SHARED) -target_compile_definitions(Extreme-Carpaccio-Order-Management-shared PRIVATE EXTREME_CARPACCIO_ORDER_MANAGEMENT_EXPORTS) +target_compile_definitions(Order-Management-shared PRIVATE EXTREME_CARPACCIO_ORDER_MANAGEMENT_EXPORTS) -target_sources(Extreme-Carpaccio-Order-Management-shared - PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/sources/extreme_carpaccio/order_management/OrderParsing.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/sources/extreme_carpaccio/order_management/Order.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/sources/extreme_carpaccio/order_management/TotalAmount.cpp - PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}/includes/extreme_carpaccio/order_management/Order.hpp - ${CMAKE_CURRENT_SOURCE_DIR}/includes/extreme_carpaccio/order_management/OrderParsing.hpp - ${CMAKE_CURRENT_SOURCE_DIR}/includes/extreme_carpaccio/order_management/TotalAmount.hpp - ${CMAKE_CURRENT_SOURCE_DIR}/includes/extreme_carpaccio/order_management/config.hpp +set(ORDER_MANAGEMENT_SHARED_PRIVATE_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/sources/extreme_carpaccio/order_management/OrderParsing.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/sources/extreme_carpaccio/order_management/Order.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/sources/extreme_carpaccio/order_management/TotalAmount.cpp +) + +set(ORDER_MANAGEMENT_SHARED_PUBLIC_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/includes/extreme_carpaccio/order_management/Order.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/includes/extreme_carpaccio/order_management/OrderParsing.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/includes/extreme_carpaccio/order_management/TotalAmount.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/includes/extreme_carpaccio/order_management/config.hpp +) + +target_sources(Order-Management-shared + PRIVATE + ${ORDER_MANAGEMENT_SHARED_PRIVATE_SOURCES} + PUBLIC + ${ORDER_MANAGEMENT_SHARED_PUBLIC_SOURCES} +) + +source_group( + TREE ${CMAKE_CURRENT_SOURCE_DIR} + FILES + ${ORDER_MANAGEMENT_SHARED_PRIVATE_SOURCES} + ${ORDER_MANAGEMENT_SHARED_PUBLIC_SOURCES} ) -target_include_directories(Extreme-Carpaccio-Order-Management-shared +target_include_directories(Order-Management-shared PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/sources PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/includes ) -target_link_libraries(Extreme-Carpaccio-Order-Management-shared PUBLIC Boost::boost PRIVATE nlohmann_json) +target_link_libraries(Order-Management-shared PUBLIC Boost::boost PRIVATE nlohmann_json) -set_property(TARGET Extreme-Carpaccio-Order-Management-shared PROPERTY FOLDER "OrderManagement") +set_property(TARGET Order-Management-shared PROPERTY FOLDER "Order Management") add_subdirectory(tests) \ No newline at end of file diff --git a/clients/cpp/OrderManagement/tests/CMakeLists.txt b/clients/cpp/OrderManagement/tests/CMakeLists.txt index ed036c48..ac45bd2a 100644 --- a/clients/cpp/OrderManagement/tests/CMakeLists.txt +++ b/clients/cpp/OrderManagement/tests/CMakeLists.txt @@ -1,22 +1,31 @@ -add_executable(Extreme-Carpaccio-Order-Management-tests) +add_executable(Order-Management-tests) -target_sources(Extreme-Carpaccio-Order-Management-tests - PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/sources/OrderParsingTests.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/sources/TotalAmountTests.cpp +set(ORDER_MANAGEMENT_TESTS_PRIVATE_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/sources/OrderParsingTests.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/sources/TotalAmountTests.cpp +) + +target_sources(Order-Management-tests + PRIVATE ${ORDER_MANAGEMENT_TESTS_PRIVATE_SOURCES} +) + +source_group( + TREE ${CMAKE_CURRENT_SOURCE_DIR} + FILES + ${ORDER_MANAGEMENT_TESTS_PRIVATE_SOURCES} ) -target_include_directories(Extreme-Carpaccio-Order-Management-tests +target_include_directories(Order-Management-tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/sources ) -target_link_libraries(Extreme-Carpaccio-Order-Management-tests +target_link_libraries(Order-Management-tests PRIVATE - Extreme-Carpaccio-Order-Management-shared + Order-Management-shared gmock_main) -add_test(NAME ctest-Extreme-Carpaccio-Order-Management-tests COMMAND Extreme-Carpaccio-Order-Management-tests) +add_test(NAME ctest-Extreme-Carpaccio-Order-Management-tests COMMAND Order-Management-tests) -set_property(TARGET Extreme-Carpaccio-Order-Management-tests PROPERTY FOLDER "OrderManagement") +set_property(TARGET Order-Management-tests PROPERTY FOLDER "Order Management") diff --git a/clients/cpp/build/feedback/toto.png b/clients/cpp/build/feedback/toto.png deleted file mode 100644 index e69de29b..00000000 diff --git a/clients/cpp/src/main.cpp b/clients/cpp/src/main.cpp deleted file mode 100644 index 314c6b4e..00000000 --- a/clients/cpp/src/main.cpp +++ /dev/null @@ -1,8 +0,0 @@ - -#include - -int main() -{ - extreme_carpaccio_client::CarpaccioServer server; - server.start(); -} From 63d36db2ed9dbdfc930a0519452685973af8ff52 Mon Sep 17 00:00:00 2001 From: NADIF Antoine Date: Fri, 15 Apr 2022 18:28:14 +0200 Subject: [PATCH 103/125] Add Github Actions to launch C++ build and tests. --- .github/workflows/cmake.yml | 44 +++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 .github/workflows/cmake.yml diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml new file mode 100644 index 00000000..7a190ab2 --- /dev/null +++ b/.github/workflows/cmake.yml @@ -0,0 +1,44 @@ +name: C++ + +on: + push: + branches-ignore: + - '*-from-video' + +env: + # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) + BUILD_TYPE: Debug + +jobs: + build-gcc: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Build & Test + uses: ashutoshvarma/action-cmake-build@master + with: + submodule-update: true + source-dir: ${{github.workspace}}/clients/cpp + build-dir: ${{github.workspace}}/clients/cpp/build + cc: gcc + cxx: g++ + build-type: Release + run-test: true + ctest-options: "--output-on-failure" + install-build: false + build-clang: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Build & Test + uses: ashutoshvarma/action-cmake-build@master + with: + submodule-update: true + source-dir: ${{github.workspace}}/clients/cpp + build-dir: ${{github.workspace}}/clients/cpp/build + cc: clang + cxx: clang++ + build-type: Release + run-test: true + ctest-options: "--output-on-failure" + install-build: false \ No newline at end of file From e3400738bbe12ff92830af7d05b0eb33732ae53c Mon Sep 17 00:00:00 2001 From: NADIF Antoine Date: Fri, 15 Apr 2022 18:49:24 +0200 Subject: [PATCH 104/125] Add explicit linking to pthread when it is available. --- clients/cpp/CMakeLists.txt | 4 ++++ clients/cpp/Client/library/CMakeLists.txt | 19 ++++++++++--------- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/clients/cpp/CMakeLists.txt b/clients/cpp/CMakeLists.txt index eb6bde97..08b261b2 100644 --- a/clients/cpp/CMakeLists.txt +++ b/clients/cpp/CMakeLists.txt @@ -17,6 +17,10 @@ include(cmake/FindGoogleTest.cmake) include(cmake/FindNlohmannJson.cmake) include(cmake/FindBoost.cmake) +set(CMAKE_THREAD_PREFER_PTHREAD TRUE) +set(THREADS_PREFER_PTHREAD_FLAG TRUE) +find_package(Threads REQUIRED) + add_subdirectory(OrderManagement) add_subdirectory(Client) diff --git a/clients/cpp/Client/library/CMakeLists.txt b/clients/cpp/Client/library/CMakeLists.txt index 6e0ad4ae..a5fb0197 100644 --- a/clients/cpp/Client/library/CMakeLists.txt +++ b/clients/cpp/Client/library/CMakeLists.txt @@ -28,18 +28,19 @@ source_group( ) target_include_directories(Client-shared - PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/sources - PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}/includes + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/sources + PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/includes ) target_link_libraries(Client-shared - PRIVATE - nlohmann_json - PUBLIC - Boost::boost - Order-Management-shared + PRIVATE + nlohmann_json + PUBLIC + Threads::Threads + Boost::boost + Order-Management-shared ) set_property(TARGET Client-shared PROPERTY FOLDER "Client") From 13de17e9542e057278559c6b79347fd88ebb813f Mon Sep 17 00:00:00 2001 From: NADIF Antoine Date: Tue, 19 Apr 2022 08:36:28 +0200 Subject: [PATCH 105/125] Refactoring and cleaning + client now handles total amount processing using the order management library. --- .../extreme_carpaccio/client/Client.cpp | 36 +++++---- .../library/tests/sources/ClientTests.cpp | 81 ++++++++----------- .../order_management/TotalAmount.hpp | 8 +- .../order_management/TotalAmount.cpp | 13 ++- .../tests/sources/OrderParsingTests.cpp | 4 +- .../tests/sources/TotalAmountTests.cpp | 12 +-- 6 files changed, 78 insertions(+), 76 deletions(-) diff --git a/clients/cpp/Client/library/sources/extreme_carpaccio/client/Client.cpp b/clients/cpp/Client/library/sources/extreme_carpaccio/client/Client.cpp index a2846e5f..2a656fbc 100644 --- a/clients/cpp/Client/library/sources/extreme_carpaccio/client/Client.cpp +++ b/clients/cpp/Client/library/sources/extreme_carpaccio/client/Client.cpp @@ -18,16 +18,21 @@ #include #include -namespace beast = boost::beast; // from -namespace http = beast::http; // from -namespace net = boost::asio; // from -using tcp = boost::asio::ip::tcp; // from - -const int version = 11; namespace extreme_carpaccio { namespace client { +namespace beast = boost::beast; +namespace http = beast::http; +namespace net = boost::asio; +using tcp = boost::asio::ip::tcp; + +namespace { + +const int version = 11; + +} // namespace + http_worker::http_worker(tcp::acceptor& acceptor, const std::string& doc_root) : acceptor_(acceptor), doc_root_(doc_root) @@ -115,19 +120,21 @@ static Feedback parseFeedback(const std::string& jsonFeedback) bool http_worker::handleRequest(http::verb requestType, const std::string & target, const std::string & contentType, const std::string & body) { - if (requestType == http::verb::post && contentType == "application/json") + const bool error = (requestType != http::verb::post || contentType != "application/json"); + + if (!error) { if (target == "/order") { - extreme_carpaccio::order_management::Order order = extreme_carpaccio::order_management::parseOrder(body); + auto order = order_management::parseOrder(body); std::cout << "Order received: " << order << std::endl; - //TO IMPLEMENT - //nlohmann::json totalAmountJson; + auto totalAmountResponse = order_management::computeTotalAmount(body); + + nlohmann::json totalAmountJson; - //totalAmountJson["total"] = computeTotalAmount(order); - //send_response(http::status::ok, totalAmountJson.dump()); - return true; + totalAmountJson["total"] = totalAmountResponse.m_totalAmount; + send_response(totalAmountResponse.m_status, totalAmountJson.dump()); } else if (target == "/feedback") { @@ -135,10 +142,9 @@ bool http_worker::handleRequest(http::verb requestType, const std::string & targ std::cout << feedback.type << " : " << feedback.content << std::endl; send_response(http::status::ok, "Feedback received"); - return false; } } - return true; + return error; } void http_worker::process_request(http::request> const& req) diff --git a/clients/cpp/Client/library/tests/sources/ClientTests.cpp b/clients/cpp/Client/library/tests/sources/ClientTests.cpp index 5498671f..7143ab0a 100644 --- a/clients/cpp/Client/library/tests/sources/ClientTests.cpp +++ b/clients/cpp/Client/library/tests/sources/ClientTests.cpp @@ -19,20 +19,22 @@ #include #include -namespace beast = boost::beast; // from -namespace http = beast::http; // from -namespace net = boost::asio; // from -using tcp = net::ip::tcp; // from +namespace extreme_carpaccio { +namespace client { +namespace test { + +namespace beast = boost::beast; +namespace http = beast::http; +namespace net = boost::asio; +using tcp = net::ip::tcp; using testing::ElementsAre; +namespace { + const char serverHost[] = "localhost"; const unsigned short serverPort = 8081; -namespace extreme_carpaccio { -namespace client { -namespace test { - static http::response generateServerResponse(boost::beast::http::verb requestType, const std::string & target, const std::string & contentType = "", const std::string & body = "") { CarpaccioServer server(8081); @@ -57,75 +59,56 @@ static http::response generateServerResponse(boost::beast::h return res; } +} // namespace + TEST(ExtremeCarpaccioClient, should_answer_404_to_incorrect_request) { - std::string target = "/je-suis-trop-fort"; + const std::string target = "/je-suis-trop-fort"; // Receive the HTTP response - auto res = generateServerResponse(http::verb::get, target); + const auto res = generateServerResponse(http::verb::get, target); // Write the message to standard out std::cout << "Response" << std::endl << res << std::endl; - EXPECT_EQ(http::status::not_found, res.result()); -} - -TEST(ExtremeCarpaccioClient, DISABLED_should_return_valid_amount_on_order_request) -{ - std::string target = "/order"; - - // Receive the HTTP response - auto res = generateServerResponse(http::verb::post, target, "application/json", "{\"prices\": [], \"quantities\": [], \"country\": \"DE\", \"reduction\": \"STANDARD\"}"); - - ASSERT_EQ(http::status::ok, res.result()); - - auto totalAmountJson = nlohmann::json::parse(boost::beast::buffers_to_string(res.body().data())); - EXPECT_NO_THROW(totalAmountJson["total"].get()); -} - -TEST(ExtremeCarpaccioClient, DISABLED_should_return_amount_computed_with_prices_and_quantities_only) -{ - std::string target = "/order"; - - auto res = generateServerResponse(http::verb::post, target, "application/json", "{\"prices\": [1,1.5], \"quantities\": [100, 200], \"country\": \"DE\", \"reduction\": \"STANDARD\"}"); - - ASSERT_EQ(http::status::ok, res.result()); - - auto totalAmountJson = nlohmann::json::parse(boost::beast::buffers_to_string(res.body().data())); - - EXPECT_EQ(100 * 1 + 200 * 1.5, totalAmountJson["total"].get()); + EXPECT_EQ(http::status::not_found, res.result()); } TEST(ExtremeCarpaccioClient, should_handle_post_feedback) { - std::string target = "/feedback"; - std::stringstream buffer; + const std::string target = "/feedback"; + // Save cout's buffer here - std::streambuf *sbuf = std::cout.rdbuf(); + std::streambuf * sbuf = std::cout.rdbuf(); + // Redirect cout to our stringstream buffer + std::stringstream buffer; std::cout.rdbuf(buffer.rdbuf()); - auto res = generateServerResponse(http::verb::post, target, "application/json", "{\"type\": \"ERROR\", \"content\": \"Field total in response is missing\"}"); + const auto res = generateServerResponse(http::verb::post, target, "application/json", "{\"type\": \"ERROR\", \"content\": \"Field total in response is missing\"}"); + + EXPECT_EQ(http::status::ok, res.result()); + EXPECT_EQ("ERROR : Field total in response is missing\n", buffer.str()); - ASSERT_EQ(http::status::ok, res.result()); - ASSERT_EQ("ERROR : Field total in response is missing\n", buffer.str()); // When done redirect cout to its old self std::cout.rdbuf(sbuf); } TEST(ExtremeCarpaccioClient, should_trace_order_description) { - std::string target = "/order"; - std::stringstream buffer; + const std::string target = "/order"; + // Save cout's buffer here - std::streambuf* sbuf = std::cout.rdbuf(); + std::streambuf * sbuf = std::cout.rdbuf(); + // Redirect cout to our stringstream buffer + std::stringstream buffer; std::cout.rdbuf(buffer.rdbuf()); - auto res = generateServerResponse(http::verb::post, target, "application/json", "{\"prices\": [1,1.5], \"quantities\": [100, 200], \"country\": \"DE\", \"reduction\": \"STANDARD\"}"); + const auto res = generateServerResponse(http::verb::post, target, "application/json", "{\"prices\": [1,1.5], \"quantities\": [100, 200], \"country\": \"DE\", \"reduction\": \"STANDARD\"}"); - //ASSERT_EQ(http::status::ok, res.result()); - ASSERT_EQ("Order received: Order{prices={1,1.5}, quantities={100,200}, country='DE', reduction='STANDARD'}\n", buffer.str()); + EXPECT_EQ("Order received: Order{prices={1,1.5}, quantities={100,200}, country='DE', reduction='STANDARD'}\n", buffer.str()); + // When done redirect cout to its old self std::cout.rdbuf(sbuf); } diff --git a/clients/cpp/OrderManagement/includes/extreme_carpaccio/order_management/TotalAmount.hpp b/clients/cpp/OrderManagement/includes/extreme_carpaccio/order_management/TotalAmount.hpp index dce164ab..d6549e30 100644 --- a/clients/cpp/OrderManagement/includes/extreme_carpaccio/order_management/TotalAmount.hpp +++ b/clients/cpp/OrderManagement/includes/extreme_carpaccio/order_management/TotalAmount.hpp @@ -12,7 +12,13 @@ namespace extreme_carpaccio { namespace order_management { -using TotalAmountResponse = std::pair; +struct EXTREME_CARPACCIO_ORDER_MANAGEMENT_API TotalAmountResponse +{ + TotalAmountResponse(boost::beast::http::status status, double totalAmount); + + boost::beast::http::status m_status; + double m_totalAmount; +}; EXTREME_CARPACCIO_ORDER_MANAGEMENT_API TotalAmountResponse computeTotalAmount(const std::string & requestBody); diff --git a/clients/cpp/OrderManagement/sources/extreme_carpaccio/order_management/TotalAmount.cpp b/clients/cpp/OrderManagement/sources/extreme_carpaccio/order_management/TotalAmount.cpp index 6156d0e2..bf9ca362 100644 --- a/clients/cpp/OrderManagement/sources/extreme_carpaccio/order_management/TotalAmount.cpp +++ b/clients/cpp/OrderManagement/sources/extreme_carpaccio/order_management/TotalAmount.cpp @@ -1,15 +1,22 @@ #include +namespace extreme_carpaccio { +namespace order_management { + namespace beast = boost::beast; namespace http = beast::http; -namespace extreme_carpaccio { -namespace order_management { +TotalAmountResponse::TotalAmountResponse(boost::beast::http::status status, double totalAmount) + : m_status(status) + , m_totalAmount(totalAmount) +{ +} + TotalAmountResponse computeTotalAmount(const std::string & /*requestBody*/) { - return std::make_pair(http::status::not_found, 42.); + return TotalAmountResponse(http::status::not_found, 42.); } } // namespace order_management diff --git a/clients/cpp/OrderManagement/tests/sources/OrderParsingTests.cpp b/clients/cpp/OrderManagement/tests/sources/OrderParsingTests.cpp index ce2f6d92..c83b5016 100644 --- a/clients/cpp/OrderManagement/tests/sources/OrderParsingTests.cpp +++ b/clients/cpp/OrderManagement/tests/sources/OrderParsingTests.cpp @@ -7,12 +7,12 @@ #include -using namespace testing; - namespace extreme_carpaccio { namespace order_management { namespace test { +using namespace testing; + TEST(OrderParsing, should_return_order_object_from_json_order) { std::string orderRequest = "{\"prices\": [1,1.5], \"quantities\": [100, 200], \"country\": \"DE\", \"reduction\": \"STANDARD\"}"; diff --git a/clients/cpp/OrderManagement/tests/sources/TotalAmountTests.cpp b/clients/cpp/OrderManagement/tests/sources/TotalAmountTests.cpp index 1236db66..442d63f0 100644 --- a/clients/cpp/OrderManagement/tests/sources/TotalAmountTests.cpp +++ b/clients/cpp/OrderManagement/tests/sources/TotalAmountTests.cpp @@ -3,22 +3,22 @@ #include +namespace extreme_carpaccio { +namespace order_management { +namespace test { + using namespace testing; namespace beast = boost::beast; namespace http = beast::http; -namespace extreme_carpaccio { -namespace order_management { -namespace test { - TEST(TotalAmount, dummy_test) { const std::string requestBody = "{\"prices\": [1,1.5], \"quantities\": [100, 200], \"country\": \"DE\", \"reduction\": \"STANDARD\"}"; auto response = computeTotalAmount(requestBody); - EXPECT_EQ(response.first, http::status::not_found); - EXPECT_EQ(response.second, 42.); + EXPECT_EQ(response.m_status, http::status::not_found); + EXPECT_EQ(response.m_totalAmount, 42.); } } // namespace tests From bd62a7986004869df15290fb41e3c7e9101e95ea Mon Sep 17 00:00:00 2001 From: NADIF Antoine Date: Tue, 19 Apr 2022 09:09:44 +0200 Subject: [PATCH 106/125] Migrate test helpers from main library to test target in a helpers subfolder. --- .../extreme_carpaccio/client/Client.hpp | 17 ---- .../extreme_carpaccio/client/Client.cpp | 84 ++++--------------- .../cpp/Client/library/tests/CMakeLists.txt | 9 ++ .../library/tests/sources/ClientTests.cpp | 52 +++--------- .../tests/sources/helpers/CarpaccioStream.cpp | 76 +++++++++++++++++ .../tests/sources/helpers/CarpaccioStream.hpp | 41 +++++++++ .../sources/helpers/TestServerResponse.cpp | 65 ++++++++++++++ .../sources/helpers/TestServerResponse.hpp | 31 +++++++ 8 files changed, 250 insertions(+), 125 deletions(-) create mode 100644 clients/cpp/Client/library/tests/sources/helpers/CarpaccioStream.cpp create mode 100644 clients/cpp/Client/library/tests/sources/helpers/CarpaccioStream.hpp create mode 100644 clients/cpp/Client/library/tests/sources/helpers/TestServerResponse.cpp create mode 100644 clients/cpp/Client/library/tests/sources/helpers/TestServerResponse.hpp diff --git a/clients/cpp/Client/library/includes/extreme_carpaccio/client/Client.hpp b/clients/cpp/Client/library/includes/extreme_carpaccio/client/Client.hpp index d93cfe29..56d0a51f 100644 --- a/clients/cpp/Client/library/includes/extreme_carpaccio/client/Client.hpp +++ b/clients/cpp/Client/library/includes/extreme_carpaccio/client/Client.hpp @@ -84,23 +84,6 @@ class EXTREME_CARPACCIO_CLIENT_API CarpaccioServer http_worker worker; }; -class EXTREME_CARPACCIO_CLIENT_API CarpaccioStream -{ -public: - CarpaccioStream(const std::string & host, unsigned short port); - ~CarpaccioStream(); - - boost::beast::http::response read(boost::beast::flat_buffer&); - void write(boost::beast::http::verb requestType, const std::string & target, const std::string & contentType, const std::string & body); - -private: - std::string m_serverHost; - boost::asio::io_context m_ioContext; - boost::asio::ip::tcp::resolver m_resolver; - boost::asio::ip::tcp::resolver::results_type m_resolverResults; - boost::beast::tcp_stream m_stream; -}; - } // namespace client } // namespace extreme_carpaccio diff --git a/clients/cpp/Client/library/sources/extreme_carpaccio/client/Client.cpp b/clients/cpp/Client/library/sources/extreme_carpaccio/client/Client.cpp index 2a656fbc..f115312a 100644 --- a/clients/cpp/Client/library/sources/extreme_carpaccio/client/Client.cpp +++ b/clients/cpp/Client/library/sources/extreme_carpaccio/client/Client.cpp @@ -203,77 +203,29 @@ void http_worker::check_deadline() }); } - CarpaccioServer::CarpaccioServer() : CarpaccioServer(HTTP_SERVER_PORT) - { +CarpaccioServer::CarpaccioServer() : CarpaccioServer(HTTP_SERVER_PORT) +{ - } +} - CarpaccioServer::CarpaccioServer(unsigned short port) - : ioc(1) - , acceptor(ioc, {boost::asio::ip::make_address(HTTP_SERVER_IP), port } ), - worker(acceptor, "./feedback") - { +CarpaccioServer::CarpaccioServer(unsigned short port) + : ioc(1) + , acceptor(ioc, {boost::asio::ip::make_address(HTTP_SERVER_IP), port } ), + worker(acceptor, "./feedback") +{ - } - - void CarpaccioServer::start() - { - worker.start(); - ioc.run(); - } - - void CarpaccioServer::stop() - { - ioc.stop(); - } - - CarpaccioStream::CarpaccioStream(const std::string & host, unsigned short port) - : m_serverHost(host) - , m_ioContext() - , m_resolver(m_ioContext) // These objects perform our I/O - , m_resolverResults(m_resolver.resolve(host, std::to_string(port))) // Look up the domain name - , m_stream(m_ioContext) - { - // Make the connection on the IP address we get from a lookup - m_stream.connect(m_resolverResults); - } - - CarpaccioStream::~CarpaccioStream() - { - // Gracefully close the socket - beast::error_code ec; - m_stream.socket().shutdown(tcp::socket::shutdown_both, ec); - - //// not_connected happens sometimes - //// so don't bother reporting it. - //if (ec && ec != beast::errc::not_connected) - // throw beast::system_error{ ec }; - } - - http::response CarpaccioStream::read(beast::flat_buffer & buffer) - { - // Declare a container to hold the response - http::response response; - - // Receive the HTTP response - http::read(m_stream, buffer, response); +} - return response; - } +void CarpaccioServer::start() +{ + worker.start(); + ioc.run(); +} - void CarpaccioStream::write(boost::beast::http::verb requestType, const std::string & target, const std::string & contentType, const std::string & body) - { - // Set up an HTTP GET request message - http::request request{ requestType, target, version }; - request.set(http::field::host, m_serverHost); - request.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING); - request.set(http::field::content_type, contentType); - request.body() = body; - request.prepare_payload(); - - // Send the HTTP request to the remote host - http::write(m_stream, request); - } +void CarpaccioServer::stop() +{ + ioc.stop(); +} } // namespace client } // namespace extreme_carpaccio diff --git a/clients/cpp/Client/library/tests/CMakeLists.txt b/clients/cpp/Client/library/tests/CMakeLists.txt index 55551802..b327edf6 100644 --- a/clients/cpp/Client/library/tests/CMakeLists.txt +++ b/clients/cpp/Client/library/tests/CMakeLists.txt @@ -3,6 +3,10 @@ add_executable(Client-tests) set(CLIENT_TESTS_PRIVATE_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/sources/ClientTests.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/sources/helpers/CarpaccioStream.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/sources/helpers/CarpaccioStream.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/sources/helpers/TestServerResponse.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/sources/helpers/TestServerResponse.cpp ) target_sources(Client-tests @@ -16,6 +20,11 @@ source_group( ${CLIENT_TESTS_PRIVATE_SOURCES} ) +target_include_directories(Client-tests + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/sources +) + target_link_libraries(Client-tests PRIVATE Client-shared diff --git a/clients/cpp/Client/library/tests/sources/ClientTests.cpp b/clients/cpp/Client/library/tests/sources/ClientTests.cpp index 7143ab0a..226d5ab6 100644 --- a/clients/cpp/Client/library/tests/sources/ClientTests.cpp +++ b/clients/cpp/Client/library/tests/sources/ClientTests.cpp @@ -1,23 +1,22 @@ -#include -#include +#include -#include -#include +#include -#include -#include +#include #include #include #include #include #include + #include #include #include -#include -#include + +#include +#include namespace extreme_carpaccio { namespace client { @@ -30,43 +29,12 @@ using tcp = net::ip::tcp; using testing::ElementsAre; -namespace { - -const char serverHost[] = "localhost"; -const unsigned short serverPort = 8081; - -static http::response generateServerResponse(boost::beast::http::verb requestType, const std::string & target, const std::string & contentType = "", const std::string & body = "") -{ - CarpaccioServer server(8081); - std::thread thread(&CarpaccioServer::start, &server); - std::this_thread::sleep_for(std::chrono::seconds(1)); - - CarpaccioStream stream(serverHost, serverPort); - - // Send the HTTP request to the remote host - stream.write(requestType, target, contentType, body); - - // This buffer is used for reading and must be persisted - beast::flat_buffer buffer; - - // Receive the HTTP response - auto res = stream.read(buffer); - - server.stop(); - - thread.detach(); - - return res; -} - -} // namespace - TEST(ExtremeCarpaccioClient, should_answer_404_to_incorrect_request) { const std::string target = "/je-suis-trop-fort"; // Receive the HTTP response - const auto res = generateServerResponse(http::verb::get, target); + const auto res = helpers::generateServerResponse(http::verb::get, target); // Write the message to standard out std::cout << "Response" << std::endl << res << std::endl; @@ -85,7 +53,7 @@ TEST(ExtremeCarpaccioClient, should_handle_post_feedback) std::stringstream buffer; std::cout.rdbuf(buffer.rdbuf()); - const auto res = generateServerResponse(http::verb::post, target, "application/json", "{\"type\": \"ERROR\", \"content\": \"Field total in response is missing\"}"); + const auto res = helpers::generateServerResponse(http::verb::post, target, "application/json", "{\"type\": \"ERROR\", \"content\": \"Field total in response is missing\"}"); EXPECT_EQ(http::status::ok, res.result()); EXPECT_EQ("ERROR : Field total in response is missing\n", buffer.str()); @@ -105,7 +73,7 @@ TEST(ExtremeCarpaccioClient, should_trace_order_description) std::stringstream buffer; std::cout.rdbuf(buffer.rdbuf()); - const auto res = generateServerResponse(http::verb::post, target, "application/json", "{\"prices\": [1,1.5], \"quantities\": [100, 200], \"country\": \"DE\", \"reduction\": \"STANDARD\"}"); + const auto res = helpers::generateServerResponse(http::verb::post, target, "application/json", "{\"prices\": [1,1.5], \"quantities\": [100, 200], \"country\": \"DE\", \"reduction\": \"STANDARD\"}"); EXPECT_EQ("Order received: Order{prices={1,1.5}, quantities={100,200}, country='DE', reduction='STANDARD'}\n", buffer.str()); diff --git a/clients/cpp/Client/library/tests/sources/helpers/CarpaccioStream.cpp b/clients/cpp/Client/library/tests/sources/helpers/CarpaccioStream.cpp new file mode 100644 index 00000000..c123063c --- /dev/null +++ b/clients/cpp/Client/library/tests/sources/helpers/CarpaccioStream.cpp @@ -0,0 +1,76 @@ + +#include + +#include +#include +#include +#include + +namespace extreme_carpaccio { +namespace client { +namespace test { +namespace helpers { + +namespace beast = boost::beast; +namespace http = beast::http; +namespace net = boost::asio; +using tcp = boost::asio::ip::tcp; + +namespace { + +const int version = 11; + +} // namespace + +CarpaccioStream::CarpaccioStream(const std::string & host, unsigned short port) + : m_serverHost(host) + , m_ioContext() + , m_resolver(m_ioContext) // These objects perform our I/O + , m_resolverResults(m_resolver.resolve(host, std::to_string(port))) // Look up the domain name + , m_stream(m_ioContext) +{ + // Make the connection on the IP address we get from a lookup + m_stream.connect(m_resolverResults); +} + +CarpaccioStream::~CarpaccioStream() +{ + // Gracefully close the socket + beast::error_code ec; + m_stream.socket().shutdown(tcp::socket::shutdown_both, ec); + + //// not_connected happens sometimes + //// so don't bother reporting it. + //if (ec && ec != beast::errc::not_connected) + // throw beast::system_error{ ec }; +} + +http::response CarpaccioStream::read(beast::flat_buffer & buffer) +{ + // Declare a container to hold the response + http::response response; + + // Receive the HTTP response + http::read(m_stream, buffer, response); + + return response; +} + +void CarpaccioStream::write(boost::beast::http::verb requestType, const std::string & target, const std::string & contentType, const std::string & body) +{ + // Set up an HTTP GET request message + http::request request{ requestType, target, version }; + request.set(http::field::host, m_serverHost); + request.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING); + request.set(http::field::content_type, contentType); + request.body() = body; + request.prepare_payload(); + + // Send the HTTP request to the remote host + http::write(m_stream, request); +} + +} // namespace helpers +} // namespace test +} // namespace client +} // namespace extreme_carpaccio diff --git a/clients/cpp/Client/library/tests/sources/helpers/CarpaccioStream.hpp b/clients/cpp/Client/library/tests/sources/helpers/CarpaccioStream.hpp new file mode 100644 index 00000000..0ea3c8ec --- /dev/null +++ b/clients/cpp/Client/library/tests/sources/helpers/CarpaccioStream.hpp @@ -0,0 +1,41 @@ + +#ifndef EXTREME_CARPACCIO_CLIENT_TEST_HELPERS_CARPACCIOSTREAM_HPP +#define EXTREME_CARPACCIO_CLIENT_TEST_HELPERS_CARPACCIOSTREAM_HPP + +#include + +#include +#include +#include +#include + +#include + +namespace extreme_carpaccio { +namespace client { +namespace test { +namespace helpers { + +class CarpaccioStream +{ +public: + CarpaccioStream(const std::string & host, unsigned short port); + ~CarpaccioStream(); + + boost::beast::http::response read(boost::beast::flat_buffer&); + void write(boost::beast::http::verb requestType, const std::string & target, const std::string & contentType, const std::string & body); + +private: + std::string m_serverHost; + boost::asio::io_context m_ioContext; + boost::asio::ip::tcp::resolver m_resolver; + boost::asio::ip::tcp::resolver::results_type m_resolverResults; + boost::beast::tcp_stream m_stream; +}; + +} // namespace test +} // namespace test +} // namespace client +} // namespace extreme_carpaccio + +#endif // EXTREME_CARPACCIO_CLIENT_TEST_HELPERS_CARPACCIOSTREAM_HPP diff --git a/clients/cpp/Client/library/tests/sources/helpers/TestServerResponse.cpp b/clients/cpp/Client/library/tests/sources/helpers/TestServerResponse.cpp new file mode 100644 index 00000000..aef827ff --- /dev/null +++ b/clients/cpp/Client/library/tests/sources/helpers/TestServerResponse.cpp @@ -0,0 +1,65 @@ + + +#include +#include + +#include + +#include +#include +#include +#include + +#include +#include + +namespace extreme_carpaccio { +namespace client { +namespace test { +namespace helpers { + +namespace beast = boost::beast; +namespace http = beast::http; +namespace net = boost::asio; +using tcp = boost::asio::ip::tcp; + +namespace { + +const char serverHost[] = "localhost"; +const unsigned short serverPort = 8081; + +} // namespace + +boost::beast::http::response generateServerResponse( + boost::beast::http::verb requestType + , const std::string & target + , const std::string & contentType + , const std::string & body +) +{ + CarpaccioServer server(8081); + std::thread thread(&CarpaccioServer::start, &server); + std::this_thread::sleep_for(std::chrono::seconds(1)); + + CarpaccioStream stream(serverHost, serverPort); + + // Send the HTTP request to the remote host + stream.write(requestType, target, contentType, body); + + // This buffer is used for reading and must be persisted + beast::flat_buffer buffer; + + // Receive the HTTP response + auto res = stream.read(buffer); + + server.stop(); + + thread.detach(); + + return res; +} + +} // namespace helpers +} // namespace test +} // namespace client +} // namespace extreme_carpaccio diff --git a/clients/cpp/Client/library/tests/sources/helpers/TestServerResponse.hpp b/clients/cpp/Client/library/tests/sources/helpers/TestServerResponse.hpp new file mode 100644 index 00000000..5fc4a156 --- /dev/null +++ b/clients/cpp/Client/library/tests/sources/helpers/TestServerResponse.hpp @@ -0,0 +1,31 @@ + +#ifndef EXTREME_CARPACCIO_CLIENT_TEST_HELERS_TESTSERVERRESPONSE_HPP +#define EXTREME_CARPACCIO_CLIENT_TEST_HELERS_TESTSERVERRESPONSE_HPP + +#include + +#include +#include +#include +#include + +#include + +namespace extreme_carpaccio { +namespace client { +namespace test { +namespace helpers { + +boost::beast::http::response generateServerResponse( + boost::beast::http::verb requestType + , const std::string & target + , const std::string & contentType = "" + , const std::string & body = "" +); + +} // namespace helpers +} // namespace test +} // namespace client +} // namespace extreme_carpaccio + +#endif // EXTREME_CARPACCIO_CLIENT_TEST_HELERS_TESTSERVERRESPONSE_HPP From 86060deaf127ea42f3509136cca3c9dd11ee9eab Mon Sep 17 00:00:00 2001 From: NADIF Antoine Date: Tue, 19 Apr 2022 09:21:10 +0200 Subject: [PATCH 107/125] Homogenize member naming convention. --- .../extreme_carpaccio/client/Client.hpp | 50 ++++++++-------- .../extreme_carpaccio/client/Client.cpp | 58 +++++++++---------- 2 files changed, 54 insertions(+), 54 deletions(-) diff --git a/clients/cpp/Client/library/includes/extreme_carpaccio/client/Client.hpp b/clients/cpp/Client/library/includes/extreme_carpaccio/client/Client.hpp index 56d0a51f..a5b6974d 100644 --- a/clients/cpp/Client/library/includes/extreme_carpaccio/client/Client.hpp +++ b/clients/cpp/Client/library/includes/extreme_carpaccio/client/Client.hpp @@ -16,6 +16,9 @@ namespace client { class http_worker { + using alloc_t = std::allocator; + using request_body_t = boost::beast::http::string_body; + public: http_worker(http_worker const&) = delete; http_worker& operator=(http_worker const&) = delete; @@ -25,49 +28,46 @@ class http_worker void start(); private: - using alloc_t = std::allocator; - //using request_body_t = http::basic_dynamic_body>; - using request_body_t = boost::beast::http::string_body; + void accept(); + + void read_request(); + void process_request(boost::beast::http::request> const& req); + + void send_response(boost::beast::http::status status, std::string const& body); + + void check_deadline(); + + bool handleRequest(boost::beast::http::verb requestType, const std::string & target, const std::string & contentType, const std::string & body); + +private: // The acceptor used to listen for incoming connections. - boost::asio::ip::tcp::acceptor& acceptor_; + boost::asio::ip::tcp::acceptor& m_acceptor; // The path to the root of the document directory. - std::string doc_root_; + std::string m_doc_root; // The socket for the currently connected client. - boost::asio::ip::tcp::socket socket_{ acceptor_.get_executor() }; + boost::asio::ip::tcp::socket m_socket{ m_acceptor.get_executor() }; // The buffer for performing reads - boost::beast::flat_static_buffer<8192> buffer_; + boost::beast::flat_static_buffer<8192> m_buffer; // The allocator used for the fields in the request and reply. - alloc_t alloc_; + alloc_t m_alloc; // The parser for reading the requests - boost::optional> parser_; + boost::optional> m_parser; // The timer putting a time limit on requests. - boost::asio::steady_timer request_deadline_{ - acceptor_.get_executor(), (std::chrono::steady_clock::time_point::max)() }; + boost::asio::steady_timer m_request_deadline{ + m_acceptor.get_executor(), (std::chrono::steady_clock::time_point::max)() }; // The string-based response message. - boost::optional>> string_response_; + boost::optional>> m_string_response; // The file-based response message. - boost::optional>> file_response_; - - void accept(); - - void read_request(); - - void process_request(boost::beast::http::request> const& req); - - void send_response(boost::beast::http::status status, std::string const& body); - - void check_deadline(); - - bool handleRequest(boost::beast::http::verb requestType, const std::string & target, const std::string & contentType, const std::string & body); + boost::optional>> m_file_response; }; class EXTREME_CARPACCIO_CLIENT_API CarpaccioServer diff --git a/clients/cpp/Client/library/sources/extreme_carpaccio/client/Client.cpp b/clients/cpp/Client/library/sources/extreme_carpaccio/client/Client.cpp index f115312a..16b2dcff 100644 --- a/clients/cpp/Client/library/sources/extreme_carpaccio/client/Client.cpp +++ b/clients/cpp/Client/library/sources/extreme_carpaccio/client/Client.cpp @@ -34,8 +34,8 @@ const int version = 11; } // namespace http_worker::http_worker(tcp::acceptor& acceptor, const std::string& doc_root) : - acceptor_(acceptor), - doc_root_(doc_root) + m_acceptor(acceptor), + m_doc_root(doc_root) { } @@ -49,11 +49,11 @@ void http_worker::accept() { // Clean up any previous connection. beast::error_code ec; - socket_.close(ec); - buffer_.consume(buffer_.size()); + m_socket.close(ec); + m_buffer.consume(m_buffer.size()); - acceptor_.async_accept( - socket_, + m_acceptor.async_accept( + m_socket, [this](beast::error_code ec) { if (ec) @@ -63,7 +63,7 @@ void http_worker::accept() else { // Request must be fully processed within 60 seconds. - request_deadline_.expires_after( + m_request_deadline.expires_after( std::chrono::seconds(60)); read_request(); @@ -84,21 +84,21 @@ void http_worker::read_request() // We construct the dynamic body with a 1MB limit // to prevent vulnerability to buffer attacks. // - parser_.emplace( + m_parser.emplace( std::piecewise_construct, std::make_tuple(), - std::make_tuple(alloc_)); + std::make_tuple(m_alloc)); http::async_read( - socket_, - buffer_, - *parser_, + m_socket, + m_buffer, + *m_parser, [this](beast::error_code ec, std::size_t) { if (ec) accept(); else - process_request(parser_->get()); + process_request(m_parser->get()); }); } @@ -160,25 +160,25 @@ void http_worker::process_request(http::requestresult(status); - string_response_->keep_alive(false); - string_response_->set(http::field::server, "Beast"); - string_response_->set(http::field::content_type, "text/plain"); - string_response_->body() = body; - string_response_->prepare_payload(); + m_string_response->result(status); + m_string_response->keep_alive(false); + m_string_response->set(http::field::server, "Beast"); + m_string_response->set(http::field::content_type, "text/plain"); + m_string_response->body() = body; + m_string_response->prepare_payload(); http::async_write( - socket_, - *string_response_, + m_socket, + *m_string_response, [this](beast::error_code ec, std::size_t) { - socket_.shutdown(tcp::socket::shutdown_send, ec); - string_response_.reset(); + m_socket.shutdown(tcp::socket::shutdown_send, ec); + m_string_response.reset(); accept(); }); } @@ -186,17 +186,17 @@ void http_worker::send_response(http::status status, std::string const& body) void http_worker::check_deadline() { // The deadline may have moved, so check it has really passed. - if (request_deadline_.expiry() <= std::chrono::steady_clock::now()) + if (m_request_deadline.expiry() <= std::chrono::steady_clock::now()) { // Close socket to cancel any outstanding operation. - socket_.close(); + m_socket.close(); // Sleep indefinitely until we're given a new deadline. - request_deadline_.expires_at( + m_request_deadline.expires_at( (std::chrono::steady_clock::time_point::max)()); } - request_deadline_.async_wait( + m_request_deadline.async_wait( [this](beast::error_code) { check_deadline(); From 3a3508eda36a6aa52e15a757a50706334d3fb1d2 Mon Sep 17 00:00:00 2001 From: NADIF Antoine Date: Tue, 19 Apr 2022 09:24:46 +0200 Subject: [PATCH 108/125] Initialize members in constructor body. --- .../includes/extreme_carpaccio/client/Client.hpp | 5 ++--- .../sources/extreme_carpaccio/client/Client.cpp | 11 +++++++++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/clients/cpp/Client/library/includes/extreme_carpaccio/client/Client.hpp b/clients/cpp/Client/library/includes/extreme_carpaccio/client/Client.hpp index a5b6974d..0d583108 100644 --- a/clients/cpp/Client/library/includes/extreme_carpaccio/client/Client.hpp +++ b/clients/cpp/Client/library/includes/extreme_carpaccio/client/Client.hpp @@ -48,7 +48,7 @@ class http_worker std::string m_doc_root; // The socket for the currently connected client. - boost::asio::ip::tcp::socket m_socket{ m_acceptor.get_executor() }; + boost::asio::ip::tcp::socket m_socket; // The buffer for performing reads boost::beast::flat_static_buffer<8192> m_buffer; @@ -60,8 +60,7 @@ class http_worker boost::optional> m_parser; // The timer putting a time limit on requests. - boost::asio::steady_timer m_request_deadline{ - m_acceptor.get_executor(), (std::chrono::steady_clock::time_point::max)() }; + boost::asio::steady_timer m_request_deadline; // The string-based response message. boost::optional>> m_string_response; diff --git a/clients/cpp/Client/library/sources/extreme_carpaccio/client/Client.cpp b/clients/cpp/Client/library/sources/extreme_carpaccio/client/Client.cpp index 16b2dcff..4b56e188 100644 --- a/clients/cpp/Client/library/sources/extreme_carpaccio/client/Client.cpp +++ b/clients/cpp/Client/library/sources/extreme_carpaccio/client/Client.cpp @@ -34,8 +34,15 @@ const int version = 11; } // namespace http_worker::http_worker(tcp::acceptor& acceptor, const std::string& doc_root) : - m_acceptor(acceptor), - m_doc_root(doc_root) + m_acceptor(acceptor) + , m_doc_root(doc_root) + , m_socket{ m_acceptor.get_executor() } + , m_buffer() + , m_alloc() + , m_parser() + , m_request_deadline{ m_acceptor.get_executor(), (std::chrono::steady_clock::time_point::max)() } + , m_string_response() + , m_file_response() { } From 793360b38a3e7310a06ef86ce147b79213a623ad Mon Sep 17 00:00:00 2001 From: NADIF Antoine Date: Tue, 19 Apr 2022 09:56:46 +0200 Subject: [PATCH 109/125] Separate the Carpaccio HTTP worker and the Carpaccio server in different files. --- clients/cpp/Client/library/CMakeLists.txt | 2 + .../client/CarpaccioHttpWorker.hpp | 68 ++++++ .../extreme_carpaccio/client/Client.hpp | 58 +---- .../client/CarpaccioHttpWorker.cpp | 215 ++++++++++++++++++ .../extreme_carpaccio/client/Client.cpp | 209 +---------------- 5 files changed, 290 insertions(+), 262 deletions(-) create mode 100644 clients/cpp/Client/library/includes/extreme_carpaccio/client/CarpaccioHttpWorker.hpp create mode 100644 clients/cpp/Client/library/sources/extreme_carpaccio/client/CarpaccioHttpWorker.cpp diff --git a/clients/cpp/Client/library/CMakeLists.txt b/clients/cpp/Client/library/CMakeLists.txt index a5fb0197..afb6144f 100644 --- a/clients/cpp/Client/library/CMakeLists.txt +++ b/clients/cpp/Client/library/CMakeLists.txt @@ -4,11 +4,13 @@ add_library(Client-shared SHARED) target_compile_definitions(Client-shared PRIVATE EXTREME_CARPACCIO_CLIENT_EXPORTS) set(CLIENT_SHARED_PRIVATE_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/sources/extreme_carpaccio/client/CarpaccioHttpWorker.cpp ${CMAKE_CURRENT_SOURCE_DIR}/sources/extreme_carpaccio/client/Client.cpp ${CMAKE_CURRENT_SOURCE_DIR}/sources/extreme_carpaccio/client/HttpConfig.hpp ) set(CLIENT_SHARED_PUBLIC_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/includes/extreme_carpaccio/client/CarpaccioHttpWorker.hpp ${CMAKE_CURRENT_SOURCE_DIR}/includes/extreme_carpaccio/client/Client.hpp ${CMAKE_CURRENT_SOURCE_DIR}/includes/extreme_carpaccio/client/config.hpp ) diff --git a/clients/cpp/Client/library/includes/extreme_carpaccio/client/CarpaccioHttpWorker.hpp b/clients/cpp/Client/library/includes/extreme_carpaccio/client/CarpaccioHttpWorker.hpp new file mode 100644 index 00000000..3dd94714 --- /dev/null +++ b/clients/cpp/Client/library/includes/extreme_carpaccio/client/CarpaccioHttpWorker.hpp @@ -0,0 +1,68 @@ + +#ifndef EXTREME_CARPACCIO_CLIENT_CARPACCIOHTTPWORKER_HPP +#define EXTREME_CARPACCIO_CLIENT_CARPACCIOHTTPWORKER_HPP + +#include +#include +#include +#include + +#include + +namespace extreme_carpaccio { +namespace client { + +class CarpaccioHttpWorker +{ + using alloc_t = std::allocator; + using request_body_t = boost::beast::http::string_body; + +public: + CarpaccioHttpWorker(CarpaccioHttpWorker const&) = delete; + CarpaccioHttpWorker& operator=(CarpaccioHttpWorker const&) = delete; + + CarpaccioHttpWorker(boost::asio::ip::tcp::acceptor& acceptor, const std::string& doc_root); + + void start(); + +private: + void accept(); + void read_request(); + void process_request(boost::beast::http::request> const& req); + void send_response(boost::beast::http::status status, std::string const& body); + void check_deadline(); + bool handleRequest(boost::beast::http::verb requestType, const std::string & target, const std::string & contentType, const std::string & body); + +private: + // The acceptor used to listen for incoming connections. + boost::asio::ip::tcp::acceptor& m_acceptor; + + // The path to the root of the document directory. + std::string m_doc_root; + + // The socket for the currently connected client. + boost::asio::ip::tcp::socket m_socket; + + // The buffer for performing reads + boost::beast::flat_static_buffer<8192> m_buffer; + + // The allocator used for the fields in the request and reply. + alloc_t m_alloc; + + // The parser for reading the requests + boost::optional> m_parser; + + // The timer putting a time limit on requests. + boost::asio::steady_timer m_request_deadline; + + // The string-based response message. + boost::optional>> m_string_response; + + // The file-based response message. + boost::optional>> m_file_response; +}; + +} // namespace client +} // namespace extreme_carpaccio + +#endif // EXTREME_CARPACCIO_CLIENT_CARPACCIOHTTPWORKER_HPP diff --git a/clients/cpp/Client/library/includes/extreme_carpaccio/client/Client.hpp b/clients/cpp/Client/library/includes/extreme_carpaccio/client/Client.hpp index 0d583108..f59a2e0d 100644 --- a/clients/cpp/Client/library/includes/extreme_carpaccio/client/Client.hpp +++ b/clients/cpp/Client/library/includes/extreme_carpaccio/client/Client.hpp @@ -2,6 +2,7 @@ #ifndef EXTREME_CARPACCIO_CLIENT_CLIENT_HPP #define EXTREME_CARPACCIO_CLIENT_CLIENT_HPP +#include #include #include @@ -14,61 +15,6 @@ namespace extreme_carpaccio { namespace client { -class http_worker -{ - using alloc_t = std::allocator; - using request_body_t = boost::beast::http::string_body; - -public: - http_worker(http_worker const&) = delete; - http_worker& operator=(http_worker const&) = delete; - - http_worker(boost::asio::ip::tcp::acceptor& acceptor, const std::string& doc_root); - - void start(); - -private: - void accept(); - - void read_request(); - - void process_request(boost::beast::http::request> const& req); - - void send_response(boost::beast::http::status status, std::string const& body); - - void check_deadline(); - - bool handleRequest(boost::beast::http::verb requestType, const std::string & target, const std::string & contentType, const std::string & body); - -private: - // The acceptor used to listen for incoming connections. - boost::asio::ip::tcp::acceptor& m_acceptor; - - // The path to the root of the document directory. - std::string m_doc_root; - - // The socket for the currently connected client. - boost::asio::ip::tcp::socket m_socket; - - // The buffer for performing reads - boost::beast::flat_static_buffer<8192> m_buffer; - - // The allocator used for the fields in the request and reply. - alloc_t m_alloc; - - // The parser for reading the requests - boost::optional> m_parser; - - // The timer putting a time limit on requests. - boost::asio::steady_timer m_request_deadline; - - // The string-based response message. - boost::optional>> m_string_response; - - // The file-based response message. - boost::optional>> m_file_response; -}; - class EXTREME_CARPACCIO_CLIENT_API CarpaccioServer { public: @@ -80,7 +26,7 @@ class EXTREME_CARPACCIO_CLIENT_API CarpaccioServer private: boost::asio::io_context ioc; boost::asio::ip::tcp::acceptor acceptor; - http_worker worker; + CarpaccioHttpWorker worker; }; } // namespace client diff --git a/clients/cpp/Client/library/sources/extreme_carpaccio/client/CarpaccioHttpWorker.cpp b/clients/cpp/Client/library/sources/extreme_carpaccio/client/CarpaccioHttpWorker.cpp new file mode 100644 index 00000000..12ef53b0 --- /dev/null +++ b/clients/cpp/Client/library/sources/extreme_carpaccio/client/CarpaccioHttpWorker.cpp @@ -0,0 +1,215 @@ + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace extreme_carpaccio { +namespace client { + +namespace beast = boost::beast; +namespace http = beast::http; +namespace net = boost::asio; +using tcp = boost::asio::ip::tcp; + +namespace { + +const int version = 11; + +struct Feedback +{ + std::string type; + std::string content; +}; + +static Feedback parseFeedback(const std::string& jsonFeedback) +{ + auto parsedFeedback = nlohmann::json::parse(jsonFeedback); + Feedback feedback = {}; + + feedback.type = parsedFeedback["type"].get(); + feedback.content = parsedFeedback["content"].get(); + return feedback; +} + +} // namespace + +CarpaccioHttpWorker::CarpaccioHttpWorker(tcp::acceptor& acceptor, const std::string& doc_root) : + m_acceptor(acceptor) + , m_doc_root(doc_root) + , m_socket{ m_acceptor.get_executor() } + , m_buffer() + , m_alloc() + , m_parser() + , m_request_deadline{ m_acceptor.get_executor(), (std::chrono::steady_clock::time_point::max)() } + , m_string_response() + , m_file_response() +{ +} + +void CarpaccioHttpWorker::start() +{ + accept(); + check_deadline(); +} + +void CarpaccioHttpWorker::accept() +{ + // Clean up any previous connection. + beast::error_code ec; + m_socket.close(ec); + m_buffer.consume(m_buffer.size()); + + m_acceptor.async_accept( + m_socket, + [this](beast::error_code ec) + { + if (ec) + { + accept(); + } + else + { + // Request must be fully processed within 60 seconds. + m_request_deadline.expires_after( + std::chrono::seconds(60)); + + read_request(); + } + }); +} + +void CarpaccioHttpWorker::read_request() +{ + // On each read the parser needs to be destroyed and + // recreated. We store it in a boost::optional to + // achieve that. + // + // Arguments passed to the parser constructor are + // forwarded to the message object. A single argument + // is forwarded to the body constructor. + // + // We construct the dynamic body with a 1MB limit + // to prevent vulnerability to buffer attacks. + // + m_parser.emplace( + std::piecewise_construct, + std::make_tuple(), + std::make_tuple(m_alloc)); + + http::async_read( + m_socket, + m_buffer, + *m_parser, + [this](beast::error_code ec, std::size_t) + { + if (ec) + accept(); + else + process_request(m_parser->get()); + }); +} + +bool CarpaccioHttpWorker::handleRequest(http::verb requestType, const std::string & target, const std::string & contentType, const std::string & body) +{ + const bool error = (requestType != http::verb::post || contentType != "application/json"); + + if (!error) + { + if (target == "/order") + { + auto order = order_management::parseOrder(body); + std::cout << "Order received: " << order << std::endl; + + auto totalAmountResponse = order_management::computeTotalAmount(body); + + nlohmann::json totalAmountJson; + + totalAmountJson["total"] = totalAmountResponse.m_totalAmount; + send_response(totalAmountResponse.m_status, totalAmountJson.dump()); + } + else if (target == "/feedback") + { + Feedback feedback = parseFeedback(body); + + std::cout << feedback.type << " : " << feedback.content << std::endl; + send_response(http::status::ok, "Feedback received"); + } + } + return error; +} + +void CarpaccioHttpWorker::process_request(http::request> const& req) +{ + const std::string contentType = req[http::field::content_type].to_string(); + const std::string body = req.body(); + + if (this->handleRequest(req.method(), req.target().to_string(), contentType, body)) + { + this->send_response(http::status::not_found, "HTTP code 404\r\n"); + } +} + +void CarpaccioHttpWorker::send_response(http::status status, std::string const& body) +{ + m_string_response.emplace( + std::piecewise_construct, + std::make_tuple(), + std::make_tuple(m_alloc)); + + m_string_response->result(status); + m_string_response->keep_alive(false); + m_string_response->set(http::field::server, "Beast"); + m_string_response->set(http::field::content_type, "text/plain"); + m_string_response->body() = body; + m_string_response->prepare_payload(); + + http::async_write( + m_socket, + *m_string_response, + [this](beast::error_code ec, std::size_t) + { + m_socket.shutdown(tcp::socket::shutdown_send, ec); + m_string_response.reset(); + accept(); + }); +} + +void CarpaccioHttpWorker::check_deadline() +{ + // The deadline may have moved, so check it has really passed. + if (m_request_deadline.expiry() <= std::chrono::steady_clock::now()) + { + // Close socket to cancel any outstanding operation. + m_socket.close(); + + // Sleep indefinitely until we're given a new deadline. + m_request_deadline.expires_at( + (std::chrono::steady_clock::time_point::max)()); + } + + m_request_deadline.async_wait( + [this](beast::error_code) + { + check_deadline(); + }); +} + +} // namespace client +} // namespace extreme_carpaccio diff --git a/clients/cpp/Client/library/sources/extreme_carpaccio/client/Client.cpp b/clients/cpp/Client/library/sources/extreme_carpaccio/client/Client.cpp index 4b56e188..298a23bc 100644 --- a/clients/cpp/Client/library/sources/extreme_carpaccio/client/Client.cpp +++ b/clients/cpp/Client/library/sources/extreme_carpaccio/client/Client.cpp @@ -1,215 +1,12 @@ + #include #include -#include -#include -#include - #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - namespace extreme_carpaccio { namespace client { -namespace beast = boost::beast; -namespace http = beast::http; -namespace net = boost::asio; -using tcp = boost::asio::ip::tcp; - -namespace { - -const int version = 11; - -} // namespace - -http_worker::http_worker(tcp::acceptor& acceptor, const std::string& doc_root) : - m_acceptor(acceptor) - , m_doc_root(doc_root) - , m_socket{ m_acceptor.get_executor() } - , m_buffer() - , m_alloc() - , m_parser() - , m_request_deadline{ m_acceptor.get_executor(), (std::chrono::steady_clock::time_point::max)() } - , m_string_response() - , m_file_response() -{ -} - -void http_worker::start() -{ - accept(); - check_deadline(); -} - -void http_worker::accept() -{ - // Clean up any previous connection. - beast::error_code ec; - m_socket.close(ec); - m_buffer.consume(m_buffer.size()); - - m_acceptor.async_accept( - m_socket, - [this](beast::error_code ec) - { - if (ec) - { - accept(); - } - else - { - // Request must be fully processed within 60 seconds. - m_request_deadline.expires_after( - std::chrono::seconds(60)); - - read_request(); - } - }); -} - -void http_worker::read_request() -{ - // On each read the parser needs to be destroyed and - // recreated. We store it in a boost::optional to - // achieve that. - // - // Arguments passed to the parser constructor are - // forwarded to the message object. A single argument - // is forwarded to the body constructor. - // - // We construct the dynamic body with a 1MB limit - // to prevent vulnerability to buffer attacks. - // - m_parser.emplace( - std::piecewise_construct, - std::make_tuple(), - std::make_tuple(m_alloc)); - - http::async_read( - m_socket, - m_buffer, - *m_parser, - [this](beast::error_code ec, std::size_t) - { - if (ec) - accept(); - else - process_request(m_parser->get()); - }); -} - -struct Feedback -{ - std::string type; - std::string content; -}; - -static Feedback parseFeedback(const std::string& jsonFeedback) -{ - auto parsedFeedback = nlohmann::json::parse(jsonFeedback); - Feedback feedback = {}; - - feedback.type = parsedFeedback["type"].get(); - feedback.content = parsedFeedback["content"].get(); - return feedback; -} - -bool http_worker::handleRequest(http::verb requestType, const std::string & target, const std::string & contentType, const std::string & body) -{ - const bool error = (requestType != http::verb::post || contentType != "application/json"); - - if (!error) - { - if (target == "/order") - { - auto order = order_management::parseOrder(body); - std::cout << "Order received: " << order << std::endl; - - auto totalAmountResponse = order_management::computeTotalAmount(body); - - nlohmann::json totalAmountJson; - - totalAmountJson["total"] = totalAmountResponse.m_totalAmount; - send_response(totalAmountResponse.m_status, totalAmountJson.dump()); - } - else if (target == "/feedback") - { - Feedback feedback = parseFeedback(body); - - std::cout << feedback.type << " : " << feedback.content << std::endl; - send_response(http::status::ok, "Feedback received"); - } - } - return error; -} - -void http_worker::process_request(http::request> const& req) -{ - const std::string contentType = req[http::field::content_type].to_string(); - const std::string body = req.body(); - - if (this->handleRequest(req.method(), req.target().to_string(), contentType, body)) - { - this->send_response(http::status::not_found, "HTTP code 404\r\n"); - } -} - -void http_worker::send_response(http::status status, std::string const& body) -{ - m_string_response.emplace( - std::piecewise_construct, - std::make_tuple(), - std::make_tuple(m_alloc)); - - m_string_response->result(status); - m_string_response->keep_alive(false); - m_string_response->set(http::field::server, "Beast"); - m_string_response->set(http::field::content_type, "text/plain"); - m_string_response->body() = body; - m_string_response->prepare_payload(); - - http::async_write( - m_socket, - *m_string_response, - [this](beast::error_code ec, std::size_t) - { - m_socket.shutdown(tcp::socket::shutdown_send, ec); - m_string_response.reset(); - accept(); - }); -} - -void http_worker::check_deadline() -{ - // The deadline may have moved, so check it has really passed. - if (m_request_deadline.expiry() <= std::chrono::steady_clock::now()) - { - // Close socket to cancel any outstanding operation. - m_socket.close(); - - // Sleep indefinitely until we're given a new deadline. - m_request_deadline.expires_at( - (std::chrono::steady_clock::time_point::max)()); - } - - m_request_deadline.async_wait( - [this](beast::error_code) - { - check_deadline(); - }); -} - CarpaccioServer::CarpaccioServer() : CarpaccioServer(HTTP_SERVER_PORT) { @@ -217,8 +14,8 @@ CarpaccioServer::CarpaccioServer() : CarpaccioServer(HTTP_SERVER_PORT) CarpaccioServer::CarpaccioServer(unsigned short port) : ioc(1) - , acceptor(ioc, {boost::asio::ip::make_address(HTTP_SERVER_IP), port } ), - worker(acceptor, "./feedback") + , acceptor(ioc, { boost::asio::ip::make_address(HTTP_SERVER_IP), port }) + , worker(acceptor, "./feedback") { } From 9a60c1cd1e365011d5c48613385f713a9c58de5a Mon Sep 17 00:00:00 2001 From: NADIF Antoine Date: Tue, 19 Apr 2022 14:43:52 +0200 Subject: [PATCH 110/125] Clean-up .gitignore: the purpose of the out--of-source build tree is to be able to ignore the build directory entirely and not have to ignore tooling specific folders and extensions. --- clients/cpp/.gitignore | 708 ----------------------------------------- 1 file changed, 708 deletions(-) diff --git a/clients/cpp/.gitignore b/clients/cpp/.gitignore index 55846b24..567609b1 100644 --- a/clients/cpp/.gitignore +++ b/clients/cpp/.gitignore @@ -1,709 +1 @@ - -# --------------------------------------------------------- -# Specific adjutments -# --------------------------------------------------------- - -# Intellij - ignore entirely .idea folder -**/.idea/** - -# ApprovalTests - generated golden master files -GoldenMasterTest.*.txt -*.txt.bak - -# --------------------------------------------------------- -# End of specific adjutments -# --------------------------------------------------------- - - -# Created by https://www.toptal.com/developers/gitignore/api/java,maven,eclipse,intellij,visualstudio,gradle,cmake,visualstudiocode,code-java,clion,diff -# Edit at https://www.toptal.com/developers/gitignore?templates=java,maven,eclipse,intellij,visualstudio,gradle,cmake,visualstudiocode,code-java,clion,diff - -### CLion ### -# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider -# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 - -# User-specific stuff -.idea/**/workspace.xml -.idea/**/tasks.xml -.idea/**/usage.statistics.xml -.idea/**/dictionaries -.idea/**/shelf - -# Generated files -.idea/**/contentModel.xml - -# Sensitive or high-churn files -.idea/**/dataSources/ -.idea/**/dataSources.ids -.idea/**/dataSources.local.xml -.idea/**/sqlDataSources.xml -.idea/**/dynamic.xml -.idea/**/uiDesigner.xml -.idea/**/dbnavigator.xml - -# Gradle -.idea/**/gradle.xml -.idea/**/libraries - -# Gradle and Maven with auto-import -# When using Gradle or Maven with auto-import, you should exclude module files, -# since they will be recreated, and may cause churn. Uncomment if using -# auto-import. -.idea/artifacts -.idea/compiler.xml -.idea/jarRepositories.xml -.idea/modules.xml -.idea/*.iml -.idea/modules -*.iml -*.ipr - -# CMake -cmake-build-*/ - -# Mongo Explorer plugin -.idea/**/mongoSettings.xml - -# File-based project format -*.iws - -# IntelliJ -out/ - -# mpeltonen/sbt-idea plugin -.idea_modules/ - -# JIRA plugin -atlassian-ide-plugin.xml - -# Cursive Clojure plugin -.idea/replstate.xml - -# Crashlytics plugin (for Android Studio and IntelliJ) -com_crashlytics_export_strings.xml -crashlytics.properties -crashlytics-build.properties -fabric.properties - -# Editor-based Rest Client -.idea/httpRequests - -# Android studio 3.1+ serialized cache file -.idea/caches/build_file_checksums.ser - -### CLion Patch ### -# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 - -# *.iml -# modules.xml -# .idea/misc.xml -# *.ipr - -# Sonarlint plugin -# https://plugins.jetbrains.com/plugin/7973-sonarlint -.idea/**/sonarlint/ - -# SonarQube Plugin -# https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin -.idea/**/sonarIssues.xml - -# Markdown Navigator plugin -# https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced -.idea/**/markdown-navigator.xml -.idea/**/markdown-navigator-enh.xml -.idea/**/markdown-navigator/ - -# Cache file creation bug -# See https://youtrack.jetbrains.com/issue/JBR-2257 -.idea/$CACHE_FILE$ - -# CodeStream plugin -# https://plugins.jetbrains.com/plugin/12206-codestream -.idea/codestream.xml - -### CMake ### -CMakeLists.txt.user -CMakeCache.txt -CMakeFiles -CMakeScripts -Testing -Makefile -cmake_install.cmake -install_manifest.txt -compile_commands.json -CTestTestfile.cmake -_deps - -### CMake Patch ### -# External projects -*-prefix/ - -### Code-Java ### -# Language Support for Java(TM) by Red Hat extension for Visual Studio Code - https://marketplace.visualstudio.com/items?itemName=redhat.java - -.project -.classpath -factoryConfiguration.json - -### Diff ### -*.patch -*.diff - -### Eclipse ### -.metadata -bin/ -tmp/ -*.tmp -*.bak -*.swp -*~.nib -local.properties -.settings/ -.loadpath -.recommenders - -# External tool builders -.externalToolBuilders/ - -# Locally stored "Eclipse launch configurations" -*.launch - -# PyDev specific (Python IDE for Eclipse) -*.pydevproject - -# CDT-specific (C/C++ Development Tooling) -.cproject - -# CDT- autotools -.autotools - -# Java annotation processor (APT) -.factorypath - -# PDT-specific (PHP Development Tools) -.buildpath - -# sbteclipse plugin -.target - -# Tern plugin -.tern-project - -# TeXlipse plugin -.texlipse - -# STS (Spring Tool Suite) -.springBeans - -# Code Recommenders -.recommenders/ - -# Annotation Processing -.apt_generated/ -.apt_generated_test/ - -# Scala IDE specific (Scala & Java development for Eclipse) -.cache-main -.scala_dependencies -.worksheet - -# Uncomment this line if you wish to ignore the project description file. -# Typically, this file would be tracked if it contains build/dependency configurations: -#.project - -### Eclipse Patch ### -# Spring Boot Tooling -.sts4-cache/ - -### Intellij ### -# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider -# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 - -# User-specific stuff - -# Generated files - -# Sensitive or high-churn files - -# Gradle - -# Gradle and Maven with auto-import -# When using Gradle or Maven with auto-import, you should exclude module files, -# since they will be recreated, and may cause churn. Uncomment if using -# auto-import. -# .idea/artifacts -# .idea/compiler.xml -# .idea/jarRepositories.xml -# .idea/modules.xml -# .idea/*.iml -# .idea/modules -# *.iml -# *.ipr - -# CMake - -# Mongo Explorer plugin - -# File-based project format - -# IntelliJ - -# mpeltonen/sbt-idea plugin - -# JIRA plugin - -# Cursive Clojure plugin - -# Crashlytics plugin (for Android Studio and IntelliJ) - -# Editor-based Rest Client - -# Android studio 3.1+ serialized cache file - -### Intellij Patch ### -# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 - -# *.iml -# modules.xml -# .idea/misc.xml -# *.ipr - -# Sonarlint plugin -# https://plugins.jetbrains.com/plugin/7973-sonarlint - -# SonarQube Plugin -# https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin - -# Markdown Navigator plugin -# https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced - -# Cache file creation bug -# See https://youtrack.jetbrains.com/issue/JBR-2257 - -# CodeStream plugin -# https://plugins.jetbrains.com/plugin/12206-codestream - -### Java ### -# Compiled class file -*.class - -# Log file -*.log - -# BlueJ files -*.ctxt - -# Mobile Tools for Java (J2ME) -.mtj.tmp/ - -# Package Files # -*.jar -*.war -*.nar -*.ear -*.zip -*.tar.gz -*.rar - -# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml -hs_err_pid* - -### Maven ### -target/ -pom.xml.tag -pom.xml.releaseBackup -pom.xml.versionsBackup -pom.xml.next -release.properties -dependency-reduced-pom.xml -buildNumber.properties -.mvn/timing.properties -# https://github.com/takari/maven-wrapper#usage-without-binary-jar -.mvn/wrapper/maven-wrapper.jar - -### VisualStudioCode ### -.vscode/* -!.vscode/tasks.json -!.vscode/launch.json -*.code-workspace - -### VisualStudioCode Patch ### -# Ignore all local history of files -.history -.ionide - -### Gradle ### -.gradle build/ - -# Ignore Gradle GUI config -gradle-app.setting - -# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) -!gradle-wrapper.jar - -# Cache of project -.gradletasknamecache - -# # Work around https://youtrack.jetbrains.com/issue/IDEA-116898 -# gradle/wrapper/gradle-wrapper.properties - -### Gradle Patch ### -**/build/ - -### VisualStudio ### -## Ignore Visual Studio temporary files, build results, and -## files generated by popular Visual Studio add-ons. -## -## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore - -# User-specific files -*.rsuser -*.suo -*.user -*.userosscache -*.sln.docstates - -# User-specific files (MonoDevelop/Xamarin Studio) -*.userprefs - -# Mono auto generated files -mono_crash.* - -# Build results -[Dd]ebug/ -[Dd]ebugPublic/ -[Rr]elease/ -[Rr]eleases/ -x64/ -x86/ -[Aa][Rr][Mm]/ -[Aa][Rr][Mm]64/ -bld/ -[Bb]in/ -[Oo]bj/ -[Ll]og/ -[Ll]ogs/ - -# Visual Studio 2015/2017 cache/options directory -.vs/ -# Uncomment if you have tasks that create the project's static files in wwwroot -#wwwroot/ - -# Visual Studio 2017 auto generated files -Generated\ Files/ - -# MSTest test Results -[Tt]est[Rr]esult*/ -[Bb]uild[Ll]og.* - -# NUnit -*.VisualState.xml -TestResult.xml -nunit-*.xml - -# Build Results of an ATL Project -[Dd]ebugPS/ -[Rr]eleasePS/ -dlldata.c - -# Benchmark Results -BenchmarkDotNet.Artifacts/ - -# .NET Core -project.lock.json -project.fragment.lock.json -artifacts/ - -# StyleCop -StyleCopReport.xml - -# Files built by Visual Studio -*_i.c -*_p.c -*_h.h -*.ilk -*.meta -*.obj -*.iobj -*.pch -*.pdb -*.ipdb -*.pgc -*.pgd -*.rsp -*.sbr -*.tlb -*.tli -*.tlh -*.tmp_proj -*_wpftmp.csproj -*.vspscc -*.vssscc -.builds -*.pidb -*.svclog -*.scc - -# Chutzpah Test files -_Chutzpah* - -# Visual C++ cache files -ipch/ -*.aps -*.ncb -*.opendb -*.opensdf -*.sdf -*.cachefile -*.VC.db -*.VC.VC.opendb - -# Visual Studio profiler -*.psess -*.vsp -*.vspx -*.sap - -# Visual Studio Trace Files -*.e2e - -# TFS 2012 Local Workspace -$tf/ - -# Guidance Automation Toolkit -*.gpState - -# ReSharper is a .NET coding add-in -_ReSharper*/ -*.[Rr]e[Ss]harper -*.DotSettings.user - -# TeamCity is a build add-in -_TeamCity* - -# DotCover is a Code Coverage Tool -*.dotCover - -# AxoCover is a Code Coverage Tool -.axoCover/* -!.axoCover/settings.json - -# Coverlet is a free, cross platform Code Coverage Tool -coverage*[.json, .xml, .info] - -# Visual Studio code coverage results -*.coverage -*.coveragexml - -# NCrunch -_NCrunch_* -.*crunch*.local.xml -nCrunchTemp_* - -# MightyMoose -*.mm.* -AutoTest.Net/ - -# Web workbench (sass) -.sass-cache/ - -# Installshield output folder -[Ee]xpress/ - -# DocProject is a documentation generator add-in -DocProject/buildhelp/ -DocProject/Help/*.HxT -DocProject/Help/*.HxC -DocProject/Help/*.hhc -DocProject/Help/*.hhk -DocProject/Help/*.hhp -DocProject/Help/Html2 -DocProject/Help/html - -# Click-Once directory -publish/ - -# Publish Web Output -*.[Pp]ublish.xml -*.azurePubxml -# Note: Comment the next line if you want to checkin your web deploy settings, -# but database connection strings (with potential passwords) will be unencrypted -*.pubxml -*.publishproj - -# Microsoft Azure Web App publish settings. Comment the next line if you want to -# checkin your Azure Web App publish settings, but sensitive information contained -# in these scripts will be unencrypted -PublishScripts/ - -# NuGet Packages -*.nupkg -# NuGet Symbol Packages -*.snupkg -# The packages folder can be ignored because of Package Restore -**/[Pp]ackages/* -# except build/, which is used as an MSBuild target. -!**/[Pp]ackages/build/ -# Uncomment if necessary however generally it will be regenerated when needed -#!**/[Pp]ackages/repositories.config -# NuGet v3's project.json files produces more ignorable files -*.nuget.props -*.nuget.targets - -# Microsoft Azure Build Output -csx/ -*.build.csdef - -# Microsoft Azure Emulator -ecf/ -rcf/ - -# Windows Store app package directories and files -AppPackages/ -BundleArtifacts/ -Package.StoreAssociation.xml -_pkginfo.txt -*.appx -*.appxbundle -*.appxupload - -# Visual Studio cache files -# files ending in .cache can be ignored -*.[Cc]ache -# but keep track of directories ending in .cache -!?*.[Cc]ache/ - -# Others -ClientBin/ -~$* -*~ -*.dbmdl -*.dbproj.schemaview -*.jfm -*.pfx -*.publishsettings -orleans.codegen.cs - -# Including strong name files can present a security risk -# (https://github.com/github/gitignore/pull/2483#issue-259490424) -#*.snk - -# Since there are multiple workflows, uncomment next line to ignore bower_components -# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) -#bower_components/ - -# RIA/Silverlight projects -Generated_Code/ - -# Backup & report files from converting an old project file -# to a newer Visual Studio version. Backup files are not needed, -# because we have git ;-) -_UpgradeReport_Files/ -Backup*/ -UpgradeLog*.XML -UpgradeLog*.htm -ServiceFabricBackup/ -*.rptproj.bak - -# SQL Server files -*.mdf -*.ldf -*.ndf - -# Business Intelligence projects -*.rdl.data -*.bim.layout -*.bim_*.settings -*.rptproj.rsuser -*- [Bb]ackup.rdl -*- [Bb]ackup ([0-9]).rdl -*- [Bb]ackup ([0-9][0-9]).rdl - -# Microsoft Fakes -FakesAssemblies/ - -# GhostDoc plugin setting file -*.GhostDoc.xml - -# Node.js Tools for Visual Studio -.ntvs_analysis.dat -node_modules/ - -# Visual Studio 6 build log -*.plg - -# Visual Studio 6 workspace options file -*.opt - -# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) -*.vbw - -# Visual Studio LightSwitch build output -**/*.HTMLClient/GeneratedArtifacts -**/*.DesktopClient/GeneratedArtifacts -**/*.DesktopClient/ModelManifest.xml -**/*.Server/GeneratedArtifacts -**/*.Server/ModelManifest.xml -_Pvt_Extensions - -# Paket dependency manager -.paket/paket.exe -paket-files/ - -# FAKE - F# Make -.fake/ - -# CodeRush personal settings -.cr/personal - -# Python Tools for Visual Studio (PTVS) -__pycache__/ -*.pyc - -# Cake - Uncomment if you are using it -# tools/** -# !tools/packages.config - -# Tabs Studio -*.tss - -# Telerik's JustMock configuration file -*.jmconfig - -# BizTalk build output -*.btp.cs -*.btm.cs -*.odx.cs -*.xsd.cs - -# OpenCover UI analysis results -OpenCover/ - -# Azure Stream Analytics local run output -ASALocalRun/ - -# MSBuild Binary and Structured Log -*.binlog - -# NVidia Nsight GPU debugger configuration file -*.nvuser - -# MFractors (Xamarin productivity tool) working folder -.mfractor/ - -# Local History for Visual Studio -.localhistory/ - -# BeatPulse healthcheck temp database -healthchecksdb - -# Backup folder for Package Reference Convert tool in Visual Studio 2017 -MigrationBackup/ - -# Ionide (cross platform F# VS Code tools) working folder -.ionide/ - -# End of https://www.toptal.com/developers/gitignore/api/java,maven,eclipse,intellij,visualstudio,gradle,cmake,visualstudiocode,code-java,clion,diff - - From 88ea4e172aa62543d2a75f2c87ec00cc0875d009 Mon Sep 17 00:00:00 2001 From: NADIF Antoine Date: Thu, 21 Apr 2022 11:40:29 +0200 Subject: [PATCH 111/125] Update TODO list. --- clients/cpp/TODOLIST.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/clients/cpp/TODOLIST.md b/clients/cpp/TODOLIST.md index 2acb5023..0d56f3eb 100644 --- a/clients/cpp/TODOLIST.md +++ b/clients/cpp/TODOLIST.md @@ -26,24 +26,24 @@ - [X] write a test to POST /feedback with a proper request - [X] implement POST /feedback - [X] test our client can receive feedback form the real extreme carpaccio server -- [ ] Add a configuration file for main options (ports and maybe others) - - [ ] check the js client to see what options are available +- [X] Add a configuration file for main options (ports and maybe others) + - [X] check the js client to see what options are available - [ ] create a config file of command line options to set these options - [ ] Feedbacks from the session on extreme carpaccio with C++ client - [x] Display the order description in the code handling the order to have it in the console - [X] We need to initialize the http server with the hostname of the user launching it - [X] We need a specific test target for functional tests - - [ ] Add guards in header files - - [ ] Finish target restructuring - - [ ] Copying dll and binary to another directory was not easy + - [X Add guards in header files + - [X] Finish target restructuring + - [ ] [This can be addressed using CMake install] Copying dll and binary to another directory was not easy - [X] Move in a dedicated file the request handling part of the client code -- [ ] Use the computeTotalAmount in the client -- [ ] Find a way to test code while the client is running (copy dll, use a static library, edit and continue ???) +- [X] Use the computeTotalAmount in the client +- [ ] [This can be addressed using CMake install] Find a way to test code while the client is running (copy dll, use a static library, edit and continue ???) - [ ] Use a different port number for tests ## PARKING -- [ ] Clean gitignore file in cpp -- [ ] Ajouter dans le cmake le Json en thirdparty pour la solution VS +- [X] Clean gitignore file in cpp + - [X] [Cannot be done, header only library] Ajouter dans le cmake le Json en thirdparty pour la solution VS - [ ] Add dependencies on sub boost headers only libraries (beast), instead on depending on full boost - [ ] Fix that : Failed to find all ICU components (missing: ICU_INCLUDE_DIR _ICU_REQUIRED_LIBS_FOUND) - [ ] Upgrade nlohman json version -- [ ] Tests crashed when Mirna launched them on their machine \ No newline at end of file +- [ ] Tests can crash randomly with a low frequency (this could be reproduced in Github Actions) From 1c3588f807d63e308f7a548c4bfdb0014fefdcfe Mon Sep 17 00:00:00 2001 From: NADIF Antoine Date: Thu, 21 Apr 2022 16:38:28 +0200 Subject: [PATCH 112/125] Use CMake install mechanism to insall targets in a dedicated folder to allow production and development to run at the same time. --- clients/cpp/.gitignore | 1 + clients/cpp/CMakeLists.txt | 2 ++ clients/cpp/Client/executable/CMakeLists.txt | 5 ++++- clients/cpp/Client/executable/sources/main.cpp | 3 +++ clients/cpp/Client/library/CMakeLists.txt | 2 ++ .../library/includes/extreme_carpaccio/client/Client.hpp | 2 +- .../library/sources/extreme_carpaccio/client/Client.cpp | 6 +++--- clients/cpp/Client/library/tests/CMakeLists.txt | 2 ++ clients/cpp/OrderManagement/CMakeLists.txt | 2 ++ clients/cpp/OrderManagement/tests/CMakeLists.txt | 2 ++ clients/cpp/TODOLIST.md | 6 +++--- 11 files changed, 25 insertions(+), 8 deletions(-) diff --git a/clients/cpp/.gitignore b/clients/cpp/.gitignore index 567609b1..f3962a15 100644 --- a/clients/cpp/.gitignore +++ b/clients/cpp/.gitignore @@ -1 +1,2 @@ build/ +install/ \ No newline at end of file diff --git a/clients/cpp/CMakeLists.txt b/clients/cpp/CMakeLists.txt index 08b261b2..d6735e4b 100644 --- a/clients/cpp/CMakeLists.txt +++ b/clients/cpp/CMakeLists.txt @@ -1,5 +1,7 @@ cmake_minimum_required(VERSION 3.19.3) +set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/../install CACHE PATH "Where the targets are installed by CMake.") + project(Extreme-Carpaccio CXX) set(CMAKE_CXX_STANDARD 14) diff --git a/clients/cpp/Client/executable/CMakeLists.txt b/clients/cpp/Client/executable/CMakeLists.txt index fedaef10..c69b6ac2 100644 --- a/clients/cpp/Client/executable/CMakeLists.txt +++ b/clients/cpp/Client/executable/CMakeLists.txt @@ -18,6 +18,9 @@ source_group( target_link_libraries(Client-exe PRIVATE - Client-shared) + Client-shared +) + +install(TARGETS Client-exe) set_property(TARGET Client-exe PROPERTY FOLDER "Client") diff --git a/clients/cpp/Client/executable/sources/main.cpp b/clients/cpp/Client/executable/sources/main.cpp index 8084f741..939382fb 100644 --- a/clients/cpp/Client/executable/sources/main.cpp +++ b/clients/cpp/Client/executable/sources/main.cpp @@ -2,11 +2,14 @@ #include #include +#include int main() { + std::cout << "Extreme Carpaccio server starting." << std::endl; extreme_carpaccio::client::CarpaccioServer server; server.start(); + std::cout << "Extreme Carpaccio server stopping." << std::endl; return EXIT_SUCCESS; } diff --git a/clients/cpp/Client/library/CMakeLists.txt b/clients/cpp/Client/library/CMakeLists.txt index afb6144f..fb53f2b7 100644 --- a/clients/cpp/Client/library/CMakeLists.txt +++ b/clients/cpp/Client/library/CMakeLists.txt @@ -45,6 +45,8 @@ target_link_libraries(Client-shared Order-Management-shared ) +install(TARGETS Client-shared) + set_property(TARGET Client-shared PROPERTY FOLDER "Client") add_subdirectory(tests) diff --git a/clients/cpp/Client/library/includes/extreme_carpaccio/client/Client.hpp b/clients/cpp/Client/library/includes/extreme_carpaccio/client/Client.hpp index f59a2e0d..2e3c7973 100644 --- a/clients/cpp/Client/library/includes/extreme_carpaccio/client/Client.hpp +++ b/clients/cpp/Client/library/includes/extreme_carpaccio/client/Client.hpp @@ -18,8 +18,8 @@ namespace client { class EXTREME_CARPACCIO_CLIENT_API CarpaccioServer { public: - CarpaccioServer(unsigned short port); CarpaccioServer(); + CarpaccioServer(unsigned short port); void start(); void stop(); diff --git a/clients/cpp/Client/library/sources/extreme_carpaccio/client/Client.cpp b/clients/cpp/Client/library/sources/extreme_carpaccio/client/Client.cpp index 298a23bc..9a9fbc15 100644 --- a/clients/cpp/Client/library/sources/extreme_carpaccio/client/Client.cpp +++ b/clients/cpp/Client/library/sources/extreme_carpaccio/client/Client.cpp @@ -7,9 +7,10 @@ namespace extreme_carpaccio { namespace client { -CarpaccioServer::CarpaccioServer() : CarpaccioServer(HTTP_SERVER_PORT) +CarpaccioServer::CarpaccioServer() + : CarpaccioServer(HTTP_SERVER_PORT) { - + } CarpaccioServer::CarpaccioServer(unsigned short port) @@ -17,7 +18,6 @@ CarpaccioServer::CarpaccioServer(unsigned short port) , acceptor(ioc, { boost::asio::ip::make_address(HTTP_SERVER_IP), port }) , worker(acceptor, "./feedback") { - } void CarpaccioServer::start() diff --git a/clients/cpp/Client/library/tests/CMakeLists.txt b/clients/cpp/Client/library/tests/CMakeLists.txt index b327edf6..8ec145a8 100644 --- a/clients/cpp/Client/library/tests/CMakeLists.txt +++ b/clients/cpp/Client/library/tests/CMakeLists.txt @@ -33,6 +33,8 @@ target_link_libraries(Client-tests nlohmann_json ) +install(TARGETS Client-tests) + add_test(NAME ctest-Extreme-Carpaccio-Client-tests COMMAND Client-tests) set_property(TARGET Client-tests PROPERTY FOLDER "Client") diff --git a/clients/cpp/OrderManagement/CMakeLists.txt b/clients/cpp/OrderManagement/CMakeLists.txt index 0b5d6287..5fd81869 100644 --- a/clients/cpp/OrderManagement/CMakeLists.txt +++ b/clients/cpp/OrderManagement/CMakeLists.txt @@ -40,6 +40,8 @@ target_include_directories(Order-Management-shared target_link_libraries(Order-Management-shared PUBLIC Boost::boost PRIVATE nlohmann_json) +install(TARGETS Order-Management-shared) + set_property(TARGET Order-Management-shared PROPERTY FOLDER "Order Management") add_subdirectory(tests) \ No newline at end of file diff --git a/clients/cpp/OrderManagement/tests/CMakeLists.txt b/clients/cpp/OrderManagement/tests/CMakeLists.txt index ac45bd2a..2dc8246a 100644 --- a/clients/cpp/OrderManagement/tests/CMakeLists.txt +++ b/clients/cpp/OrderManagement/tests/CMakeLists.txt @@ -26,6 +26,8 @@ target_link_libraries(Order-Management-tests Order-Management-shared gmock_main) +install(TARGETS Order-Management-tests) + add_test(NAME ctest-Extreme-Carpaccio-Order-Management-tests COMMAND Order-Management-tests) set_property(TARGET Order-Management-tests PROPERTY FOLDER "Order Management") diff --git a/clients/cpp/TODOLIST.md b/clients/cpp/TODOLIST.md index 0d56f3eb..0a0ad9a5 100644 --- a/clients/cpp/TODOLIST.md +++ b/clients/cpp/TODOLIST.md @@ -35,10 +35,10 @@ - [X] We need a specific test target for functional tests - [X Add guards in header files - [X] Finish target restructuring - - [ ] [This can be addressed using CMake install] Copying dll and binary to another directory was not easy + - [X] [This can be addressed using CMake install] Copying dll and binary to another directory was not easy - [X] Move in a dedicated file the request handling part of the client code - [X] Use the computeTotalAmount in the client -- [ ] [This can be addressed using CMake install] Find a way to test code while the client is running (copy dll, use a static library, edit and continue ???) +- [X] [This can be addressed using CMake install] Find a way to test code while the client is running (copy dll, use a static library, edit and continue ???) - [ ] Use a different port number for tests ## PARKING - [X] Clean gitignore file in cpp @@ -46,4 +46,4 @@ - [ ] Add dependencies on sub boost headers only libraries (beast), instead on depending on full boost - [ ] Fix that : Failed to find all ICU components (missing: ICU_INCLUDE_DIR _ICU_REQUIRED_LIBS_FOUND) - [ ] Upgrade nlohman json version -- [ ] Tests can crash randomly with a low frequency (this could be reproduced in Github Actions) +- [ ] [This seems caused by a failure to connect to the server port] Tests can crash randomly with a low frequency (this could be reproduced in Github Actions) From d79b06e0debda041396d1cbe0a646797c2ab0eab Mon Sep 17 00:00:00 2001 From: NADIF Antoine Date: Wed, 27 Apr 2022 15:49:36 +0200 Subject: [PATCH 113/125] Have the tests always run on server port plus 1 to avoid conflicts. --- clients/cpp/Client/library/CMakeLists.txt | 2 +- .../extreme_carpaccio/client/HttpConfig.hpp | 0 .../library/tests/sources/helpers/CarpaccioStream.cpp | 10 +++++++++- .../tests/sources/helpers/TestServerResponse.cpp | 7 ++++--- clients/cpp/TODOLIST.md | 2 +- 5 files changed, 15 insertions(+), 6 deletions(-) rename clients/cpp/Client/library/{sources => includes}/extreme_carpaccio/client/HttpConfig.hpp (100%) diff --git a/clients/cpp/Client/library/CMakeLists.txt b/clients/cpp/Client/library/CMakeLists.txt index fb53f2b7..38b181d2 100644 --- a/clients/cpp/Client/library/CMakeLists.txt +++ b/clients/cpp/Client/library/CMakeLists.txt @@ -6,13 +6,13 @@ target_compile_definitions(Client-shared PRIVATE EXTREME_CARPACCIO_CLIENT_EXPORT set(CLIENT_SHARED_PRIVATE_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/sources/extreme_carpaccio/client/CarpaccioHttpWorker.cpp ${CMAKE_CURRENT_SOURCE_DIR}/sources/extreme_carpaccio/client/Client.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/sources/extreme_carpaccio/client/HttpConfig.hpp ) set(CLIENT_SHARED_PUBLIC_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/includes/extreme_carpaccio/client/CarpaccioHttpWorker.hpp ${CMAKE_CURRENT_SOURCE_DIR}/includes/extreme_carpaccio/client/Client.hpp ${CMAKE_CURRENT_SOURCE_DIR}/includes/extreme_carpaccio/client/config.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/includes/extreme_carpaccio/client/HttpConfig.hpp ) target_sources(Client-shared diff --git a/clients/cpp/Client/library/sources/extreme_carpaccio/client/HttpConfig.hpp b/clients/cpp/Client/library/includes/extreme_carpaccio/client/HttpConfig.hpp similarity index 100% rename from clients/cpp/Client/library/sources/extreme_carpaccio/client/HttpConfig.hpp rename to clients/cpp/Client/library/includes/extreme_carpaccio/client/HttpConfig.hpp diff --git a/clients/cpp/Client/library/tests/sources/helpers/CarpaccioStream.cpp b/clients/cpp/Client/library/tests/sources/helpers/CarpaccioStream.cpp index c123063c..cdf68123 100644 --- a/clients/cpp/Client/library/tests/sources/helpers/CarpaccioStream.cpp +++ b/clients/cpp/Client/library/tests/sources/helpers/CarpaccioStream.cpp @@ -6,6 +6,8 @@ #include #include +#include + namespace extreme_carpaccio { namespace client { namespace test { @@ -30,7 +32,13 @@ CarpaccioStream::CarpaccioStream(const std::string & host, unsigned short port) , m_stream(m_ioContext) { // Make the connection on the IP address we get from a lookup - m_stream.connect(m_resolverResults); + try { + m_stream.connect(m_resolverResults); + } + catch (...) + { + std::cerr << "Unknown error when attempting to connect to the Carpaccio server!"; + } } CarpaccioStream::~CarpaccioStream() diff --git a/clients/cpp/Client/library/tests/sources/helpers/TestServerResponse.cpp b/clients/cpp/Client/library/tests/sources/helpers/TestServerResponse.cpp index aef827ff..61102d84 100644 --- a/clients/cpp/Client/library/tests/sources/helpers/TestServerResponse.cpp +++ b/clients/cpp/Client/library/tests/sources/helpers/TestServerResponse.cpp @@ -4,6 +4,7 @@ #include #include +#include #include #include @@ -26,7 +27,7 @@ using tcp = boost::asio::ip::tcp; namespace { const char serverHost[] = "localhost"; -const unsigned short serverPort = 8081; +const unsigned short testServerPort = HTTP_SERVER_PORT + 1; } // namespace @@ -37,11 +38,11 @@ boost::beast::http::response generateServerRes , const std::string & body ) { - CarpaccioServer server(8081); + CarpaccioServer server(testServerPort); std::thread thread(&CarpaccioServer::start, &server); std::this_thread::sleep_for(std::chrono::seconds(1)); - CarpaccioStream stream(serverHost, serverPort); + CarpaccioStream stream(serverHost, testServerPort); // Send the HTTP request to the remote host stream.write(requestType, target, contentType, body); diff --git a/clients/cpp/TODOLIST.md b/clients/cpp/TODOLIST.md index 0a0ad9a5..6f04409f 100644 --- a/clients/cpp/TODOLIST.md +++ b/clients/cpp/TODOLIST.md @@ -39,7 +39,7 @@ - [X] Move in a dedicated file the request handling part of the client code - [X] Use the computeTotalAmount in the client - [X] [This can be addressed using CMake install] Find a way to test code while the client is running (copy dll, use a static library, edit and continue ???) -- [ ] Use a different port number for tests +- [X] Use a different port number for tests ## PARKING - [X] Clean gitignore file in cpp - [X] [Cannot be done, header only library] Ajouter dans le cmake le Json en thirdparty pour la solution VS From 322789d2f6e1ed313baa1c687d201974c625c2cc Mon Sep 17 00:00:00 2001 From: NADIF Antoine Date: Wed, 27 Apr 2022 16:01:07 +0200 Subject: [PATCH 114/125] Disable ICU backend for Boost and add CPM cmake files to the Doc target. --- clients/cpp/CMakeLists.txt | 4 ++++ clients/cpp/TODOLIST.md | 2 +- clients/cpp/cmake/FindBoost.cmake | 2 ++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/clients/cpp/CMakeLists.txt b/clients/cpp/CMakeLists.txt index d6735e4b..af41c857 100644 --- a/clients/cpp/CMakeLists.txt +++ b/clients/cpp/CMakeLists.txt @@ -31,6 +31,10 @@ add_custom_target(Docs SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/Retrospective.md ${CMAKE_CURRENT_SOURCE_DIR}/TODOLIST.md + ${CMAKE_CURRENT_SOURCE_DIR}/cmake/CPM.cmake + ${CMAKE_CURRENT_SOURCE_DIR}/cmake/FindBoost.cmake + ${CMAKE_CURRENT_SOURCE_DIR}/cmake/FindGoogleTest.cmake + ${CMAKE_CURRENT_SOURCE_DIR}/cmake/FindNlohmannJson.cmake ${CMAKE_CURRENT_SOURCE_DIR}/../README.md) set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT Order-Management-tests) diff --git a/clients/cpp/TODOLIST.md b/clients/cpp/TODOLIST.md index 6f04409f..ae5b8146 100644 --- a/clients/cpp/TODOLIST.md +++ b/clients/cpp/TODOLIST.md @@ -44,6 +44,6 @@ - [X] Clean gitignore file in cpp - [X] [Cannot be done, header only library] Ajouter dans le cmake le Json en thirdparty pour la solution VS - [ ] Add dependencies on sub boost headers only libraries (beast), instead on depending on full boost -- [ ] Fix that : Failed to find all ICU components (missing: ICU_INCLUDE_DIR _ICU_REQUIRED_LIBS_FOUND) +- [X] Fix that : Failed to find all ICU components (missing: ICU_INCLUDE_DIR _ICU_REQUIRED_LIBS_FOUND) - [ ] Upgrade nlohman json version - [ ] [This seems caused by a failure to connect to the server port] Tests can crash randomly with a low frequency (this could be reproduced in Github Actions) diff --git a/clients/cpp/cmake/FindBoost.cmake b/clients/cpp/cmake/FindBoost.cmake index bd357e9d..06381b65 100644 --- a/clients/cpp/cmake/FindBoost.cmake +++ b/clients/cpp/cmake/FindBoost.cmake @@ -1,5 +1,7 @@ # Fetch Boost +set(BOOST_LOCALE_ENABLE_ICU_BACKEND OFF) + CPMAddPackage("gh:Orphis/boost-cmake#7f97a08b64bd5d2e53e932ddf80c40544cf45edf@1.71.0") #CPMFindPackage( From 53db00458abf955e4baa710afd824ef04a6424d0 Mon Sep 17 00:00:00 2001 From: NADIF Antoine Date: Wed, 27 Apr 2022 18:47:04 +0200 Subject: [PATCH 115/125] Upgrade nlohmann_json version by adapting its retrieval through CPM --- clients/cpp/Client/library/CMakeLists.txt | 2 +- .../cpp/Client/library/tests/CMakeLists.txt | 2 +- clients/cpp/OrderManagement/CMakeLists.txt | 2 +- clients/cpp/TODOLIST.md | 2 +- clients/cpp/cmake/FindNlohmannJson.cmake | 20 ++++++------------- 5 files changed, 10 insertions(+), 18 deletions(-) diff --git a/clients/cpp/Client/library/CMakeLists.txt b/clients/cpp/Client/library/CMakeLists.txt index 38b181d2..e86471ec 100644 --- a/clients/cpp/Client/library/CMakeLists.txt +++ b/clients/cpp/Client/library/CMakeLists.txt @@ -38,7 +38,7 @@ target_include_directories(Client-shared target_link_libraries(Client-shared PRIVATE - nlohmann_json + nlohmann_json::nlohmann_json PUBLIC Threads::Threads Boost::boost diff --git a/clients/cpp/Client/library/tests/CMakeLists.txt b/clients/cpp/Client/library/tests/CMakeLists.txt index 8ec145a8..6cc800e0 100644 --- a/clients/cpp/Client/library/tests/CMakeLists.txt +++ b/clients/cpp/Client/library/tests/CMakeLists.txt @@ -30,7 +30,7 @@ target_link_libraries(Client-tests Client-shared gmock_main Boost::boost - nlohmann_json + nlohmann_json::nlohmann_json ) install(TARGETS Client-tests) diff --git a/clients/cpp/OrderManagement/CMakeLists.txt b/clients/cpp/OrderManagement/CMakeLists.txt index 5fd81869..40a34c8b 100644 --- a/clients/cpp/OrderManagement/CMakeLists.txt +++ b/clients/cpp/OrderManagement/CMakeLists.txt @@ -38,7 +38,7 @@ target_include_directories(Order-Management-shared ${CMAKE_CURRENT_SOURCE_DIR}/includes ) -target_link_libraries(Order-Management-shared PUBLIC Boost::boost PRIVATE nlohmann_json) +target_link_libraries(Order-Management-shared PUBLIC Boost::boost PRIVATE nlohmann_json::nlohmann_json) install(TARGETS Order-Management-shared) diff --git a/clients/cpp/TODOLIST.md b/clients/cpp/TODOLIST.md index ae5b8146..6f61d88c 100644 --- a/clients/cpp/TODOLIST.md +++ b/clients/cpp/TODOLIST.md @@ -45,5 +45,5 @@ - [X] [Cannot be done, header only library] Ajouter dans le cmake le Json en thirdparty pour la solution VS - [ ] Add dependencies on sub boost headers only libraries (beast), instead on depending on full boost - [X] Fix that : Failed to find all ICU components (missing: ICU_INCLUDE_DIR _ICU_REQUIRED_LIBS_FOUND) -- [ ] Upgrade nlohman json version +- [X] Upgrade nlohman json version - [ ] [This seems caused by a failure to connect to the server port] Tests can crash randomly with a low frequency (this could be reproduced in Github Actions) diff --git a/clients/cpp/cmake/FindNlohmannJson.cmake b/clients/cpp/cmake/FindNlohmannJson.cmake index 78939bea..40773106 100644 --- a/clients/cpp/cmake/FindNlohmannJson.cmake +++ b/clients/cpp/cmake/FindNlohmannJson.cmake @@ -1,16 +1,8 @@ # Fetch nlohmann_json -CPMFindPackage( - NAME nlohmann_json - VERSION 3.6.1 - # the git repo is incredibly large, so we download the archived include directory - URL https://github.com/nlohmann/json/releases/download/v3.6.1/include.zip - URL_HASH SHA256=69cc88207ce91347ea530b227ff0776db82dcb8de6704e1a3d74f4841bc651cf -) - -if (nlohmann_json_ADDED) - add_library(nlohmann_json INTERFACE IMPORTED) - target_include_directories(nlohmann_json INTERFACE ${nlohmann_json_SOURCE_DIR}) -else() - message(FATAL_ERROR "nlohman json dependency not found") -endif() \ No newline at end of file +CPMAddPackage( + NAME nlohmannjson + GITHUB_REPOSITORY nlohmann/json + GIT_TAG v3.10.5 + VERSION 3.10.5 +) \ No newline at end of file From eb1d074979731fcf21dc3d712ef8434ce9d222dc Mon Sep 17 00:00:00 2001 From: NADIF Antoine Date: Wed, 27 Apr 2022 19:09:54 +0200 Subject: [PATCH 116/125] Upgrade googletest version. --- clients/cpp/cmake/FindGoogleTest.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clients/cpp/cmake/FindGoogleTest.cmake b/clients/cpp/cmake/FindGoogleTest.cmake index dad94cb3..c4aa21da 100644 --- a/clients/cpp/cmake/FindGoogleTest.cmake +++ b/clients/cpp/cmake/FindGoogleTest.cmake @@ -3,7 +3,7 @@ CPMAddPackage( NAME googletest GITHUB_REPOSITORY google/googletest - GIT_TAG release-1.10.0 - VERSION 1.10.0 + GIT_TAG release-1.11.0 + VERSION 1.11.0 OPTIONS "INSTALL_GTEST OFF" "gtest_force_shared_crt" "BUILD_GMOCK ON" ) From 00fbad10ee4a3431695aee42d05fb486a1d13c9a Mon Sep 17 00:00:00 2001 From: NADIF Antoine Date: Thu, 28 Apr 2022 14:39:07 +0200 Subject: [PATCH 117/125] Properly retrieve boost without ICU locale backend. --- clients/cpp/TODOLIST.md | 4 ++-- clients/cpp/cmake/FindBoost.cmake | 18 +++++++----------- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/clients/cpp/TODOLIST.md b/clients/cpp/TODOLIST.md index 6f61d88c..783fed28 100644 --- a/clients/cpp/TODOLIST.md +++ b/clients/cpp/TODOLIST.md @@ -29,11 +29,11 @@ - [X] Add a configuration file for main options (ports and maybe others) - [X] check the js client to see what options are available - [ ] create a config file of command line options to set these options -- [ ] Feedbacks from the session on extreme carpaccio with C++ client +- [X] Feedbacks from the session on extreme carpaccio with C++ client - [x] Display the order description in the code handling the order to have it in the console - [X] We need to initialize the http server with the hostname of the user launching it - [X] We need a specific test target for functional tests - - [X Add guards in header files + - [X] Add guards in header files - [X] Finish target restructuring - [X] [This can be addressed using CMake install] Copying dll and binary to another directory was not easy - [X] Move in a dedicated file the request handling part of the client code diff --git a/clients/cpp/cmake/FindBoost.cmake b/clients/cpp/cmake/FindBoost.cmake index 06381b65..ebea7397 100644 --- a/clients/cpp/cmake/FindBoost.cmake +++ b/clients/cpp/cmake/FindBoost.cmake @@ -1,13 +1,9 @@ # Fetch Boost -set(BOOST_LOCALE_ENABLE_ICU_BACKEND OFF) - -CPMAddPackage("gh:Orphis/boost-cmake#7f97a08b64bd5d2e53e932ddf80c40544cf45edf@1.71.0") - -#CPMFindPackage( -# NAME Boost -# GITHUB_REPOSITORY Orphis/boost-cmake -# VERSION 1.67.0 -# # setting FIND_PACKAGE_ARGUMENTS allow usage with `CPM_USE_LOCAL_PACKAGES` -# FIND_PACKAGE_ARGUMENTS "COMPONENTS system" -#) \ No newline at end of file +CPMAddPackage( + NAME orphisboost + GITHUB_REPOSITORY Orphis/boost-cmake + GIT_TAG 7f97a08b64bd5d2e53e932ddf80c40544cf45edf + VERSION 1.71.0 + OPTIONS "BOOST_LOCALE_ENABLE_ICU_BACKEND OFF" +) From 78853c3cee77608387233deeae4e2ea0db9456c9 Mon Sep 17 00:00:00 2001 From: NADIF Antoine Date: Thu, 28 Apr 2022 14:42:08 +0200 Subject: [PATCH 118/125] Include install step in CI runs. --- .github/workflows/cmake.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 7a190ab2..08ff619b 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -25,7 +25,7 @@ jobs: build-type: Release run-test: true ctest-options: "--output-on-failure" - install-build: false + install-build: true build-clang: runs-on: ubuntu-latest steps: @@ -41,4 +41,4 @@ jobs: build-type: Release run-test: true ctest-options: "--output-on-failure" - install-build: false \ No newline at end of file + install-build: true \ No newline at end of file From b04cdbfad1fb64223f2beafd2154fc7092c70a24 Mon Sep 17 00:00:00 2001 From: NADIF Antoine Date: Thu, 28 Apr 2022 14:53:44 +0200 Subject: [PATCH 119/125] Prevent Boost targets from showing up in the IDE solution. --- clients/cpp/cmake/FindBoost.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/clients/cpp/cmake/FindBoost.cmake b/clients/cpp/cmake/FindBoost.cmake index ebea7397..99a12fd5 100644 --- a/clients/cpp/cmake/FindBoost.cmake +++ b/clients/cpp/cmake/FindBoost.cmake @@ -6,4 +6,5 @@ CPMAddPackage( GIT_TAG 7f97a08b64bd5d2e53e932ddf80c40544cf45edf VERSION 1.71.0 OPTIONS "BOOST_LOCALE_ENABLE_ICU_BACKEND OFF" + EXCLUDE_FROM_ALL true ) From a0600364394b8d94cb2d24161a11544d391f8373 Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 28 Apr 2022 15:37:47 +0200 Subject: [PATCH 120/125] Use default ip and default port in client construction. --- clients/cpp/Client/executable/sources/main.cpp | 3 ++- .../includes/extreme_carpaccio/client/Client.hpp | 3 +-- .../includes/extreme_carpaccio/client/HttpConfig.hpp | 4 ++-- .../sources/extreme_carpaccio/client/Client.cpp | 10 ++-------- .../tests/sources/helpers/TestServerResponse.cpp | 4 ++-- 5 files changed, 9 insertions(+), 15 deletions(-) diff --git a/clients/cpp/Client/executable/sources/main.cpp b/clients/cpp/Client/executable/sources/main.cpp index 939382fb..faa29b81 100644 --- a/clients/cpp/Client/executable/sources/main.cpp +++ b/clients/cpp/Client/executable/sources/main.cpp @@ -1,5 +1,6 @@ #include +#include #include #include @@ -7,7 +8,7 @@ int main() { std::cout << "Extreme Carpaccio server starting." << std::endl; - extreme_carpaccio::client::CarpaccioServer server; + extreme_carpaccio::client::CarpaccioServer server(DEFAULT_HTTP_SERVER_IP, DEFAULT_HTTP_SERVER_PORT); server.start(); std::cout << "Extreme Carpaccio server stopping." << std::endl; diff --git a/clients/cpp/Client/library/includes/extreme_carpaccio/client/Client.hpp b/clients/cpp/Client/library/includes/extreme_carpaccio/client/Client.hpp index 2e3c7973..9dd317b9 100644 --- a/clients/cpp/Client/library/includes/extreme_carpaccio/client/Client.hpp +++ b/clients/cpp/Client/library/includes/extreme_carpaccio/client/Client.hpp @@ -18,8 +18,7 @@ namespace client { class EXTREME_CARPACCIO_CLIENT_API CarpaccioServer { public: - CarpaccioServer(); - CarpaccioServer(unsigned short port); + CarpaccioServer(const std::string& ip, unsigned short port); void start(); void stop(); diff --git a/clients/cpp/Client/library/includes/extreme_carpaccio/client/HttpConfig.hpp b/clients/cpp/Client/library/includes/extreme_carpaccio/client/HttpConfig.hpp index 26de681f..27357bc3 100644 --- a/clients/cpp/Client/library/includes/extreme_carpaccio/client/HttpConfig.hpp +++ b/clients/cpp/Client/library/includes/extreme_carpaccio/client/HttpConfig.hpp @@ -2,8 +2,8 @@ #ifndef EXTREME_CARPACCIO_CLIENT_HTTPCONFIG_HPP #define EXTREME_CARPACCIO_CLIENT_HTTPCONFIG_HPP -#define HTTP_SERVER_IP "127.0.0.1" -#define HTTP_SERVER_PORT 8081 +#define DEFAULT_HTTP_SERVER_IP "127.0.0.1" +#define DEFAULT_HTTP_SERVER_PORT 8081 namespace extreme_carpaccio { namespace client { diff --git a/clients/cpp/Client/library/sources/extreme_carpaccio/client/Client.cpp b/clients/cpp/Client/library/sources/extreme_carpaccio/client/Client.cpp index 9a9fbc15..badd189e 100644 --- a/clients/cpp/Client/library/sources/extreme_carpaccio/client/Client.cpp +++ b/clients/cpp/Client/library/sources/extreme_carpaccio/client/Client.cpp @@ -7,15 +7,9 @@ namespace extreme_carpaccio { namespace client { -CarpaccioServer::CarpaccioServer() - : CarpaccioServer(HTTP_SERVER_PORT) -{ - -} - -CarpaccioServer::CarpaccioServer(unsigned short port) +CarpaccioServer::CarpaccioServer(const std::string& ip, unsigned short port) : ioc(1) - , acceptor(ioc, { boost::asio::ip::make_address(HTTP_SERVER_IP), port }) + , acceptor(ioc, { boost::asio::ip::make_address(ip), port }) , worker(acceptor, "./feedback") { } diff --git a/clients/cpp/Client/library/tests/sources/helpers/TestServerResponse.cpp b/clients/cpp/Client/library/tests/sources/helpers/TestServerResponse.cpp index 61102d84..b973b76c 100644 --- a/clients/cpp/Client/library/tests/sources/helpers/TestServerResponse.cpp +++ b/clients/cpp/Client/library/tests/sources/helpers/TestServerResponse.cpp @@ -27,7 +27,7 @@ using tcp = boost::asio::ip::tcp; namespace { const char serverHost[] = "localhost"; -const unsigned short testServerPort = HTTP_SERVER_PORT + 1; +const unsigned short testServerPort = DEFAULT_HTTP_SERVER_PORT + 1; } // namespace @@ -38,7 +38,7 @@ boost::beast::http::response generateServerRes , const std::string & body ) { - CarpaccioServer server(testServerPort); + CarpaccioServer server(DEFAULT_HTTP_SERVER_IP, testServerPort); std::thread thread(&CarpaccioServer::start, &server); std::this_thread::sleep_for(std::chrono::seconds(1)); From fe45d482b4e1300a1beaa4fee1775a83cd87dbdd Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 28 Apr 2022 15:49:44 +0200 Subject: [PATCH 121/125] Add the possibility to pass ip and port as parameters of client executable --- clients/cpp/Client/executable/sources/main.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/clients/cpp/Client/executable/sources/main.cpp b/clients/cpp/Client/executable/sources/main.cpp index faa29b81..9e2d99cf 100644 --- a/clients/cpp/Client/executable/sources/main.cpp +++ b/clients/cpp/Client/executable/sources/main.cpp @@ -5,10 +5,18 @@ #include #include -int main() +int main(int argc, char *argv[]) { - std::cout << "Extreme Carpaccio server starting." << std::endl; - extreme_carpaccio::client::CarpaccioServer server(DEFAULT_HTTP_SERVER_IP, DEFAULT_HTTP_SERVER_PORT); + std::string ip = DEFAULT_HTTP_SERVER_IP; + unsigned short port = DEFAULT_HTTP_SERVER_PORT; + + if (argc == 3) + { + ip = argv[1]; + port = std::atoi(argv[2]); + } + std::cout << "Extreme Carpaccio server starting with ip " << ip << " and port " << port << "." << std::endl; + extreme_carpaccio::client::CarpaccioServer server(ip, port); server.start(); std::cout << "Extreme Carpaccio server stopping." << std::endl; From dfc7da6eb9efe967fe6f20e3a33f5f348df25085 Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 31 Aug 2023 15:36:25 +0200 Subject: [PATCH 122/125] First version of cpp README --- clients/cpp/README.md | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 clients/cpp/README.md diff --git a/clients/cpp/README.md b/clients/cpp/README.md new file mode 100644 index 00000000..6fc26cc3 --- /dev/null +++ b/clients/cpp/README.md @@ -0,0 +1,31 @@ +# Extreme Carpaccio C++ starting code + +By default, the kata's CMake file is referencing C++ version 14. + + +## Getting ready + +### 1 - Clone the kata repository + +### 2 - Go to the kata's `cpp` directory + +### 3 - Run the build setup script + +The kata comes with a setup script to simplify initializing the project. + +This setup script does the following: + +- Create a build directory: ***cpp/build***. All build-related files are generated under this directory. +- Download a copy of cmake compatible with your platform. +- Download the dependencies required to build and test the kata (such as GoogleTest). +- Generate the solution file ***Extreme-Carpaccio.sln*** for **Visual Studio 2017** on Windows, + or the project file ***Extreme-Carpaccio.xcodeproj*** for **Xcode** on macOS. +- Run an initial build and test of the kata to ensure that everything is set up properly. + +```shell +./cpp_easy_setup.sh +``` + +## Project organization + +C++ HTTP client is implemented in Client folder. Order management code has to be modidied. \ No newline at end of file From 0cd27b69520f78590f437f2754bf6630eb8a5c55 Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 7 Sep 2023 16:18:03 +0200 Subject: [PATCH 123/125] Upgrading to C++ 17 --- clients/cpp/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clients/cpp/CMakeLists.txt b/clients/cpp/CMakeLists.txt index af41c857..85520be0 100644 --- a/clients/cpp/CMakeLists.txt +++ b/clients/cpp/CMakeLists.txt @@ -4,7 +4,7 @@ set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/../install CACHE PATH "Where the ta project(Extreme-Carpaccio CXX) -set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD 17) enable_testing() set_property(GLOBAL PROPERTY USE_FOLDERS ON) From 4e650feb5d2eebed92ca33dc20ba488c4be9dd7d Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 7 Sep 2023 16:34:40 +0200 Subject: [PATCH 124/125] Removing Retrospective and TODOLIST. Enriching README --- clients/cpp/README.md | 7 +++-- clients/cpp/Retrospective.md | 53 ------------------------------------ clients/cpp/TODOLIST.md | 49 --------------------------------- 3 files changed, 5 insertions(+), 104 deletions(-) delete mode 100644 clients/cpp/Retrospective.md delete mode 100644 clients/cpp/TODOLIST.md diff --git a/clients/cpp/README.md b/clients/cpp/README.md index 6fc26cc3..1b29fc76 100644 --- a/clients/cpp/README.md +++ b/clients/cpp/README.md @@ -1,6 +1,6 @@ # Extreme Carpaccio C++ starting code -By default, the kata's CMake file is referencing C++ version 14. +By default, the kata's CMake file is referencing C++ version 17. ## Getting ready @@ -28,4 +28,7 @@ This setup script does the following: ## Project organization -C++ HTTP client is implemented in Client folder. Order management code has to be modidied. \ No newline at end of file +C++ HTTP client is implemented in "Client" folder. HTTP client executable, once built, can be found under build\bin folder. + +Order handling related code is under "Order Management" folder. + diff --git a/clients/cpp/Retrospective.md b/clients/cpp/Retrospective.md deleted file mode 100644 index a187c8b2..00000000 --- a/clients/cpp/Retrospective.md +++ /dev/null @@ -1,53 +0,0 @@ -# RETROSPECTIVE - -05/27/2021 -07/15/2021 -09/02/2021 -10/14/2021 - -## What did we do ? -- We did some cmake and CPM -- We wanted to build a extreme carpaccio client in cpp -- We have all dependencies to create an answer to server -- We updated CPM to latest version -- We made a copy of Bowling game kata to have all cmake config ready -- We debugged requests format using JS version of carpaccio -07/15/2021 -- We changed our approach, we chose to get the full example code and tested it successfully -- We change the allocator by using the default allocator, and it worked -09/02/2021 -- We built a test on the client's http server using a get request -- We started to create class structure of server to host ioc, so that we can call start/stop on it -10/14/2021 -- We refactored the Carpaccio Server and the Stream to simplify the tests - -## What did we learn ? -- Patrice learnt on client/server problematic and REST requests -07/15/2021 -- We learnt that folder and file need to exist to be able to retrieve them from the server -- Starting with something that works and try to refactoring seems to be a good solution -09/02/2021 -- We learnt how to build a thread in c++, we learnt about thread joining -10/14/2021 -- We learnt that we could create a thread with a class member function -## Puzzle -- Dependencies handling in cpp is sport ! -- We have the boost example of GET, will it work with POST ? -- Can we use boost to build the server ? -07/15/2021 -- boost beast is a bit tricky to understand and troubleshoot -- Example of server using boost library is not real good c++ !! -09/02/2021 -- We had some issues with threads. How can we stop server in a clean way ? How can we remove sleep ? -- It takes time to build this C++ implementation of Extreme Carpaccio client -- It's not trivial to build http server in c++, and we are still not handling requests of the extreme carpaccio game -10/14/2021 -- Be careful about relative paths in CMakeLists.txt -- Never commit anything inside the build directory! - -## Decide -- We miss some libraries in boost cmake so we need to add tham to build simple http client with boost -- We will add a Jira ticket to continue working on that -- 07/15/2021 -09/02/2021 -- Option 1 : We can check what is the feedback from Morrigan on Extreme Carpaccio, and if we get good feedback, we continue investigating on c++ version \ No newline at end of file diff --git a/clients/cpp/TODOLIST.md b/clients/cpp/TODOLIST.md deleted file mode 100644 index 783fed28..00000000 --- a/clients/cpp/TODOLIST.md +++ /dev/null @@ -1,49 +0,0 @@ -# TO DO LIST - -## TODO -- [X] Write a test sending an http request - - [X] Deal with all the cmake arcane... -- [X] Create a main exe that starts a server -- [X] Manual test that it can display a bmp, test it in the browser -- [X] Update our test to check that client can get a file from the server -- [X] Deal with starting & stopping the server correctly in the test to avoid resource leaks -- [X] Implement the POST /order command - - [X] check what the request and answers should look like from the js versions - - [X] write a test to POST /order with a proper request - - [X] implement POST /order - - [X] test our client with the real extreme carpaccio server - - [X] make sure we can parse the json order and build an order object - - [X] make sure we can parse the json order - - [X] use correct field to pass the body of the request? - - [X] build an order object from the json (cf value_ field of the res object) - - [X] Put the order object in a specific file - - [X] Refactor handleRequest - - [X] Return total amount json - - [X] make sure we can easily build a json response (and play the game) - - [X] By default return error 404 as answer to the request to be in line with other implementations -- [X] Implement the POST /feedback command - - [X] check what the request, answers and behavior should look like from the js versions - - [X] write a test to POST /feedback with a proper request - - [X] implement POST /feedback - - [X] test our client can receive feedback form the real extreme carpaccio server -- [X] Add a configuration file for main options (ports and maybe others) - - [X] check the js client to see what options are available - - [ ] create a config file of command line options to set these options -- [X] Feedbacks from the session on extreme carpaccio with C++ client - - [x] Display the order description in the code handling the order to have it in the console - - [X] We need to initialize the http server with the hostname of the user launching it - - [X] We need a specific test target for functional tests - - [X] Add guards in header files - - [X] Finish target restructuring - - [X] [This can be addressed using CMake install] Copying dll and binary to another directory was not easy -- [X] Move in a dedicated file the request handling part of the client code -- [X] Use the computeTotalAmount in the client -- [X] [This can be addressed using CMake install] Find a way to test code while the client is running (copy dll, use a static library, edit and continue ???) -- [X] Use a different port number for tests -## PARKING -- [X] Clean gitignore file in cpp - - [X] [Cannot be done, header only library] Ajouter dans le cmake le Json en thirdparty pour la solution VS -- [ ] Add dependencies on sub boost headers only libraries (beast), instead on depending on full boost -- [X] Fix that : Failed to find all ICU components (missing: ICU_INCLUDE_DIR _ICU_REQUIRED_LIBS_FOUND) -- [X] Upgrade nlohman json version -- [ ] [This seems caused by a failure to connect to the server port] Tests can crash randomly with a low frequency (this could be reproduced in Github Actions) From 44ebe43935c46d4d3ecc9ab6981e3712d2961a02 Mon Sep 17 00:00:00 2001 From: pdalesme Date: Thu, 7 Sep 2023 19:26:43 +0200 Subject: [PATCH 125/125] dereferencing in cmake list --- clients/cpp/CMakeLists.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/clients/cpp/CMakeLists.txt b/clients/cpp/CMakeLists.txt index 85520be0..3f86ec26 100644 --- a/clients/cpp/CMakeLists.txt +++ b/clients/cpp/CMakeLists.txt @@ -29,8 +29,6 @@ add_subdirectory(Client) #Globals add_custom_target(Docs SOURCES - ${CMAKE_CURRENT_SOURCE_DIR}/Retrospective.md - ${CMAKE_CURRENT_SOURCE_DIR}/TODOLIST.md ${CMAKE_CURRENT_SOURCE_DIR}/cmake/CPM.cmake ${CMAKE_CURRENT_SOURCE_DIR}/cmake/FindBoost.cmake ${CMAKE_CURRENT_SOURCE_DIR}/cmake/FindGoogleTest.cmake