fix(runtime): harden application service boundaries
This commit is contained in:
@@ -56,3 +56,48 @@ target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}/../shared
|
||||
|
||||
# Run the Flutter tool portions of the build. This must not be removed.
|
||||
add_dependencies(${BINARY_NAME} flutter_assemble)
|
||||
|
||||
option(PLEZY_BUILD_MPV_PROPERTY_CONTRACT_TESTS
|
||||
"Build the focused Windows mpv property-result contract tests" OFF)
|
||||
if(PLEZY_BUILD_MPV_PROPERTY_CONTRACT_TESTS)
|
||||
enable_testing()
|
||||
|
||||
add_executable(mpv_property_result_contract_test
|
||||
"../../shared/mpv/mpv_player_common_test.cpp"
|
||||
)
|
||||
apply_standard_settings(mpv_property_result_contract_test)
|
||||
target_link_libraries(mpv_property_result_contract_test PRIVATE "${MPV_LIB_DIR}/libmpv.dll.a")
|
||||
target_include_directories(mpv_property_result_contract_test PRIVATE "${MPV_INCLUDE_DIR}")
|
||||
|
||||
add_executable(mpv_player_property_contract_test
|
||||
"mpv/mpv_player.cpp"
|
||||
"mpv/mpv_player_property_contract_test.cpp"
|
||||
)
|
||||
apply_standard_settings(mpv_player_property_contract_test)
|
||||
target_compile_definitions(mpv_player_property_contract_test PRIVATE "NOMINMAX")
|
||||
target_link_libraries(
|
||||
mpv_player_property_contract_test
|
||||
PRIVATE flutter "${MPV_LIB_DIR}/libmpv.dll.a" simdutf "user32.lib"
|
||||
)
|
||||
target_include_directories(
|
||||
mpv_player_property_contract_test
|
||||
PRIVATE
|
||||
"${CMAKE_SOURCE_DIR}"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
"${MPV_INCLUDE_DIR}"
|
||||
"${CMAKE_SOURCE_DIR}/../shared/cpp"
|
||||
)
|
||||
|
||||
foreach(test_target IN ITEMS mpv_property_result_contract_test mpv_player_property_contract_test)
|
||||
add_custom_command(
|
||||
TARGET ${test_target}
|
||||
POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"${MPV_LIB_DIR}/libmpv-2.dll"
|
||||
"$<TARGET_FILE_DIR:${test_target}>"
|
||||
)
|
||||
endforeach()
|
||||
|
||||
add_test(NAME mpv_property_result_contract_test COMMAND mpv_property_result_contract_test)
|
||||
add_test(NAME mpv_player_property_contract_test COMMAND mpv_player_property_contract_test)
|
||||
endif()
|
||||
|
||||
@@ -295,7 +295,7 @@ void MpvPlayer::SetProperty(const std::string& name, const std::string& value) {
|
||||
|
||||
void MpvPlayer::SetPropertyAsync(const std::string& name, const std::string& value, StatusCallback callback) {
|
||||
if (!mpv_) {
|
||||
if (callback) callback(0);
|
||||
if (callback) callback(MPV_ERROR_UNINITIALIZED);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -87,6 +87,8 @@ class MpvPlayer {
|
||||
void NotifyPowerResume();
|
||||
|
||||
private:
|
||||
friend class MpvPlayerPropertyContractTestPeer;
|
||||
|
||||
void StartEventLoop();
|
||||
void StopEventLoop();
|
||||
void EventLoop();
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <utility>
|
||||
|
||||
#include "mpv_player.h"
|
||||
|
||||
namespace mpv {
|
||||
|
||||
class MpvPlayerPropertyContractTestPeer {
|
||||
public:
|
||||
static void RegisterPendingPropertyWrite(MpvPlayer& player, MpvPlayer::StatusCallback callback) {
|
||||
player.pending_requests_.RegisterStatus(std::move(callback));
|
||||
}
|
||||
};
|
||||
|
||||
namespace {
|
||||
|
||||
void Check(bool condition, const char* message) {
|
||||
if (!condition) {
|
||||
std::cerr << "mpv_player_property_contract_test: " << message << '\n';
|
||||
std::exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void TestUnavailablePropertyWriteFails() {
|
||||
MpvPlayer player;
|
||||
int callback_count = 0;
|
||||
int status = MPV_ERROR_SUCCESS;
|
||||
|
||||
player.SetPropertyAsync("pause", "yes", [&](int error) {
|
||||
++callback_count;
|
||||
status = error;
|
||||
});
|
||||
|
||||
Check(callback_count == 1, "a property write without an mpv handle must complete exactly once");
|
||||
Check(status == MPV_ERROR_UNINITIALIZED, "a property write without an mpv handle must fail as uninitialized");
|
||||
}
|
||||
|
||||
void TestPendingPropertyWriteFailsOnDispose() {
|
||||
MpvPlayer player;
|
||||
int callback_count = 0;
|
||||
int status = MPV_ERROR_SUCCESS;
|
||||
MpvPlayerPropertyContractTestPeer::RegisterPendingPropertyWrite(player, [&](int error) {
|
||||
++callback_count;
|
||||
status = error;
|
||||
});
|
||||
|
||||
player.Dispose();
|
||||
Check(callback_count == 1, "dispose must complete a pending property write exactly once");
|
||||
Check(status < 0, "dispose must fail a pending property write");
|
||||
|
||||
player.Dispose();
|
||||
Check(callback_count == 1, "repeated dispose must not complete a property write twice");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace mpv
|
||||
|
||||
int main() {
|
||||
mpv::TestUnavailablePropertyWriteFails();
|
||||
mpv::TestPendingPropertyWriteFailsOnDispose();
|
||||
std::cout << "mpv_player_property_contract_test: PASS\n";
|
||||
return 0;
|
||||
}
|
||||
@@ -247,7 +247,7 @@ void MpvPlayerPlugin::HandleMethodCall(
|
||||
return; // Response will be sent asynchronously
|
||||
} else if (method == "setProperty") {
|
||||
if (!player_ || !player_->IsInitialized()) {
|
||||
result->Error("NOT_INITIALIZED", "Player not initialized");
|
||||
result->Error(plezy::mpv_common::kSetPropertyNotInitializedCode, "Player not initialized");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -273,8 +273,17 @@ void MpvPlayerPlugin::HandleMethodCall(
|
||||
auto result_ptr =
|
||||
std::make_shared<std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>>>(std::move(result));
|
||||
player_->SetPropertyAsync(
|
||||
std::get<std::string>(name_it->second), std::get<std::string>(value_it->second),
|
||||
[this, result_ptr](int error) { PostToPlatformThread([result_ptr]() { (*result_ptr)->Success(); }); });
|
||||
std::get<std::string>(name_it->second), std::get<std::string>(value_it->second), [this, result_ptr](int error) {
|
||||
PostToPlatformThread([result_ptr, error]() {
|
||||
if (plezy::mpv_common::SetPropertyStatusSucceeded(error)) {
|
||||
(*result_ptr)->Success();
|
||||
} else {
|
||||
(*result_ptr)
|
||||
->Error(
|
||||
plezy::mpv_common::kSetPropertyFailedCode, plezy::mpv_common::SetPropertyErrorDescription(error));
|
||||
}
|
||||
});
|
||||
});
|
||||
return;
|
||||
} else if (method == "setLogLevel") {
|
||||
if (!player_ || !player_->IsInitialized()) {
|
||||
|
||||
Reference in New Issue
Block a user