1011 lines
37 KiB
C++
1011 lines
37 KiB
C++
#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 <filesystem>
|
|
#include <fstream>
|
|
#include <string>
|
|
#include <string_view>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
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<std::string> 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<std::string> 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<std::string> 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<std::string> picked_file_types;
|
|
std::vector<std::string> save_file_types;
|
|
std::vector<std::string> 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 << "<layouts />";
|
|
}
|
|
|
|
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 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_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(
|
|
"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();
|
|
}
|