修复若干bug
This commit is contained in:
+50
-107
@@ -13,10 +13,8 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <rigtorp/MPMCQueue.h>
|
||||
#include <thread>
|
||||
|
||||
namespace renderive {
|
||||
namespace {
|
||||
|
||||
bool unique_roles(const Triple_Buffer_View& view) {
|
||||
std::array<bool, 3> seen{};
|
||||
for (std::uint8_t index : view.index) {
|
||||
@@ -26,7 +24,6 @@ bool unique_roles(const Triple_Buffer_View& view) {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Frame_Lifecycle_Record render_frame(std::uint64_t begin_ns, std::uint64_t end_ns) {
|
||||
Frame_Lifecycle_Record frame;
|
||||
frame.render_role_enter_ns = begin_ns;
|
||||
@@ -34,7 +31,6 @@ Frame_Lifecycle_Record render_frame(std::uint64_t begin_ns, std::uint64_t end_ns
|
||||
frame.render_end_ns = end_ns;
|
||||
return frame;
|
||||
}
|
||||
|
||||
bool wait_until(std::function<bool()> predicate) {
|
||||
auto deadline = std::chrono::steady_clock::now() + std::chrono::seconds(2);
|
||||
while (std::chrono::steady_clock::now() < deadline) {
|
||||
@@ -44,7 +40,6 @@ bool wait_until(std::function<bool()> predicate) {
|
||||
}
|
||||
return predicate();
|
||||
}
|
||||
|
||||
std::shared_ptr<Frame_Lifecycle_Record> performance_frame(std::uint64_t frame_id, int width = 240, int height = 80) {
|
||||
auto frame = std::make_shared<Frame_Lifecycle_Record>();
|
||||
frame->frame_id = frame_id;
|
||||
@@ -68,7 +63,6 @@ std::shared_ptr<Frame_Lifecycle_Record> performance_frame(std::uint64_t frame_id
|
||||
frame->worker.executor_at_finish.completed_task_nodes = frame_id;
|
||||
return frame;
|
||||
}
|
||||
|
||||
bool valid_utf8(const std::string& text) {
|
||||
for (std::size_t i = 0; i < text.size();) {
|
||||
unsigned char c = static_cast<unsigned char>(text[i]);
|
||||
@@ -93,16 +87,13 @@ bool valid_utf8(const std::string& text) {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST(Renderive_Canvas, TextUsesPenAndFillUsesBrush) {
|
||||
auto diagnostics = Canvas::default_font_diagnostics();
|
||||
ASSERT_TRUE(diagnostics.face_valid);
|
||||
ASSERT_TRUE(diagnostics.font_valid);
|
||||
ASSERT_GT(diagnostics.test_width, 0.0);
|
||||
ASSERT_GT(diagnostics.test_height, 0.0);
|
||||
|
||||
Image image(400, 100);
|
||||
image.fill(Color::transparent());
|
||||
{
|
||||
@@ -113,7 +104,6 @@ TEST(Renderive_Canvas, TextUsesPenAndFillUsesBrush) {
|
||||
canvas.draw_text(PointF{10.0, 10.0}, "0123456789 ABC \xE4\xB8\xAD\xE6\x96\x87");
|
||||
canvas.draw_text(RectF{10.0, 50.0, 300.0, 30.0}, Text_Align::Left | Text_Align::Top, "0123");
|
||||
}
|
||||
|
||||
EXPECT_EQ(premultiplied_to_color(image.row(2)[2]), Color::white());
|
||||
int dark_pixels = 0;
|
||||
for (int y = 8; y < 82; ++y) {
|
||||
@@ -127,18 +117,15 @@ TEST(Renderive_Canvas, TextUsesPenAndFillUsesBrush) {
|
||||
}
|
||||
EXPECT_GT(dark_pixels, 20);
|
||||
}
|
||||
|
||||
TEST(Renderive_Triple_Buffer, RoleSwapsAreTryOnlyAndDeterministic) {
|
||||
Triple_Role_Buffer_Control control;
|
||||
control.reset();
|
||||
EXPECT_TRUE(unique_roles(control.read_view()));
|
||||
|
||||
auto first = control.try_swap_role(Frame_Rendering, Frame_Middle, [](const Triple_Buffer_View&) {
|
||||
return true;
|
||||
});
|
||||
EXPECT_EQ(first.result, Triple_Buffer_Result::Success);
|
||||
EXPECT_TRUE(unique_roles(control.read_view()));
|
||||
|
||||
auto painting = control.try_acquire_role(Frame_Painting);
|
||||
ASSERT_EQ(painting.result, Triple_Buffer_Result::Success);
|
||||
auto blocked = control.try_swap_role(Frame_Middle, Frame_Painting, [](const Triple_Buffer_View&) {
|
||||
@@ -146,7 +133,6 @@ TEST(Renderive_Triple_Buffer, RoleSwapsAreTryOnlyAndDeterministic) {
|
||||
});
|
||||
EXPECT_EQ(blocked.result, Triple_Buffer_Result::Busy);
|
||||
control.unmark_use(painting.lease);
|
||||
|
||||
for (int i = 0; i < 1000000; ++i) {
|
||||
auto a = control.try_swap_role(Frame_Rendering, Frame_Middle, [](const Triple_Buffer_View&) {
|
||||
return true;
|
||||
@@ -159,7 +145,6 @@ TEST(Renderive_Triple_Buffer, RoleSwapsAreTryOnlyAndDeterministic) {
|
||||
ASSERT_TRUE(unique_roles(control.read_view()));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Renderive_Frame_Pipeline, PublishAndPaintUseMiddleVersionOnly) {
|
||||
Plot_Frame_Pipeline pipeline;
|
||||
auto lease = pipeline.try_acquire_render_frame();
|
||||
@@ -170,18 +155,15 @@ TEST(Renderive_Frame_Pipeline, PublishAndPaintUseMiddleVersionOnly) {
|
||||
lease.frame->metadata->render_end_ns = 20;
|
||||
lease.frame->version.store(1, std::memory_order_release);
|
||||
lease.reset();
|
||||
|
||||
auto published = pipeline.try_publish_rendered_frame(25);
|
||||
EXPECT_TRUE(pipeline.middle_frame_ready());
|
||||
EXPECT_TRUE(published.request_present);
|
||||
EXPECT_EQ(published.dropped_frame_record, nullptr);
|
||||
|
||||
auto painting = pipeline.try_acquire_paint_frame(30);
|
||||
EXPECT_TRUE(painting.has_new_frame);
|
||||
EXPECT_TRUE(static_cast<bool>(painting.lease));
|
||||
EXPECT_FALSE(pipeline.middle_frame_ready());
|
||||
}
|
||||
|
||||
TEST(Renderive_Frame_Pipeline, PaintAcquireFailureKeepsPendingRequest) {
|
||||
Plot_Frame_Pipeline pipeline;
|
||||
auto lease = pipeline.try_acquire_render_frame();
|
||||
@@ -192,11 +174,9 @@ TEST(Renderive_Frame_Pipeline, PaintAcquireFailureKeepsPendingRequest) {
|
||||
lease.frame->metadata->render_end_ns = 20;
|
||||
lease.frame->version.store(1, std::memory_order_release);
|
||||
lease.reset();
|
||||
|
||||
auto published = pipeline.try_publish_rendered_frame(25);
|
||||
ASSERT_TRUE(published.request_present);
|
||||
EXPECT_TRUE(pipeline.paint_request_pending.load(std::memory_order_acquire));
|
||||
|
||||
auto busy = pipeline.frame_control.try_acquire_role(Frame_Painting);
|
||||
ASSERT_EQ(busy.result, Triple_Buffer_Result::Success);
|
||||
auto failed = pipeline.try_acquire_paint_frame(30);
|
||||
@@ -204,18 +184,15 @@ TEST(Renderive_Frame_Pipeline, PaintAcquireFailureKeepsPendingRequest) {
|
||||
EXPECT_FALSE(failed.present_request_was_pending);
|
||||
EXPECT_TRUE(pipeline.paint_request_pending.load(std::memory_order_acquire));
|
||||
pipeline.frame_control.unmark_use(busy.lease);
|
||||
|
||||
auto consumed = pipeline.try_acquire_paint_frame(35);
|
||||
EXPECT_TRUE(consumed.present_request_was_pending);
|
||||
EXPECT_TRUE(static_cast<bool>(consumed.lease));
|
||||
}
|
||||
|
||||
TEST(Renderive_MPMCQueue, UsesTryOnlyBoundedCapacity) {
|
||||
rigtorp::MPMCQueue<int> queue(2);
|
||||
EXPECT_TRUE(queue.try_push(1));
|
||||
EXPECT_TRUE(queue.try_push(2));
|
||||
EXPECT_FALSE(queue.try_push(3));
|
||||
|
||||
int value = 0;
|
||||
EXPECT_TRUE(queue.try_pop(value));
|
||||
EXPECT_EQ(value, 1);
|
||||
@@ -223,7 +200,6 @@ TEST(Renderive_MPMCQueue, UsesTryOnlyBoundedCapacity) {
|
||||
EXPECT_EQ(value, 2);
|
||||
EXPECT_FALSE(queue.try_pop(value));
|
||||
}
|
||||
|
||||
TEST(Renderive_Frame_Feedback, SelectsRenderPaintAndUserSources) {
|
||||
Frame_Feedback_Controller controller;
|
||||
controller.set_max_render_fps(200.0);
|
||||
@@ -232,7 +208,6 @@ TEST(Renderive_Frame_Feedback, SelectsRenderPaintAndUserSources) {
|
||||
controller.on_render_completed(render_limited);
|
||||
}
|
||||
EXPECT_EQ(controller.state().source, Refresh_Limit_Source::Render);
|
||||
|
||||
controller.reset();
|
||||
controller.set_max_render_fps(200.0);
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
@@ -244,7 +219,6 @@ TEST(Renderive_Frame_Feedback, SelectsRenderPaintAndUserSources) {
|
||||
controller.on_frame_presented(frame);
|
||||
}
|
||||
EXPECT_EQ(controller.state().source, Refresh_Limit_Source::Paint);
|
||||
|
||||
controller.reset();
|
||||
controller.set_max_render_fps(30.0);
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
@@ -256,7 +230,6 @@ TEST(Renderive_Frame_Feedback, SelectsRenderPaintAndUserSources) {
|
||||
}
|
||||
EXPECT_EQ(controller.state().source, Refresh_Limit_Source::User);
|
||||
}
|
||||
|
||||
TEST(Renderive_Render_Executor, FrameAdmissionIsBounded) {
|
||||
Render_Executor executor(Render_Runtime_Config{1});
|
||||
std::atomic_bool entered{false};
|
||||
@@ -270,19 +243,19 @@ TEST(Renderive_Render_Executor, FrameAdmissionIsBounded) {
|
||||
Task([&]() {
|
||||
entered.store(true, std::memory_order_release);
|
||||
while (!release.load(std::memory_order_acquire))
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
}),
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
}),
|
||||
{},
|
||||
Task([&]() {
|
||||
completed.fetch_add(1, std::memory_order_acq_rel);
|
||||
}),
|
||||
}),
|
||||
first_stat,
|
||||
1,
|
||||
true
|
||||
}));
|
||||
}));
|
||||
ASSERT_TRUE(wait_until([&]() {
|
||||
return entered.load(std::memory_order_acquire);
|
||||
}));
|
||||
}));
|
||||
auto second_stat = std::make_shared<Frame_Worker_Stats>();
|
||||
EXPECT_TRUE(executor.try_submit(Render_Executor_Task{
|
||||
2,
|
||||
@@ -292,11 +265,11 @@ TEST(Renderive_Render_Executor, FrameAdmissionIsBounded) {
|
||||
{},
|
||||
Task([&]() {
|
||||
completed.fetch_add(1, std::memory_order_acq_rel);
|
||||
}),
|
||||
}),
|
||||
second_stat,
|
||||
1,
|
||||
true
|
||||
}));
|
||||
}));
|
||||
auto third_stat = std::make_shared<Frame_Worker_Stats>();
|
||||
EXPECT_TRUE(executor.try_submit(Render_Executor_Task{
|
||||
3,
|
||||
@@ -306,11 +279,11 @@ TEST(Renderive_Render_Executor, FrameAdmissionIsBounded) {
|
||||
{},
|
||||
Task([&]() {
|
||||
completed.fetch_add(1, std::memory_order_acq_rel);
|
||||
}),
|
||||
}),
|
||||
third_stat,
|
||||
1,
|
||||
true
|
||||
}));
|
||||
}));
|
||||
auto duplicate_stat = std::make_shared<Frame_Worker_Stats>();
|
||||
EXPECT_FALSE(executor.try_submit(Render_Executor_Task{
|
||||
2,
|
||||
@@ -322,7 +295,7 @@ TEST(Renderive_Render_Executor, FrameAdmissionIsBounded) {
|
||||
duplicate_stat,
|
||||
1,
|
||||
true
|
||||
}));
|
||||
}));
|
||||
auto overflow_stat = std::make_shared<Frame_Worker_Stats>();
|
||||
EXPECT_FALSE(executor.try_submit(Render_Executor_Task{
|
||||
4,
|
||||
@@ -334,66 +307,61 @@ TEST(Renderive_Render_Executor, FrameAdmissionIsBounded) {
|
||||
overflow_stat,
|
||||
1,
|
||||
true
|
||||
}));
|
||||
}));
|
||||
release.store(true, std::memory_order_release);
|
||||
ASSERT_TRUE(wait_until([&]() {
|
||||
return completed.load(std::memory_order_acquire) == 3;
|
||||
}));
|
||||
}));
|
||||
executor.shutdown();
|
||||
}
|
||||
|
||||
TEST(Renderive_Render_Executor, TaskflowTopologyRunsInFrameOrder) {
|
||||
Render_Executor executor(Render_Runtime_Config{2});
|
||||
std::atomic_int sequence{0};
|
||||
std::atomic_bool completed{false};
|
||||
auto stat = std::make_shared<Frame_Worker_Stats>();
|
||||
|
||||
ASSERT_TRUE(executor.try_submit(Render_Executor_Task{
|
||||
1,
|
||||
1,
|
||||
Render_Task_Kind::Frame,
|
||||
Task{},
|
||||
[&sequence](tf::Taskflow& taskflow, tf::Task entry, tf::Task exit) {
|
||||
auto prepare = taskflow.emplace([&sequence]() {
|
||||
int expected = 0;
|
||||
sequence.compare_exchange_strong(expected, 1, std::memory_order_acq_rel);
|
||||
auto prepare = taskflow.emplace([&sequence]() {
|
||||
int expected = 0;
|
||||
sequence.compare_exchange_strong(expected, 1, std::memory_order_acq_rel);
|
||||
});
|
||||
auto draw = taskflow.emplace([&sequence]() {
|
||||
int expected = 1;
|
||||
sequence.compare_exchange_strong(expected, 2, std::memory_order_acq_rel);
|
||||
auto draw = taskflow.emplace([&sequence]() {
|
||||
int expected = 1;
|
||||
sequence.compare_exchange_strong(expected, 2, std::memory_order_acq_rel);
|
||||
});
|
||||
auto finalize = taskflow.emplace([&sequence]() {
|
||||
int expected = 2;
|
||||
sequence.compare_exchange_strong(expected, 3, std::memory_order_acq_rel);
|
||||
auto finalize = taskflow.emplace([&sequence]() {
|
||||
int expected = 2;
|
||||
sequence.compare_exchange_strong(expected, 3, std::memory_order_acq_rel);
|
||||
});
|
||||
entry.precede(prepare);
|
||||
prepare.precede(draw);
|
||||
draw.precede(finalize);
|
||||
finalize.precede(exit);
|
||||
entry.precede(prepare);
|
||||
prepare.precede(draw);
|
||||
draw.precede(finalize);
|
||||
finalize.precede(exit);
|
||||
},
|
||||
Task([&completed]() {
|
||||
completed.store(true, std::memory_order_release);
|
||||
}),
|
||||
}),
|
||||
stat,
|
||||
3,
|
||||
true
|
||||
}));
|
||||
|
||||
}));
|
||||
ASSERT_TRUE(wait_until([&]() {
|
||||
return completed.load(std::memory_order_acquire);
|
||||
}));
|
||||
}));
|
||||
EXPECT_EQ(sequence.load(std::memory_order_acquire), 3);
|
||||
EXPECT_EQ(stat->task_count, 3u);
|
||||
executor.shutdown();
|
||||
}
|
||||
|
||||
TEST(Renderive_Render_Executor, QueuedFramesRunRoundRobinByPlot) {
|
||||
Render_Executor executor(Render_Runtime_Config{1});
|
||||
std::atomic_bool first_entered{false};
|
||||
std::atomic_bool release_first{false};
|
||||
std::atomic_int order_index{0};
|
||||
std::array<int, 3> order{};
|
||||
|
||||
ASSERT_TRUE(executor.try_submit(Render_Executor_Task{
|
||||
1,
|
||||
1,
|
||||
@@ -401,56 +369,53 @@ TEST(Renderive_Render_Executor, QueuedFramesRunRoundRobinByPlot) {
|
||||
Task([&]() {
|
||||
first_entered.store(true, std::memory_order_release);
|
||||
while (!release_first.load(std::memory_order_acquire))
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
order[order_index.fetch_add(1, std::memory_order_acq_rel)] = 1;
|
||||
}),
|
||||
}),
|
||||
{},
|
||||
Task([]() {}),
|
||||
std::make_shared<Frame_Worker_Stats>(),
|
||||
1,
|
||||
true
|
||||
}));
|
||||
}));
|
||||
ASSERT_TRUE(wait_until([&]() {
|
||||
return first_entered.load(std::memory_order_acquire);
|
||||
}));
|
||||
|
||||
}));
|
||||
ASSERT_TRUE(executor.try_submit(Render_Executor_Task{
|
||||
2,
|
||||
1,
|
||||
Render_Task_Kind::Frame,
|
||||
Task([&]() {
|
||||
order[order_index.fetch_add(1, std::memory_order_acq_rel)] = 2;
|
||||
}),
|
||||
}),
|
||||
{},
|
||||
Task([]() {}),
|
||||
std::make_shared<Frame_Worker_Stats>(),
|
||||
1,
|
||||
true
|
||||
}));
|
||||
}));
|
||||
ASSERT_TRUE(executor.try_submit(Render_Executor_Task{
|
||||
3,
|
||||
1,
|
||||
Render_Task_Kind::Frame,
|
||||
Task([&]() {
|
||||
order[order_index.fetch_add(1, std::memory_order_acq_rel)] = 3;
|
||||
}),
|
||||
}),
|
||||
{},
|
||||
Task([]() {}),
|
||||
std::make_shared<Frame_Worker_Stats>(),
|
||||
1,
|
||||
true
|
||||
}));
|
||||
|
||||
}));
|
||||
release_first.store(true, std::memory_order_release);
|
||||
ASSERT_TRUE(wait_until([&]() {
|
||||
return order_index.load(std::memory_order_acquire) == 3;
|
||||
}));
|
||||
}));
|
||||
EXPECT_EQ(order[0], 1);
|
||||
EXPECT_EQ(order[1], 2);
|
||||
EXPECT_EQ(order[2], 3);
|
||||
executor.shutdown();
|
||||
}
|
||||
|
||||
TEST(Renderive_Performance_Shower, ToggleDoesNotReenterRenderableTreeUnsafely) {
|
||||
Plot_Core plot(std::make_unique<Latency_Eager_Refresh_Strategy>());
|
||||
plot.init();
|
||||
@@ -464,7 +429,6 @@ TEST(Renderive_Performance_Shower, ToggleDoesNotReenterRenderableTreeUnsafely) {
|
||||
EXPECT_FALSE(performance_overlay_enabled(plot));
|
||||
EXPECT_TRUE(root->children_snapshot().empty());
|
||||
}
|
||||
|
||||
TEST(Renderive_Performance_Shower, TogglePreservesAttachedOptions) {
|
||||
Plot_Core plot(std::make_unique<Latency_Eager_Refresh_Strategy>());
|
||||
plot.init();
|
||||
@@ -472,7 +436,6 @@ TEST(Renderive_Performance_Shower, TogglePreservesAttachedOptions) {
|
||||
options.font.size = 17.0;
|
||||
options.background = Color{10, 20, 30, 255};
|
||||
options.foreground = Color{240, 240, 240, 255};
|
||||
|
||||
auto original = attach_performance_overlay(plot, options);
|
||||
ASSERT_TRUE(original);
|
||||
set_performance_overlay_enabled(plot, true);
|
||||
@@ -480,21 +443,18 @@ TEST(Renderive_Performance_Shower, TogglePreservesAttachedOptions) {
|
||||
set_performance_overlay_enabled(plot, false);
|
||||
EXPECT_FALSE(performance_overlay_enabled(plot));
|
||||
set_performance_overlay_enabled(plot, true);
|
||||
|
||||
auto toggled = performance_overlay(plot);
|
||||
ASSERT_EQ(toggled, original);
|
||||
EXPECT_EQ(toggled->options().font.size, options.font.size);
|
||||
EXPECT_EQ(toggled->options().background, options.background);
|
||||
EXPECT_EQ(toggled->options().foreground, options.foreground);
|
||||
}
|
||||
|
||||
TEST(Renderive_Hover_Info, DefaultTextPenContrastsWithDefaultBackground) {
|
||||
TEST(Renderive_Hover_Tooltip, DefaultTextPenContrastsWithDefaultBackground) {
|
||||
Hover_Tooltip_State state;
|
||||
EXPECT_EQ(state.tooltip_background_brush.color, Color::white());
|
||||
EXPECT_EQ(state.tooltip_text_pen.color, Color::black());
|
||||
}
|
||||
|
||||
TEST(Renderive_Performance_Shower, WorkerConsumesSharedFrameRecord) {
|
||||
TEST(Renderive_Performance_Overlay, WorkerConsumesSharedFrameRecord) {
|
||||
auto state = std::make_shared<Performance_Worker_State>();
|
||||
state->enabled.store(true, std::memory_order_release);
|
||||
auto frame = std::make_shared<Frame_Lifecycle_Record>();
|
||||
@@ -511,7 +471,6 @@ TEST(Renderive_Performance_Shower, WorkerConsumesSharedFrameRecord) {
|
||||
frame->outcome = Frame_Outcome::Presented;
|
||||
Performance_Frame_Record record = frame;
|
||||
ASSERT_TRUE(state->metric_queue.try_push(record));
|
||||
|
||||
schedule_performance_metrics_worker(state);
|
||||
auto deadline = std::chrono::steady_clock::now() + std::chrono::seconds(2);
|
||||
std::shared_ptr<const Performance_Display_Snapshot> snapshot;
|
||||
@@ -522,13 +481,11 @@ TEST(Renderive_Performance_Shower, WorkerConsumesSharedFrameRecord) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
}
|
||||
state->cancelled.store(true, std::memory_order_release);
|
||||
|
||||
ASSERT_TRUE(snapshot);
|
||||
EXPECT_FALSE(snapshot->lines.empty());
|
||||
EXPECT_TRUE(state->aggregate.has_frame);
|
||||
EXPECT_EQ(state->aggregate.latest.frame_id, 7);
|
||||
}
|
||||
|
||||
TEST(Renderive_Performance_Shower, OptionsAffectSnapshotRendering) {
|
||||
Performance_Overlay shower;
|
||||
Performance_Overlay_Options options;
|
||||
@@ -539,11 +496,10 @@ TEST(Renderive_Performance_Shower, OptionsAffectSnapshotRendering) {
|
||||
shower.set_enabled(true);
|
||||
shower.set_viewport(Size{260, 120}, 1);
|
||||
shower.collect_frame(performance_frame(1, 260, 120));
|
||||
|
||||
ASSERT_TRUE(wait_until([&]() {
|
||||
auto snapshot = shower.display_snapshot();
|
||||
return snapshot && !snapshot->image.empty();
|
||||
}));
|
||||
}));
|
||||
auto snapshot = shower.display_snapshot();
|
||||
ASSERT_TRUE(snapshot);
|
||||
ASSERT_FALSE(snapshot->image.empty());
|
||||
@@ -551,35 +507,31 @@ TEST(Renderive_Performance_Shower, OptionsAffectSnapshotRendering) {
|
||||
EXPECT_GT(snapshot->line_height, 12.0);
|
||||
EXPECT_EQ(premultiplied_to_color(snapshot->image.row(1)[1]), options.background);
|
||||
}
|
||||
|
||||
TEST(Renderive_Performance_Shower, OutcomeWidthIsSeededWithLongestEnumText) {
|
||||
auto state = std::make_shared<Performance_Worker_State>();
|
||||
state->enabled.store(true, std::memory_order_release);
|
||||
auto outcome_width = [&]() {
|
||||
return state->field_layout_states[static_cast<std::size_t>(Performance_Metric_Id::Outcome)].max_value_width;
|
||||
};
|
||||
|
||||
auto presented = performance_frame(1, 260, 120);
|
||||
presented->outcome = Frame_Outcome::Presented;
|
||||
ASSERT_TRUE(state->metric_queue.try_push(Performance_Frame_Record{presented}));
|
||||
schedule_performance_metrics_worker(state);
|
||||
ASSERT_TRUE(wait_until([&]() {
|
||||
return state->aggregate.latest.frame_id == 1 && !state->worker_active.load(std::memory_order_acquire);
|
||||
}));
|
||||
}));
|
||||
double seeded_width = outcome_width();
|
||||
EXPECT_GT(seeded_width, 0.0);
|
||||
|
||||
auto dropped = performance_frame(2, 260, 120);
|
||||
dropped->outcome = Frame_Outcome::Worker_Budget_Dropped;
|
||||
ASSERT_TRUE(state->metric_queue.try_push(Performance_Frame_Record{dropped}));
|
||||
schedule_performance_metrics_worker(state);
|
||||
ASSERT_TRUE(wait_until([&]() {
|
||||
return state->aggregate.latest.frame_id == 2 && !state->worker_active.load(std::memory_order_acquire);
|
||||
}));
|
||||
}));
|
||||
EXPECT_EQ(outcome_width(), seeded_width);
|
||||
state->cancelled.store(true, std::memory_order_release);
|
||||
}
|
||||
|
||||
TEST(Renderive_Performance_Shower, NumericFieldWidthIsMonotonicAcrossResetAndResize) {
|
||||
auto state = std::make_shared<Performance_Worker_State>();
|
||||
state->enabled.store(true, std::memory_order_release);
|
||||
@@ -595,7 +547,7 @@ TEST(Renderive_Performance_Shower, NumericFieldWidthIsMonotonicAcrossResetAndRes
|
||||
ASSERT_TRUE(wait_until([&]() {
|
||||
auto snapshot = state->published_snapshot.load(std::memory_order_acquire);
|
||||
return snapshot && state->aggregate.latest.frame_id == frame_id && !state->worker_active.load(std::memory_order_acquire);
|
||||
}));
|
||||
}));
|
||||
double current = frame_width();
|
||||
EXPECT_GE(current, previous);
|
||||
previous = current;
|
||||
@@ -604,14 +556,12 @@ TEST(Renderive_Performance_Shower, NumericFieldWidthIsMonotonicAcrossResetAndRes
|
||||
if (frame_id == 2 || frame_id == 8)
|
||||
EXPECT_EQ(current, wide);
|
||||
}
|
||||
|
||||
state->reset_requested.store(true, std::memory_order_release);
|
||||
schedule_performance_metrics_worker(state);
|
||||
ASSERT_TRUE(wait_until([&]() {
|
||||
return !state->worker_active.load(std::memory_order_acquire);
|
||||
}));
|
||||
}));
|
||||
EXPECT_EQ(frame_width(), wide);
|
||||
|
||||
state->viewport_width.store(180, std::memory_order_release);
|
||||
state->viewport_height.store(90, std::memory_order_release);
|
||||
state->viewport_version.store(2, std::memory_order_release);
|
||||
@@ -620,11 +570,10 @@ TEST(Renderive_Performance_Shower, NumericFieldWidthIsMonotonicAcrossResetAndRes
|
||||
ASSERT_TRUE(wait_until([&]() {
|
||||
auto snapshot = state->published_snapshot.load(std::memory_order_acquire);
|
||||
return snapshot && snapshot->viewport_version == 2 && !state->worker_active.load(std::memory_order_acquire);
|
||||
}));
|
||||
}));
|
||||
EXPECT_EQ(frame_width(), wide);
|
||||
state->cancelled.store(true, std::memory_order_release);
|
||||
}
|
||||
|
||||
TEST(Renderive_Performance_Shower, ScrollCommandsUpdateOffsetAndClamp) {
|
||||
Performance_Overlay shower;
|
||||
shower.set_enabled(true);
|
||||
@@ -634,16 +583,14 @@ TEST(Renderive_Performance_Shower, ScrollCommandsUpdateOffsetAndClamp) {
|
||||
ASSERT_TRUE(wait_until([&]() {
|
||||
auto snapshot = shower.display_snapshot();
|
||||
return snapshot && snapshot->max_scroll_offset > 0.0;
|
||||
}));
|
||||
|
||||
}));
|
||||
auto snapshot = shower.display_snapshot();
|
||||
ASSERT_TRUE(snapshot);
|
||||
EXPECT_TRUE(shower.handle_wheel(PointF{5.0, 5.0}, -120.0, 0.0));
|
||||
ASSERT_TRUE(wait_until([&]() {
|
||||
auto next = shower.display_snapshot();
|
||||
return next && next->scroll_offset > snapshot->scroll_offset;
|
||||
}));
|
||||
|
||||
}));
|
||||
snapshot = shower.display_snapshot();
|
||||
ASSERT_TRUE(snapshot);
|
||||
PointF page_down{snapshot->scroll_track_rect.x + 1.0, snapshot->scroll_thumb_rect.bottom() + 1.0};
|
||||
@@ -651,8 +598,7 @@ TEST(Renderive_Performance_Shower, ScrollCommandsUpdateOffsetAndClamp) {
|
||||
ASSERT_TRUE(wait_until([&]() {
|
||||
auto next = shower.display_snapshot();
|
||||
return next && next->scroll_offset > snapshot->scroll_offset;
|
||||
}));
|
||||
|
||||
}));
|
||||
snapshot = shower.display_snapshot();
|
||||
ASSERT_TRUE(snapshot);
|
||||
PointF thumb_center{snapshot->scroll_thumb_rect.x + 1.0, snapshot->scroll_thumb_rect.y + snapshot->scroll_thumb_rect.height * 0.5};
|
||||
@@ -662,9 +608,8 @@ TEST(Renderive_Performance_Shower, ScrollCommandsUpdateOffsetAndClamp) {
|
||||
ASSERT_TRUE(wait_until([&]() {
|
||||
auto next = shower.display_snapshot();
|
||||
return next && next->max_scroll_offset > 0.0 && next->scroll_offset > next->max_scroll_offset * 0.8;
|
||||
}));
|
||||
}));
|
||||
}
|
||||
|
||||
TEST(Renderive_Performance_Shower, Utf8WrappingKeepsValidText) {
|
||||
Performance_Overlay shower;
|
||||
shower.set_enabled(true);
|
||||
@@ -680,15 +625,13 @@ TEST(Renderive_Performance_Shower, Utf8WrappingKeepsValidText) {
|
||||
ASSERT_TRUE(wait_until([&]() {
|
||||
auto snapshot = shower.display_snapshot();
|
||||
return snapshot && !snapshot->lines.empty();
|
||||
}));
|
||||
}));
|
||||
auto snapshot = shower.display_snapshot();
|
||||
ASSERT_TRUE(snapshot);
|
||||
for (const auto& line : snapshot->lines)
|
||||
EXPECT_TRUE(valid_utf8(line)) << line;
|
||||
}
|
||||
|
||||
} // namespace renderive
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
|
||||
Reference in New Issue
Block a user