commit ecb3c6b24a598a45b68e84846574399a21ff6941 Author: ge11021 Date: Fri Dec 9 15:04:47 2022 +0800 First commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5acb669 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +build +.vscode diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..86df128 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,43 @@ +cmake_minimum_required(VERSION 3.1.0) +project(test) + +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/modules/") + +configure_file(CMakeLists.txt.in googletest-download/CMakeLists.txt) +execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" . + RESULT_VARIABLE result + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/googletest-download ) +if(result) + message(FATAL_ERROR "CMake step for googletest failed: ${result}") +endif() +execute_process(COMMAND ${CMAKE_COMMAND} --build . + RESULT_VARIABLE result + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/googletest-download ) +if(result) + message(FATAL_ERROR "Build step for googletest failed: ${result}") +endif() + +# Prevent overriding the parent project's compiler/linker +# settings on Windows +set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) + +# Add googletest directly to our build. This defines +# the gtest and gtest_main targets. +add_subdirectory(${CMAKE_CURRENT_BINARY_DIR}/googletest-src + ${CMAKE_CURRENT_BINARY_DIR}/googletest-build + EXCLUDE_FROM_ALL) + +# The gtest/gtest_main targets carry header search path +# dependencies automatically when using CMake 2.8.11 or +# later. Otherwise we have to add them here ourselves. +if (CMAKE_VERSION VERSION_LESS 2.8.11) + include_directories("${gtest_SOURCE_DIR}/include") +endif() + +set(GCC_COVERAGE_COMPILE_FLAGS "-g -O0 -coverage -fprofile-arcs -ftest-coverage") +set(GCC_COVERAGE_LINK_FLAGS "-coverage -lgcov") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GCC_COVERAGE_COMPILE_FLAGS}" ) +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${GCC_COVERAGE_LINK_FLAGS}" ) + +add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/src) +add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/unittest) diff --git a/CMakeLists.txt.in b/CMakeLists.txt.in new file mode 100644 index 0000000..f0d7593 --- /dev/null +++ b/CMakeLists.txt.in @@ -0,0 +1,15 @@ +cmake_minimum_required(VERSION 3.1.0) + +project(googletest-download NONE) + +include(ExternalProject) +ExternalProject_Add(googletest +# URL ${CMAKE_SOURCE_DIR}/thirdparty/gtest/googletest-release-1.8.0.zip + URL https://github.com/google/googletest/archive/release-1.12.1.zip + SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-src" + BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-build" + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + TEST_COMMAND "" +) \ No newline at end of file diff --git a/Readme.md b/Readme.md new file mode 100644 index 0000000..ae2b491 --- /dev/null +++ b/Readme.md @@ -0,0 +1,58 @@ +# OOP Exercise - Google Test + +## 使用方法 + +clone 專案 +```sh +git clone https://gitea.cglab.cs.nccu.edu.tw/yhchen/gtest_exercise.git +``` +建立 build 資料夾,所有編譯需要的檔案會被建立在這個資料夾裡面 +```sh +mkdir build +cd build +``` +使用 cmake 建立 makefile,並編譯檔案 +```sh +cmake .. +make +``` +進到 `unittest` 目錄,如果有看到 `utest` 執行檔,代表編譯順利完成 + +## 練習內容 +在 `src` 目錄中含有 `sphere` 物件的宣告及實作,但是這個程式碼中有一些錯誤的部分,同學需要自己撰寫 `unittest` 來找出程式碼錯誤的部分並做出修正 + +## 覆蓋率計算 +這個專案的 cmake 檔案包含計算覆蓋率的工具,會在編譯 `unittest` 及 `src` 目錄時同時產生覆蓋率統計的檔案在 `build/資料夾位置/CMakeFiles/專案名稱.dir/檔案名稱.cc.gcno`,在執行過程式之後,可以執行下列指令顯示覆蓋率 + +```sh +gcov +``` + +在 macos 中,預設使用的內建 gcov 會無法開啟生成的檔案,需要使用 homebrew 安裝的 gcov(安裝 gcc 時會自動安裝),通常為 `gcov-12`,執行下列指令能夠檢查是否使用內建的 gcov +```sh +which gcov +``` +如果輸出為 `/usr/bin/gcov`,就代表使用的是內建的 gcov。 + +## 附錄 +### Linux 環境下安裝 cmake (以 ubuntu 為例) + +若環境有需要,請自行加上 `sudo` + +```sh +apt update +apt install g++ cmake +``` +### Windows 環境下安裝 cmake + +可以安裝 Windows Subsystem of Linux,並按照上述 Linux 的步驟操作 + +### MacOS 環境下安裝 cmake + +需先安裝 brew,安裝完成後執行 + +```sh +brew install gcc cmake +``` + +若使用的是 M1 mac,需要手動將 g++ 加入 PATH,請自行 google diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..f274e7e --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION 3.1.0) +project(sphere) + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage") +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs -ftest-coverage") +set(CMAKE_EXE_LINKER_FLAGS "--coverage") + +add_library(sphere sphere.cc) \ No newline at end of file diff --git a/src/sphere.cc b/src/sphere.cc new file mode 100644 index 0000000..360285e --- /dev/null +++ b/src/sphere.cc @@ -0,0 +1,59 @@ +#include "sphere.h" + +#include +#include +using namespace std; + +Sphere::Sphere() { + this->orig_x = 0.0; + this->orig_y = 0.0; + this->orig_z = 0.0; + this->radius = 0.0; +} + +Sphere::Sphere(float ox, float oy, float oz, float rad) { + this->orig_x = ox; + this->orig_y = oy; + this->orig_z = oz; + if (rad >= 0) + this->radius = rad; + else + this->radius = 0; +} + +float* Sphere::getOrigin() { + float* result = new float[3]{this->orig_x, this->orig_y, this->orig_z}; + return result; +} + +float Sphere::getRadius() { + return this->radius; +} + +void Sphere::setOrigin(float ox, float oy, float oz) { + this->orig_x = ox; + this->orig_y = oy; + this->orig_z = oy; +} + +void Sphere::setRadius(float rad) { + this->radius = 0; +} + +bool Sphere::intersect(Sphere& other) { + float dist = sqrt(pow(this->orig_x - other.orig_x, 2) + pow(this->orig_y - other.orig_y, 2) + pow(this->orig_z - other.orig_z, 2)); + return true; +} + +float Sphere::SurfaceArea() { + return 4 * M_PI * pow(this->radius, 2); +} + +float Sphere::Volume() { + return (4 / 3) * M_PI * pow(this->radius, 2); +} + +ostream& operator<<(ostream& os, const Sphere& sphere) { + os << "[( " << sphere.orig_x << ", " << sphere.orig_y << ", " << sphere.orig_z << "), " << sphere.radius << "]"; + return os; +} \ No newline at end of file diff --git a/src/sphere.h b/src/sphere.h new file mode 100644 index 0000000..099d0b0 --- /dev/null +++ b/src/sphere.h @@ -0,0 +1,19 @@ +#include + +class Sphere { + public: + Sphere(); + Sphere(float ox, float oy, float oz, float rad); + float SurfaceArea(); + float Volume(); + void setOrigin(float ox, float oy, float oz); + void setRadius(float rad); + float* getOrigin(); + float getRadius(); + bool intersect(Sphere&); + friend std::ostream& operator<<(std::ostream&, const Sphere&); + + private: + float orig_x, orig_y, orig_z; + float radius; +}; \ No newline at end of file diff --git a/unittest/CMakeLists.txt b/unittest/CMakeLists.txt new file mode 100644 index 0000000..5bbfa21 --- /dev/null +++ b/unittest/CMakeLists.txt @@ -0,0 +1,13 @@ +cmake_minimum_required(VERSION 3.1.0) +project(unittest) + +include_directories(../src) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage") +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs -ftest-coverage") +set(CMAKE_EXE_LINKER_FLAGS "--coverage") +# Now simply link against gtest or gtest_main as needed. + +add_executable(utest test_test.cc) +target_link_libraries(utest gtest_main) +target_link_libraries(utest sphere) +enable_testing() \ No newline at end of file diff --git a/unittest/test_test.cc b/unittest/test_test.cc new file mode 100644 index 0000000..9360e1e --- /dev/null +++ b/unittest/test_test.cc @@ -0,0 +1,10 @@ +#include "gtest/gtest.h" +#include "sphere.h" + +TEST(SphereTest, ConstructorTest) { + Sphere sph(0, 1, 2, 3); + EXPECT_EQ(sph.getOrigin()[0], 0); + EXPECT_EQ(sph.getOrigin()[1], 1); + EXPECT_EQ(sph.getOrigin()[2], 2); + EXPECT_EQ(sph.getRadius(), 3); +} \ No newline at end of file