blob: 09f9fb37c33877aed6cb58918712c1254d556b21 [file] [log] [blame]
// Copyright 2024 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/sensors/playback/serialization.h"
#include <fcntl.h>
#include <fidl/fuchsia.hardware.sensors/cpp/fidl.h>
#include <lib/fdio/io.h>
#include <lib/syslog/cpp/macros.h>
#include <stdio.h>
#include <gtest/gtest.h>
#include "src/sensors/playback/proto_conversion.h"
using fuchsia_hardware_sensors::Driver;
using fuchsia_hardware_sensors::Playback;
using fuchsia_math::QuaternionF;
using fuchsia_math::Vec3F;
using fuchsia_sensors_types::EventPayload;
using fuchsia_sensors_types::Pose;
using fuchsia_sensors_types::SensorEvent;
using fuchsia_sensors_types::SensorId;
using fuchsia_sensors_types::SensorInfo;
using fuchsia_sensors_types::SensorReportingMode;
using fuchsia_sensors_types::SensorType;
using fuchsia_sensors_types::SensorWakeUpType;
using fuchsia_sensors_types::UncalibratedVec3FSample;
using RecordedSensorEvent = sensors::playback::io::Deserializer::RecordedSensorEvent;
namespace sensors::playback::io {
namespace test {
constexpr SensorId kAccelSensorId = 1;
constexpr SensorId kGyroSensorId = 2;
SensorInfo CreateAccelerometer(SensorId accel_sensor_id) {
SensorInfo accelerometer_info;
accelerometer_info.sensor_id(accel_sensor_id);
accelerometer_info.name("accelerometer");
accelerometer_info.vendor("Accelomax");
accelerometer_info.version(1);
accelerometer_info.sensor_type(SensorType::kAccelerometer);
accelerometer_info.wake_up(SensorWakeUpType::kWakeUp);
accelerometer_info.reporting_mode(SensorReportingMode::kContinuous);
return accelerometer_info;
}
SensorInfo CreateGyroscope(SensorId gyro_sensor_id) {
SensorInfo gyroscope_info;
gyroscope_info.sensor_id(gyro_sensor_id);
gyroscope_info.name("gyroscope");
gyroscope_info.vendor("Gyrocorp");
gyroscope_info.version(1);
gyroscope_info.sensor_type(SensorType::kGyroscope);
gyroscope_info.wake_up(SensorWakeUpType::kWakeUp);
gyroscope_info.reporting_mode(SensorReportingMode::kContinuous);
return gyroscope_info;
}
void CreateAccelerometerEvents(SensorId accel_sensor_id, std::vector<SensorEvent>& event_list) {
const int64_t kOneMillisecondInNanoseconds = 1e6;
for (int i = 0; i < 99; i++) {
Vec3F sample{{
.x = i % 3 == 0 ? 1.0f : 0.0f,
.y = i % 3 == 1 ? 1.0f : 0.0f,
.z = i % 3 == 2 ? 1.0f : 0.0f,
}};
SensorEvent event{{.payload = EventPayload::WithVec3(sample)}};
event.timestamp() = i * kOneMillisecondInNanoseconds;
event.sensor_id() = accel_sensor_id;
event.sensor_type() = SensorType::kAccelerometer;
event.sequence_number() = i;
event_list.push_back(event);
}
}
void CreateGyroscopeEvents(SensorId gyro_sensor_id, std::vector<SensorEvent>& event_list) {
const int64_t kOneMillisecondInNanoseconds = 1e6;
for (int i = 0; i < 9; i++) {
Vec3F sample{{
.x = i % 3 == 1 ? 1.0f : 0.0f,
.y = i % 3 == 2 ? 1.0f : 0.0f,
.z = i % 3 == 0 ? 1.0f : 0.0f,
}};
SensorEvent event{{.payload = EventPayload::WithVec3(sample)}};
event.timestamp() = i * 10 * kOneMillisecondInNanoseconds;
event.sensor_id() = gyro_sensor_id;
event.sensor_type() = SensorType::kGyroscope;
event.sequence_number() = i;
event_list.push_back(event);
}
}
TEST(SensorsPlaybackProtoConversionTest, EnumConversionTest) {
SensorType fidl_type = SensorType::kGyroscope;
fuchsia::sensors::SensorType proto_type = ConvertEnum<fuchsia::sensors::SensorType>(fidl_type);
ASSERT_EQ(ConvertEnum<SensorType>(proto_type), fidl_type);
}
TEST(SensorsPlaybackProtoConversionTest, SensorInfoConversionTest) {
SensorInfo fidl_sensor_info = CreateAccelerometer(kAccelSensorId);
fuchsia::sensors::SensorInfo proto_sensor_info;
FidlToProtoSensorInfo(fidl_sensor_info, proto_sensor_info);
SensorInfo fidl_sensor_info2;
ProtoToFidlSensorInfo(proto_sensor_info, fidl_sensor_info2);
ASSERT_EQ(fidl_sensor_info, fidl_sensor_info2);
}
TEST(SensorsPlaybackProtoConversionTest, Vec3FConversionTest) {
Vec3F fidl_vec{{
.x = 1.0f,
.y = 2.0f,
.z = 3.0f,
}};
fuchsia::sensors::Vec3F proto_vec = FidlToProtoVec3F(fidl_vec);
Vec3F fidl_vec2 = ProtoToFidlVec3F(proto_vec);
ASSERT_EQ(fidl_vec, fidl_vec2);
}
TEST(SensorsPlaybackProtoConversionTest, Quaternion3FConversionTest) {
QuaternionF fidl_quaternion{{
.x = 1.0f,
.y = 2.0f,
.z = 3.0f,
.w = 4.0f,
}};
fuchsia::sensors::QuaternionF proto_quaternion = FidlToProtoQuaternionF(fidl_quaternion);
QuaternionF fidl_quaternion2 = ProtoToFidlQuaternionF(proto_quaternion);
ASSERT_EQ(fidl_quaternion, fidl_quaternion2);
}
TEST(SensorsPlaybackProtoConversionTest, UncalibratedVec3FSampleConversionTest) {
Vec3F sample{{
.x = 1.0f,
.y = 2.0f,
.z = 3.0f,
}};
Vec3F biases{{
.x = 4.0f,
.y = 5.0f,
.z = 6.0f,
}};
UncalibratedVec3FSample fidl_uncalibrated_vec;
fidl_uncalibrated_vec.sample(sample);
fidl_uncalibrated_vec.biases(biases);
fuchsia::sensors::UncalibratedVec3FSample proto_uncalibrated_vec =
FidlToProtoUncalibratedVec3FSample(fidl_uncalibrated_vec);
UncalibratedVec3FSample fidl_uncalibrated_vec2 =
ProtoToFidlUncalibratedVec3FSample(proto_uncalibrated_vec);
ASSERT_EQ(fidl_uncalibrated_vec, fidl_uncalibrated_vec2);
}
TEST(SensorsPlaybackProtoConversionTest, PoseConversionTest) {
Vec3F translation{{
.x = 1.0f,
.y = 2.0f,
.z = 3.0f,
}};
QuaternionF rotation{{
.x = 4.0f,
.y = 5.0f,
.z = 6.0f,
.w = 7.0f,
}};
Vec3F translation_delta{{
.x = 8.0f,
.y = 9.0f,
.z = 10.0f,
}};
QuaternionF rotation_delta{{
.x = 11.0f,
.y = 12.0f,
.z = 13.0f,
.w = 14.0f,
}};
Pose fidl_pose;
fidl_pose.translation(translation);
fidl_pose.rotation(rotation);
fidl_pose.translation_delta(translation_delta);
fidl_pose.rotation_delta(rotation_delta);
fuchsia::sensors::Pose proto_pose = FidlToProtoPose(fidl_pose);
Pose fidl_pose2 = ProtoToFidlPose(proto_pose);
ASSERT_EQ(fidl_pose, fidl_pose2);
}
TEST(SensorsPlaybackProtoConversionTest, Vec3SensorEventConversionTest) {
Vec3F sample{{
.x = 1.0f,
.y = 2.0f,
.z = 3.0f,
}};
SensorEvent fidl_event{{.payload = EventPayload::WithVec3(sample)}};
fidl_event.timestamp() = 54321;
fidl_event.sensor_id() = kAccelSensorId;
fidl_event.sensor_type() = SensorType::kAccelerometer;
fidl_event.sequence_number() = 1.0;
fuchsia::sensors::SensorEvent proto_event = FidlToProtoSensorEvent(fidl_event);
SensorEvent fidl_event2 = ProtoToFidlSensorEvent(proto_event);
ASSERT_EQ(fidl_event, fidl_event2);
}
TEST(SensorsPlaybackProtoConversionTest, QuaternionSensorEventConversionTest) {
QuaternionF sample{{
.x = 1.0f,
.y = 2.0f,
.z = 3.0f,
.w = 4.0f,
}};
SensorEvent fidl_event{{.payload = EventPayload::WithQuaternion(sample)}};
fidl_event.timestamp() = 54321;
fidl_event.sensor_id() = kAccelSensorId;
fidl_event.sensor_type() = SensorType::kAccelerometer;
fidl_event.sequence_number() = 1.0;
fuchsia::sensors::SensorEvent proto_event = FidlToProtoSensorEvent(fidl_event);
SensorEvent fidl_event2 = ProtoToFidlSensorEvent(proto_event);
ASSERT_EQ(fidl_event, fidl_event2);
}
TEST(SensorsPlaybackProtoConversionTest, UncalibratedVec3SensorEventConversionTest) {
Vec3F sample{{
.x = 1.0f,
.y = 2.0f,
.z = 3.0f,
}};
Vec3F biases{{
.x = 4.0f,
.y = 5.0f,
.z = 6.0f,
}};
UncalibratedVec3FSample uncalibrated_vec;
uncalibrated_vec.sample(sample);
uncalibrated_vec.biases(biases);
SensorEvent fidl_event{{.payload = EventPayload::WithUncalibratedVec3(uncalibrated_vec)}};
fidl_event.timestamp() = 54321;
fidl_event.sensor_id() = kAccelSensorId;
fidl_event.sensor_type() = SensorType::kAccelerometer;
fidl_event.sequence_number() = 1.0;
fuchsia::sensors::SensorEvent proto_event = FidlToProtoSensorEvent(fidl_event);
SensorEvent fidl_event2 = ProtoToFidlSensorEvent(proto_event);
ASSERT_EQ(fidl_event, fidl_event2);
}
TEST(SensorsPlaybackProtoConversionTest, FloatSensorEventConversionTest) {
SensorEvent fidl_event{{.payload = EventPayload::WithFloat_(5.0f)}};
fidl_event.timestamp() = 54321;
fidl_event.sensor_id() = kAccelSensorId;
fidl_event.sensor_type() = SensorType::kAccelerometer;
fidl_event.sequence_number() = 1.0;
fuchsia::sensors::SensorEvent proto_event = FidlToProtoSensorEvent(fidl_event);
SensorEvent fidl_event2 = ProtoToFidlSensorEvent(proto_event);
ASSERT_EQ(fidl_event, fidl_event2);
}
TEST(SensorsPlaybackProtoConversionTest, IntegerSensorEventConversionTest) {
SensorEvent fidl_event{{.payload = EventPayload::WithInteger(5)}};
fidl_event.timestamp() = 54321;
fidl_event.sensor_id() = kAccelSensorId;
fidl_event.sensor_type() = SensorType::kAccelerometer;
fidl_event.sequence_number() = 1.0;
fuchsia::sensors::SensorEvent proto_event = FidlToProtoSensorEvent(fidl_event);
SensorEvent fidl_event2 = ProtoToFidlSensorEvent(proto_event);
ASSERT_EQ(fidl_event, fidl_event2);
}
TEST(SensorsPlaybackProtoConversionTest, PoseSensorEventConversionTest) {
Vec3F translation{{
.x = 1.0f,
.y = 2.0f,
.z = 3.0f,
}};
QuaternionF rotation{{
.x = 4.0f,
.y = 5.0f,
.z = 6.0f,
.w = 7.0f,
}};
Vec3F translation_delta{{
.x = 8.0f,
.y = 9.0f,
.z = 10.0f,
}};
QuaternionF rotation_delta{{
.x = 11.0f,
.y = 12.0f,
.z = 13.0f,
.w = 14.0f,
}};
Pose pose;
pose.translation(translation);
pose.rotation(rotation);
pose.translation_delta(translation_delta);
pose.rotation_delta(rotation_delta);
SensorEvent fidl_event{{.payload = EventPayload::WithPose(pose)}};
fidl_event.timestamp() = 54321;
fidl_event.sensor_id() = kAccelSensorId;
fidl_event.sensor_type() = SensorType::kAccelerometer;
fidl_event.sequence_number() = 1.0;
fuchsia::sensors::SensorEvent proto_event = FidlToProtoSensorEvent(fidl_event);
SensorEvent fidl_event2 = ProtoToFidlSensorEvent(proto_event);
ASSERT_EQ(fidl_event, fidl_event2);
}
const char kTestDatasetPath[] = "/tmp/dataset";
class SensorsPlaybackSerializationTest : public testing::Test {
void TearDown() override { unlink(kTestDatasetPath); }
};
TEST_F(SensorsPlaybackSerializationTest, SerializeDeserializeTest) {
const std::string dataset_name = "Test Dataset";
std::vector<SensorInfo> sensor_list;
std::vector<SensorEvent> event_list;
sensor_list.push_back(CreateAccelerometer(kAccelSensorId));
CreateAccelerometerEvents(kAccelSensorId, event_list);
sensor_list.push_back(CreateGyroscope(kGyroSensorId));
CreateGyroscopeEvents(kGyroSensorId, event_list);
std::sort(event_list.begin(), event_list.end(), [](const SensorEvent& a, const SensorEvent& b) {
return a.timestamp() < b.timestamp();
});
{
Serializer serializer(kTestDatasetPath);
ASSERT_EQ(serializer.Open(dataset_name, sensor_list), ZX_OK);
for (const SensorEvent& event : event_list) {
ASSERT_EQ(serializer.WriteEvent(event, event.timestamp()), ZX_OK);
}
}
std::string read_dataset_name;
std::vector<SensorInfo> read_sensor_list;
std::vector<SensorEvent> read_event_list;
Deserializer deserializer(kTestDatasetPath);
ASSERT_EQ(deserializer.Open(read_dataset_name, read_sensor_list), ZX_OK);
ASSERT_EQ(dataset_name, read_dataset_name);
ASSERT_EQ(sensor_list, read_sensor_list);
fit::result<zx_status_t, RecordedSensorEvent> result = fit::error(ZX_ERR_BAD_STATE);
for (;;) {
result = deserializer.ReadEvent();
if (result.is_ok()) {
ASSERT_EQ(result->receipt_timestamp, result->event.timestamp());
read_event_list.push_back(result->event);
} else {
break;
}
}
ASSERT_EQ(result.error_value(), ZX_OK);
ASSERT_EQ(event_list, read_event_list);
}
TEST_F(SensorsPlaybackSerializationTest, DeserializeFailureNoSuchFile) {
std::string read_dataset_name;
std::vector<SensorInfo> read_sensor_list;
Deserializer deserializer("FileThatDoesNotExist");
ASSERT_EQ(deserializer.Open(read_dataset_name, read_sensor_list), ZX_ERR_IO);
}
TEST_F(SensorsPlaybackSerializationTest, DeserializeFailureReadWhenFileNotOpen) {
Deserializer deserializer("FileThatDoesNotExist");
auto result = deserializer.ReadEvent();
ASSERT_FALSE(result.is_ok());
ASSERT_EQ(result.error_value(), ZX_ERR_BAD_STATE);
}
TEST_F(SensorsPlaybackSerializationTest, DeserializeFailureSeekWhenFileNotOpen) {
Deserializer deserializer("FileThatDoesNotExist");
zx_status_t result = deserializer.SeekToFirstEvent();
ASSERT_EQ(result, ZX_ERR_BAD_STATE);
}
TEST_F(SensorsPlaybackSerializationTest, DeserializeFailureIncompleteHeaderSize) {
std::string read_dataset_name;
std::vector<SensorInfo> read_sensor_list;
{
// Create the file but write nothing to it.
FileDescriptor fd = ::open(kTestDatasetPath, O_WRONLY | O_CREAT);
ASSERT_GE(fd.value(), 0);
}
Deserializer deserializer(kTestDatasetPath);
ASSERT_EQ(deserializer.Open(read_dataset_name, read_sensor_list), ZX_ERR_BAD_STATE);
}
TEST_F(SensorsPlaybackSerializationTest, DeserializeFailureIncompleteHeader) {
std::string read_dataset_name;
std::vector<SensorInfo> read_sensor_list;
{
// Create the file and write a header size but no header.
size_t header_size = 90;
FileDescriptor fd = ::open(kTestDatasetPath, O_WRONLY | O_CREAT);
ASSERT_GE(fd.value(), 0);
ASSERT_EQ(::write(fd, &header_size, sizeof(header_size)),
static_cast<long>(sizeof(header_size)));
}
Deserializer deserializer(kTestDatasetPath);
ASSERT_EQ(deserializer.Open(read_dataset_name, read_sensor_list), ZX_ERR_BAD_STATE);
}
TEST_F(SensorsPlaybackSerializationTest, DeserializeFailureGarbageHeader) {
std::string read_dataset_name;
std::vector<SensorInfo> read_sensor_list;
{
// Create the file and write a valid header size, but a garbage header that won't parse.
const char kGarbageString[] = "This is not a valid header.";
size_t header_size = sizeof(kGarbageString);
FileDescriptor fd = ::open(kTestDatasetPath, O_WRONLY | O_CREAT);
ASSERT_GE(fd.value(), 0);
ASSERT_EQ(::write(fd, &header_size, sizeof(header_size)),
static_cast<long>(sizeof(header_size)));
ASSERT_EQ(::write(fd, kGarbageString, header_size), static_cast<long>(header_size));
}
Deserializer deserializer(kTestDatasetPath);
ASSERT_EQ(deserializer.Open(read_dataset_name, read_sensor_list), ZX_ERR_BAD_STATE);
}
TEST_F(SensorsPlaybackSerializationTest, DeserializeFailureIncompleteEventSize) {
const std::string dataset_name = "Test Dataset";
std::vector<SensorInfo> sensor_list;
sensor_list.push_back(CreateAccelerometer(kAccelSensorId));
sensor_list.push_back(CreateGyroscope(kGyroSensorId));
fuchsia::sensors::DatasetHeader header = CreateDatasetHeader(dataset_name, sensor_list);
{
// Create the file and write a valid header size/header, but then an incomplete event size.
FileDescriptor fd = ::open(kTestDatasetPath, O_WRONLY | O_CREAT);
ASSERT_GE(fd.value(), 0);
std::string header_bytes;
ASSERT_TRUE(header.SerializeToString(&header_bytes));
size_t header_size = header_bytes.size();
ASSERT_EQ(::write(fd, &header_size, sizeof(header_size)),
static_cast<long>(sizeof(header_size)));
ASSERT_EQ(::write(fd, header_bytes.data(), header_size), static_cast<long>(header_size));
size_t event_size = 10;
ASSERT_EQ(::write(fd, &event_size, 1), 1);
}
std::string read_dataset_name;
std::vector<SensorInfo> read_sensor_list;
Deserializer deserializer(kTestDatasetPath);
ASSERT_EQ(deserializer.Open(read_dataset_name, read_sensor_list), ZX_OK);
ASSERT_EQ(dataset_name, read_dataset_name);
ASSERT_EQ(sensor_list, read_sensor_list);
auto result = deserializer.ReadEvent();
ASSERT_FALSE(result.is_ok());
ASSERT_EQ(result.error_value(), ZX_ERR_BAD_STATE);
}
TEST_F(SensorsPlaybackSerializationTest, DeserializeFailureEOFAfterEventSize) {
const std::string dataset_name = "Test Dataset";
std::vector<SensorInfo> sensor_list;
sensor_list.push_back(CreateAccelerometer(kAccelSensorId));
sensor_list.push_back(CreateGyroscope(kGyroSensorId));
fuchsia::sensors::DatasetHeader header = CreateDatasetHeader(dataset_name, sensor_list);
{
// Create the file and write a valid header size/header, then an event size but no event.
FileDescriptor fd = ::open(kTestDatasetPath, O_WRONLY | O_CREAT);
ASSERT_GE(fd.value(), 0);
std::string header_bytes;
ASSERT_TRUE(header.SerializeToString(&header_bytes));
size_t header_size = header_bytes.size();
ASSERT_EQ(::write(fd, &header_size, sizeof(header_size)),
static_cast<long>(sizeof(header_size)));
ASSERT_EQ(::write(fd, header_bytes.data(), header_size), static_cast<long>(header_size));
size_t event_size = 10;
ASSERT_EQ(::write(fd, &event_size, sizeof(event_size)), static_cast<long>(sizeof(event_size)));
}
std::string read_dataset_name;
std::vector<SensorInfo> read_sensor_list;
Deserializer deserializer(kTestDatasetPath);
ASSERT_EQ(deserializer.Open(read_dataset_name, read_sensor_list), ZX_OK);
ASSERT_EQ(dataset_name, read_dataset_name);
ASSERT_EQ(sensor_list, read_sensor_list);
auto result = deserializer.ReadEvent();
ASSERT_FALSE(result.is_ok());
ASSERT_EQ(result.error_value(), ZX_ERR_BAD_STATE);
}
TEST_F(SensorsPlaybackSerializationTest, DeserializeFailureIncompleteEvent) {
const std::string dataset_name = "Test Dataset";
std::vector<SensorInfo> sensor_list;
sensor_list.push_back(CreateAccelerometer(kAccelSensorId));
sensor_list.push_back(CreateGyroscope(kGyroSensorId));
fuchsia::sensors::DatasetHeader header = CreateDatasetHeader(dataset_name, sensor_list);
{
// Create the file and write a valid header size/header, then an event size greater than 1, then
// a random byte.
FileDescriptor fd = ::open(kTestDatasetPath, O_WRONLY | O_CREAT);
ASSERT_GE(fd.value(), 0);
std::string header_bytes;
ASSERT_TRUE(header.SerializeToString(&header_bytes));
size_t header_size = header_bytes.size();
ASSERT_EQ(::write(fd, &header_size, sizeof(header_size)),
static_cast<long>(sizeof(header_size)));
ASSERT_EQ(::write(fd, header_bytes.data(), header_size), static_cast<long>(header_size));
size_t event_size = 10;
ASSERT_EQ(::write(fd, &event_size, sizeof(event_size)), static_cast<long>(sizeof(event_size)));
ASSERT_EQ(::write(fd, "a", 1), 1);
}
std::string read_dataset_name;
std::vector<SensorInfo> read_sensor_list;
Deserializer deserializer(kTestDatasetPath);
ASSERT_EQ(deserializer.Open(read_dataset_name, read_sensor_list), ZX_OK);
ASSERT_EQ(dataset_name, read_dataset_name);
ASSERT_EQ(sensor_list, read_sensor_list);
auto result = deserializer.ReadEvent();
ASSERT_FALSE(result.is_ok());
ASSERT_EQ(result.error_value(), ZX_ERR_BAD_STATE);
}
TEST_F(SensorsPlaybackSerializationTest, DeserializeFailureGarbageEvent) {
const std::string dataset_name = "Test Dataset";
std::vector<SensorInfo> sensor_list;
sensor_list.push_back(CreateAccelerometer(kAccelSensorId));
sensor_list.push_back(CreateGyroscope(kGyroSensorId));
fuchsia::sensors::DatasetHeader header = CreateDatasetHeader(dataset_name, sensor_list);
{
// Create the file and write a valid header size/header, then a valid event size, then a garbage
// "event" that won't parse.
FileDescriptor fd = ::open(kTestDatasetPath, O_WRONLY | O_CREAT);
ASSERT_GE(fd.value(), 0);
std::string header_bytes;
ASSERT_TRUE(header.SerializeToString(&header_bytes));
size_t header_size = header_bytes.size();
ASSERT_EQ(::write(fd, &header_size, sizeof(header_size)),
static_cast<long>(sizeof(header_size)));
ASSERT_EQ(::write(fd, header_bytes.data(), header_size), static_cast<long>(header_size));
char kGarbageString[] = "This is not a valid event.";
size_t event_size = sizeof(kGarbageString);
ASSERT_EQ(::write(fd, &event_size, sizeof(event_size)), static_cast<long>(sizeof(event_size)));
ASSERT_EQ(::write(fd, kGarbageString, event_size), static_cast<long>(event_size));
}
std::string read_dataset_name;
std::vector<SensorInfo> read_sensor_list;
Deserializer deserializer(kTestDatasetPath);
ASSERT_EQ(deserializer.Open(read_dataset_name, read_sensor_list), ZX_OK);
ASSERT_EQ(dataset_name, read_dataset_name);
ASSERT_EQ(sensor_list, read_sensor_list);
auto result = deserializer.ReadEvent();
ASSERT_FALSE(result.is_ok());
ASSERT_EQ(result.error_value(), ZX_ERR_BAD_STATE);
}
} // namespace test
} // namespace sensors::playback::io