commit d35d096374aeda996ca74ab42aebbcc59b138236 Author: arod571431 Date: Wed Jul 23 23:06:27 2025 +0800 First_Commit diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..884fa5e --- /dev/null +++ b/.clang-format @@ -0,0 +1,6 @@ +BasedOnStyle: LLVM +IndentWidth: 4 +AccessModifierOffset: -4 +AllowShortFunctionsOnASingleLine: Inline +AlwaysBreakTemplateDeclarations: Yes +PackConstructorInitializers: Never diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..71bd017 --- /dev/null +++ b/.gitignore @@ -0,0 +1,492 @@ +# .gitignore file for CLion, Visual Studio, and Visual Studio Code + +# From JetBrains .gitignore template +# https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore + +# 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 + +# AWS User-specific +.idea/**/aws.xml + +# 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 + +# SonarLint plugin +.idea/sonarlint/ + +# 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 + +# From Visual Studio .gitignore template +# https://github.com/github/gitignore/blob/main/VisualStudio.gitignore + +## 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/main/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/ +[Ww][Ii][Nn]32/ +[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/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# 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 +*.tmp_proj +*_wpftmp.csproj +*.log +*.tlog +*.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 +coverage*.xml +coverage*.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 6 auto-generated project file (contains which files were open etc.) +*.vbp + +# Visual Studio 6 workspace and project file (working project files containing files to include in project) +*.dsw +*.dsp + +# Visual Studio 6 technical files +*.ncb +*.aps + +# 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/ + +# Visual Studio History (VSHistory) files +.vshistory/ + +# 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/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd + +# VS Code files for those working on multiple tools +# .vscode/* +# !.vscode/settings.json +# !.vscode/tasks.json +# !.vscode/launch.json +# !.vscode/extensions.json +# *.code-workspace + +# Local History for Visual Studio Code +.history/ + +# Windows Installer files from build outputs +*.cab +*.msi +*.msix +*.msm +*.msp + +# JetBrains +*.sln.iml +/.idea/ +# Custom writen VSCode .gitignore +.vscode/ + +# Default build directory for CMake extension +build/ + +*_build/ diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..6e5f6a6 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,100 @@ +# ! ------------------------------------------------------------------ ! +# ! Changing this file incorrectly can cause your program to not build ! +# ! If you don't know CMake well DO NOT touch this file ! +# ! ------------------------------------------------------------------ ! + +cmake_minimum_required(VERSION 3.20) +project(OOP VERSION 0.1.0) +enable_testing() + +set(CMAKE_CXX_STANDARD 17) + + +#### GTest +option(FETCH_GOOGLETEST "Download googletest source" ON) +if(FETCH_GOOGLETEST) + # reference: https://google.github.io/googletest/quickstart-cmake.html + include(FetchContent) + FetchContent_Declare( + googletest + GIT_REPOSITORY https://github.com/google/googletest.git + GIT_TAG release-1.12.1 + ) + # For Windows: Prevent overriding the parent project's compiler/linker settings + set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) + FetchContent_MakeAvailable(googletest) +else() + message("Using custom googletest installation") + # reference: https://cmake.org/cmake/help/latest/module/FindGTest.html + find_package(GTest REQUIRED) +endif() + +include(files.cmake) + +set(SRC_DIR ${CMAKE_SOURCE_DIR}/src) +set(INCLUDE_DIR ${CMAKE_SOURCE_DIR}/include) +set(TEST_DIR ${CMAKE_SOURCE_DIR}/test) + +list(TRANSFORM SRC_FILES PREPEND ${SRC_DIR}/) +list(TRANSFORM INCLUDE_FILES PREPEND ${INCLUDE_DIR}/) +list(TRANSFORM TEST_FILES PREPEND ${TEST_DIR}/) + +find_program(MEMORYCHECK_COMMAND valgrind) +set(MEMORYCHECK_COMMAND_OPTIONS + "--error-exitcode=1 --track-origins=yes --leak-check=full" +) +include(CTest) + +option(COVERAGE "Enable coverage" OFF) + +if(COVERAGE) + set(CMAKE_C_FLAGS "--coverage -g -O0") + set(CMAKE_CXX_FLAGS "--coverage -g -O0") + + include(scripts/CodeCoverage.cmake) + set(CODE_COVERAGE_VERBOSE ON) + set(COVERAGE_EXCLUDE + ${CMAKE_BINARY_DIR}/_deps/* + ${PROJECT_SOURCE_DIR}/test/* + ) + + if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + set(GCOVR_ADDITIONAL_ARGS + --gcov-executable "llvm-cov gcov" + ) + endif() + + append_coverage_compiler_flags() + setup_target_for_coverage_gcovr_html( + NAME ut_all_coverage + DEPENDENCIES ut_all + EXCLUDE ${COVERAGE_EXCLUDE} + ) +endif() + +if(MSVC) + set(TARGET_COMPILER_OPTIONS + /W4 + ) +else() + set(TARGET_COMPILER_OPTIONS + -Wall -pedantic + ) +endif() + +add_executable(ut_all + ${SRC_FILES} + ${INCLUDE_FILES} + ${TEST_FILES} +) +target_link_libraries(ut_all + GTest::gtest_main +) +target_include_directories(ut_all PRIVATE + ${INCLUDE_DIR} +) +target_compile_options(ut_all PRIVATE + ${TARGET_COMPILER_OPTIONS} +) +include(GoogleTest) +gtest_discover_tests(ut_all) diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..d805b4d --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 NOOBDY + +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. diff --git a/README.md b/README.md new file mode 100644 index 0000000..6f2ea5f --- /dev/null +++ b/README.md @@ -0,0 +1,240 @@ +# Homework 03 + +> 這份作業由物件導向程式設計助教群所製。 +> 如有問題,歡迎使用以下方式聯繫助教: + +>> Email: t111590004@ntut.org.tw +>> MS Teams: 張意昌 +⚠️ Due: 2024/11/13 11:59 p.m. ⚠️ + + + +## 說明 + +### 目標 + +- [ ] 學會繼承以及其使用。 +- [ ] 學會純虛擬函數。 +- [ ] 學會 `std::share_ptr` 的應用。 + +### 檔案架構 + +請確認提交是否符合以下的檔案架構,否則無法進行評分。 + +```txt= +./ +├── CMakeLists.txt +├── LICENSE +├── README.md +├── .gitignore +├── .clang-format +├── files.cmake +├── include +│ └── Drink.hpp +│ └── Food.hpp +│ └── Ingredients.hpp +│ └── MainDish.hpp +│ └── OishiiPapa.hpp +│ └── Order.hpp +│ └── Package.hpp +│ └── SideDish.hpp +├── scripts +│ ├── CodeCoverage.cmake +│ └── coverage.sh +├── src +│ └── Drink.cpp +│ └── Food.cpp +│ └── MainDish.cpp +│ └── OishiiPapa.cpp +│ └── Order.cpp +│ └── Package.cpp +│ └── SideDish.cpp +└── test + └── ut_Food.cpp + └── ut_Oishiipapa.cpp + └── ut_Package.cpp +``` + + + +## 題目評分 + +- [80%]完成第一部分。 + - `MAINDISH_TEST` 20% + - `SIDEDISH_TEST` 20% + - `DRINK_TEST` 10% + - `PACKAGE_TEST` 30% +- [20%]完成第二部分。 + - `OISHIIPAPA_TEST` 20% +- 依照完成部分比例給分,取上傳紀錄中最高者記錄之。 +## 注意事項 + +- 你不應該上傳 `/bin` 資料夾至專案上。 + - 你的功課不應該出現 Memory Leak,否則將會扣作業總分 10 分。 + - 你不應該上傳 `/bin` 資料夾至專案庫,編譯結果不應該上傳至專案庫上,若在助教確認功課評分時 `/bin` 資料夾存在在專案庫中,扣除作業總分 5 分。 + +## 敘述 + +> 嗨,歡迎參加 OOP 課程。 +> +> 想必你已經完成了 Lecture 03 的課程,並瞭解有關於繼承的觀念。 +> (若還不了解的話,可以查看 Lecture 03 的簡報) +> +> 在這個任務中,你會了解如何使用課堂上所描述的繼承觀念。 + +請嘗試完成任務,並在 Jenkins 上拿到綠色的 Correct 勾勾。 + +## 題目敘述 + +> 在這份任務中,我們嘗試設計出速食店的餐點。 + +`Original Oishii Papa` 是一間在世界各地有許多分店的美味速食店,`kesshoban` 想要在北科的藍光園地內開設一間分店,現在請你幫他完成一個簡單的管理系統。 + +由於 `Original Oishii Papa` 的核心精神是以簡單、美味為主,所以店內只有簡單的漢堡與美食組合,以下是他的餐點: + + +| 品名 |英文品名| 食材 | 價格 | +| -------- |-----| -------- | -------- | +| 豬肉堡 |PorkBurger| 一份豬排、一份生菜、一份漢堡麵包、一份起司 | 59 | +| 牛肉堡 |BeefBurger| 一份牛排、一份生菜、一份漢堡麵包、一份起司 | 69 | +| 魚排堡 |FishBurger| 一份魚排、一份生菜、一份漢堡麵包、一份起司 | 79 | + +* 以上主餐會存在 `Ingredients.hpp` 的 `enum class Production` 裡。 + +當然,主餐也可以增加一些不同的配料,以下是可以增加的配料 + +| 品名 |英文品名| 價格 | +| -------- |-----| -------- | +| 豬肉 |PorkSteak| 20 | +| 牛肉 |BeefSteak| 20 | +| 魚排 |FishSteak| 20 | +| 生菜 |Lattuce | 10 | +| 起司 |Cheese | 10 | + +* 以上主餐會存在 `Ingredients.hpp` 的 `enum class Ingredients` 裡,請參考食材名稱區。 + + +| 品名 |英文品名| 食材 | 備註 | +| -------- |-----| -------- | -------- | +| 薯條 |Frenchfries| 一份薯條 | 小份44
大份59 | +| 雞塊 |Nugget| 一份雞塊 | 小份44
大份59 | +| 沙拉 |Salad| 一份沙拉 | 59 | + +* 以上附餐會存在 `Ingredients.hpp` 的 `enum class Production` 裡。 + + +| 品名 |英文品名| 食材 | 備註 | +| -------- |-----| -------- | -------- | +| 可樂 |Cola| 一份可樂 | 中杯28
大杯38 | +| 雪碧 |Spirit|一份雪碧 | 中杯28
大杯38 | +| 焦糖奶茶 |CaramelMilktea|一份奶茶、一份焦糖 | 中杯44 | +| 咖啡拿鐵 |Latte |一份咖啡、一份牛奶 | 中杯45
大杯55 | + +* 以上飲料會存在 `Ingredients.hpp` 的 `enum class Production` 裡。 + +以上是整間速食店的餐點,接下來會給予相對應的食材。 + + +| 食材中文 | 食材英文 | +| -------- | -------- | +| 豬排 | PorkSteak | +| 牛排 | BeefSteak | +| 魚排 | FishSteak | +| 漢堡麵包 | BurgerBread | +| 生菜 | Lattuce | +| 起司 | Cheese | +| 薯條 | FranchFries | +| 雞塊 | ChickenNugget | +| 沙拉 | Salad | +| 可樂 | Cola | +| 雪碧 | Spirit | +| 奶茶 | Milktea | +| 焦糖 | Caramel | +| 咖啡 | Coffee | +| 牛奶 | Milk | + +* 以上食材會存在 `Ingredients.hpp` 的 `enum class Ingredients` 裡。 + +* 在 `Ingreditents.hpp` 內,所有的東西都會用英文呈現,例如:豬排堡是 `Production::PorkBurger` 。 + +### 任務一、在基礎類別中完成getter與setter + +- 在本次任務中,有一個基礎類別,也就是 `Food.hpp`。 +- 請於 `Food(Production id)` 內完成建構子。 +- 請於 `void getid()` 這個 `function` 內,回傳 `Production id` 這個物件。 +- 請於 `std::vector GetIngredient()` 這個 `function` 內,回傳 `std::vector ingredient` 這個物件。 +- 請設置 `void MakeFood()` 為一個純虛擬函數。 +- 請於 `int GetMoney()` 內 ,回傳 `int money` 這個物件。 + +### 任務二、在衍伸類別中完成物件 + +- 接下來會有三個 `class`,分別為 `maindish.hpp` 、 `sidedish.hpp` 、 `drink.hpp` ,這三個物件皆為 `food.hpp` 的衍伸物件,請根據對應的任務完成相對應的內容。 + +- 共通部分 + - 對於 `void MakeFood()` 這個 `function` ,請覆寫掉 `food.hpp` 內的 `void CountMoney()` 這個 `function` ,請將對應的 `Production` 設置好特定的 `ingredients` 並塞入 `std::vector ingredients` 內,並且計算好價格後放入 `money` 內。 + + +- `maindish.hpp` + - 對於 `void AddIngredients(std::vector addtional)` 加入 `std::vector addtional` ,並且重新計算價格。 + - 若 `addtional` 內有任一一項食材未出現在 `額外配料Addtional` 的表格內,請拋出 `std::invalid_argument` 。 +- `sidedish.hpp` + - 除了 `沙拉` 以外的物件,如果 `void MakeLarger()` 被呼叫,你就要將 `SideDishType type` 設定成 `SideDishType::BIG` 。 + - 對於 `SideDishType GetType()` ,你應該回傳 `SideDishType type` 。 +- `drink.hpp` + - 除了 `焦糖奶茶` 以外的物件,如果 `void makelarger()` 被呼叫,你要將 `ml` 設定成 `750` 。 + +- 有以下一個部分請你要注意 + - 在設計 `void MakeFood()` 時,請依照表格給的順序做填充,例如:豬排堡,那麼順序就是 `豬肉排、生菜、漢堡麵包、起司` 。 +### 任務三、完成包裝的物件 + +- 接下來有一個叫做 `Package.hpp` 的檔案,是製作一份完整的餐點。 +- 對於 `void SetMainDish(MainDish maindish)` 你應該要將 `maindish` 設置在 `std::shared_ptr maindish` 內。 +- 對於 `void SetSideDish(SideDish sidedish)` 你應該要將 `sidedish` 設置在 `std::shared_ptr sidedish` 內。 +- 對於 `void SetDrink(Drink drink)` 你應該要將 `drink` 設置在 `std::shared_ptr drink` 內。 +- 對於 `void CountMoney()` 你應該要計算當前這份 `Package` 內的餐點總價是多少後設定在 `money` 裡面,計算規則可以參考表格,並且當 `maindish` 、 `sidedish` 及 `drink` 都有東西時,請將 `money` 減少 `15`。 + + +## 題目敘述 (Part 2) + +接下來這個部分將會實作一個簡易的速食店系統,請根據對應的任務完成相對應的功能。 + +速食店的 `class` 為 `OishiiPapa.hpp` 。 + +### 任務一、觀察訂單物件 + +- 接下來請觀察 `Order.hpp` 這個物件,將會告訴你訂單的應用。 + - `std::vector product` 內存放該筆訂單所需求的產品,我們保證順序一定是 `{主餐,附餐,飲料}` 。 + - Ex: `std::vector product = {PorkBurger,_NULL,Cola}` , 代表只需要 `豬排堡` 以及 `可樂` 。 + - `std::vector addtional` 內代表 `主餐` 所需要的加料。 + - `std::vector larger` 代表 `附餐` 及 `飲料` 是否需要加大,我們保證順序一定是 `{附餐,飲料}` 。 + - Ex: `std::vector larger = {false,true}` ,代表附餐不用加大但飲料一定要。 + - 保證沒有出現的餐點的那欄一定是 `false` 。 + - 根據 `std::vector GetProductInfo()` ,你應該回傳 `std::vector product` 。 + - 根據 `std::vector GetAddtionalInfo()` , 你應該回傳 `std::vector addtional` 。 + - 根據 `std::vector GetLargerInfo` ,你應該回傳 `std::vector larger` 。 +### 任務二、根據接收到的訂單製作物件 +- 對於 `void SendOrder(Order order)` ,你應該將 `order` 傳入 `std::queue pipeline` 內。 +- 對於 `void MakeDish()` ,請根據物件 `std::queue pipeline` 內最上方的 `Order` 回傳,進行相對應的 `Package` 製作,並且將製作好的物件放入 `std::queue chest` 內。 + - 若當前的 `chest` 大小至少 `15` ,則不要製作餐點,將 `Order` 丟入 `std::queue pipeline` 內。 + - 若當前的 `std::queue pipeline` 為空,則拋出 `std::out_of_range()` 。 +### 任務三、進行餐點管理 +- 對於 `Package Pickup()` 這個function,請觀察 `std::queue chest` 這個物件,當 function 被呼叫時,你應該將最上面的 `Package` 回傳,並且對 `money` 進行調整,如果 `chest` 大小小於 `15` 且 `std::queue pipeline` 不為空,將 `std::queue pipeline` 內最上方的 `Order` 丟出來並製作餐點。 + - 若當前的 `std::queue chest` 為空,則拋出 `std::out_of_range()` 。 +### 任務提示 +- 提示:你應該先取的 `chest` 最上方的 `Package` ,之後再判斷是否要製作新的餐點,然後回傳 `Package` 。 +- `std::queue chest` 以及 `std::queue pipeline` 為 `queue` 這個資料結構,你應該去了解這個資料結構的用途,你可以參考[這篇](https://hackmd.io/@Ben1102/S1zcfIqnu)的介紹,用法會放在任務附註。 + +## 任務附註 + +- 你只需要實作任務所描述的function。 +- 關於 `std::invalid_argument` ,你可以參考[這篇](https://en.cppreference.com/w/cpp/error/invalid_argument)。 +- `std::invalid_argument`內可以寫任意東西。 +- 關於 `std::out_of_range` ,你可以參考[這篇](https://en.cppreference.com/w/cpp/error/out_of_range)。 +- `std::out_of_range`內可以寫任意東西。 +- 關於 `std::queue` ,你可以參考[這篇](https://en.cppreference.com/w/cpp/container/queue)。 +- 關於 `std::shared_ptr` ,你可以參考[這篇](https://en.cppreference.com/w/cpp/memory/shared_ptr)。 + +## Homework's meme + + +![meme](https://hackmd.io/_uploads/S1UnbyLbkg.png) diff --git a/files.cmake b/files.cmake new file mode 100644 index 0000000..888e737 --- /dev/null +++ b/files.cmake @@ -0,0 +1,26 @@ +set(SRC_FILES + Drink.cpp + Food.cpp + MainDish.cpp + OishiiPapa.cpp + Order.cpp + Package.cpp + SideDish.cpp +) + +set(INCLUDE_FILES + Drink.hpp + Food.hpp + Ingredients.hpp + MainDish.hpp + OishiiPapa.hpp + Order.hpp + Package.hpp + SideDish.hpp +) + +set(TEST_FILES + ut_Food.cpp + ut_Package.cpp + ut_Oishiipapa.cpp +) diff --git a/include/Drink.hpp b/include/Drink.hpp new file mode 100644 index 0000000..6e227b3 --- /dev/null +++ b/include/Drink.hpp @@ -0,0 +1,22 @@ +// +// Created by User on 2024/10/29. +// + +#ifndef OOP_DRINK_HPP +#define OOP_DRINK_HPP + +#include +#include "Food.hpp" +#include "Ingredients.hpp" + +class Drink final : public Food { +private: + int ml; +public: + Drink(Production id); + virtual void MakeFood() override; + void MakeLarger(); + int GetMl(); +}; + +#endif // OOP_DRINK_HPP diff --git a/include/Food.hpp b/include/Food.hpp new file mode 100644 index 0000000..3c61aa0 --- /dev/null +++ b/include/Food.hpp @@ -0,0 +1,25 @@ +// +// Created by User on 2024/10/29. +// + +#ifndef OOP_FOOD_HPP +#define OOP_FOOD_HPP + +#include +#include +#include "Ingredients.hpp" + +class Food { +protected: + Production id; + std::vector ingredient; + int money; +public: + Food(Production id); + Production getId() const; + std::vector GetIngredient(); + virtual void MakeFood() = 0; + int GetMoney(); +}; + +#endif // OOP_FOOD_HPP diff --git a/include/Ingredients.hpp b/include/Ingredients.hpp new file mode 100644 index 0000000..6c4b60e --- /dev/null +++ b/include/Ingredients.hpp @@ -0,0 +1,41 @@ +// +// Created by User on 2024/10/29. +// + +#ifndef OOP_INGREDIENTS_H +#define OOP_INGREDIENTS_H + +enum class Ingredients: unsigned long long{ + _NULL = 0, + PorkSteak, + BeefSteak, + FishSteak, + BurgerBread, + Lattuce, + Cheese, + FranchFries, + ChickenNugget, + Salad, + Cola, + Spirit, + Milktea, + Caramel, + Coffee, + Milk, +}; + +enum class Production: unsigned long long { + _NULL = 0, + PorkBurger, + BeefBurger, + FishBurger, + Frenchfries, + Nugget, + Salad, + Cola, + Spirit, + CaramelMilktea, + Latte, +}; + +#endif // OOP_INGREDIENTS_H diff --git a/include/MainDish.hpp b/include/MainDish.hpp new file mode 100644 index 0000000..12e63ef --- /dev/null +++ b/include/MainDish.hpp @@ -0,0 +1,22 @@ +// +// Created by User on 2024/10/29. +// + +#ifndef OOP_MAINDISH_HPP +#define OOP_MAINDISH_HPP + +#include "Food.hpp" +#include +#include +#include "Ingredients.hpp" + +class MainDish : public Food { +private: + std::vector addtional; +public: + MainDish(Production id); + void MakeFood() override; + void AddIngredients(std::vector addtional); +}; + +#endif // OOP_MAINDISH_HPP diff --git a/include/OishiiPapa.hpp b/include/OishiiPapa.hpp new file mode 100644 index 0000000..1688c80 --- /dev/null +++ b/include/OishiiPapa.hpp @@ -0,0 +1,24 @@ +#ifndef OISHII_PAPA_HPP +#define OISHII_PAPA_HPP + +#include "Drink.hpp" +#include "MainDish.hpp" +#include "SideDish.hpp" +#include "Package.hpp" +#include "Order.hpp" +#include +class OishiiPapa{ +private: + std::queue pipeline; + std::queue chest; + int money = 0; +public: + OishiiPapa(); + void MakeDish(); + void SendOrder(Order order); + Package Pickup(); + int GetMoney(); + Order GetOrderInfo(); +}; + +#endif \ No newline at end of file diff --git a/include/Order.hpp b/include/Order.hpp new file mode 100644 index 0000000..413a21b --- /dev/null +++ b/include/Order.hpp @@ -0,0 +1,19 @@ +#ifndef ORDER_HPP +#define ORDER_HPP + +#include +#include "Ingredients.hpp" + +class Order{ +private: + std::vector product; + std::vector addtional; + std::vector larger; +public: + Order(std::vector product, std::vector addtional ,std::vector larger); + std::vector GetProductInfo(); + std::vector GetAddtionalInfo(); + std::vector GetLargerInfo(); +}; + +#endif \ No newline at end of file diff --git a/include/Package.hpp b/include/Package.hpp new file mode 100644 index 0000000..4e14347 --- /dev/null +++ b/include/Package.hpp @@ -0,0 +1,29 @@ +// +// Created by User on 2024/10/29. +// + +#ifndef OOP_PACKAGE_HPP +#define OOP_PACKAGE_HPP + +#include "MainDish.hpp" +#include "SideDish.hpp" +#include "Drink.hpp" +#include +#include + +class Package { +private: + std::shared_ptr maindish = nullptr; + std::shared_ptr sidedish = nullptr; + std::shared_ptr drink = nullptr; + int money = 0; +public: + Package(); + void CountMoney(); + void SetMainDish(MainDish maindish); + void SetSideDish(SideDish sidedish); + void SetDrink(Drink drink); + int GetMoney(); +}; + +#endif // OOP_PACKAGE_HPP diff --git a/include/SideDish.hpp b/include/SideDish.hpp new file mode 100644 index 0000000..459c1be --- /dev/null +++ b/include/SideDish.hpp @@ -0,0 +1,28 @@ +// +// Created by User on 2024/10/29. +// + +#ifndef OOP_SIDEDISH_HPP +#define OOP_SIDEDISH_HPP + +#include +#include +#include "Food.hpp" +#include "Ingredients.hpp" + +enum class SideDishType { + BIG = 0, + SMALL = 1 +}; + +class SideDish final : public Food { +private: + SideDishType type = SideDishType::SMALL; +public: + SideDish(Production id); + void MakeFood() override; + void MakeLarger(); + SideDishType GetType(); +}; + +#endif // OOP_SIDEDISH_HPP diff --git a/score.json b/score.json new file mode 100644 index 0000000..f4c261d --- /dev/null +++ b/score.json @@ -0,0 +1,26 @@ +{ + "homework_name": "HW3", + "semester": "2024f", + "testsuites": [ + { + "testsuite": "MAINDISH_TEST", + "score": 20 + }, + { + "testsuite": "SIDEDISH_TEST", + "score": 20 + }, + { + "testsuite": "DRINK_TEST", + "score": 10 + }, + { + "testsuite": "PACKAGE_TEST", + "score": 30 + }, + { + "testsuite": "OISHIIPAPA_TEST", + "score": 20 + } + ] +} \ No newline at end of file diff --git a/scripts/CodeCoverage.cmake b/scripts/CodeCoverage.cmake new file mode 100644 index 0000000..d4a039f --- /dev/null +++ b/scripts/CodeCoverage.cmake @@ -0,0 +1,742 @@ +# Copyright (c) 2012 - 2017, Lars Bilke +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its contributors +# may be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# CHANGES: +# +# 2012-01-31, Lars Bilke +# - Enable Code Coverage +# +# 2013-09-17, Joakim Söderberg +# - Added support for Clang. +# - Some additional usage instructions. +# +# 2016-02-03, Lars Bilke +# - Refactored functions to use named parameters +# +# 2017-06-02, Lars Bilke +# - Merged with modified version from github.com/ufz/ogs +# +# 2019-05-06, Anatolii Kurotych +# - Remove unnecessary --coverage flag +# +# 2019-12-13, FeRD (Frank Dana) +# - Deprecate COVERAGE_LCOVR_EXCLUDES and COVERAGE_GCOVR_EXCLUDES lists in favor +# of tool-agnostic COVERAGE_EXCLUDES variable, or EXCLUDE setup arguments. +# - CMake 3.4+: All excludes can be specified relative to BASE_DIRECTORY +# - All setup functions: accept BASE_DIRECTORY, EXCLUDE list +# - Set lcov basedir with -b argument +# - Add automatic --demangle-cpp in lcovr, if 'c++filt' is available (can be +# overridden with NO_DEMANGLE option in setup_target_for_coverage_lcovr().) +# - Delete output dir, .info file on 'make clean' +# - Remove Python detection, since version mismatches will break gcovr +# - Minor cleanup (lowercase function names, update examples...) +# +# 2019-12-19, FeRD (Frank Dana) +# - Rename Lcov outputs, make filtered file canonical, fix cleanup for targets +# +# 2020-01-19, Bob Apthorpe +# - Added gfortran support +# +# 2020-02-17, FeRD (Frank Dana) +# - Make all add_custom_target()s VERBATIM to auto-escape wildcard characters +# in EXCLUDEs, and remove manual escaping from gcovr targets +# +# 2021-01-19, Robin Mueller +# - Add CODE_COVERAGE_VERBOSE option which will allow to print out commands which are run +# - Added the option for users to set the GCOVR_ADDITIONAL_ARGS variable to supply additional +# flags to the gcovr command +# +# 2020-05-04, Mihchael Davis +# - Add -fprofile-abs-path to make gcno files contain absolute paths +# - Fix BASE_DIRECTORY not working when defined +# - Change BYPRODUCT from folder to index.html to stop ninja from complaining about double defines +# +# 2021-05-10, Martin Stump +# - Check if the generator is multi-config before warning about non-Debug builds +# +# 2022-02-22, Marko Wehle +# - Change gcovr output from -o for --xml and --html output respectively. +# This will allow for Multiple Output Formats at the same time by making use of GCOVR_ADDITIONAL_ARGS, e.g. GCOVR_ADDITIONAL_ARGS "--txt". +# +# 2022-09-28, Sebastian Mueller +# - fix append_coverage_compiler_flags_to_target to correctly add flags +# - replace "-fprofile-arcs -ftest-coverage" with "--coverage" (equivalent) +# +# USAGE: +# +# 1. Copy this file into your cmake modules path. +# +# 2. Add the following line to your CMakeLists.txt (best inside an if-condition +# using a CMake option() to enable it just optionally): +# include(CodeCoverage) +# +# 3. Append necessary compiler flags for all supported source files: +# append_coverage_compiler_flags() +# Or for specific target: +# append_coverage_compiler_flags_to_target(YOUR_TARGET_NAME) +# +# 3.a (OPTIONAL) Set appropriate optimization flags, e.g. -O0, -O1 or -Og +# +# 4. If you need to exclude additional directories from the report, specify them +# using full paths in the COVERAGE_EXCLUDES variable before calling +# setup_target_for_coverage_*(). +# Example: +# set(COVERAGE_EXCLUDES +# '${PROJECT_SOURCE_DIR}/src/dir1/*' +# '/path/to/my/src/dir2/*') +# Or, use the EXCLUDE argument to setup_target_for_coverage_*(). +# Example: +# setup_target_for_coverage_lcov( +# NAME coverage +# EXECUTABLE testrunner +# EXCLUDE "${PROJECT_SOURCE_DIR}/src/dir1/*" "/path/to/my/src/dir2/*") +# +# 4.a NOTE: With CMake 3.4+, COVERAGE_EXCLUDES or EXCLUDE can also be set +# relative to the BASE_DIRECTORY (default: PROJECT_SOURCE_DIR) +# Example: +# set(COVERAGE_EXCLUDES "dir1/*") +# setup_target_for_coverage_gcovr_html( +# NAME coverage +# EXECUTABLE testrunner +# BASE_DIRECTORY "${PROJECT_SOURCE_DIR}/src" +# EXCLUDE "dir2/*") +# +# 5. Use the functions described below to create a custom make target which +# runs your test executable and produces a code coverage report. +# +# 6. Build a Debug build: +# cmake -DCMAKE_BUILD_TYPE=Debug .. +# make +# make my_coverage_target +# + +include(CMakeParseArguments) + +option(CODE_COVERAGE_VERBOSE "Verbose information" FALSE) + +# Check prereqs +find_program( GCOV_PATH gcov ) +find_program( LCOV_PATH NAMES lcov lcov.bat lcov.exe lcov.perl) +find_program( FASTCOV_PATH NAMES fastcov fastcov.py ) +find_program( GENHTML_PATH NAMES genhtml genhtml.perl genhtml.bat ) +find_program( GCOVR_PATH gcovr PATHS ${CMAKE_SOURCE_DIR}/scripts/test) +find_program( CPPFILT_PATH NAMES c++filt ) + +if(NOT GCOV_PATH) + message(FATAL_ERROR "gcov not found! Aborting...") +endif() # NOT GCOV_PATH + +# Check supported compiler (Clang, GNU and Flang) +get_property(LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES) +foreach(LANG ${LANGUAGES}) + if("${CMAKE_${LANG}_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang") + if("${CMAKE_${LANG}_COMPILER_VERSION}" VERSION_LESS 3) + message(FATAL_ERROR "Clang version must be 3.0.0 or greater! Aborting...") + endif() + elseif(NOT "${CMAKE_${LANG}_COMPILER_ID}" MATCHES "GNU" + AND NOT "${CMAKE_${LANG}_COMPILER_ID}" MATCHES "(LLVM)?[Ff]lang") + message(FATAL_ERROR "Compiler is not GNU or Flang! Aborting...") + endif() +endforeach() + +set(COVERAGE_COMPILER_FLAGS "-g --coverage" + CACHE INTERNAL "") +if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)") + include(CheckCXXCompilerFlag) + check_cxx_compiler_flag(-fprofile-abs-path HAVE_fprofile_abs_path) + if(HAVE_fprofile_abs_path) + set(COVERAGE_COMPILER_FLAGS "${COVERAGE_COMPILER_FLAGS} -fprofile-abs-path") + endif() +endif() + +set(CMAKE_Fortran_FLAGS_COVERAGE + ${COVERAGE_COMPILER_FLAGS} + CACHE STRING "Flags used by the Fortran compiler during coverage builds." + FORCE ) +set(CMAKE_CXX_FLAGS_COVERAGE + ${COVERAGE_COMPILER_FLAGS} + CACHE STRING "Flags used by the C++ compiler during coverage builds." + FORCE ) +set(CMAKE_C_FLAGS_COVERAGE + ${COVERAGE_COMPILER_FLAGS} + CACHE STRING "Flags used by the C compiler during coverage builds." + FORCE ) +set(CMAKE_EXE_LINKER_FLAGS_COVERAGE + "" + CACHE STRING "Flags used for linking binaries during coverage builds." + FORCE ) +set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE + "" + CACHE STRING "Flags used by the shared libraries linker during coverage builds." + FORCE ) +mark_as_advanced( + CMAKE_Fortran_FLAGS_COVERAGE + CMAKE_CXX_FLAGS_COVERAGE + CMAKE_C_FLAGS_COVERAGE + CMAKE_EXE_LINKER_FLAGS_COVERAGE + CMAKE_SHARED_LINKER_FLAGS_COVERAGE ) + +get_property(GENERATOR_IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) +if(NOT (CMAKE_BUILD_TYPE STREQUAL "Debug" OR GENERATOR_IS_MULTI_CONFIG)) + message(WARNING "Code coverage results with an optimised (non-Debug) build may be misleading") +endif() # NOT (CMAKE_BUILD_TYPE STREQUAL "Debug" OR GENERATOR_IS_MULTI_CONFIG) + +if(CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_Fortran_COMPILER_ID STREQUAL "GNU") + link_libraries(gcov) +endif() + +# Defines a target for running and collection code coverage information +# Builds dependencies, runs the given executable and outputs reports. +# NOTE! The executable should always have a ZERO as exit code otherwise +# the coverage generation will not complete. +# +# setup_target_for_coverage_lcov( +# NAME testrunner_coverage # New target name +# EXECUTABLE testrunner -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR +# DEPENDENCIES testrunner # Dependencies to build first +# BASE_DIRECTORY "../" # Base directory for report +# # (defaults to PROJECT_SOURCE_DIR) +# EXCLUDE "src/dir1/*" "src/dir2/*" # Patterns to exclude (can be relative +# # to BASE_DIRECTORY, with CMake 3.4+) +# NO_DEMANGLE # Don't demangle C++ symbols +# # even if c++filt is found +# ) +function(setup_target_for_coverage_lcov) + + set(options NO_DEMANGLE SONARQUBE) + set(oneValueArgs BASE_DIRECTORY NAME) + set(multiValueArgs EXCLUDE EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES LCOV_ARGS GENHTML_ARGS) + cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + if(NOT LCOV_PATH) + message(FATAL_ERROR "lcov not found! Aborting...") + endif() # NOT LCOV_PATH + + if(NOT GENHTML_PATH) + message(FATAL_ERROR "genhtml not found! Aborting...") + endif() # NOT GENHTML_PATH + + # Set base directory (as absolute path), or default to PROJECT_SOURCE_DIR + if(DEFINED Coverage_BASE_DIRECTORY) + get_filename_component(BASEDIR ${Coverage_BASE_DIRECTORY} ABSOLUTE) + else() + set(BASEDIR ${PROJECT_SOURCE_DIR}) + endif() + + # Collect excludes (CMake 3.4+: Also compute absolute paths) + set(LCOV_EXCLUDES "") + foreach(EXCLUDE ${Coverage_EXCLUDE} ${COVERAGE_EXCLUDES} ${COVERAGE_LCOV_EXCLUDES}) + if(CMAKE_VERSION VERSION_GREATER 3.4) + get_filename_component(EXCLUDE ${EXCLUDE} ABSOLUTE BASE_DIR ${BASEDIR}) + endif() + list(APPEND LCOV_EXCLUDES "${EXCLUDE}") + endforeach() + list(REMOVE_DUPLICATES LCOV_EXCLUDES) + + # Conditional arguments + if(CPPFILT_PATH AND NOT ${Coverage_NO_DEMANGLE}) + set(GENHTML_EXTRA_ARGS "--demangle-cpp") + endif() + + # Setting up commands which will be run to generate coverage data. + # Cleanup lcov + set(LCOV_CLEAN_CMD + ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} -directory . + -b ${BASEDIR} --zerocounters + ) + # Create baseline to make sure untouched files show up in the report + set(LCOV_BASELINE_CMD + ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} -c -i -d . -b + ${BASEDIR} -o ${Coverage_NAME}.base + ) + # Run tests + set(LCOV_EXEC_TESTS_CMD + ${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS} + ) + # Capturing lcov counters and generating report + set(LCOV_CAPTURE_CMD + ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} --directory . -b + ${BASEDIR} --capture --output-file ${Coverage_NAME}.capture + ) + # add baseline counters + set(LCOV_BASELINE_COUNT_CMD + ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} -a ${Coverage_NAME}.base + -a ${Coverage_NAME}.capture --output-file ${Coverage_NAME}.total + ) + # filter collected data to final coverage report + set(LCOV_FILTER_CMD + ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} --remove + ${Coverage_NAME}.total ${LCOV_EXCLUDES} --output-file ${Coverage_NAME}.info + ) + # Generate HTML output + set(LCOV_GEN_HTML_CMD + ${GENHTML_PATH} ${GENHTML_EXTRA_ARGS} ${Coverage_GENHTML_ARGS} -o + ${Coverage_NAME} ${Coverage_NAME}.info + ) + if(${Coverage_SONARQUBE}) + # Generate SonarQube output + set(GCOVR_XML_CMD + ${GCOVR_PATH} --sonarqube ${Coverage_NAME}_sonarqube.xml -r ${BASEDIR} ${GCOVR_ADDITIONAL_ARGS} + ${GCOVR_EXCLUDE_ARGS} --object-directory=${PROJECT_BINARY_DIR} + ) + set(GCOVR_XML_CMD_COMMAND + COMMAND ${GCOVR_XML_CMD} + ) + set(GCOVR_XML_CMD_BYPRODUCTS ${Coverage_NAME}_sonarqube.xml) + set(GCOVR_XML_CMD_COMMENT COMMENT "SonarQube code coverage info report saved in ${Coverage_NAME}_sonarqube.xml.") + endif() + + + if(CODE_COVERAGE_VERBOSE) + message(STATUS "Executed command report") + message(STATUS "Command to clean up lcov: ") + string(REPLACE ";" " " LCOV_CLEAN_CMD_SPACED "${LCOV_CLEAN_CMD}") + message(STATUS "${LCOV_CLEAN_CMD_SPACED}") + + message(STATUS "Command to create baseline: ") + string(REPLACE ";" " " LCOV_BASELINE_CMD_SPACED "${LCOV_BASELINE_CMD}") + message(STATUS "${LCOV_BASELINE_CMD_SPACED}") + + message(STATUS "Command to run the tests: ") + string(REPLACE ";" " " LCOV_EXEC_TESTS_CMD_SPACED "${LCOV_EXEC_TESTS_CMD}") + message(STATUS "${LCOV_EXEC_TESTS_CMD_SPACED}") + + message(STATUS "Command to capture counters and generate report: ") + string(REPLACE ";" " " LCOV_CAPTURE_CMD_SPACED "${LCOV_CAPTURE_CMD}") + message(STATUS "${LCOV_CAPTURE_CMD_SPACED}") + + message(STATUS "Command to add baseline counters: ") + string(REPLACE ";" " " LCOV_BASELINE_COUNT_CMD_SPACED "${LCOV_BASELINE_COUNT_CMD}") + message(STATUS "${LCOV_BASELINE_COUNT_CMD_SPACED}") + + message(STATUS "Command to filter collected data: ") + string(REPLACE ";" " " LCOV_FILTER_CMD_SPACED "${LCOV_FILTER_CMD}") + message(STATUS "${LCOV_FILTER_CMD_SPACED}") + + message(STATUS "Command to generate lcov HTML output: ") + string(REPLACE ";" " " LCOV_GEN_HTML_CMD_SPACED "${LCOV_GEN_HTML_CMD}") + message(STATUS "${LCOV_GEN_HTML_CMD_SPACED}") + + if(${Coverage_SONARQUBE}) + message(STATUS "Command to generate SonarQube XML output: ") + string(REPLACE ";" " " GCOVR_XML_CMD_SPACED "${GCOVR_XML_CMD}") + message(STATUS "${GCOVR_XML_CMD_SPACED}") + endif() + endif() + + # Setup target + add_custom_target(${Coverage_NAME} + COMMAND ${LCOV_CLEAN_CMD} + COMMAND ${LCOV_BASELINE_CMD} + COMMAND ${LCOV_EXEC_TESTS_CMD} + COMMAND ${LCOV_CAPTURE_CMD} + COMMAND ${LCOV_BASELINE_COUNT_CMD} + COMMAND ${LCOV_FILTER_CMD} + COMMAND ${LCOV_GEN_HTML_CMD} + ${GCOVR_XML_CMD_COMMAND} + + # Set output files as GENERATED (will be removed on 'make clean') + BYPRODUCTS + ${Coverage_NAME}.base + ${Coverage_NAME}.capture + ${Coverage_NAME}.total + ${Coverage_NAME}.info + ${GCOVR_XML_CMD_BYPRODUCTS} + ${Coverage_NAME}/index.html + WORKING_DIRECTORY ${PROJECT_BINARY_DIR} + DEPENDS ${Coverage_DEPENDENCIES} + VERBATIM # Protect arguments to commands + COMMENT "Resetting code coverage counters to zero.\nProcessing code coverage counters and generating report." + ) + + # Show where to find the lcov info report + add_custom_command(TARGET ${Coverage_NAME} POST_BUILD + COMMAND ; + COMMENT "Lcov code coverage info report saved in ${Coverage_NAME}.info." + ${GCOVR_XML_CMD_COMMENT} + ) + + # Show info where to find the report + add_custom_command(TARGET ${Coverage_NAME} POST_BUILD + COMMAND ; + COMMENT "Open ./${Coverage_NAME}/index.html in your browser to view the coverage report." + ) + +endfunction() # setup_target_for_coverage_lcov + +# Defines a target for running and collection code coverage information +# Builds dependencies, runs the given executable and outputs reports. +# NOTE! The executable should always have a ZERO as exit code otherwise +# the coverage generation will not complete. +# +# setup_target_for_coverage_gcovr_xml( +# NAME ctest_coverage # New target name +# EXECUTABLE ctest -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR +# DEPENDENCIES executable_target # Dependencies to build first +# BASE_DIRECTORY "../" # Base directory for report +# # (defaults to PROJECT_SOURCE_DIR) +# EXCLUDE "src/dir1/*" "src/dir2/*" # Patterns to exclude (can be relative +# # to BASE_DIRECTORY, with CMake 3.4+) +# ) +# The user can set the variable GCOVR_ADDITIONAL_ARGS to supply additional flags to the +# GCVOR command. +function(setup_target_for_coverage_gcovr_xml) + + set(options NONE) + set(oneValueArgs BASE_DIRECTORY NAME) + set(multiValueArgs EXCLUDE EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES) + cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + if(NOT GCOVR_PATH) + message(FATAL_ERROR "gcovr not found! Aborting...") + endif() # NOT GCOVR_PATH + + # Set base directory (as absolute path), or default to PROJECT_SOURCE_DIR + if(DEFINED Coverage_BASE_DIRECTORY) + get_filename_component(BASEDIR ${Coverage_BASE_DIRECTORY} ABSOLUTE) + else() + set(BASEDIR ${PROJECT_SOURCE_DIR}) + endif() + + # Collect excludes (CMake 3.4+: Also compute absolute paths) + set(GCOVR_EXCLUDES "") + foreach(EXCLUDE ${Coverage_EXCLUDE} ${COVERAGE_EXCLUDES} ${COVERAGE_GCOVR_EXCLUDES}) + if(CMAKE_VERSION VERSION_GREATER 3.4) + get_filename_component(EXCLUDE ${EXCLUDE} ABSOLUTE BASE_DIR ${BASEDIR}) + endif() + list(APPEND GCOVR_EXCLUDES "${EXCLUDE}") + endforeach() + list(REMOVE_DUPLICATES GCOVR_EXCLUDES) + + # Combine excludes to several -e arguments + set(GCOVR_EXCLUDE_ARGS "") + foreach(EXCLUDE ${GCOVR_EXCLUDES}) + list(APPEND GCOVR_EXCLUDE_ARGS "-e") + list(APPEND GCOVR_EXCLUDE_ARGS "${EXCLUDE}") + endforeach() + + # Set up commands which will be run to generate coverage data + # Run tests + set(GCOVR_XML_EXEC_TESTS_CMD + ${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS} + ) + # Running gcovr + set(GCOVR_XML_CMD + ${GCOVR_PATH} --xml ${Coverage_NAME}.xml -r ${BASEDIR} ${GCOVR_ADDITIONAL_ARGS} + ${GCOVR_EXCLUDE_ARGS} --object-directory=${PROJECT_BINARY_DIR} + ) + + if(CODE_COVERAGE_VERBOSE) + message(STATUS "Executed command report") + + message(STATUS "Command to run tests: ") + string(REPLACE ";" " " GCOVR_XML_EXEC_TESTS_CMD_SPACED "${GCOVR_XML_EXEC_TESTS_CMD}") + message(STATUS "${GCOVR_XML_EXEC_TESTS_CMD_SPACED}") + + message(STATUS "Command to generate gcovr XML coverage data: ") + string(REPLACE ";" " " GCOVR_XML_CMD_SPACED "${GCOVR_XML_CMD}") + message(STATUS "${GCOVR_XML_CMD_SPACED}") + endif() + + add_custom_target(${Coverage_NAME} + COMMAND ${GCOVR_XML_EXEC_TESTS_CMD} + COMMAND ${GCOVR_XML_CMD} + + BYPRODUCTS ${Coverage_NAME}.xml + WORKING_DIRECTORY ${PROJECT_BINARY_DIR} + DEPENDS ${Coverage_DEPENDENCIES} + VERBATIM # Protect arguments to commands + COMMENT "Running gcovr to produce Cobertura code coverage report." + ) + + # Show info where to find the report + add_custom_command(TARGET ${Coverage_NAME} POST_BUILD + COMMAND ; + COMMENT "Cobertura code coverage report saved in ${Coverage_NAME}.xml." + ) +endfunction() # setup_target_for_coverage_gcovr_xml + +# Defines a target for running and collection code coverage information +# Builds dependencies, runs the given executable and outputs reports. +# NOTE! The executable should always have a ZERO as exit code otherwise +# the coverage generation will not complete. +# +# setup_target_for_coverage_gcovr_html( +# NAME ctest_coverage # New target name +# EXECUTABLE ctest -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR +# DEPENDENCIES executable_target # Dependencies to build first +# BASE_DIRECTORY "../" # Base directory for report +# # (defaults to PROJECT_SOURCE_DIR) +# EXCLUDE "src/dir1/*" "src/dir2/*" # Patterns to exclude (can be relative +# # to BASE_DIRECTORY, with CMake 3.4+) +# ) +# The user can set the variable GCOVR_ADDITIONAL_ARGS to supply additional flags to the +# GCVOR command. +function(setup_target_for_coverage_gcovr_html) + + set(options NONE) + set(oneValueArgs BASE_DIRECTORY NAME) + set(multiValueArgs EXCLUDE EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES) + cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + if(NOT GCOVR_PATH) + message(FATAL_ERROR "gcovr not found! Aborting...") + endif() # NOT GCOVR_PATH + + # Set base directory (as absolute path), or default to PROJECT_SOURCE_DIR + if(DEFINED Coverage_BASE_DIRECTORY) + get_filename_component(BASEDIR ${Coverage_BASE_DIRECTORY} ABSOLUTE) + else() + set(BASEDIR ${PROJECT_SOURCE_DIR}) + endif() + + # Collect excludes (CMake 3.4+: Also compute absolute paths) + set(GCOVR_EXCLUDES "") + foreach(EXCLUDE ${Coverage_EXCLUDE} ${COVERAGE_EXCLUDES} ${COVERAGE_GCOVR_EXCLUDES}) + if(CMAKE_VERSION VERSION_GREATER 3.4) + get_filename_component(EXCLUDE ${EXCLUDE} ABSOLUTE BASE_DIR ${BASEDIR}) + endif() + list(APPEND GCOVR_EXCLUDES "${EXCLUDE}") + endforeach() + list(REMOVE_DUPLICATES GCOVR_EXCLUDES) + + # Combine excludes to several -e arguments + set(GCOVR_EXCLUDE_ARGS "") + foreach(EXCLUDE ${GCOVR_EXCLUDES}) + list(APPEND GCOVR_EXCLUDE_ARGS "-e") + list(APPEND GCOVR_EXCLUDE_ARGS "${EXCLUDE}") + endforeach() + + # Set up commands which will be run to generate coverage data + # Run tests + set(GCOVR_HTML_EXEC_TESTS_CMD + ${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS} + ) + # Create folder + set(GCOVR_HTML_FOLDER_CMD + ${CMAKE_COMMAND} -E make_directory ${PROJECT_BINARY_DIR}/${Coverage_NAME} + ) + # Running gcovr + set(GCOVR_HTML_CMD + ${GCOVR_PATH} --html ${Coverage_NAME}/index.html --html-details -r ${BASEDIR} ${GCOVR_ADDITIONAL_ARGS} + ${GCOVR_EXCLUDE_ARGS} --object-directory=${PROJECT_BINARY_DIR} + ) + + if(CODE_COVERAGE_VERBOSE) + message(STATUS "Executed command report") + + message(STATUS "Command to run tests: ") + string(REPLACE ";" " " GCOVR_HTML_EXEC_TESTS_CMD_SPACED "${GCOVR_HTML_EXEC_TESTS_CMD}") + message(STATUS "${GCOVR_HTML_EXEC_TESTS_CMD_SPACED}") + + message(STATUS "Command to create a folder: ") + string(REPLACE ";" " " GCOVR_HTML_FOLDER_CMD_SPACED "${GCOVR_HTML_FOLDER_CMD}") + message(STATUS "${GCOVR_HTML_FOLDER_CMD_SPACED}") + + message(STATUS "Command to generate gcovr HTML coverage data: ") + string(REPLACE ";" " " GCOVR_HTML_CMD_SPACED "${GCOVR_HTML_CMD}") + message(STATUS "${GCOVR_HTML_CMD_SPACED}") + endif() + + add_custom_target(${Coverage_NAME} + COMMAND ${GCOVR_HTML_EXEC_TESTS_CMD} + COMMAND ${GCOVR_HTML_FOLDER_CMD} + COMMAND ${GCOVR_HTML_CMD} + + BYPRODUCTS ${PROJECT_BINARY_DIR}/${Coverage_NAME}/index.html # report directory + WORKING_DIRECTORY ${PROJECT_BINARY_DIR} + DEPENDS ${Coverage_DEPENDENCIES} + VERBATIM # Protect arguments to commands + COMMENT "Running gcovr to produce HTML code coverage report." + ) + + # Show info where to find the report + add_custom_command(TARGET ${Coverage_NAME} POST_BUILD + COMMAND ; + COMMENT "Open ./${Coverage_NAME}/index.html in your browser to view the coverage report." + ) + +endfunction() # setup_target_for_coverage_gcovr_html + +# Defines a target for running and collection code coverage information +# Builds dependencies, runs the given executable and outputs reports. +# NOTE! The executable should always have a ZERO as exit code otherwise +# the coverage generation will not complete. +# +# setup_target_for_coverage_fastcov( +# NAME testrunner_coverage # New target name +# EXECUTABLE testrunner -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR +# DEPENDENCIES testrunner # Dependencies to build first +# BASE_DIRECTORY "../" # Base directory for report +# # (defaults to PROJECT_SOURCE_DIR) +# EXCLUDE "src/dir1/" "src/dir2/" # Patterns to exclude. +# NO_DEMANGLE # Don't demangle C++ symbols +# # even if c++filt is found +# SKIP_HTML # Don't create html report +# POST_CMD perl -i -pe s!${PROJECT_SOURCE_DIR}/!!g ctest_coverage.json # E.g. for stripping source dir from file paths +# ) +function(setup_target_for_coverage_fastcov) + + set(options NO_DEMANGLE SKIP_HTML) + set(oneValueArgs BASE_DIRECTORY NAME) + set(multiValueArgs EXCLUDE EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES FASTCOV_ARGS GENHTML_ARGS POST_CMD) + cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + if(NOT FASTCOV_PATH) + message(FATAL_ERROR "fastcov not found! Aborting...") + endif() + + if(NOT Coverage_SKIP_HTML AND NOT GENHTML_PATH) + message(FATAL_ERROR "genhtml not found! Aborting...") + endif() + + # Set base directory (as absolute path), or default to PROJECT_SOURCE_DIR + if(Coverage_BASE_DIRECTORY) + get_filename_component(BASEDIR ${Coverage_BASE_DIRECTORY} ABSOLUTE) + else() + set(BASEDIR ${PROJECT_SOURCE_DIR}) + endif() + + # Collect excludes (Patterns, not paths, for fastcov) + set(FASTCOV_EXCLUDES "") + foreach(EXCLUDE ${Coverage_EXCLUDE} ${COVERAGE_EXCLUDES} ${COVERAGE_FASTCOV_EXCLUDES}) + list(APPEND FASTCOV_EXCLUDES "${EXCLUDE}") + endforeach() + list(REMOVE_DUPLICATES FASTCOV_EXCLUDES) + + # Conditional arguments + if(CPPFILT_PATH AND NOT ${Coverage_NO_DEMANGLE}) + set(GENHTML_EXTRA_ARGS "--demangle-cpp") + endif() + + # Set up commands which will be run to generate coverage data + set(FASTCOV_EXEC_TESTS_CMD ${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS}) + + set(FASTCOV_CAPTURE_CMD ${FASTCOV_PATH} ${Coverage_FASTCOV_ARGS} --gcov ${GCOV_PATH} + --search-directory ${BASEDIR} + --process-gcno + --output ${Coverage_NAME}.json + --exclude ${FASTCOV_EXCLUDES} + ) + + set(FASTCOV_CONVERT_CMD ${FASTCOV_PATH} + -C ${Coverage_NAME}.json --lcov --output ${Coverage_NAME}.info + ) + + if(Coverage_SKIP_HTML) + set(FASTCOV_HTML_CMD ";") + else() + set(FASTCOV_HTML_CMD ${GENHTML_PATH} ${GENHTML_EXTRA_ARGS} ${Coverage_GENHTML_ARGS} + -o ${Coverage_NAME} ${Coverage_NAME}.info + ) + endif() + + set(FASTCOV_POST_CMD ";") + if(Coverage_POST_CMD) + set(FASTCOV_POST_CMD ${Coverage_POST_CMD}) + endif() + + if(CODE_COVERAGE_VERBOSE) + message(STATUS "Code coverage commands for target ${Coverage_NAME} (fastcov):") + + message(" Running tests:") + string(REPLACE ";" " " FASTCOV_EXEC_TESTS_CMD_SPACED "${FASTCOV_EXEC_TESTS_CMD}") + message(" ${FASTCOV_EXEC_TESTS_CMD_SPACED}") + + message(" Capturing fastcov counters and generating report:") + string(REPLACE ";" " " FASTCOV_CAPTURE_CMD_SPACED "${FASTCOV_CAPTURE_CMD}") + message(" ${FASTCOV_CAPTURE_CMD_SPACED}") + + message(" Converting fastcov .json to lcov .info:") + string(REPLACE ";" " " FASTCOV_CONVERT_CMD_SPACED "${FASTCOV_CONVERT_CMD}") + message(" ${FASTCOV_CONVERT_CMD_SPACED}") + + if(NOT Coverage_SKIP_HTML) + message(" Generating HTML report: ") + string(REPLACE ";" " " FASTCOV_HTML_CMD_SPACED "${FASTCOV_HTML_CMD}") + message(" ${FASTCOV_HTML_CMD_SPACED}") + endif() + if(Coverage_POST_CMD) + message(" Running post command: ") + string(REPLACE ";" " " FASTCOV_POST_CMD_SPACED "${FASTCOV_POST_CMD}") + message(" ${FASTCOV_POST_CMD_SPACED}") + endif() + endif() + + # Setup target + add_custom_target(${Coverage_NAME} + + # Cleanup fastcov + COMMAND ${FASTCOV_PATH} ${Coverage_FASTCOV_ARGS} --gcov ${GCOV_PATH} + --search-directory ${BASEDIR} + --zerocounters + + COMMAND ${FASTCOV_EXEC_TESTS_CMD} + COMMAND ${FASTCOV_CAPTURE_CMD} + COMMAND ${FASTCOV_CONVERT_CMD} + COMMAND ${FASTCOV_HTML_CMD} + COMMAND ${FASTCOV_POST_CMD} + + # Set output files as GENERATED (will be removed on 'make clean') + BYPRODUCTS + ${Coverage_NAME}.info + ${Coverage_NAME}.json + ${Coverage_NAME}/index.html # report directory + + WORKING_DIRECTORY ${PROJECT_BINARY_DIR} + DEPENDS ${Coverage_DEPENDENCIES} + VERBATIM # Protect arguments to commands + COMMENT "Resetting code coverage counters to zero. Processing code coverage counters and generating report." + ) + + set(INFO_MSG "fastcov code coverage info report saved in ${Coverage_NAME}.info and ${Coverage_NAME}.json.") + if(NOT Coverage_SKIP_HTML) + string(APPEND INFO_MSG " Open ${PROJECT_BINARY_DIR}/${Coverage_NAME}/index.html in your browser to view the coverage report.") + endif() + # Show where to find the fastcov info report + add_custom_command(TARGET ${Coverage_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E echo ${INFO_MSG} + ) + +endfunction() # setup_target_for_coverage_fastcov + +function(append_coverage_compiler_flags) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE) + set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE) + message(STATUS "Appending code coverage compiler flags: ${COVERAGE_COMPILER_FLAGS}") +endfunction() # append_coverage_compiler_flags + +# Setup coverage for specific library +function(append_coverage_compiler_flags_to_target name) + separate_arguments(_flag_list NATIVE_COMMAND "${COVERAGE_COMPILER_FLAGS}") + target_compile_options(${name} PRIVATE ${_flag_list}) + if(CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_Fortran_COMPILER_ID STREQUAL "GNU") + target_link_libraries(${name} PRIVATE gcov) + endif() +endfunction() diff --git a/scripts/coverage.sh b/scripts/coverage.sh new file mode 100644 index 0000000..ccf24b5 --- /dev/null +++ b/scripts/coverage.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +# This script is intended to be used in automated testing +# Specifically, in a Linux environment with certain packages installed +# If you want to use this script, please copy this file and make changes +# However, we DO NOT guarantee this script would work on every machine + +: ${CC:=gcc} +: ${CXX:=g++} + +BUILD_DIR=coverage_build + +cmake \ + -B $BUILD_DIR \ + -DCOVERAGE=ON \ + -DCMAKE_C_COMPILER=$CC \ + -DCMAKE_CXX_COMPILER=$CXX \ + +cmake --build $BUILD_DIR + +"./${BUILD_DIR}/ut_all" + +cmake --build $BUILD_DIR --target ut_all_coverage diff --git a/src/Drink.cpp b/src/Drink.cpp new file mode 100644 index 0000000..a36da9a --- /dev/null +++ b/src/Drink.cpp @@ -0,0 +1,40 @@ +// +// Created by User on 2024/10/29. +// + +#include "Drink.hpp" +Drink::Drink(Production id) : Food(id){ + MakeFood(); +} +void Drink::MakeFood() { + switch (id) { + case Production::Cola: + ingredient = {Ingredients::Cola}; + money = 28; + break; + case Production::Spirit: + ingredient = {Ingredients::Spirit}; + money = 28; + break; + case Production::CaramelMilktea: + ingredient = {Ingredients::Caramel,Ingredients::Milktea}; + money = 44; + break; + case Production::Latte: + ingredient = {Ingredients::Milk,Ingredients::Coffee}; + money = 45; + break; + } +} +void Drink::MakeLarger(){ + switch (id) { + case Production::CaramelMilktea: + break; + default: + ml = 750; + money+=10; + } +} +int Drink::GetMl(){ + return ml; +} \ No newline at end of file diff --git a/src/Food.cpp b/src/Food.cpp new file mode 100644 index 0000000..a1b723d --- /dev/null +++ b/src/Food.cpp @@ -0,0 +1,16 @@ +// +// Created by User on 2024/10/29. +// +#include "Food.hpp" + + +Food::Food(Production id) : id(id) {} +Production Food::getId() const { + return id; +} +std::vector Food::GetIngredient(){ + return ingredient; +} +int Food::GetMoney() { + return money; +} \ No newline at end of file diff --git a/src/MainDish.cpp b/src/MainDish.cpp new file mode 100644 index 0000000..47352d3 --- /dev/null +++ b/src/MainDish.cpp @@ -0,0 +1,52 @@ +// +// Created by User on 2024/10/29. +// + +#include "MainDish.hpp" + + +MainDish::MainDish(Production id) : Food(id){ + MakeFood(); +} +void MainDish::MakeFood() { + switch (id) { + case Production::PorkBurger: + ingredient = {Ingredients::PorkSteak,Ingredients::Lattuce,Ingredients::BurgerBread,Ingredients::Cheese}; + money = 59; + break; + case Production::BeefBurger: + ingredient = {Ingredients::BeefSteak,Ingredients::Lattuce,Ingredients::BurgerBread,Ingredients::Cheese}; + money = 69; + break; + case Production::FishBurger: + ingredient = {Ingredients::FishSteak,Ingredients::Lattuce,Ingredients::BurgerBread,Ingredients::Cheese}; + money = 79; + break; + } +} +void MainDish::AddIngredients(std::vector addtional){ + this->addtional = addtional; + int add_mon = 0; + for(auto i:addtional){ + switch (i) { + case Ingredients::PorkSteak: + add_mon+=20; + break; + case Ingredients::BeefSteak: + add_mon+=20; + break; + case Ingredients::FishSteak: + add_mon+=20; + break; + case Ingredients::Lattuce: + add_mon+=10; + break; + case Ingredients::Cheese: + add_mon+=10; + break; + default: + throw std::invalid_argument("Can't add the thing to here."); + } + } + money += add_mon; +} diff --git a/src/OishiiPapa.cpp b/src/OishiiPapa.cpp new file mode 100644 index 0000000..63395de --- /dev/null +++ b/src/OishiiPapa.cpp @@ -0,0 +1,55 @@ +#include "OishiiPapa.hpp" + + +OishiiPapa::OishiiPapa() {} +int OishiiPapa::GetMoney() { + return money; +} +void OishiiPapa::SendOrder(Order order){ + pipeline.push(order); + if(chest.size() >= 15){ + return; + } + MakeDish(); +} +void OishiiPapa::MakeDish() { + if(pipeline.empty()){ + throw std::out_of_range("Pipeline is empty"); + } + + auto order = pipeline.front(); + pipeline.pop(); + Package pack; + auto product = order.GetProductInfo(); + auto addtion = order.GetAddtionalInfo(); + auto large = order.GetLargerInfo(); + if(product[0] != Production::_NULL){ + MainDish maindish(product[0]); + if(addtion.size()) maindish.AddIngredients(addtion); + pack.SetMainDish(maindish); + } + if(product[1] != Production::_NULL){ + SideDish sideDish(product[1]); + if(large[0]) sideDish.MakeLarger(); + pack.SetSideDish(sideDish); + } + if(product[2] != Production::_NULL){ + Drink drink(product[2]); + if(large[1]) drink.MakeLarger(); + pack.SetDrink(drink); + } + pack.CountMoney(); + chest.push(pack); +} +Package OishiiPapa::Pickup() { + if(chest.empty()){ + throw std::out_of_range("Chest is empty"); + } + auto tmp = chest.front(); + chest.pop(); + if(chest.size() < 15 && !pipeline.empty()) { + MakeDish(); + } + money += tmp.GetMoney(); + return tmp; +} \ No newline at end of file diff --git a/src/Order.cpp b/src/Order.cpp new file mode 100644 index 0000000..3de9339 --- /dev/null +++ b/src/Order.cpp @@ -0,0 +1,20 @@ + + +#include + + +Order::Order(std::vector product, std::vector addtional, std::vector larger) { + this->addtional = addtional; + this->product = product; + this->larger = larger; +} + +std::vector Order::GetProductInfo(){ + return product; +} +std::vector Order::GetAddtionalInfo(){ + return addtional; +} +std::vector Order::GetLargerInfo(){ + return larger; +} \ No newline at end of file diff --git a/src/Package.cpp b/src/Package.cpp new file mode 100644 index 0000000..f652390 --- /dev/null +++ b/src/Package.cpp @@ -0,0 +1,32 @@ +// +// Created by User on 2024/10/29. +// + +#include "Package.hpp" + +Package::Package(){ +} +void Package::CountMoney(){ + if(maindish != NULL){ + money += maindish->GetMoney(); + } + if(sidedish != NULL){ + money += sidedish->GetMoney(); + } + if(drink != NULL){ + money += drink->GetMoney(); + } + if(sidedish && maindish && drink) money-=15; +} +int Package::GetMoney(){ + return money; +} +void Package::SetDrink(Drink drink) { + this->drink = std::make_shared(drink); +} +void Package::SetMainDish(MainDish maindish) { + this->maindish = std::make_shared(maindish); +} +void Package::SetSideDish(SideDish sidedish) { + this->sidedish = std::make_shared(sidedish); +} \ No newline at end of file diff --git a/src/SideDish.cpp b/src/SideDish.cpp new file mode 100644 index 0000000..469c4bd --- /dev/null +++ b/src/SideDish.cpp @@ -0,0 +1,37 @@ +// +// Created by User on 2024/10/29. +// + +#include "SideDish.hpp" + +SideDish::SideDish(Production id) : Food(id) { + MakeFood(); +} + +void SideDish::MakeFood() { + switch (id) { + case Production::Frenchfries: + ingredient = {Ingredients::FranchFries}; + money = 44; + break; + case Production::Nugget: + ingredient = {Ingredients::ChickenNugget}; + money = 44; + break; + case Production::Salad: + ingredient = {Ingredients::Salad}; + money = 59; + break; + } +} + +void SideDish::MakeLarger(){ + switch (id) { + case Production::Salad: + break; + default: + money+=15; + type = SideDishType::BIG; + } +} +SideDishType SideDish::GetType() {return type;} \ No newline at end of file diff --git a/test/ut_Food.cpp b/test/ut_Food.cpp new file mode 100644 index 0000000..ca06918 --- /dev/null +++ b/test/ut_Food.cpp @@ -0,0 +1,128 @@ +#include +#include +#include "MainDish.hpp" +#include "SideDish.hpp" +#include "Drink.hpp" + +TEST(MAINDISH_TEST, check_maindish_should_have_correct_id){ + MainDish mainDish(Production::BeefBurger); + + Production product = mainDish.getId(); + + ASSERT_EQ(product,Production::BeefBurger); +} +TEST(MAINDISH_TEST, check_maindish_should_have_correct_money){ + MainDish mainDish(Production::FishBurger); + + int price = mainDish.GetMoney(); + + ASSERT_EQ(price,79); +} +TEST(MAINDISH_TEST, check_maindish_should_have_correct_ingredients){ + MainDish mainDish(Production::FishBurger); + + auto ingredients = mainDish.GetIngredient(); + + ASSERT_EQ(ingredients[0],Ingredients::FishSteak); + ASSERT_EQ(ingredients[1],Ingredients::Lattuce); + ASSERT_EQ(ingredients[2],Ingredients::BurgerBread); + ASSERT_EQ(ingredients[3],Ingredients::Cheese); +} +TEST(MAINDISH_TEST, check_maindish_should_throw_invalid_argument_for_additional_food){ + MainDish mainDish(Production::FishBurger); + std::vector addition = {Ingredients::Lattuce,Ingredients::Caramel}; + + ASSERT_THROW(mainDish.AddIngredients(addition),std::invalid_argument); +} + +TEST(MAINDISH_TEST, check_maindish_should_throw_invalid_argument_for_additional_food_two){ + MainDish mainDish(Production::FishBurger); + std::vector addition = { + Ingredients::Cola, + Ingredients::Caramel, + Ingredients::ChickenNugget, + Ingredients::Lattuce, + Ingredients::Milk, + Ingredients::Milktea, + Ingredients::Spirit, + }; + + ASSERT_THROW(mainDish.AddIngredients(addition),std::invalid_argument); +} +TEST(MAINDISH_TEST, check_maindish_should_have_correct_money_after_get_addtional_food){ + MainDish mainDish(Production::FishBurger); + std::vector addition = {Ingredients::Lattuce,Ingredients::FishSteak}; + + mainDish.AddIngredients(addition); + int price = mainDish.GetMoney(); + + ASSERT_EQ(price,109); +} +TEST(MAINDISH_TEST, check_maindish_should_have_correct_money_after_get_addtional_food_two){ + MainDish mainDish(Production::FishBurger); + std::vector addition = { + Ingredients::Lattuce, + Ingredients::FishSteak, + Ingredients::BeefSteak, + Ingredients::Cheese, + }; + + mainDish.AddIngredients(addition); + int price = mainDish.GetMoney(); + + ASSERT_EQ(price,139); +} +TEST(SIDEDISH_TEST, check_sidedish_should_have_correct_id){ + SideDish sidedish(Production::Frenchfries); + + Production product = sidedish.getId(); + + ASSERT_EQ(product,Production::Frenchfries); +} +TEST(SIDEDISH_TEST, check_sidedish_is_small){ + SideDish sidedish(Production::Nugget); + + SideDishType product = sidedish.GetType(); + + ASSERT_EQ(product,SideDishType::SMALL); +} + +TEST(SIDEDISH_TEST, check_sidedish_can_make_larger){ + SideDish sidedish(Production::Frenchfries); + sidedish.MakeLarger(); + + SideDishType product = sidedish.GetType(); + + ASSERT_EQ(product,SideDishType::BIG); +} + +TEST(SIDEDISH_TEST, check_sidedish_make_larger_maintain_same){ + SideDish sidedish(Production::Salad); + + sidedish.MakeLarger(); + SideDishType product = sidedish.GetType(); + + ASSERT_EQ(product,SideDishType::SMALL); +} +TEST(DRINK_TEST,check_drink_have_correct_id){ + Drink drink(Production::Latte); + + Production product = drink.getId(); + + ASSERT_EQ(product,Production::Latte); +} +TEST(DRINK_TEST,check_drink_have_correct_price){ + Drink drink(Production::CaramelMilktea); + + int price = drink.GetMoney(); + + ASSERT_EQ(price,44); +} +TEST(DRINK_TEST,check_drink_make_larger){ + Drink drink(Production::Cola); + drink.MakeLarger(); + + int cc = drink.GetMl(); + + ASSERT_EQ(cc,750); +} \ No newline at end of file diff --git a/test/ut_Oishiipapa.cpp b/test/ut_Oishiipapa.cpp new file mode 100644 index 0000000..748d161 --- /dev/null +++ b/test/ut_Oishiipapa.cpp @@ -0,0 +1,211 @@ +#include "OishiiPapa.hpp" +#include "Order.hpp" +#include +#include + +TEST(OISHIIPAPA_TEST, check_papa_should_throw_exception_for_chest){ + OishiiPapa ohpapa; + + ASSERT_THROW(ohpapa.Pickup(),std::out_of_range); +} +TEST(OISHIIPAPA_TEST, check_papa_should_throw_exception_for_pipeline){ + OishiiPapa ohpapa; + + ASSERT_THROW(ohpapa.MakeDish(),std::out_of_range); +} +TEST(OISHIIPAPA_TEST, check_papa_should_take_care_of_pickup){ + //Make Object Oishii Papa. + OishiiPapa ohpapa; + + //Production. + std::vector product1 = {Production::PorkBurger,Production::_NULL,Production::_NULL}; + std::vector product2 = {Production::FishBurger,Production::_NULL,Production::_NULL}; + std::vector product3 = {Production::BeefBurger,Production::_NULL,Production::_NULL}; + std::vector product4 = {Production::_NULL,Production::Frenchfries,Production::_NULL}; + std::vector product5 = {Production::_NULL,Production::Nugget,Production::_NULL}; + std::vector product6 = {Production::_NULL,Production::Salad,Production::_NULL}; + std::vector product7 = {Production::_NULL,Production::_NULL,Production::Spirit}; + std::vector product8 = {Production::_NULL,Production::_NULL,Production::Cola}; + std::vector product9 = {Production::_NULL,Production::_NULL,Production::CaramelMilktea}; + std::vector product10 = {Production::_NULL,Production::_NULL,Production::Latte}; + std::vector product11 = {Production::PorkBurger,Production::_NULL,Production::Cola}; + std::vector product12 = {Production::FishBurger,Production::Frenchfries,Production::CaramelMilktea}; + std::vector product13 = {Production::BeefBurger,Production::Nugget,Production::Cola}; + std::vector product14 = {Production::FishBurger,Production::Salad,Production::Spirit}; + std::vector product15 = {Production::BeefBurger,Production::Salad,Production::Latte}; + std::vector product16 = {Production::PorkBurger,Production::Nugget,Production::Cola}; + std::vector product17 = {Production::PorkBurger,Production::Frenchfries,Production::_NULL}; + //Addtional Ingredients. + std::vector additional1 = {Ingredients::Lattuce,Ingredients::Cheese}; + std::vector additional2 = {Ingredients::PorkSteak,Ingredients::Cheese}; + std::vector additional3 = {Ingredients::FishSteak,Ingredients::Lattuce}; + std::vector additional4 = {Ingredients::BeefSteak,Ingredients::BeefSteak}; + std::vector additional5 = {Ingredients::Lattuce,Ingredients::PorkSteak,Ingredients::Cheese}; + std::vector additional6 = {Ingredients::Lattuce,Ingredients::PorkSteak,Ingredients::FishSteak}; + std::vector additional7 = {Ingredients::Lattuce,Ingredients::BeefSteak}; + std::vector additional8 = {}; + //If larger. + std::vector condition1 = {true, true}; + std::vector condition2 = {true, false}; + std::vector condition3 = {false, true}; + std::vector condition4 = {false, false}; + //Make order object. + Order OrderList1(product1,additional1,condition4); + Order OrderList2(product2,additional2,condition4); + Order OrderList3(product3,additional3,condition4); + Order OrderList4(product4,additional8,condition2); + Order OrderList5(product5,additional8,condition2); + Order OrderList6(product6,additional8,condition4); + Order OrderList7(product7,additional8,condition4); + Order OrderList8(product8,additional8,condition3); + Order OrderList9(product9,additional8,condition4); + Order OrderList10(product10,additional8,condition3); + Order OrderList11(product11,additional1,condition3); + Order OrderList12(product12,additional2,condition2); + Order OrderList13(product13,additional3,condition1); + Order OrderList14(product14,additional4,condition3); + Order OrderList15(product15,additional5,condition3); + Order OrderList16(product16,additional6,condition4); + Order OrderList17(product16,additional7,condition1); + Order OrderList18(product16,additional8,condition1); + Order OrderList19(product15,additional8,condition3); + Order OrderList20(product17,additional1,condition2); + + //Test. + ohpapa.SendOrder(OrderList1); + ohpapa.SendOrder(OrderList2); + ohpapa.SendOrder(OrderList3); + ohpapa.SendOrder(OrderList4); + ohpapa.SendOrder(OrderList5); + ohpapa.SendOrder(OrderList6); + ohpapa.SendOrder(OrderList7); + ohpapa.SendOrder(OrderList8); + ohpapa.SendOrder(OrderList9); + ohpapa.SendOrder(OrderList10); + ohpapa.SendOrder(OrderList11); + ohpapa.SendOrder(OrderList12); + ohpapa.SendOrder(OrderList13); + ohpapa.SendOrder(OrderList14); + ohpapa.SendOrder(OrderList15); + ohpapa.SendOrder(OrderList16); + ohpapa.SendOrder(OrderList17); + ohpapa.SendOrder(OrderList18); + ohpapa.SendOrder(OrderList19); + ohpapa.SendOrder(OrderList20); + //Result. + + Package pack; + MainDish pb(Production::PorkBurger); + pb.AddIngredients(additional1); + pack.SetMainDish(pb); + pack.CountMoney(); + + auto tmp = ohpapa.Pickup(); + + ASSERT_EQ(tmp.GetMoney(),pack.GetMoney()); + ASSERT_EQ(ohpapa.GetMoney(),pack.GetMoney()); +} +TEST(OISHIIPAPA_TEST, check_papa_should_take_care_of_pickup_part2){ + //Make Object Oishii Papa. + OishiiPapa ohpapa; + + //Production. + std::vector product1 = {Production::PorkBurger,Production::_NULL,Production::_NULL}; + std::vector product2 = {Production::FishBurger,Production::_NULL,Production::_NULL}; + std::vector product3 = {Production::BeefBurger,Production::_NULL,Production::_NULL}; + std::vector product4 = {Production::_NULL,Production::Frenchfries,Production::_NULL}; + std::vector product5 = {Production::_NULL,Production::Nugget,Production::_NULL}; + std::vector product6 = {Production::_NULL,Production::Salad,Production::_NULL}; + std::vector product7 = {Production::_NULL,Production::_NULL,Production::Spirit}; + std::vector product8 = {Production::_NULL,Production::_NULL,Production::Cola}; + std::vector product9 = {Production::_NULL,Production::_NULL,Production::CaramelMilktea}; + std::vector product10 = {Production::_NULL,Production::_NULL,Production::Latte}; + std::vector product11 = {Production::PorkBurger,Production::_NULL,Production::Cola}; + std::vector product12 = {Production::FishBurger,Production::Frenchfries,Production::CaramelMilktea}; + std::vector product13 = {Production::BeefBurger,Production::Nugget,Production::Cola}; + std::vector product14 = {Production::FishBurger,Production::Salad,Production::Spirit}; + std::vector product15 = {Production::BeefBurger,Production::Salad,Production::Latte}; + std::vector product16 = {Production::PorkBurger,Production::Nugget,Production::Cola}; + std::vector product17 = {Production::PorkBurger,Production::Frenchfries,Production::_NULL}; + //Addtional Ingredients. + std::vector additional1 = {Ingredients::Lattuce,Ingredients::Cheese}; + std::vector additional2 = {Ingredients::PorkSteak,Ingredients::Cheese}; + std::vector additional3 = {Ingredients::FishSteak,Ingredients::Lattuce}; + std::vector additional4 = {Ingredients::BeefSteak,Ingredients::BeefSteak}; + std::vector additional5 = {Ingredients::Lattuce,Ingredients::PorkSteak,Ingredients::Cheese}; + std::vector additional6 = {Ingredients::Lattuce,Ingredients::PorkSteak,Ingredients::FishSteak}; + std::vector additional7 = {Ingredients::Lattuce,Ingredients::BeefSteak}; + std::vector additional8 = {}; + //If larger. + std::vector condition1 = {true, true}; + std::vector condition2 = {true, false}; + std::vector condition3 = {false, true}; + std::vector condition4 = {false, false}; + //Make order object. + Order OrderList1(product1,additional1,condition4); + Order OrderList2(product2,additional2,condition4); + Order OrderList3(product3,additional3,condition4); + Order OrderList4(product4,additional8,condition2); + Order OrderList5(product5,additional8,condition2); + Order OrderList6(product6,additional8,condition4); + Order OrderList7(product7,additional8,condition4); + Order OrderList8(product8,additional8,condition3); + Order OrderList9(product9,additional8,condition4); + Order OrderList10(product10,additional8,condition3); + Order OrderList11(product11,additional1,condition3); + Order OrderList12(product12,additional2,condition2); + Order OrderList13(product13,additional3,condition1); + Order OrderList14(product14,additional4,condition3); + Order OrderList15(product15,additional5,condition3); + Order OrderList16(product16,additional6,condition4); + Order OrderList17(product16,additional7,condition1); + Order OrderList18(product16,additional8,condition1); + Order OrderList19(product15,additional8,condition3); + Order OrderList20(product17,additional1,condition2); + + //Test. + ohpapa.SendOrder(OrderList1); + ohpapa.SendOrder(OrderList2); + ohpapa.SendOrder(OrderList3); + ohpapa.SendOrder(OrderList4); + ohpapa.SendOrder(OrderList5); + ohpapa.SendOrder(OrderList6); + ohpapa.SendOrder(OrderList7); + ohpapa.SendOrder(OrderList8); + ohpapa.SendOrder(OrderList9); + ohpapa.SendOrder(OrderList10); + ohpapa.SendOrder(OrderList11); + ohpapa.SendOrder(OrderList12); + ohpapa.SendOrder(OrderList13); + ohpapa.SendOrder(OrderList14); + ohpapa.SendOrder(OrderList15); + ohpapa.SendOrder(OrderList16); + ohpapa.SendOrder(OrderList17); + ohpapa.SendOrder(OrderList18); + ohpapa.SendOrder(OrderList19); + ohpapa.SendOrder(OrderList20); + //Result. + + ohpapa.Pickup(); + ohpapa.Pickup(); + ohpapa.Pickup(); + ohpapa.Pickup(); + ohpapa.Pickup(); + ohpapa.Pickup(); + ohpapa.Pickup(); + ohpapa.Pickup(); + ohpapa.Pickup(); + ohpapa.Pickup(); + ohpapa.Pickup(); + ohpapa.Pickup(); + ohpapa.Pickup(); + ohpapa.Pickup(); + ohpapa.Pickup(); + ohpapa.Pickup(); + ohpapa.Pickup(); + ohpapa.Pickup(); + ohpapa.Pickup(); + ohpapa.Pickup(); + + ASSERT_EQ(ohpapa.GetMoney(),2317); +} \ No newline at end of file diff --git a/test/ut_Package.cpp b/test/ut_Package.cpp new file mode 100644 index 0000000..cf6efa9 --- /dev/null +++ b/test/ut_Package.cpp @@ -0,0 +1,51 @@ +#include +#include +#include "Package.hpp" + +TEST(PACKAGE_TEST, check_package_should_have_correct_money){ + Package pack; + MainDish maindish(Production::PorkBurger); + SideDish sidedish(Production::Frenchfries); + + pack.SetMainDish(maindish); + pack.SetSideDish(sidedish); + pack.CountMoney(); + + int price = pack.GetMoney(); + + ASSERT_EQ(price,103); +} + +TEST(PACKAGE_TEST, check_package_should_have_correct_money_for_pack){ + Package pack; + MainDish maindish(Production::PorkBurger); + SideDish sidedish(Production::Frenchfries); + Drink drink(Production::Cola); + drink.MakeLarger(); + + pack.SetMainDish(maindish); + pack.SetSideDish(sidedish); + pack.SetDrink(drink); + pack.CountMoney(); + + int price = pack.GetMoney(); + + ASSERT_EQ(maindish.GetMoney(),59); + ASSERT_EQ(sidedish.GetMoney(),44); + ASSERT_EQ(drink.GetMoney(),38); + ASSERT_EQ(price,126); +} + +TEST(PACKAGE_TEST, check_package_should_have_correct_money_for_only_a_thing){ + Package pack; + MainDish maindish(Production::PorkBurger); + + + pack.SetMainDish(maindish); + pack.CountMoney(); + + int price = pack.GetMoney(); + + ASSERT_EQ(maindish.GetMoney(),59); + ASSERT_EQ(price,59); +} \ No newline at end of file