use crate::encode::Encode;
use crate::messages::GeoJson;
#[test]
fn test_geojson_schema_preserves_schema_name() {
let schema = GeoJson::get_schema();
assert!(schema.is_some());
assert_eq!(schema.unwrap().name, "foxglove.GeoJSON");
}
#[test]
fn test_log_message_can_be_encoded() {
use crate::messages::{Log, Timestamp, log::Level};
let msg = Log {
timestamp: Some(Timestamp::new(5, 10)),
level: Level::Error as i32,
message: "hello".to_string(),
name: "logger".to_string(),
file: "file".to_string(),
line: 123,
};
let schema = Log::get_schema();
assert!(schema.is_some());
assert_eq!(schema.unwrap().name, "foxglove.Log");
let mut buf = Vec::new();
msg.encode(&mut buf).expect("encoding should succeed");
assert!(!buf.is_empty());
}
#[test]
fn test_timestamp_creation() {
use crate::messages::Timestamp;
let ts = Timestamp::new(123, 456);
assert_eq!(ts.sec(), 123);
assert_eq!(ts.nsec(), 456);
}
#[test]
#[allow(deprecated)]
fn test_schemas_reexports_same_types_as_messages() {
use crate::messages;
use crate::schemas;
let msg_from_messages: messages::Log = messages::Log {
timestamp: Some(messages::Timestamp::new(1, 2)),
level: messages::log::Level::Info as i32,
message: "test".to_string(),
..Default::default()
};
let msg_from_schemas: schemas::Log = schemas::Log {
timestamp: Some(schemas::Timestamp::new(1, 2)),
level: schemas::log::Level::Info as i32,
message: "test".to_string(),
..Default::default()
};
let mut buf1 = Vec::new();
let mut buf2 = Vec::new();
msg_from_messages.encode(&mut buf1).unwrap();
msg_from_schemas.encode(&mut buf2).unwrap();
assert_eq!(buf1, buf2);
assert_eq!(
messages::Log::get_schema().unwrap().name,
schemas::Log::get_schema().unwrap().name
);
}
#[test]
#[allow(deprecated)]
fn test_schemas_reexports_common_types() {
use crate::messages;
use crate::schemas;
use std::any::TypeId;
assert_eq!(TypeId::of::<messages::Log>(), TypeId::of::<schemas::Log>());
assert_eq!(
TypeId::of::<messages::Timestamp>(),
TypeId::of::<schemas::Timestamp>()
);
assert_eq!(
TypeId::of::<messages::Duration>(),
TypeId::of::<schemas::Duration>()
);
assert_eq!(
TypeId::of::<messages::CompressedImage>(),
TypeId::of::<schemas::CompressedImage>()
);
assert_eq!(
TypeId::of::<messages::SceneUpdate>(),
TypeId::of::<schemas::SceneUpdate>()
);
assert_eq!(
TypeId::of::<messages::PointCloud>(),
TypeId::of::<schemas::PointCloud>()
);
}
#[test]
#[allow(deprecated)]
fn test_schemas_glob_import_works() {
#[allow(unused_imports)]
use crate::schemas::*;
let _ts = Timestamp::new(100, 200);
let _color = Color {
r: 1.0,
g: 0.5,
b: 0.0,
a: 1.0,
};
}
#[cfg(feature = "derive")]
#[test]
fn test_protobuf_field_for_message_type() {
use crate::messages::Log;
use crate::protobuf::ProtobufField;
use prost_types::field_descriptor_proto::Type as ProstFieldType;
assert_eq!(Log::field_type(), ProstFieldType::Message);
assert_eq!(
Log::wire_type(),
prost::encoding::WireType::LengthDelimited as u32
);
assert_eq!(Log::type_name().as_deref(), Some(".foxglove.Log"));
let fds = Log::file_descriptors();
assert!(
fds.iter().any(|fd| fd.name() == "foxglove/Log.proto"),
"expected foxglove/Log.proto descriptor, got: {:?}",
fds.iter().map(|f| f.name()).collect::<Vec<_>>()
);
}
#[cfg(feature = "derive")]
#[test]
fn test_protobuf_field_for_timestamp() {
use crate::messages::Timestamp;
use crate::protobuf::ProtobufField;
use prost_types::field_descriptor_proto::Type as ProstFieldType;
assert_eq!(Timestamp::field_type(), ProstFieldType::Message);
assert_eq!(
Timestamp::wire_type(),
prost::encoding::WireType::LengthDelimited as u32
);
assert_eq!(
Timestamp::type_name().as_deref(),
Some(".google.protobuf.Timestamp")
);
let fd = Timestamp::file_descriptor().expect("Timestamp should have a file descriptor");
assert_eq!(fd.name(), "google/protobuf/timestamp.proto");
}
#[cfg(feature = "derive")]
#[test]
fn test_protobuf_field_write_roundtrip() {
use crate::messages::{Log, Timestamp, log::Level};
use crate::protobuf::ProtobufField;
let msg = Log {
timestamp: Some(Timestamp::new(100, 200)),
level: Level::Info as i32,
message: "hello".to_string(),
..Default::default()
};
let mut buf = Vec::new();
msg.write(&mut buf);
assert_eq!(ProtobufField::encoded_len(&msg), buf.len());
let decoded = <Log as prost::Message>::decode_length_delimited(buf.as_slice())
.expect("should decode length-delimited written bytes");
assert_eq!(msg, decoded);
}
#[cfg(feature = "serde")]
#[test]
fn test_log_json_roundtrip_with_enum_strings() {
use crate::messages::{Log, Timestamp, log::Level};
let msg = Log {
timestamp: Some(Timestamp::new(1_000_000, 500)),
level: Level::Error as i32,
message: "something went wrong".to_string(),
name: "my_node".to_string(),
file: "main.rs".to_string(),
line: 99,
};
let json = serde_json::to_string(&msg).expect("serialization should succeed");
assert!(
json.contains("\"ERROR\""),
"enum should serialize as string name, got: {json}"
);
let parsed: Log = serde_json::from_str(&json).expect("deserialization should succeed");
assert_eq!(msg, parsed);
}
#[cfg(feature = "serde")]
#[test]
fn test_compressed_image_json_roundtrip_with_base64() {
use bytes::Bytes;
use crate::messages::{CompressedImage, Timestamp};
let image_data = vec![0xDE, 0xAD, 0xBE, 0xEF, 0x01, 0x02, 0x03];
let msg = CompressedImage {
timestamp: Some(Timestamp::new(42, 0)),
frame_id: "camera".to_string(),
data: Bytes::from(image_data),
format: "png".to_string(),
};
let json = serde_json::to_string(&msg).expect("serialization should succeed");
assert!(
json.contains("3q2+7wECAw=="),
"bytes should serialize as base64, got: {json}"
);
let parsed: CompressedImage =
serde_json::from_str(&json).expect("deserialization should succeed");
assert_eq!(msg, parsed);
}