14#include <unordered_map>
26 std::memcpy(&size, bytes.data() + 1,
sizeof(size));
28 return out.
Read(in, size);
33TEST(MultiGpuMirror, positions_round_trip_bit_exact) {
37 camera.
location[0] = 12345.678901234;
42 camera.
rotation[1] = 0.70710678118654757;
44 camera.
rotation[3] = 0.70710678118654746;
50 std::ostringstream out;
52 const std::string bytes = out.str();
57 ASSERT_TRUE(ReadPositions(bytes, got));
60 for (
int i = 0; i < 3; ++i) {
63 for (
int i = 0; i < 4; ++i) {
69TEST(MultiGpuMirror, positions_from_a_newer_build_keep_their_known_fields) {
71 std::ostringstream payload;
72 const uint32_t count = 2u;
73 const uint16_t record_size = 64u;
74 payload.write(
reinterpret_cast<const char *
>(&count),
sizeof(count));
75 payload.write(
reinterpret_cast<const char *
>(&record_size),
sizeof(record_size));
76 for (uint32_t
id = 1u;
id <= count; ++id) {
77 payload.write(
reinterpret_cast<const char *
>(&
id),
sizeof(
id));
78 const double values[7] = {double(
id), 2.0, 3.0, 0.0, 0.0, 0.0, 1.0};
79 payload.write(
reinterpret_cast<const char *
>(values),
sizeof(values));
80 const uint32_t extra = 0xFFFFFFFFu;
81 payload.write(
reinterpret_cast<const char *
>(&extra),
sizeof(extra));
83 const std::string body = payload.str();
84 std::istringstream in(body);
86 ASSERT_TRUE(got.
Read(in,
static_cast<uint32_t
>(body.size())));
89 EXPECT_EQ(got.
positions[1].location[0], 2.0);
92TEST(MultiGpuMirror, truncated_positions_fail) {
95 std::ostringstream out;
97 const std::string bytes = out.str();
99 std::istringstream in(body);
101 EXPECT_FALSE(got.
Read(in,
static_cast<uint32_t
>(body.size())));
104TEST(MultiGpuMirror, order_parents_first_depth_two) {
106 const std::vector<uint32_t> ids = {3u, 2u, 4u, 1u};
107 const std::unordered_map<uint32_t, uint32_t> parents = {{3u, 2u}, {2u, 1u}};
108 const std::vector<uint32_t> order = OrderParentsFirst(ids, parents);
109 EXPECT_EQ(order, (std::vector<uint32_t>{4u, 1u, 2u, 3u}));
112TEST(MultiGpuMirror, missing_parent_and_cycle_are_guarded) {
114 const std::vector<uint32_t> ids = {5u, 6u, 7u, 8u};
115 const std::unordered_map<uint32_t, uint32_t> parents = {{5u, 99u}, {6u, 7u}, {7u, 6u}, {8u, 7u}};
116 const std::vector<uint32_t> order = OrderParentsFirst(ids, parents);
117 ASSERT_EQ(order.size(), ids.size());
119 const auto pos = [&](uint32_t id) {
120 return std::find(order.begin(), order.end(),
id) - order.begin();
122 for (uint32_t
id : ids) {
123 EXPECT_EQ(std::count(order.begin(), order.end(),
id), 1);
125 EXPECT_LT(pos(7u), pos(8u));
132 std::memcpy(&size, bytes.data() + 1,
sizeof(size));
134 return out.
Read(in, size);
139TEST(MultiGpuMirror, vehicle_parts_round_trip) {
143 car.
wheels = {{12.5f, 361.25f, 3.5f}, {-12.5f, 0.125f, -1.0f}, {0.0f, 90.0f, 0.0f}, {0.0f, 180.0f, 2.25f}};
146 door.
location = {10.0, -85.5, 40.25};
147 door.
rotation = {0.0, 0.0, 0.38268343236508978, 0.92387953251128674};
154 bike.
wheels = {{5.0f, 10.0f, 0.5f}, {0.0f, 10.0f, 0.25f}};
157 std::ostringstream out;
159 const std::string bytes = out.str();
162 ASSERT_TRUE(ReadParts(bytes, got));
164 ASSERT_EQ(got.
vehicles[0].wheels.size(), 4u);
165 EXPECT_EQ(got.
vehicles[0].wheels[1].steer, -12.5f);
166 EXPECT_EQ(got.
vehicles[0].wheels[0].spin, 361.25f);
167 EXPECT_EQ(got.
vehicles[0].wheels[3].suspension_offset, 2.25f);
168 ASSERT_EQ(got.
vehicles[0].open_doors.size(), 1u);
169 EXPECT_EQ(got.
vehicles[0].open_doors[0].door, 1u);
172 EXPECT_EQ(got.
vehicles[0].current_gear, std::optional<int32_t>(-1));
173 EXPECT_TRUE(got.
vehicles[0].manual_gear_shift);
174 EXPECT_TRUE(got.
vehicles[0].simulating_physics);
175 EXPECT_EQ(got.
vehicles[1].actor_id, 22u);
176 EXPECT_EQ(got.
vehicles[1].wheels.size(), 2u);
177 EXPECT_TRUE(got.
vehicles[1].open_doors.empty());
178 EXPECT_FALSE(got.
vehicles[1].current_gear.has_value());
181TEST(MultiGpuMirror, vehicle_parts_from_a_newer_build_keep_their_known_fields) {
184 std::ostringstream wheels;
185 const uint32_t count = 1u;
186 const uint16_t record_size = 16u;
187 wheels.write(
reinterpret_cast<const char *
>(&count),
sizeof(count));
188 wheels.write(
reinterpret_cast<const char *
>(&record_size),
sizeof(record_size));
189 const float values[4] = {1.0f, 2.0f, 3.0f, 99.0f};
190 wheels.write(
reinterpret_cast<const char *
>(values),
sizeof(values));
191 std::ostringstream record;
192 const uint32_t
id = 5u;
193 record.write(
reinterpret_cast<const char *
>(&
id),
sizeof(
id));
196 std::ostringstream payload;
197 payload.write(
reinterpret_cast<const char *
>(&count),
sizeof(count));
200 const std::string body = payload.str();
201 std::istringstream in(body);
203 ASSERT_TRUE(got.
Read(in,
static_cast<uint32_t
>(body.size())));
205 ASSERT_EQ(got.
vehicles[0].wheels.size(), 1u);
206 EXPECT_EQ(got.
vehicles[0].wheels[0].suspension_offset, 3.0f);
209TEST(MultiGpuMirror, truncated_vehicle_parts_fail) {
216 std::ostringstream out;
218 const std::string bytes = out.str();
220 std::istringstream in(body);
222 EXPECT_FALSE(got.
Read(in,
static_cast<uint32_t
>(body.size())));
constexpr std::size_t kFrameDataHeaderSize
Frame data (the SEND_FRAME payload) is a sequence of packets [uint8 id][uint32 payload size][payload]...
void WriteField(std::ostream &out, uint8_t kind, const std::string &value)
void WriteSizedBytes(std::ostream &out, const std::string &bytes)
One [u32 size][bytes] entry: a variable-size record or, after a kind byte, a TLV value.
std::vector< uint32_t > OrderParentsFirst(const std::vector< uint32_t > &ids, const std::unordered_map< uint32_t, uint32_t > &parents)
Order in which to place actors so that every parent is placed before its children: by attachment dept...
An open door, which on the primary is a physics body of its own: its pose relative to the vehicle,...
std::array< double, 3 > location
std::array< double, 4 > rotation
One record of frame data packet 34: an actor's world pose as the primary holds it,...
double rotation[4]
x, y, z, w
Frame data packet 34: every live actor's pose in this frame.
bool Read(std::istream &in, uint32_t size)
Reads a payload of size bytes; records that grew in a newer build are read up to the fields known her...
void Write(std::ostream &out) const
static constexpr uint16_t kRecordSizeV1
static constexpr uint8_t kPacketId
std::vector< MirroredPosition > positions
Frame data packet 32, every frame: the moving parts of every vehicle.
static constexpr uint8_t kPacketId
std::vector< VehicleParts > vehicles
void Write(std::ostream &out) const
bool Read(std::istream &in, uint32_t size)
A vehicle's moving parts: every wheel, by wheel index, and the doors open (any other door is closed),...
std::vector< DoorPose > open_doors
std::vector< WheelPose > wheels
std::optional< int32_t > current_gear
bool simulating_physics
Whether the primary's body simulates physics (it reports no angular velocity otherwise).
TEST(MultiGpuMirror, positions_round_trip_bit_exact)