-
Notifications
You must be signed in to change notification settings - Fork 113
Add C++ test to obs-studio-server #1706
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
base: messages-pacing-during-congestion
Are you sure you want to change the base?
Changes from all commits
99d1c4d
c22425c
dd5a1c8
c0a2371
be78a66
72bea85
323733b
290fc88
51ddb28
72e7d20
c600680
83be350
73c542a
64f5339
39d3004
b1ba437
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -424,9 +424,38 @@ elseif(WIN32) | |
| ) | ||
| endif () | ||
|
|
||
| set(OSN_SERVER_CORE_SOURCES ${osn-server_SOURCES}) | ||
| list(REMOVE_ITEM OSN_SERVER_CORE_SOURCES "${PROJECT_SOURCE_DIR}/source/main.cpp") | ||
|
|
||
| add_library( | ||
| obs-studio-server-lib STATIC | ||
| ${OSN_SERVER_CORE_SOURCES} | ||
| ) | ||
|
|
||
| IF(WIN32) | ||
| target_compile_definitions( | ||
| obs-studio-server-lib | ||
| PUBLIC | ||
| WIN32_LEAN_AND_MEAN | ||
| NOMINMAX | ||
| UNICODE | ||
| _UNICODE | ||
| ) | ||
| ENDIF() | ||
|
|
||
| target_include_directories(obs-studio-server-lib PUBLIC ${PROJECT_INCLUDE_PATHS}) | ||
|
|
||
| if(WIN32) | ||
| target_link_libraries(obs-studio-server-lib PUBLIC ${PROJECT_LIBRARIES} optimized crashpad strmiids StackWalker) | ||
| else() | ||
| target_link_libraries(obs-studio-server-lib PUBLIC ${PROJECT_LIBRARIES} crashpad ${COREFOUNDATION} ${COCOA} ${IOSURF} ${GLKIT} ${AVFOUNDATION} ${IOKit} ${SECURITY_LIBRARY} ${BSM_LIBRARY}) | ||
| endif() | ||
|
|
||
| target_link_libraries(obs-studio-server-lib PUBLIC libcurl) | ||
|
|
||
| add_executable( | ||
| ${PROJECT_NAME} | ||
| ${osn-server_SOURCES} | ||
| "${PROJECT_SOURCE_DIR}/source/main.cpp" | ||
| ) | ||
|
|
||
| if(WIN32) | ||
|
|
@@ -436,16 +465,7 @@ if(WIN32) | |
| target_sources(${PROJECT_NAME} PUBLIC "${PROJECT_BINARY_DIR}/version.rc") | ||
| endif() | ||
|
|
||
| #target_link_libraries(${PROJECT_NAME} CURL::libcurl) | ||
| target_link_libraries(${PROJECT_NAME} libcurl) | ||
|
|
||
| if(WIN32) | ||
| target_include_directories(${PROJECT_NAME} PUBLIC ${PROJECT_INCLUDE_PATHS}) | ||
| target_link_libraries(${PROJECT_NAME} ${PROJECT_LIBRARIES} optimized crashpad strmiids) | ||
| else() | ||
| target_include_directories(${PROJECT_NAME} PUBLIC ${PROJECT_INCLUDE_PATHS} ${COREFOUNDATION} ${COCOA} ${IOSURF} ${GLKIT} ${AVFOUNDATION} ${IOKit} ${SECURITY_LIBRARY} ${BSM_LIBRARY}) | ||
| target_link_libraries(${PROJECT_NAME} ${PROJECT_LIBRARIES} crashpad ${COREFOUNDATION} ${COCOA} ${IOSURF} ${GLKIT} ${AVFOUNDATION} ${IOKit} ${SECURITY_LIBRARY} ${BSM_LIBRARY}) | ||
| endif() | ||
| target_link_libraries(${PROJECT_NAME} obs-studio-server-lib) | ||
|
|
||
| if(MSVC) | ||
| add_definitions(-D_CRT_SECURE_NO_WARNINGS -D_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS) | ||
|
|
@@ -483,17 +503,6 @@ else() | |
| ) | ||
| ENDIF() | ||
|
|
||
| IF(WIN32) | ||
| target_compile_definitions( | ||
| ${PROJECT_NAME} | ||
| PRIVATE | ||
| WIN32_LEAN_AND_MEAN | ||
| NOMINMAX | ||
| UNICODE | ||
| _UNICODE | ||
| ) | ||
| ENDIF() | ||
|
|
||
| IF( NOT CLANG_ANALYZE_CONFIG) | ||
| cppcheck_add_project(${PROJECT_NAME}) | ||
| ENDIF() | ||
|
|
@@ -598,3 +607,52 @@ if (APPLE) | |
| DESTINATION "../../Contents/Frameworks" USE_SOURCE_PERMISSIONS | ||
| ) | ||
| endif() | ||
|
|
||
| if(BUILD_TESTING) | ||
| include(Catch) | ||
|
|
||
| add_executable( | ||
| obs_studio_server_unit_tests | ||
| "tests/test-osn-source.cpp" | ||
| "tests/obs-setup.cpp" | ||
| "tests/obs-setup.hpp" | ||
| ) | ||
|
|
||
| target_compile_definitions( | ||
| obs_studio_server_unit_tests | ||
| PRIVATE | ||
| OSN_SOURCE_DIR="${CMAKE_SOURCE_DIR}" | ||
| OSN_TEST_WD="${CMAKE_INSTALL_PREFIX}" | ||
| ) | ||
|
|
||
| target_link_libraries( | ||
| obs_studio_server_unit_tests | ||
| PRIVATE | ||
| Catch2::Catch2WithMain | ||
| obs-studio-server-lib | ||
| ) | ||
|
|
||
| if(APPLE) | ||
| add_custom_command( | ||
| TARGET obs_studio_server_unit_tests | ||
| POST_BUILD | ||
| COMMAND /usr/bin/codesign --force --sign - "$<TARGET_FILE:obs_studio_server_unit_tests>" | ||
| COMMENT "Ad-hoc signing obs_studio_server_unit_tests before Catch2 test discovery" | ||
| VERBATIM | ||
| ) | ||
| endif() | ||
|
|
||
| catch_discover_tests( | ||
| obs_studio_server_unit_tests | ||
| TEST_PREFIX "obs_studio_server_unit_tests::" | ||
| DL_PATHS | ||
| "$<TARGET_FILE_DIR:Catch2::Catch2>" | ||
| "$<TARGET_FILE_DIR:Catch2::Catch2WithMain>" | ||
| "$<TARGET_FILE_DIR:libcurl>" | ||
| if(APPLE) | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. CMake does not parse In CMake, this is a command invocation: catch_discover_tests(
obs_studio_server_unit_tests
DL_PATHS
...
if(APPLE)
...
endif()
)Everything between |
||
| "${libobs_SOURCE_DIR}/OBS.app/Contents/Frameworks" | ||
| elseif(WIN32) | ||
| "${libobs_SOURCE_DIR}/bin/64bit" | ||
| endif() | ||
| ) | ||
| endif() | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,58 @@ | ||
| #include <catch2/catch_test_macros.hpp> | ||
| #include <fstream> | ||
| #include "nodeobs_api.h" | ||
| #include "osn-error.hpp" | ||
| #include <obs.h> | ||
| #include "shared.hpp" | ||
| #include <string> | ||
| #include "obs-setup.hpp" | ||
| #include <vector> | ||
|
|
||
| namespace osn::tests { | ||
|
|
||
| void setWorkingFolder(const std::string &wd) | ||
| { | ||
| std::vector<ipc::value> args = {ipc::value(wd)}; | ||
| std::vector<ipc::value> response; | ||
| OBS_API::SetWorkingDirectory(nullptr, 0, args, response); | ||
| REQUIRE(response.size() >= 2); | ||
| ErrorCode error = (ErrorCode)response[0].value_union.ui64; | ||
| CHECK(error == ErrorCode::Ok); | ||
|
sandboxcoder marked this conversation as resolved.
|
||
| } | ||
|
sandboxcoder marked this conversation as resolved.
|
||
|
|
||
| void setupApi() | ||
| { | ||
| #if defined(__APPLE__) | ||
| g_util_osx = new UtilInt(); | ||
| g_util_osx->init(); | ||
| // Workaround normal app startup where "browser_source" plugin is initialized | ||
| CHECK(!g_util_osx->hasInitApi()); | ||
| g_util_osx->nextState(); | ||
| CHECK(g_util_osx->hasInitApi()); | ||
| #endif | ||
| const std::string appPath = std::string(OSN_SOURCE_DIR) + "/tests/osn-tests/osnData/slobs-client"; | ||
| std::vector<ipc::value> args = {ipc::value(appPath), ipc::value("en-US"), ipc::value("0.00.00-preview.0"), ipc::value("")}; | ||
| std::vector<ipc::value> response; | ||
| OBS_API::OBS_API_initAPI(nullptr, 0, args, response); | ||
| REQUIRE(response.size() >= 2); | ||
| ErrorCode error = (ErrorCode)response[0].value_union.ui64; | ||
| CHECK(error == ErrorCode::Ok); | ||
|
sandboxcoder marked this conversation as resolved.
|
||
| } | ||
|
|
||
| ObsSetup::ObsSetup() | ||
| { | ||
| setWorkingFolder(OSN_TEST_WD); | ||
| setupApi(); | ||
| } | ||
|
|
||
| ObsSetup::~ObsSetup() | ||
| { | ||
| std::vector<ipc::value> args = {}; | ||
| std::vector<ipc::value> response; | ||
| OBS_API::OBS_API_destroyOBS_API(nullptr, 0, args, response); | ||
| REQUIRE(response.size() >= 1); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. https://catch2-temp.readthedocs.io/en/latest/configuration.html#disabling-exceptions |
||
| ErrorCode error = (ErrorCode)response[0].value_union.ui64; | ||
| CHECK(error == ErrorCode::Ok); | ||
|
sandboxcoder marked this conversation as resolved.
|
||
| } | ||
|
|
||
| } // namespace osn::tests | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| #pragma once | ||
|
|
||
| namespace osn::tests { | ||
| // This helper object uses RAII pattern to initialize & destroy OBS API | ||
| class ObsSetup { | ||
| public: | ||
| ObsSetup(); | ||
| ~ObsSetup(); | ||
| }; | ||
| } // namespace osn::tests |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,87 @@ | ||
| #include <catch2/catch_test_macros.hpp> | ||
| #include <mutex> | ||
| #include "nodeobs_api.h" | ||
| #include "osn-error.hpp" | ||
| #include "osn-input.hpp" | ||
| #include "osn-source.hpp" | ||
| #include <obs.h> | ||
| #include "shared.hpp" | ||
| #include <string> | ||
| #include "obs-setup.hpp" | ||
| #include <thread> | ||
| #include <vector> | ||
|
|
||
| TEST_CASE("Run osn::source tests") | ||
| { | ||
| osn::tests::ObsSetup setupOBS; | ||
|
|
||
|
sandboxcoder marked this conversation as resolved.
|
||
| SECTION("Get properties of browser source while releasing concurrently does not crash") | ||
|
sandboxcoder marked this conversation as resolved.
|
||
| { | ||
| auto sourceCount = osn::Source::Manager::GetInstance().size(); | ||
| const int iterations = 20; | ||
| std::vector<std::thread> workers; | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If a later |
||
| std::vector<uint8_t> releaseOk(iterations, 0); | ||
| std::vector<ErrorCode> getPropertiesCode(iterations, ErrorCode::Error); | ||
|
sandboxcoder marked this conversation as resolved.
|
||
|
|
||
| for (int i = 0; i < iterations; i++) { | ||
| const std::string sourceName = "test-input-" + std::to_string(i); | ||
| std::vector<ipc::value> args = {ipc::value("browser_source"), ipc::value(sourceName)}; | ||
| std::vector<ipc::value> response; | ||
|
|
||
| osn::Input::Create(nullptr, 0, args, response); | ||
| REQUIRE(response.size() >= 2); | ||
| ErrorCode error = (ErrorCode)response[0].value_union.ui64; | ||
| REQUIRE(error == ErrorCode::Ok); | ||
|
|
||
| uint64_t sourceId = response[1].value_union.ui64; | ||
|
|
||
| workers.push_back(std::thread([sourceId, i, &getPropertiesCode]() { | ||
| std::vector<ipc::value> propArgs = {ipc::value(sourceId)}; | ||
| std::vector<ipc::value> propResponse; | ||
| osn::Source::GetProperties(nullptr, 0, propArgs, propResponse); | ||
| if (propResponse.size() >= 1) { | ||
| getPropertiesCode[i] = (ErrorCode)propResponse[0].value_union.ui64; | ||
| } | ||
| })); | ||
|
|
||
| workers.push_back(std::thread([sourceId, i, &releaseOk]() { | ||
|
|
||
| #if defined(TRIGGER_CRASH) | ||
| // TODO: Enable this code block once staging (commit cc4a0431) is merged. | ||
| // Release the refcount to trigger actual private data destruction | ||
| obs_source_t *src = osn::Source::Manager::GetInstance().find(sourceId); // may be null already | ||
| if (src) { | ||
| obs_source_release(src); | ||
| releaseOk[i] = true; | ||
| } | ||
| #else | ||
| // TODO: delete this block after staging (commit cc4a0431) is merged. | ||
| std::vector<ipc::value> propArgs = {ipc::value(sourceId)}; | ||
| std::vector<ipc::value> propResponse; | ||
| osn::Source::Release(nullptr, 0, propArgs, propResponse); | ||
| // Capture result for checking on the main thread after join. | ||
| if (propResponse.size() >= 1) { | ||
| releaseOk[i] = ((ErrorCode)propResponse[0].value_union.ui64 == ErrorCode::Ok); | ||
| } | ||
| #endif | ||
| })); | ||
| } | ||
|
|
||
| for (std::thread &worker : workers) { | ||
| if (worker.joinable()) | ||
| worker.join(); | ||
| } | ||
|
|
||
| // Check release results on the main thread where Catch2 is safe to use. | ||
| for (int i = 0; i < iterations; i++) { | ||
| CHECK(releaseOk[i]); | ||
| // ErrorCode::InvalidReference is possible if the source was deleted before we could acquire the source | ||
| bool expectedErrorCode = getPropertiesCode[i] == ErrorCode::Ok || getPropertiesCode[i] == ErrorCode::InvalidReference; | ||
| CHECK(expectedErrorCode); | ||
| } | ||
| #if defined(TRIGGER_CRASH) | ||
| // TODO: Enable this code block once staging (commit cc4a0431) is merged. | ||
| CHECK(sourceCount == osn::Source::Manager::GetInstance().size()); // Check to see if all objects released. | ||
| #endif | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.