#include "test_harness.h" #include "platform_api/asset_file_load_policy.h" #include "platform_api/network_tls_policy.h" #include "platform_api/platform_policy.h" #include "platform_api/platform_services.h" #include #include #include #include #include #include namespace { class FakePlatformServices final : public pp::platform::PlatformServices { public: explicit FakePlatformServices(std::string clipboard_value) : clipboard_value_(std::move(clipboard_value)) { } [[nodiscard]] pp::platform::PlatformStoragePaths prepare_storage_paths() override { ++storage_prepares; return storage_paths; } void log_stacktrace() override { ++stacktrace_logs; } void trigger_crash_test() override { ++crash_tests; } [[nodiscard]] std::string clipboard_text() override { ++clipboard_reads; return clipboard_value_; } [[nodiscard]] bool set_clipboard_text(std::string_view text) override { ++clipboard_writes; clipboard_value_.assign(text); return true; } void set_cursor_visible(bool visible) override { ++cursor_updates; cursor_visible = visible; } void set_virtual_keyboard_visible(bool visible) override { ++keyboard_updates; keyboard_visible = visible; } void attach_ui_thread() override { ++ui_thread_attaches; } void detach_ui_thread() override { ++ui_thread_detaches; } void acquire_render_context() override { ++render_context_acquires; } void release_render_context() override { ++render_context_releases; } void present_render_context() override { ++render_context_presents; } void bind_default_render_target() override { ++default_render_target_binds; } void bind_main_render_target() override { ++main_render_target_binds; } void apply_render_platform_hints() override { ++render_platform_hint_applies; } void install_render_debug_callback() override { ++render_debug_callback_installs; } void begin_render_capture_frame() override { ++render_capture_begins; } void end_render_capture_frame() override { ++render_capture_ends; } [[nodiscard]] bool deletes_recorded_files_on_clear() override { ++recording_delete_policy_checks; return deletes_recorded_files; } void clear_recorded_files(std::string_view recording_path) override { ++recording_clears; cleared_recording_path.assign(recording_path); } void publish_exported_image(std::string_view path) override { ++exported_image_publishes; exported_image_path.assign(path); } void flush_persistent_storage() override { ++persistent_storage_flushes; } [[nodiscard]] std::vector document_browse_roots( std::string_view work_path, std::string_view data_path) override { ++document_browse_root_requests; browse_work_path.assign(work_path); browse_data_path.assign(data_path); return browse_roots; } void save_ui_state() override { ++ui_state_saves; } [[nodiscard]] bool enables_live_asset_reloading() override { ++live_asset_reload_policy_checks; return live_asset_reloading; } void update_platform_frame(float delta_time_seconds) override { ++platform_frame_updates; last_platform_delta = delta_time_seconds; } void report_rendered_frames(int frames) override { ++frame_reports; last_frame_report = frames; } void display_file(std::string_view path) override { ++display_file_requests; displayed_path.assign(path); } void share_file(std::string_view path) override { ++share_file_requests; shared_path.assign(path); } void request_app_close() override { ++app_close_requests; } [[nodiscard]] bool start_vr_mode() override { ++vr_starts; return vr_start_success; } void stop_vr_mode() override { ++vr_stops; } void pick_image(pp::platform::PickedPathCallback callback) override { ++pick_image_requests; callback(picker_path); } void pick_file(std::vector file_types, pp::platform::PickedPathCallback callback) override { ++pick_file_requests; picked_file_types = std::move(file_types); callback(picker_path); } void pick_save_file(std::vector file_types, pp::platform::PickedPathCallback callback) override { ++pick_save_file_requests; save_file_types = std::move(file_types); callback(save_path); } void pick_directory(pp::platform::PickedPathCallback callback) override { ++pick_directory_requests; callback(directory_path); } [[nodiscard]] bool supports_working_directory_picker() override { ++working_directory_picker_support_checks; return working_directory_picker_supported; } [[nodiscard]] std::string format_working_directory_path(std::string_view path) override { ++working_directory_path_format_requests; last_working_directory_path.assign(path); return formatted_working_directory_path; } [[nodiscard]] bool uses_prepared_file_writes() override { ++prepared_file_write_policy_checks; return prepared_file_writes; } [[nodiscard]] bool uses_work_directory_document_export_collections() override { ++document_export_collection_policy_checks; return work_directory_document_export_collections; } [[nodiscard]] bool disables_network_tls_verification() override { ++network_tls_policy_checks; return network_tls_verification_disabled; } [[nodiscard]] bool uses_ppbr_export_data_directory_override() override { ++ppbr_export_data_directory_override_checks; return ppbr_export_data_directory_override; } [[nodiscard]] bool supports_sonarpen() override { ++sonarpen_support_checks; return sonarpen_supported; } void start_sonarpen() override { ++sonarpen_starts; } [[nodiscard]] int default_canvas_resolution() override { ++default_canvas_resolution_requests; return canvas_resolution; } [[nodiscard]] bool draws_canvas_tip_for_pointer( bool is_mouse, bool is_stylus, bool is_left_button_release) override { ++canvas_tip_policy_checks; last_canvas_tip_mouse = is_mouse; last_canvas_tip_stylus = is_stylus; last_canvas_tip_left_release = is_left_button_release; return canvas_tip_visible; } [[nodiscard]] float adjust_canvas_input_pressure(float pressure) override { ++canvas_pressure_adjustments; last_canvas_pressure = pressure; return adjusted_canvas_pressure; } [[nodiscard]] pp::platform::PreparedFileTarget prepare_writable_file( std::string_view type, std::string_view default_name, std::string_view data_path, std::string_view temporary_path) override { ++prepare_writable_file_requests; writable_file_type.assign(type); writable_file_default_name.assign(default_name); writable_file_data_path.assign(data_path); writable_file_temporary_path.assign(temporary_path); return writable_file_target; } void save_prepared_file( std::string_view path, std::string_view suggested_name, pp::platform::PreparedFileCallback callback) override { ++save_prepared_file_requests; prepared_file_path.assign(path); prepared_file_name.assign(suggested_name); callback(prepared_file_path, prepared_file_saved); } int clipboard_reads = 0; int clipboard_writes = 0; int cursor_updates = 0; int keyboard_updates = 0; int ui_thread_attaches = 0; int ui_thread_detaches = 0; int render_context_acquires = 0; int render_context_releases = 0; int render_context_presents = 0; int default_render_target_binds = 0; int main_render_target_binds = 0; int render_platform_hint_applies = 0; int render_debug_callback_installs = 0; int render_capture_begins = 0; int render_capture_ends = 0; int storage_prepares = 0; int stacktrace_logs = 0; int crash_tests = 0; int recording_delete_policy_checks = 0; int recording_clears = 0; int exported_image_publishes = 0; int persistent_storage_flushes = 0; int document_browse_root_requests = 0; int ui_state_saves = 0; int live_asset_reload_policy_checks = 0; int platform_frame_updates = 0; int frame_reports = 0; int display_file_requests = 0; int share_file_requests = 0; int app_close_requests = 0; int vr_starts = 0; int vr_stops = 0; int pick_image_requests = 0; int pick_file_requests = 0; int pick_save_file_requests = 0; int pick_directory_requests = 0; int working_directory_picker_support_checks = 0; int working_directory_path_format_requests = 0; int prepared_file_write_policy_checks = 0; int document_export_collection_policy_checks = 0; int network_tls_policy_checks = 0; int ppbr_export_data_directory_override_checks = 0; int sonarpen_support_checks = 0; int sonarpen_starts = 0; int default_canvas_resolution_requests = 0; int canvas_tip_policy_checks = 0; int canvas_pressure_adjustments = 0; int prepare_writable_file_requests = 0; int save_prepared_file_requests = 0; bool cursor_visible = false; bool keyboard_visible = false; bool prepared_file_saved = true; bool vr_start_success = false; bool prepared_file_writes = true; bool working_directory_picker_supported = false; bool work_directory_document_export_collections = false; bool network_tls_verification_disabled = false; bool ppbr_export_data_directory_override = false; bool sonarpen_supported = false; int canvas_resolution = 1536; bool canvas_tip_visible = false; bool last_canvas_tip_mouse = false; bool last_canvas_tip_stylus = false; bool last_canvas_tip_left_release = false; bool deletes_recorded_files = true; bool live_asset_reloading = true; float last_platform_delta = 0.0f; float last_canvas_pressure = 0.0f; float adjusted_canvas_pressure = 0.75f; int last_frame_report = 0; std::string displayed_path; std::string shared_path; std::string prepared_file_path; std::string prepared_file_name; std::string cleared_recording_path; std::string exported_image_path; std::string browse_work_path; std::string browse_data_path; std::string writable_file_type; std::string writable_file_default_name; std::string writable_file_data_path; std::string writable_file_temporary_path; std::string picker_path = "D:/Paint/import.png"; std::string save_path = "D:/Paint/export.ppi"; std::string directory_path = "D:/Paint"; std::string last_working_directory_path; std::string formatted_working_directory_path = "D:/Paint/Absolute"; pp::platform::PlatformStoragePaths storage_paths{ "D:/Paint", "D:/Paint/work", "D:/Paint/frames", "D:/Paint/tmp", }; std::vector picked_file_types; std::vector save_file_types; std::vector browse_roots = { "D:/Paint/work", "D:/Paint/Inbox", }; pp::platform::PreparedFileTarget writable_file_target{ "D:/Paint/tmp/export.mp4", "export.mp4", true, }; private: std::string clipboard_value_; }; void platform_services_dispatch_clipboard_reads_and_writes(pp::tests::Harness& harness) { FakePlatformServices fake("#112233"); pp::platform::PlatformServices& services = fake; PP_EXPECT(harness, services.clipboard_text() == "#112233"); PP_EXPECT(harness, services.set_clipboard_text("#ff00aa")); PP_EXPECT(harness, services.clipboard_text() == "#ff00aa"); PP_EXPECT(harness, fake.clipboard_reads == 2); PP_EXPECT(harness, fake.clipboard_writes == 1); } void platform_services_dispatch_storage_path_preparation(pp::tests::Harness& harness) { FakePlatformServices fake("unused"); pp::platform::PlatformServices& services = fake; const auto paths = services.prepare_storage_paths(); PP_EXPECT(harness, fake.storage_prepares == 1); PP_EXPECT(harness, paths.data_path == "D:/Paint"); PP_EXPECT(harness, paths.work_path == "D:/Paint/work"); PP_EXPECT(harness, paths.recording_path == "D:/Paint/frames"); PP_EXPECT(harness, paths.temporary_path == "D:/Paint/tmp"); } void platform_services_dispatch_diagnostics(pp::tests::Harness& harness) { FakePlatformServices fake("unused"); pp::platform::PlatformServices& services = fake; services.log_stacktrace(); services.trigger_crash_test(); PP_EXPECT(harness, fake.stacktrace_logs == 1); PP_EXPECT(harness, fake.crash_tests == 1); } void platform_services_preserve_empty_clipboard_writes(pp::tests::Harness& harness) { FakePlatformServices fake("initial"); pp::platform::PlatformServices& services = fake; PP_EXPECT(harness, services.set_clipboard_text("")); PP_EXPECT(harness, services.clipboard_text().empty()); PP_EXPECT(harness, fake.clipboard_writes == 1); } void platform_services_dispatch_visibility_updates(pp::tests::Harness& harness) { FakePlatformServices fake("unused"); pp::platform::PlatformServices& services = fake; services.set_cursor_visible(true); services.set_virtual_keyboard_visible(true); services.set_cursor_visible(false); services.set_virtual_keyboard_visible(false); PP_EXPECT(harness, fake.cursor_updates == 2); PP_EXPECT(harness, fake.keyboard_updates == 2); PP_EXPECT(harness, !fake.cursor_visible); PP_EXPECT(harness, !fake.keyboard_visible); } void platform_services_dispatch_ui_thread_lifecycle(pp::tests::Harness& harness) { FakePlatformServices fake("unused"); pp::platform::PlatformServices& services = fake; services.attach_ui_thread(); services.detach_ui_thread(); PP_EXPECT(harness, fake.ui_thread_attaches == 1); PP_EXPECT(harness, fake.ui_thread_detaches == 1); } void platform_services_dispatch_render_context_lifecycle(pp::tests::Harness& harness) { FakePlatformServices fake("unused"); pp::platform::PlatformServices& services = fake; services.acquire_render_context(); services.present_render_context(); services.bind_default_render_target(); services.bind_main_render_target(); services.apply_render_platform_hints(); services.install_render_debug_callback(); services.release_render_context(); PP_EXPECT(harness, fake.render_context_acquires == 1); PP_EXPECT(harness, fake.render_context_presents == 1); PP_EXPECT(harness, fake.default_render_target_binds == 1); PP_EXPECT(harness, fake.main_render_target_binds == 1); PP_EXPECT(harness, fake.render_platform_hint_applies == 1); PP_EXPECT(harness, fake.render_debug_callback_installs == 1); PP_EXPECT(harness, fake.render_context_releases == 1); } void platform_services_dispatch_render_capture_hooks(pp::tests::Harness& harness) { FakePlatformServices fake("unused"); pp::platform::PlatformServices& services = fake; services.begin_render_capture_frame(); services.end_render_capture_frame(); PP_EXPECT(harness, fake.render_capture_begins == 1); PP_EXPECT(harness, fake.render_capture_ends == 1); } void platform_services_dispatch_recording_cleanup(pp::tests::Harness& harness) { FakePlatformServices fake("unused"); pp::platform::PlatformServices& services = fake; PP_EXPECT(harness, services.deletes_recorded_files_on_clear()); services.clear_recorded_files("D:/Paint/frames"); PP_EXPECT(harness, fake.recording_delete_policy_checks == 1); PP_EXPECT(harness, fake.recording_clears == 1); PP_EXPECT(harness, fake.cleared_recording_path == "D:/Paint/frames"); } void platform_services_dispatch_exported_image_and_storage_flush(pp::tests::Harness& harness) { FakePlatformServices fake("unused"); pp::platform::PlatformServices& services = fake; services.publish_exported_image("D:/Paint/export.png"); services.flush_persistent_storage(); PP_EXPECT(harness, fake.exported_image_publishes == 1); PP_EXPECT(harness, fake.exported_image_path == "D:/Paint/export.png"); PP_EXPECT(harness, fake.persistent_storage_flushes == 1); } void platform_services_dispatch_document_browse_roots(pp::tests::Harness& harness) { FakePlatformServices fake("unused"); pp::platform::PlatformServices& services = fake; const auto roots = services.document_browse_roots("D:/Paint/work", "D:/Paint"); PP_EXPECT(harness, fake.document_browse_root_requests == 1); PP_EXPECT(harness, fake.browse_work_path == "D:/Paint/work"); PP_EXPECT(harness, fake.browse_data_path == "D:/Paint"); PP_EXPECT(harness, roots.size() == 2); PP_EXPECT(harness, roots[0] == "D:/Paint/work"); PP_EXPECT(harness, roots[1] == "D:/Paint/Inbox"); } void platform_services_dispatch_ui_state_save(pp::tests::Harness& harness) { FakePlatformServices fake("unused"); pp::platform::PlatformServices& services = fake; services.save_ui_state(); PP_EXPECT(harness, fake.ui_state_saves == 1); } void platform_services_dispatch_live_asset_reload_policy(pp::tests::Harness& harness) { FakePlatformServices fake("unused"); pp::platform::PlatformServices& services = fake; PP_EXPECT(harness, services.enables_live_asset_reloading()); fake.live_asset_reloading = false; PP_EXPECT(harness, !services.enables_live_asset_reloading()); PP_EXPECT(harness, fake.live_asset_reload_policy_checks == 2); } void platform_services_dispatch_frame_hooks(pp::tests::Harness& harness) { FakePlatformServices fake("unused"); pp::platform::PlatformServices& services = fake; services.update_platform_frame(0.125f); services.report_rendered_frames(42); PP_EXPECT(harness, fake.platform_frame_updates == 1); PP_EXPECT(harness, fake.last_platform_delta == 0.125f); PP_EXPECT(harness, fake.frame_reports == 1); PP_EXPECT(harness, fake.last_frame_report == 42); } void platform_services_dispatch_file_actions(pp::tests::Harness& harness) { FakePlatformServices fake("unused"); pp::platform::PlatformServices& services = fake; services.display_file("D:/Paint/export.png"); services.share_file("D:/Paint/demo.ppi"); services.request_app_close(); PP_EXPECT(harness, fake.display_file_requests == 1); PP_EXPECT(harness, fake.share_file_requests == 1); PP_EXPECT(harness, fake.app_close_requests == 1); PP_EXPECT(harness, fake.displayed_path == "D:/Paint/export.png"); PP_EXPECT(harness, fake.shared_path == "D:/Paint/demo.ppi"); } void platform_services_dispatch_vr_lifecycle(pp::tests::Harness& harness) { FakePlatformServices fake("unused"); pp::platform::PlatformServices& services = fake; PP_EXPECT(harness, !services.start_vr_mode()); fake.vr_start_success = true; PP_EXPECT(harness, services.start_vr_mode()); services.stop_vr_mode(); PP_EXPECT(harness, fake.vr_starts == 2); PP_EXPECT(harness, fake.vr_stops == 1); } void platform_services_dispatch_picker_callbacks(pp::tests::Harness& harness) { FakePlatformServices fake("unused"); pp::platform::PlatformServices& services = fake; std::string image_path; std::string file_path; std::string save_path; std::string directory_path; services.pick_image([&](std::string path) { image_path = std::move(path); }); services.pick_file({ "ppi", "ppbr" }, [&](std::string path) { file_path = std::move(path); }); services.pick_save_file({ "ppi" }, [&](std::string path) { save_path = std::move(path); }); services.pick_directory([&](std::string path) { directory_path = std::move(path); }); PP_EXPECT(harness, fake.pick_image_requests == 1); PP_EXPECT(harness, fake.pick_file_requests == 1); PP_EXPECT(harness, fake.pick_save_file_requests == 1); PP_EXPECT(harness, fake.pick_directory_requests == 1); PP_EXPECT(harness, image_path == "D:/Paint/import.png"); PP_EXPECT(harness, file_path == "D:/Paint/import.png"); PP_EXPECT(harness, save_path == "D:/Paint/export.ppi"); PP_EXPECT(harness, directory_path == "D:/Paint"); PP_EXPECT(harness, fake.picked_file_types.size() == 2); PP_EXPECT(harness, fake.save_file_types.size() == 1); } void platform_services_dispatch_working_directory_picker_policy(pp::tests::Harness& harness) { FakePlatformServices fake("unused"); pp::platform::PlatformServices& services = fake; PP_EXPECT(harness, !services.supports_working_directory_picker()); fake.working_directory_picker_supported = true; PP_EXPECT(harness, services.supports_working_directory_picker()); const auto formatted = services.format_working_directory_path("D:/Paint"); PP_EXPECT(harness, formatted == "D:/Paint/Absolute"); PP_EXPECT(harness, fake.last_working_directory_path == "D:/Paint"); PP_EXPECT(harness, fake.working_directory_picker_support_checks == 2); PP_EXPECT(harness, fake.working_directory_path_format_requests == 1); } void platform_services_dispatch_prepared_file_save(pp::tests::Harness& harness) { FakePlatformServices fake("unused"); pp::platform::PlatformServices& services = fake; std::string saved_path; bool saved = false; services.save_prepared_file( "D:/Paint/export.mp4", "export.mp4", [&](std::string path, bool success) { saved_path = std::move(path); saved = success; }); PP_EXPECT(harness, fake.save_prepared_file_requests == 1); PP_EXPECT(harness, fake.prepared_file_path == "D:/Paint/export.mp4"); PP_EXPECT(harness, fake.prepared_file_name == "export.mp4"); PP_EXPECT(harness, saved_path == "D:/Paint/export.mp4"); PP_EXPECT(harness, saved); } void platform_services_dispatch_writable_file_target(pp::tests::Harness& harness) { FakePlatformServices fake("unused"); pp::platform::PlatformServices& services = fake; PP_EXPECT(harness, services.uses_prepared_file_writes()); fake.prepared_file_writes = false; PP_EXPECT(harness, !services.uses_prepared_file_writes()); fake.prepared_file_writes = true; const auto target = services.prepare_writable_file("mp4", "export", "D:/Paint", "D:/Paint/tmp"); PP_EXPECT(harness, fake.prepared_file_write_policy_checks == 2); PP_EXPECT(harness, fake.prepare_writable_file_requests == 1); PP_EXPECT(harness, fake.writable_file_type == "mp4"); PP_EXPECT(harness, fake.writable_file_default_name == "export"); PP_EXPECT(harness, fake.writable_file_data_path == "D:/Paint"); PP_EXPECT(harness, fake.writable_file_temporary_path == "D:/Paint/tmp"); PP_EXPECT(harness, target.path == "D:/Paint/tmp/export.mp4"); PP_EXPECT(harness, target.suggested_name == "export.mp4"); PP_EXPECT(harness, target.write_on_background_thread); } void platform_services_dispatch_document_export_collection_policy(pp::tests::Harness& harness) { FakePlatformServices fake("unused"); pp::platform::PlatformServices& services = fake; PP_EXPECT(harness, !services.uses_work_directory_document_export_collections()); fake.work_directory_document_export_collections = true; PP_EXPECT(harness, services.uses_work_directory_document_export_collections()); PP_EXPECT(harness, fake.document_export_collection_policy_checks == 2); } void platform_services_dispatch_network_tls_policy(pp::tests::Harness& harness) { FakePlatformServices fake("unused"); pp::platform::PlatformServices& services = fake; PP_EXPECT(harness, !services.disables_network_tls_verification()); fake.network_tls_verification_disabled = true; PP_EXPECT(harness, services.disables_network_tls_verification()); PP_EXPECT(harness, fake.network_tls_policy_checks == 2); } void default_network_tls_policy_matches_build_target(pp::tests::Harness& harness) { #if defined(__ANDROID__) PP_EXPECT(harness, pp::platform::default_disables_network_tls_verification()); #else PP_EXPECT(harness, !pp::platform::default_disables_network_tls_verification()); #endif } void asset_file_load_policy_preserves_platform_reload_behavior(pp::tests::Harness& harness) { const auto temp_path = std::filesystem::temp_directory_path() / "panopainter-platform-api-file-policy.xml"; { std::ofstream file(temp_path); file << ""; } const auto first_load = pp::platform::plan_asset_file_load( temp_path.string(), false, 0); PP_EXPECT(harness, first_load.should_read_file); PP_EXPECT(harness, first_load.skipped_load_result); const auto repeated_load = pp::platform::plan_asset_file_load( temp_path.string(), true, first_load.last_write_time); PP_EXPECT(harness, !repeated_load.should_read_file); #if defined(_WIN32) || defined(__OSX__) PP_EXPECT(harness, !repeated_load.skipped_load_result); #else PP_EXPECT(harness, repeated_load.skipped_load_result); #endif std::filesystem::remove(temp_path); } void asset_file_load_policy_preserves_family_reload_behavior(pp::tests::Harness& harness) { const auto missing_desktop = pp::platform::plan_asset_file_load_with_probe( pp::platform::PlatformFamily::windows, false, 7, {}); PP_EXPECT(harness, !missing_desktop.should_read_file); PP_EXPECT(harness, !missing_desktop.skipped_load_result); PP_EXPECT(harness, missing_desktop.last_write_time == 7); const auto stale_desktop = pp::platform::plan_asset_file_load_with_probe( pp::platform::PlatformFamily::macos, true, 7, { true, 7 }); PP_EXPECT(harness, !stale_desktop.should_read_file); PP_EXPECT(harness, !stale_desktop.skipped_load_result); PP_EXPECT(harness, stale_desktop.last_write_time == 7); const auto fresh_desktop = pp::platform::plan_asset_file_load_with_probe( pp::platform::PlatformFamily::windows, true, 7, { true, 8 }); PP_EXPECT(harness, fresh_desktop.should_read_file); PP_EXPECT(harness, fresh_desktop.skipped_load_result); PP_EXPECT(harness, fresh_desktop.last_write_time == 8); const auto first_mobile = pp::platform::plan_asset_file_load_with_probe( pp::platform::PlatformFamily::ios, false, 7, {}); PP_EXPECT(harness, first_mobile.should_read_file); PP_EXPECT(harness, first_mobile.skipped_load_result); PP_EXPECT(harness, first_mobile.last_write_time == 7); const auto repeated_web = pp::platform::plan_asset_file_load_with_probe( pp::platform::PlatformFamily::webgl, true, 7, { true, 99 }); PP_EXPECT(harness, !repeated_web.should_read_file); PP_EXPECT(harness, repeated_web.skipped_load_result); PP_EXPECT(harness, repeated_web.last_write_time == 7); } void platform_services_dispatch_ppbr_export_directory_policy(pp::tests::Harness& harness) { FakePlatformServices fake("unused"); pp::platform::PlatformServices& services = fake; PP_EXPECT(harness, !services.uses_ppbr_export_data_directory_override()); fake.ppbr_export_data_directory_override = true; PP_EXPECT(harness, services.uses_ppbr_export_data_directory_override()); PP_EXPECT(harness, fake.ppbr_export_data_directory_override_checks == 2); } void platform_services_dispatch_sonarpen_policy_and_start(pp::tests::Harness& harness) { FakePlatformServices fake("unused"); pp::platform::PlatformServices& services = fake; PP_EXPECT(harness, !services.supports_sonarpen()); fake.sonarpen_supported = true; PP_EXPECT(harness, services.supports_sonarpen()); services.start_sonarpen(); PP_EXPECT(harness, fake.sonarpen_support_checks == 2); PP_EXPECT(harness, fake.sonarpen_starts == 1); } void platform_services_dispatch_default_canvas_resolution(pp::tests::Harness& harness) { FakePlatformServices fake("unused"); pp::platform::PlatformServices& services = fake; PP_EXPECT(harness, services.default_canvas_resolution() == 1536); fake.canvas_resolution = 512; PP_EXPECT(harness, services.default_canvas_resolution() == 512); PP_EXPECT(harness, fake.default_canvas_resolution_requests == 2); } void platform_services_dispatch_canvas_input_policy(pp::tests::Harness& harness) { FakePlatformServices fake("unused"); pp::platform::PlatformServices& services = fake; PP_EXPECT(harness, !services.draws_canvas_tip_for_pointer(true, false, true)); fake.canvas_tip_visible = true; PP_EXPECT(harness, services.draws_canvas_tip_for_pointer(false, true, false)); PP_EXPECT(harness, fake.canvas_tip_policy_checks == 2); PP_EXPECT(harness, !fake.last_canvas_tip_mouse); PP_EXPECT(harness, fake.last_canvas_tip_stylus); PP_EXPECT(harness, !fake.last_canvas_tip_left_release); const auto pressure = services.adjust_canvas_input_pressure(0.5f); PP_EXPECT(harness, pressure == 0.75f); PP_EXPECT(harness, fake.last_canvas_pressure == 0.5f); PP_EXPECT(harness, fake.canvas_pressure_adjustments == 1); } void platform_policy_preserves_recording_and_export_storage_rules(pp::tests::Harness& harness) { PP_EXPECT(harness, pp::platform::platform_deletes_recorded_files_on_clear(pp::platform::PlatformFamily::ios)); PP_EXPECT(harness, pp::platform::platform_deletes_recorded_files_on_clear(pp::platform::PlatformFamily::macos)); PP_EXPECT(harness, !pp::platform::platform_deletes_recorded_files_on_clear(pp::platform::PlatformFamily::windows)); PP_EXPECT(harness, pp::platform::platform_publishes_exported_images(pp::platform::PlatformFamily::ios)); PP_EXPECT(harness, !pp::platform::platform_publishes_exported_images(pp::platform::PlatformFamily::macos)); PP_EXPECT(harness, pp::platform::platform_flushes_persistent_storage(pp::platform::PlatformFamily::webgl)); PP_EXPECT(harness, !pp::platform::platform_flushes_persistent_storage(pp::platform::PlatformFamily::windows)); } void platform_policy_preserves_document_browse_roots(pp::tests::Harness& harness) { const auto ios_roots = pp::platform::platform_document_browse_roots( pp::platform::PlatformFamily::ios, "D:/Paint/work", "D:/Paint"); const auto desktop_roots = pp::platform::platform_document_browse_roots( pp::platform::PlatformFamily::windows, "D:/Paint/work", "D:/Paint"); PP_EXPECT(harness, ios_roots.size() == 2); PP_EXPECT(harness, ios_roots[0] == "D:/Paint/work"); PP_EXPECT(harness, ios_roots[1] == "D:/Paint/Inbox"); PP_EXPECT(harness, desktop_roots.size() == 1); PP_EXPECT(harness, desktop_roots[0] == "D:/Paint/work"); } void platform_policy_preserves_picker_and_prepared_file_rules(pp::tests::Harness& harness) { PP_EXPECT(harness, pp::platform::platform_supports_working_directory_picker(pp::platform::PlatformFamily::windows)); PP_EXPECT(harness, pp::platform::platform_supports_working_directory_picker(pp::platform::PlatformFamily::macos)); PP_EXPECT(harness, !pp::platform::platform_supports_working_directory_picker(pp::platform::PlatformFamily::ios)); PP_EXPECT(harness, pp::platform::platform_uses_prepared_file_writes(pp::platform::PlatformFamily::ios)); PP_EXPECT(harness, pp::platform::platform_uses_prepared_file_writes(pp::platform::PlatformFamily::webgl)); PP_EXPECT(harness, !pp::platform::platform_uses_prepared_file_writes(pp::platform::PlatformFamily::windows)); PP_EXPECT(harness, pp::platform::platform_uses_work_directory_document_export_collections(pp::platform::PlatformFamily::ios)); PP_EXPECT(harness, !pp::platform::platform_uses_work_directory_document_export_collections(pp::platform::PlatformFamily::webgl)); const auto ios_target = pp::platform::plan_platform_writable_file( pp::platform::PlatformFamily::ios, "mp4", "timelapse", "/PanoPainter", "/tmp"); PP_EXPECT(harness, ios_target.path == "/tmp/timelapse.mp4"); PP_EXPECT(harness, ios_target.suggested_name == "timelapse.mp4"); PP_EXPECT(harness, ios_target.write_on_background_thread); const auto web_target = pp::platform::plan_platform_writable_file( pp::platform::PlatformFamily::webgl, "png", "export", "/PanoPainter", "/tmp"); PP_EXPECT(harness, web_target.path == "/PanoPainter/export.png"); PP_EXPECT(harness, web_target.suggested_name == "export.png"); PP_EXPECT(harness, !web_target.write_on_background_thread); const auto desktop_target = pp::platform::plan_platform_writable_file( pp::platform::PlatformFamily::windows, "png", "export", "/PanoPainter", "/tmp"); PP_EXPECT(harness, desktop_target.path.empty()); PP_EXPECT(harness, desktop_target.suggested_name.empty()); } void platform_policy_preserves_ui_asset_and_input_rules(pp::tests::Harness& harness) { PP_EXPECT(harness, pp::platform::platform_enables_live_asset_reloading(pp::platform::PlatformFamily::windows)); PP_EXPECT(harness, pp::platform::platform_enables_live_asset_reloading(pp::platform::PlatformFamily::macos)); PP_EXPECT(harness, !pp::platform::platform_enables_live_asset_reloading(pp::platform::PlatformFamily::ios)); PP_EXPECT(harness, pp::platform::platform_uses_asset_file_mtime_reload(pp::platform::PlatformFamily::windows)); PP_EXPECT(harness, pp::platform::platform_uses_asset_file_mtime_reload(pp::platform::PlatformFamily::macos)); PP_EXPECT(harness, !pp::platform::platform_uses_asset_file_mtime_reload(pp::platform::PlatformFamily::android)); PP_EXPECT(harness, pp::platform::platform_saves_native_ui_state(pp::platform::PlatformFamily::windows)); PP_EXPECT(harness, pp::platform::platform_saves_native_ui_state(pp::platform::PlatformFamily::macos)); PP_EXPECT(harness, !pp::platform::platform_saves_native_ui_state(pp::platform::PlatformFamily::webgl)); PP_EXPECT(harness, pp::platform::platform_uses_ppbr_export_data_directory_override(pp::platform::PlatformFamily::macos)); PP_EXPECT(harness, !pp::platform::platform_uses_ppbr_export_data_directory_override(pp::platform::PlatformFamily::windows)); PP_EXPECT(harness, pp::platform::platform_supports_sonarpen(pp::platform::PlatformFamily::ios)); PP_EXPECT(harness, !pp::platform::platform_supports_sonarpen(pp::platform::PlatformFamily::android)); PP_EXPECT(harness, pp::platform::platform_default_canvas_resolution(pp::platform::PlatformFamily::webgl) == 512); PP_EXPECT(harness, pp::platform::platform_default_canvas_resolution(pp::platform::PlatformFamily::windows) == 1536); PP_EXPECT(harness, pp::platform::platform_draws_canvas_tip_for_pointer( pp::platform::PlatformFamily::ios, true, false, false)); PP_EXPECT(harness, !pp::platform::platform_draws_canvas_tip_for_pointer( pp::platform::PlatformFamily::ios, true, false, true)); PP_EXPECT(harness, pp::platform::platform_draws_canvas_tip_for_pointer( pp::platform::PlatformFamily::windows, false, true, true)); } } int main() { pp::tests::Harness harness; harness.run("platform services dispatch storage path preparation", platform_services_dispatch_storage_path_preparation); harness.run("platform services dispatch diagnostics", platform_services_dispatch_diagnostics); harness.run("platform services dispatch clipboard reads and writes", platform_services_dispatch_clipboard_reads_and_writes); harness.run("platform services preserve empty clipboard writes", platform_services_preserve_empty_clipboard_writes); harness.run("platform services dispatch visibility updates", platform_services_dispatch_visibility_updates); harness.run("platform services dispatch UI thread lifecycle", platform_services_dispatch_ui_thread_lifecycle); harness.run("platform services dispatch render context lifecycle", platform_services_dispatch_render_context_lifecycle); harness.run("platform services dispatch render capture hooks", platform_services_dispatch_render_capture_hooks); harness.run("platform services dispatch recording cleanup", platform_services_dispatch_recording_cleanup); harness.run("platform services dispatch exported image and storage flush", platform_services_dispatch_exported_image_and_storage_flush); harness.run("platform services dispatch document browse roots", platform_services_dispatch_document_browse_roots); harness.run("platform services dispatch UI state save", platform_services_dispatch_ui_state_save); harness.run("platform services dispatch live asset reload policy", platform_services_dispatch_live_asset_reload_policy); harness.run("platform services dispatch frame hooks", platform_services_dispatch_frame_hooks); harness.run("platform services dispatch file actions", platform_services_dispatch_file_actions); harness.run("platform services dispatch VR lifecycle", platform_services_dispatch_vr_lifecycle); harness.run("platform services dispatch picker callbacks", platform_services_dispatch_picker_callbacks); harness.run( "platform services dispatch working directory picker policy", platform_services_dispatch_working_directory_picker_policy); harness.run("platform services dispatch prepared file save", platform_services_dispatch_prepared_file_save); harness.run("platform services dispatch writable file target", platform_services_dispatch_writable_file_target); harness.run( "platform services dispatch document export collection policy", platform_services_dispatch_document_export_collection_policy); harness.run("platform services dispatch network tls policy", platform_services_dispatch_network_tls_policy); harness.run("default network tls policy matches build target", default_network_tls_policy_matches_build_target); harness.run( "asset file load policy preserves platform reload behavior", asset_file_load_policy_preserves_platform_reload_behavior); harness.run( "asset file load policy preserves family reload behavior", asset_file_load_policy_preserves_family_reload_behavior); harness.run( "platform services dispatch ppbr export directory policy", platform_services_dispatch_ppbr_export_directory_policy); harness.run("platform services dispatch sonarpen policy and start", platform_services_dispatch_sonarpen_policy_and_start); harness.run("platform services dispatch default canvas resolution", platform_services_dispatch_default_canvas_resolution); harness.run("platform services dispatch canvas input policy", platform_services_dispatch_canvas_input_policy); harness.run( "platform policy preserves recording and export storage rules", platform_policy_preserves_recording_and_export_storage_rules); harness.run("platform policy preserves document browse roots", platform_policy_preserves_document_browse_roots); harness.run( "platform policy preserves picker and prepared file rules", platform_policy_preserves_picker_and_prepared_file_rules); harness.run( "platform policy preserves UI asset and input rules", platform_policy_preserves_ui_asset_and_input_rules); return harness.finish(); }