加上纯色websocket

This commit is contained in:
2026-08-26 18:06:48 +08:00
parent 272d85caac
commit 2de8a35fff
28 changed files with 2061 additions and 549 deletions
+59
View File
@@ -0,0 +1,59 @@
#include <gtest/gtest.h>
#include <web_server/src/frame_sampling/Frame_Sampler.hpp>
#include <web_server/src/frame_sampling/websocket_pixel/WebSocket_Pixel_Frame.hpp>
#include <cstddef>
#include <cstdint>
#include <memory>
#include <vector>
namespace aethera::web::frame_sampling {
namespace {
std::shared_ptr<const Plot_Pixel_Frame> native_bgra_frame() {
auto pixels = std::make_shared<std::vector<std::byte>>(16U);
(*pixels)[0] = std::byte{11};
(*pixels)[1] = std::byte{22};
(*pixels)[2] = std::byte{33};
(*pixels)[3] = std::byte{44};
return std::make_shared<const Plot_Pixel_Frame>(Plot_Pixel_Frame{
std::move(pixels), Plot_Pixel_Layout::bgra8,
std::chrono::microseconds{12'345}, 1, 9, 1, 9, 2, 2});
}
}
TEST(Frame_Sampler, First_Deadline_Samples_Latest_Without_Format_Conversion) {
Frame_Sampler sampler(30.0, 2, 2, 1, {"plot"}, 0);
ASSERT_EQ(sampler.accept_frame(0, native_bgra_frame()),
Frame_Sampler::Accept_Frame_Result::accepted);
const auto sample = sampler.sample();
ASSERT_TRUE(sample);
EXPECT_EQ(sample->composition.layout, Plot_Pixel_Layout::bgra8);
EXPECT_EQ(sample->composition.pixels[0], std::byte{11});
EXPECT_EQ(sample->composition.pixels[1], std::byte{22});
EXPECT_EQ(sample->composition.pixels[2], std::byte{33});
EXPECT_EQ(sample->composition.pixels[3], std::byte{44});
EXPECT_EQ(sample->tick.sequence, 9U);
EXPECT_DOUBLE_EQ(sample->tick.time_milliseconds, 12.345);
EXPECT_FALSE(sampler.sample());
const auto state = sampler.state();
EXPECT_DOUBLE_EQ(state.target_frame_rate_fps, 30.0);
EXPECT_EQ(state.sampled_frames, 1U);
EXPECT_EQ(state.early_ticks, 1U);
}
TEST(WebSocket_Pixel_Frame, Header_Describes_Unchanged_Native_Payload) {
Frame_Sampler sampler(30.0, 2, 2, 1, {"plot"}, 0);
ASSERT_EQ(sampler.accept_frame(0, native_bgra_frame()),
Frame_Sampler::Accept_Frame_Result::accepted);
const auto sample = sampler.sample();
ASSERT_TRUE(sample);
const auto packet = websocket_pixel::pack_websocket_pixel_frame(*sample);
ASSERT_EQ(packet.bytes.size(), 48U + 16U);
EXPECT_EQ(packet.bytes.substr(0, 4), "AERP");
EXPECT_EQ(static_cast<std::uint8_t>(packet.bytes[8]), 1U);
EXPECT_EQ(static_cast<std::uint8_t>(packet.bytes[48]), 11U);
EXPECT_EQ(static_cast<std::uint8_t>(packet.bytes[49]), 22U);
EXPECT_EQ(static_cast<std::uint8_t>(packet.bytes[50]), 33U);
EXPECT_EQ(static_cast<std::uint8_t>(packet.bytes[51]), 44U);
}
}
@@ -1,61 +0,0 @@
#include <gtest/gtest.h>
#include <web_server/src/detail/Gallery_Frame_Clock.hpp>
#include <chrono>
#include <condition_variable>
#include <exception>
#include <mutex>
#include <thread>
#include <vector>
namespace aethera::web::detail {
TEST(Gallery_Frame_Clock, Produces_One_Monotonic_Absolute_Timeline) {
std::mutex mutex;
std::condition_variable condition;
std::vector<Plot_Render_Tick> ticks;
std::exception_ptr failure;
{
Gallery_Frame_Clock clock(
100.0,
[&](Plot_Render_Tick tick) {
std::lock_guard lock(mutex);
ticks.push_back(tick);
condition.notify_all();
},
[&](std::exception_ptr value) {
std::lock_guard lock(mutex);
failure = std::move(value);
condition.notify_all();
});
clock.start();
clock.start();
{
std::unique_lock lock(mutex);
ASSERT_TRUE(condition.wait_for(lock, std::chrono::seconds(2), [&] {
return ticks.size() >= 8 || failure;
}));
ASSERT_FALSE(failure);
ASSERT_GE(ticks.size(), 8U);
for (std::size_t index = 1; index < ticks.size(); ++index) {
EXPECT_GT(ticks[index].sequence, ticks[index - 1].sequence);
EXPECT_GT(ticks[index].time_milliseconds,
ticks[index - 1].time_milliseconds);
}
EXPECT_NEAR(ticks.front().time_milliseconds,
static_cast<double>(ticks.front().sequence) * 10.0,
0.001);
}
clock.stop();
std::this_thread::sleep_for(std::chrono::milliseconds(30));
std::size_t stopped_count{};
{
std::lock_guard lock(mutex);
stopped_count = ticks.size();
}
std::this_thread::sleep_for(std::chrono::milliseconds(30));
{
std::lock_guard lock(mutex);
EXPECT_EQ(ticks.size(), stopped_count);
}
}
}
}