Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

append unit testing framework #121

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ directml*/

# Build artifacts
build/
test_build/
lib/
bin/
core/_core.cpp
Expand Down
19 changes: 17 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,18 @@ cmake_minimum_required(VERSION 3.16)
project(VoiceVoxCore)

# TODO: download onnxruntime
set(ONNXRUNTIME_DIR "${CMAKE_CURRENT_SOURCE_DIR}/onnxruntime" CACHE PATH "Path to ONNX Runtime")
set(MODEL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/model" CACHE PATH "Path to model")
set(ONNXRUNTIME_DIR
"${CMAKE_CURRENT_SOURCE_DIR}/onnxruntime"
CACHE PATH "Path to ONNX Runtime")
set(MODEL_DIR
"${CMAKE_CURRENT_SOURCE_DIR}/model"
CACHE PATH "Path to model")
set(CORE_DIR
"${CMAKE_CURRENT_SOURCE_DIR}/core"
CACHE PATH "Path to core")
set(DEPENDENT_DLLS
""
CACHE INTERNAL "Dependent DLLs of core.dll")

set(CMAKE_POSITION_INDEPENDENT_CODE ON)

Expand All @@ -18,3 +28,8 @@ endif()

add_subdirectory(core)
add_subdirectory(open_jtalk/src)

if(BUILD_TEST)
enable_testing()
add_subdirectory(tests)
endif()
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,11 @@ cmake --build . --config Release
cmake --install .
cd ..

#(省略可能) C++のテスト実行
cmake -S . -B test_build -DBUILD_TEST=YES
cmake --build test_build
ctest --test-dir test_build --verbose

# (省略可能) pythonモジュールのテスト
python setup.py test

Expand Down
18 changes: 15 additions & 3 deletions core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ message("core will be installed to: ${CMAKE_INSTALL_PREFIX}")

file(GLOB_RECURSE core_sources "src/*.cpp")
# coreライブラリのビルド設定
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
add_library(core
SHARED ${core_sources}
${EMBED_YUKARIN_S_OUTPUTS}
Expand All @@ -51,6 +52,9 @@ if(NOT DIRECTML)
"${ONNXRUNTIME_DIR}/lib/*.lib"
"${ONNXRUNTIME_DIR}/lib/*.so"
"${ONNXRUNTIME_DIR}/lib/*.so.*")
file(GLOB ONNXRUNTIME_DLLS
"${ONNXRUNTIME_DIR}/lib/*.dll")
set(DEPENDENT_DLLS "${DEPENDENT_DLLS};${ONNXRUNTIME_DLLS}" PARENT_SCOPE)
target_include_directories(core
PRIVATE ${ONNXRUNTIME_DIR}/include)
target_link_directories(core PUBLIC ${ONNXRUNTIME_DIR}/lib)
Expand Down Expand Up @@ -79,6 +83,9 @@ else()
file(GLOB DIRECTML_LIBS
"${DIRECTML_DIR}/bin/${DML_ARCH}-win/*.dll"
"${DIRECTML_DIR}/bin/${DML_ARCH}-win/*.lib")
file(GLOB DIRECTML_DLLS
"${DIRECTML_DIR}/bin/${DML_ARCH}-win/*.dll")
set(DEPENDENT_DLLS "${DEPENDENT_DLLS};${DIRECTML_DLLS}" PARENT_SCOPE)

target_include_directories(core PRIVATE ${DIRECTML_DIR}/include)
target_link_directories(core PUBLIC ${DIRECTML_DIR}/bin/${DML_ARCH}-win/)
Expand All @@ -91,7 +98,7 @@ else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D DIRECTML")
endif()

set_property(TARGET core PROPERTY CXX_STANDARD 17)
set_property(TARGET core PROPERTY CXX_STANDARD 20)
set_property(TARGET core PROPERTY POSITION_INDEPENDENT_CODE ON) # fPIC
# rpath設定
if (APPLE)
Expand All @@ -102,8 +109,13 @@ elseif (UNIX)
endif ()

target_compile_options(core PRIVATE
$<$<CXX_COMPILER_ID:MSVC>: /W4 /O2 /utf-8 /DVOICEVOX_CORE_EXPORTS>
$<$<CXX_COMPILER_ID:GNU>: -Wall -Wextra -O2 -DVOICEVOX_CORE_EXPORTS>
$<$<CXX_COMPILER_ID:MSVC>: /W4 /utf-8 /DVOICEVOX_CORE_EXPORTS>
$<$<CXX_COMPILER_ID:GNU>: -Wall -Wextra -DVOICEVOX_CORE_EXPORTS>
)

add_compile_options(TARGET core
$<$<CONFIG:Release>:$<CXX_COMPILER_ID:MSVC>: /O2>
$<$<CONFIG:Release>:$<CXX_COMPILER_ID:GNU>: -O2>
)

target_include_directories(core
Expand Down
31 changes: 31 additions & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
cmake_minimum_required(VERSION 3.16)

project(VoiceVoxCoreTest)

include(FetchContent)
FetchContent_Declare(
Catch2
GIT_REPOSITORY https://github.com/catchorg/Catch2.git
GIT_TAG v3.0.0-preview5)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

完全に余談ですがCatch2のドキュメントでcmakeのFetchContent機能を知りました。
このプロジェクトが依存してるopenjtalkもcmakeで作られてるようなので、やろうと思えばopenjtalkもFetchContentでとってくるようにし、git submoduleの依存から脱却できそうだなと思いました。
もっとも将来的にcmakeを使ってないライブラリに依存するようになった場合はまたgit submoduleを使わないといけなさそうですが

FetchContent_MakeAvailable(Catch2)
file(GLOB_RECURSE unit_test_files "unit_tests/*.cpp")
add_executable(unit_test ${unit_test_files})
Yosshi999 marked this conversation as resolved.
Show resolved Hide resolved
target_compile_options(
unit_test PRIVATE $<$<CXX_COMPILER_ID:MSVC>: /W4 /utf-8>
$<$<CXX_COMPILER_ID:GNU>: -Wall -Wextra>)
set_property(TARGET unit_test PROPERTY CXX_STANDARD 20)
set_property(TARGET Catch2 PROPERTY CXX_STANDARD 20)
target_include_directories(unit_test PRIVATE ${Catch2_SOURCE_DIR}/src)
target_include_directories(unit_test PRIVATE ${CORE_DIR}/src)
target_link_libraries(unit_test PRIVATE Catch2::Catch2WithMain)
target_link_libraries(unit_test PRIVATE core)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[QUESTION] これ僕の環境だとリンクに失敗するんですが他の方再現しますか?

kana_parser_test.obj : error LNK2019: 未解決の外部シンボル "class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __cdecl voicevox::core::engine::e
xtract_one_character(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,unsigned __int64,unsigned __int64 &)" (?extract_one_ch 
aracter@engine@core@voicevox@@YA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@AEBV45@_KAEA_K@Z) が関数 "void __cdecl CATCH2_INTERNAL_TEST_0(void)" (?CATCH2_
INTERNAL_TEST_0@@YAXXZ) で参照されました 

Copy link
Contributor Author

@qwerty2501 qwerty2501 May 7, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

オプションを修正してみましたが、これでだめなら coreのCMakeLists.txtでcore targetがSHARED指定されてるからかもしれないです

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

エラーメッセージ的に標準ライブラリとのリンクに失敗しているようだったので、unit_testとcoreの標準ライブラリのバージョンをそろえてみました

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

修正後のコードでコンパイルしてみたところ、同じエラーが出たっぽいです。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Catch2が原因ぽそうだけど直せるだろうか・・・

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

おそらくcoreがextract_one_characterをexportしてないせいでリンクが通らないので、
coreのcmakelistsに set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) を追記することですべての関数をexportさせるか、
static版も作ってそっちにリンクする必要があるのだと思います。

またshared版はもう一つ課題があって、リンクが通ったとしても今度はcore.dllとonnxruntime.dllをunit_testのバイナリがあるところにコピーしてくる必要があります。これはcmakeでやるのは結構厳しくて、cmake 3.21の依存dllを引っぱってくる機能

  add_custom_command(TARGET unit_test POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E copy
    $<TARGET_RUNTIME_DLLS:unit_test> $<TARGET_FILE_DIR:unit_test>
    COMMAND_EXPAND_LISTS )

ではcore.dllしか拾ってくれません。(ちなみにcore.dllを持ってくるだけなら3.21に上げる必要は無く、 $<TARGET_FILE:core> がcore.dllへのパスを指してるのでそれを -E copy するだけで足ります)

つまり現状core/CMakeLists.txtで定義したONNXRUNTIME_LIBSとかをこっちに持ってきて別途 -E copy する必要があります。

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yosshi999@7b4d430
一応これでビルドが通る?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Yosshi999 そのcommitを参考に修正しました

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

問題なくテストできてそうなことを確認しました!!

1/1 Test #1: extract_one_character ............ Passed 0.02 sec

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

こちらでも動作確認できました!

if (WIN32)
add_custom_command(TARGET unit_test POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"$<TARGET_FILE:core>;${DEPENDENT_DLLS}" $<TARGET_FILE_DIR:unit_test>
COMMAND_EXPAND_LISTS )
endif (WIN32)
list(APPEND CMAKE_MODULE_PATH ${Catch2_SOURCE_DIR}/extras)
include(Catch)
include(CTest)
catch_discover_tests(unit_test)
36 changes: 36 additions & 0 deletions tests/unit_tests/core/engine/kana_parser_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#include "engine/kana_parser.h"

#include <catch2/catch_test_macros.hpp>
#include <catch2/generators/catch_generators.hpp>

using namespace voicevox::core::engine;

TEST_CASE("extract_one_character") {
struct TestCase {
std::string name;
struct {
std::string text;
size_t pos;
} given;
struct {
std::string one_char;
size_t after_size;
} expected;
};
auto t = GENERATE(TestCase{.name = "target_is_alphabet",
.given = {.text = "abcd", .pos = 2},
.expected = {.one_char = "c", .after_size = 1}},
TestCase{.name = "target_is_hiragana",
.given = {.text = "acあd", .pos = 2},
.expected = {.one_char = "あ", .after_size = 3}},
TestCase{.name = "target_is_4byte_kanji",
.given = {.text = "ace𠀋", .pos = 3},
.expected = {.one_char = "𠀋", .after_size = 4}});

SECTION(t.name) {
size_t size;
auto actual_one_char = extract_one_character(t.given.text, t.given.pos, size);
CHECK(t.expected.one_char == actual_one_char);
CHECK(t.expected.after_size == size);
}
}