From 6c742f726e4bc113c3453a834fadbe0be7a9f61f Mon Sep 17 00:00:00 2001 From: pwiatr3 Date: Sat, 15 Jan 2022 12:33:17 +0100 Subject: [PATCH] done --- CMakeLists.txt | 25 +++++++++++++++++++---- Car.cpp | 24 ++++++++++++++++++++++ Car.hpp | 33 ++++++++++++++++++++++++++++++ ElectricCar.cpp | 18 +++++++++++------ ElectricCar.hpp | 18 +++++++++-------- HybridCar.cpp | 17 +++++++--------- HybridCar.hpp | 18 +++++++---------- InvalidGear.hpp | 6 ++++++ PetrolCar.cpp | 24 +++++++++++++++------- PetrolCar.hpp | 22 ++++++++++++-------- PetrolEngine.cpp | 9 +++++++++ PetrolEngine.hpp | 3 +++ main.cpp | 37 +++++++++++++++++----------------- test.cpp | 52 ++++++++++++++++++++++++++++++++++++++++++++++++ 14 files changed, 234 insertions(+), 72 deletions(-) create mode 100644 Car.cpp create mode 100644 Car.hpp create mode 100644 InvalidGear.hpp create mode 100644 test.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index e6ff1b6..c8ca2f4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,18 +2,35 @@ cmake_minimum_required(VERSION 3.2) set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED ON) +#set(CMAKE_CXX_COMPILER g++-10) project(Cars) +include(FetchContent) +FetchContent_Declare( + googletest + GIT_REPOSITORY https://github.com/google/googletest.git + GIT_TAG main +) +# For Windows: Prevent overriding the parent project's compiler/linker settings +set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) +FetchContent_MakeAvailable(googletest) set(SRC_LIST + Car.cpp ElectricCar.cpp ElectricEngine.cpp HybridCar.cpp - main.cpp PetrolCar.cpp PetrolEngine.cpp ) -add_executable(${PROJECT_NAME} ${SRC_LIST}) -target_compile_options(${PROJECT_NAME} PUBLIC -Wall -Werror -Wpedantic -Wextra) -target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_SOURCE_DIR}) +add_executable(${PROJECT_NAME} ${SRC_LIST} main.cpp) + +#target_compile_options(${PROJECT_NAME} PUBLIC -Wall -Wpedantic -Wextra) +#target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_SOURCE_DIR}) + +add_executable(${PROJECT_NAME}-ut ${SRC_LIST} test.cpp) +target_link_libraries(${PROJECT_NAME}-ut gtest_main) + +enable_testing() +add_test(NAME ${PROJECT_NAME}_test COMMAND ${PROJECT_NAME}) diff --git a/Car.cpp b/Car.cpp new file mode 100644 index 0000000..3c8d980 --- /dev/null +++ b/Car.cpp @@ -0,0 +1,24 @@ +#include "Car.hpp" +#include + +void Car::turnLeft() { std::cout << __FUNCTION__ << std::endl; } +void Car::turnRight() { std::cout << __FUNCTION__ << std::endl; } + +void Car::brake() { + speed_ = 0.0; +} +void Car::accelerate(int speed) { + if(speed < 0.0) { + throw std::range_error("Speed can't be below zero!"); + } + if(speed > maxSpeed) { + throw std::range_error("Speed can't be over 300.0 km/h!"); + } + speed_ = speed; +} +void Car::changeEngine(std::unique_ptr) { + throw std::invalid_argument("This is not a petrol car!"); +} +void Car::changeEngine(std::unique_ptr) { + throw std::invalid_argument("This is not an electric car!"); +} \ No newline at end of file diff --git a/Car.hpp b/Car.hpp new file mode 100644 index 0000000..cb470dd --- /dev/null +++ b/Car.hpp @@ -0,0 +1,33 @@ +#pragma once +#include +#include +#include "ElectricEngine.hpp" +#include "PetrolEngine.hpp" + +constexpr float maxSpeed = 300.0; + +class Car +{ +public: + virtual ~Car(){} + + void turnLeft(); + void turnRight(); + void brake(); + void accelerate(int speed); + virtual void refill() = 0; + virtual void changeEngine(std::unique_ptr enginePtr); + virtual void changeEngine(std::unique_ptr enginePtr); + + // getters + float getSpeed() const { return speed_; } + + // execption + class CarMoving : public std::logic_error { + public: + CarMoving(const std::string &msg) : + std::logic_error(msg) {} + }; +private: + float speed_; +}; \ No newline at end of file diff --git a/ElectricCar.cpp b/ElectricCar.cpp index d5e479e..09a0648 100644 --- a/ElectricCar.cpp +++ b/ElectricCar.cpp @@ -1,16 +1,22 @@ #include "ElectricCar.hpp" #include -ElectricCar::ElectricCar(ElectricEngine* engine) - : engine_(engine) +ElectricCar::ElectricCar(std::unique_ptr engine) + : engine_(std::move(engine)) { std::cout << __FUNCTION__ << std::endl; } ElectricCar::~ElectricCar() { std::cout << __FUNCTION__ << std::endl; } -void ElectricCar::turnLeft() { std::cout << __FUNCTION__ << std::endl; } -void ElectricCar::turnRight() { std::cout << __FUNCTION__ << std::endl; } -void ElectricCar::brake() { std::cout << __FUNCTION__ << std::endl; } -void ElectricCar::accelerate(int) { std::cout << __FUNCTION__ << std::endl; } void ElectricCar::charge() { std::cout << __FUNCTION__ << std::endl; } +void ElectricCar::changeEngine(std::unique_ptr electricEngine) { + if(this->getSpeed() != 0.0) { + engine_ = std::move(electricEngine); + return; + } + throw Car::CarMoving{"Can't change an engine when car is moving!"}; +} +void ElectricCar::refill() { + charge(); +} diff --git a/ElectricCar.hpp b/ElectricCar.hpp index 261bf83..b08991f 100644 --- a/ElectricCar.hpp +++ b/ElectricCar.hpp @@ -1,16 +1,18 @@ +#pragma once +#include "Car.hpp" #include "ElectricEngine.hpp" -class ElectricCar +class ElectricCar : public virtual Car { public: - ElectricCar(ElectricEngine* engine); + ElectricCar(std::unique_ptr engine); ~ElectricCar(); - void turnLeft(); - void turnRight(); - void brake(); - void accelerate(int speed); - void charge(); - ElectricEngine* engine_; + void changeEngine(std::unique_ptr electricEngine); + void refill() override; + +private: + void charge(); + std::unique_ptr engine_; }; diff --git a/HybridCar.cpp b/HybridCar.cpp index 25c0a7c..c061786 100644 --- a/HybridCar.cpp +++ b/HybridCar.cpp @@ -1,19 +1,16 @@ #include "HybridCar.hpp" #include -HybridCar::HybridCar(PetrolEngine* petrolEng, ElectricEngine* electricEng) - : petrolEngine_(petrolEng) - , electricEngine_(electricEng) +HybridCar::HybridCar(std::unique_ptr petrolEng, std::unique_ptr electricEng) + : ElectricCar(std::move(electricEng)) + , PetrolCar(std::move(petrolEng)) { std::cout << __FUNCTION__ << std::endl; } HybridCar::~HybridCar() { std::cout << __FUNCTION__ << std::endl; } -void HybridCar::turnLeft() { std::cout << __FUNCTION__ << std::endl; } -void HybridCar::turnRight() { std::cout << __FUNCTION__ << std::endl; } -void HybridCar::brake() { std::cout << __FUNCTION__ << std::endl; } -void HybridCar::accelerate(int) { std::cout << __FUNCTION__ << std::endl; } -void HybridCar::charge() { std::cout << __FUNCTION__ << std::endl; } -void HybridCar::refuel() { std::cout << __FUNCTION__ << std::endl; } - +void HybridCar::refill() { + ElectricCar::refill(); + PetrolCar::refill(); +} diff --git a/HybridCar.hpp b/HybridCar.hpp index f66faa7..5e1420f 100644 --- a/HybridCar.hpp +++ b/HybridCar.hpp @@ -1,19 +1,15 @@ +#pragma once +#include "ElectricCar.hpp" #include "ElectricEngine.hpp" +#include "PetrolCar.hpp" #include "PetrolEngine.hpp" +#include -class HybridCar +class HybridCar : public ElectricCar, public PetrolCar { public: - HybridCar(PetrolEngine* petrolEng, ElectricEngine* electricEng); + HybridCar(std::unique_ptr petrolEng, std::unique_ptr electricEng); ~HybridCar(); - void turnLeft(); - void turnRight(); - void brake(); - void accelerate(int speed); - void charge(); - void refuel(); - - PetrolEngine* petrolEngine_; - ElectricEngine* electricEngine_; + void refill() override; }; diff --git a/InvalidGear.hpp b/InvalidGear.hpp new file mode 100644 index 0000000..d4b8920 --- /dev/null +++ b/InvalidGear.hpp @@ -0,0 +1,6 @@ +#pragma once +#include + +struct InvalidGear : public std::logic_error { + InvalidGear(std::string msg) : std::logic_error(msg) {} +}; \ No newline at end of file diff --git a/PetrolCar.cpp b/PetrolCar.cpp index 56554b0..1d04b39 100644 --- a/PetrolCar.cpp +++ b/PetrolCar.cpp @@ -1,16 +1,26 @@ #include "PetrolCar.hpp" #include - -PetrolCar::PetrolCar(PetrolEngine* engine) - : engine_(engine) + +PetrolCar::PetrolCar(std::unique_ptr engine) + : engine_(std::move(engine)) { std::cout << __FUNCTION__ << std::endl; } PetrolCar::~PetrolCar() { std::cout << __FUNCTION__ << std::endl; } -void PetrolCar::turnLeft() { std::cout << __FUNCTION__ << std::endl; } -void PetrolCar::turnRight() { std::cout << __FUNCTION__ << std::endl; } -void PetrolCar::brake() { std::cout << __FUNCTION__ << std::endl; } -void PetrolCar::accelerate(int) { std::cout << __FUNCTION__ << std::endl; } void PetrolCar::refuel() { std::cout << __FUNCTION__ << std::endl; } +void PetrolCar::changeGear(int gear) { + engine_->changeGear(gear); +} +void PetrolCar::changeEngine(std::unique_ptr petrolEngine) { + if(this->getSpeed() != 0.0) { + engine_ = std::move(petrolEngine); + return; + } + throw Car::CarMoving{"Can't change an engine when car is moving!"}; +} + +void PetrolCar::refill() { + refuel(); +} diff --git a/PetrolCar.hpp b/PetrolCar.hpp index 4fb7a88..bee37f6 100644 --- a/PetrolCar.hpp +++ b/PetrolCar.hpp @@ -1,16 +1,22 @@ +#pragma once +#include +#include #include "PetrolEngine.hpp" +#include "Car.hpp" -class PetrolCar + +class PetrolCar : virtual public Car { public: - PetrolCar(PetrolEngine* engine); + PetrolCar(std::unique_ptr petrolEngine); ~PetrolCar(); - void turnLeft(); - void turnRight(); - void brake(); - void accelerate(int speed); - void refuel(); - PetrolEngine* engine_; + void changeGear(int gear); + void changeEngine(std::unique_ptr petrolEngine); + void refill() override; + +private: + void refuel(); + std::unique_ptr engine_; }; diff --git a/PetrolEngine.cpp b/PetrolEngine.cpp index 2aeceb9..863344e 100644 --- a/PetrolEngine.cpp +++ b/PetrolEngine.cpp @@ -1,5 +1,7 @@ #include "PetrolEngine.hpp" #include +#include + PetrolEngine::PetrolEngine(int power, float capacity, int gears) : power_(power) @@ -15,6 +17,13 @@ void PetrolEngine::changeGear(int gear) // TODO: Add checking if gear is between -1 and gears_ // -1 is for REAR // 0 is for NEUTRAL + if(gear < -1 || gear > gears_) { + throw InvalidGear("Invalid gear. Gear needs to be between 1 and " + std::to_string(gear)); + } + if(gear != 0 && abs(gear - currentGear_) != 1) { + throw InvalidGear("Invalid gear change from: " + std::to_string(currentGear_)+ " to: " + std::to_string(gear)); + } currentGear_ = gear; + std::cout << __FUNCTION__ << std::endl; } diff --git a/PetrolEngine.hpp b/PetrolEngine.hpp index b222bb9..83a4747 100644 --- a/PetrolEngine.hpp +++ b/PetrolEngine.hpp @@ -1,11 +1,14 @@ #pragma once +#include "InvalidGear.hpp" class PetrolEngine { public: + PetrolEngine(int power, float capacity, int gears); void changeGear(int gear); +private: int power_; // in HP float capacity_; // in ccm int gears_; diff --git a/main.cpp b/main.cpp index f364af4..3fbecd7 100644 --- a/main.cpp +++ b/main.cpp @@ -1,3 +1,4 @@ +#include "Car.hpp" #include "PetrolCar.hpp" #include "ElectricCar.hpp" #include "HybridCar.hpp" @@ -5,24 +6,24 @@ int main() { - std::cout << std::endl << "OPEL" << std::endl; - PetrolCar opel(new PetrolEngine(120, 1800, 6)); - opel.accelerate(50); - opel.brake(); - opel.accelerate(-900); - opel.refuel(); + // std::cout << std::endl << "OPEL" << std::endl; + // PetrolCar opel(new PetrolEngine(120, 1800, 6)); + // opel.accelerate(50); + // opel.brake(); + // opel.accelerate(-900); + // opel.refuel(); - std::cout << std::endl << "NISSAN" << std::endl; - ElectricCar nissan(new ElectricEngine(130, 650)); - nissan.charge(); - nissan.accelerate(80); - nissan.engine_ = new ElectricEngine(150, 700); // Changing an engine during driving is not safe - nissan.turnLeft(); + // std::cout << std::endl << "NISSAN" << std::endl; + // ElectricCar nissan(new ElectricEngine(130, 650)); + // nissan.charge(); + // nissan.accelerate(80); + // nissan.engine_ = new ElectricEngine(150, 700); // Changing an engine during driving is not safe + // nissan.turnLeft(); - std::cout << std::endl << "TOYOTA" << std::endl; - HybridCar toyota(new PetrolEngine(80, 1400, 5), new ElectricEngine(100, 540)); - toyota.accelerate(100); - toyota.brake(); - toyota.charge(); - toyota.refuel(); + // std::cout << std::endl << "TOYOTA" << std::endl; + // HybridCar toyota(new PetrolEngine(80, 1400, 5), new ElectricEngine(100, 540)); + // toyota.accelerate(100); + // toyota.brake(); + // toyota.charge(); + // toyota.refuel(); } diff --git a/test.cpp b/test.cpp new file mode 100644 index 0000000..9698951 --- /dev/null +++ b/test.cpp @@ -0,0 +1,52 @@ +#include "gtest/gtest.h" +#include "Car.hpp" +#include "PetrolCar.hpp" +#include "ElectricCar.hpp" +#include "HybridCar.hpp" +#include "InvalidGear.hpp"" + + +// Tests throwing std::range_error when accelerate to speed = -999 or speed > maxSpeed is invoked +TEST(PetrolCarClassTest, ShouldThrowRangeError) { + PetrolCar opel(std::make_unique(120, 1800, 6)); + EXPECT_THROW(opel.accelerate(-999), std::range_error); + EXPECT_THROW(opel.accelerate(350), std::range_error); + +} +// Tests throwing InvalidGear when wrong gear is set +TEST(PetrolCarChangeGearTest, ShouldThrowIvalidGear) { + PetrolCar opel(std::make_unique(120, 1800, 6)); + EXPECT_THROW(opel.changeGear(-2), InvalidGear); + EXPECT_THROW(opel.changeGear(7), InvalidGear); + EXPECT_THROW(opel.changeGear(2), InvalidGear); + opel.changeGear(1); + EXPECT_THROW(opel.changeGear(5), InvalidGear); +} +// Tests if changeGear doesn't throw an exception +TEST(PetrolCarChangeGearTest, ShouldNotThrowException) { + PetrolCar opel(std::make_unique(120, 1800, 6)); + EXPECT_NO_THROW(opel.changeGear(1)); + EXPECT_NO_THROW(opel.changeGear(2)); + EXPECT_NO_THROW(opel.changeGear(3)); + EXPECT_NO_THROW(opel.changeGear(2)); + EXPECT_NO_THROW(opel.changeGear(1)); + EXPECT_NO_THROW(opel.changeGear(0)); + EXPECT_NO_THROW(opel.changeGear(-1)); +} +// Tests throwing std::range_error when accelerate to speed = -999 or speed > maxSpeed is invoked +TEST(ElectricCarClassTest, ShouldThrowRangeError) { + ElectricCar nissan(std::make_unique(130, 650)); + EXPECT_THROW(nissan.accelerate(-999), std::range_error); + EXPECT_THROW(nissan.accelerate(350), std::range_error); +} +// Tests throwing std::invalid_argument when changing engine for the wrong one +TEST(CarClassPointerTest, ShouldThrowInvalidArgument) { + ElectricCar nissan(std::make_unique(130, 650)); + Car * car = &nissan; + // Electric car can't have petrol engine + EXPECT_THROW(car->changeEngine(std::make_unique(150, 700, 7)), std::invalid_argument); + PetrolCar opel(std::make_unique(120, 1800, 6)); + car = &opel; + // Petrol car can't have electric engine + EXPECT_THROW(car->changeEngine(std::make_unique(130, 650)), std::invalid_argument); +} \ No newline at end of file