fix(runtime): harden application service boundaries

This commit is contained in:
edde746
2026-07-24 03:46:46 +02:00
parent 658da37b48
commit e0bf66eea8
309 changed files with 32574 additions and 4369 deletions
+45
View File
@@ -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()
+1 -1
View File
@@ -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;
}
+2
View File
@@ -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;
}
+12 -3
View File
@@ -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()) {