#![allow(clippy::assertions_on_constants)]
use std::sync::Arc;
use crate::api::y2026_1 as api;
use crate::api::{ApiVersion, ContractBody};
use crate::bus::{Codec, MessagePack, QueryCode};
use crate::prelude::*;
use crate::runtime::RuntimeBehavior;
#[derive(phoxal::Runtime)]
#[phoxal(id = "asset-test", api = y2026_1)]
struct AssetTest {
present: bool,
}
#[phoxal::runtime]
impl AssetTest {
#[setup]
async fn setup(_ctx: &mut SetupContext<Self>) -> Result<Self> {
Ok(Self { present: true })
}
#[server(topic = api::topic::new().asset().get())]
async fn get(
&mut self,
request: api::asset::GetRequest,
) -> ServerResult<api::asset::GetResponse> {
if self.present && request.path == "ok" {
Ok(api::asset::GetResponse::Found {
bytes: vec![1, 2, 3],
})
} else {
Err(phoxal::bus::QueryFailure::not_found("no such asset"))
}
}
}
#[tokio::test]
async fn exclusive_server_dispatch_ok_error_and_unknown() {
let mut rt = AssetTest { present: true };
assert_eq!(AssetTest::__exclusive_server_topics(), &["asset/get"]);
assert!(AssetTest::__snapshot_server_topics().is_empty());
assert!(!AssetTest::HAS_SNAPSHOT);
assert!(
AssetTest::SERVER_CONTRACTS
.iter()
.any(|c| c.family == <api::asset::GetRequest as ContractBody>::FAMILY)
);
let api = <<api::asset::GetRequest as ContractBody>::Api as ApiVersion>::ID;
let family = <api::asset::GetRequest as ContractBody>::FAMILY;
let request = MessagePack::encode(&api::asset::GetRequest {
path: "ok".to_string(),
})
.unwrap();
let reply = rt
.__serve_exclusive("asset/get", api, family, &request)
.await
.unwrap();
let response: api::asset::GetResponse = MessagePack::decode(&reply.payload).unwrap();
assert!(matches!(response, api::asset::GetResponse::Found { .. }));
assert_eq!(
reply.family,
<api::asset::GetResponse as ContractBody>::FAMILY
);
let request = MessagePack::encode(&api::asset::GetRequest {
path: "missing".to_string(),
})
.unwrap();
let failure = rt
.__serve_exclusive("asset/get", api, family, &request)
.await
.unwrap_err();
assert_eq!(failure.code, QueryCode::NotFound);
let failure = rt
.__serve_exclusive("asset/get", "y2026_2", family, &request)
.await
.unwrap_err();
assert_eq!(failure.code, QueryCode::InvalidArgument);
let failure = rt
.__serve_exclusive("other/topic", api, family, &request)
.await
.unwrap_err();
assert_eq!(failure.code, QueryCode::Unimplemented);
}
#[derive(phoxal::Runtime)]
#[phoxal(id = "map-test", api = y2026_1)]
struct MapTest {
grid: Arc<Vec<u8>>,
}
struct MapTestState {
grid: Arc<Vec<u8>>,
}
#[phoxal::runtime]
impl MapTest {
#[setup]
async fn setup(_ctx: &mut SetupContext<Self>) -> Result<Self> {
Ok(Self {
grid: Arc::new(vec![0; 4]),
})
}
#[server_snapshot(topic = api::topic::new().map().submap())]
async fn submap(
state: Snapshot<MapTestState>,
_request: api::map::SubmapRequest,
) -> ServerResult<api::map::SubmapResponse> {
Ok(api::map::SubmapResponse {
width: 2,
height: 2,
resolution_m: 0.1,
cells: state.grid.as_ref().clone(),
})
}
#[snapshot]
fn snapshot(&self) -> MapTestState {
MapTestState {
grid: Arc::clone(&self.grid),
}
}
}
#[tokio::test]
async fn snapshot_server_dispatch_reads_committed_state() {
let rt = MapTest {
grid: Arc::new(vec![1, 2, 3, 4]),
};
assert!(MapTest::HAS_SNAPSHOT);
assert_eq!(MapTest::__snapshot_server_topics(), &["map/submap"]);
let snapshot = Arc::new(rt.__take_snapshot());
let request = MessagePack::encode(&api::map::SubmapRequest {
min_x_m: 0.0,
min_y_m: 0.0,
max_x_m: 1.0,
max_y_m: 1.0,
})
.unwrap();
let api = <<api::map::SubmapRequest as ContractBody>::Api as ApiVersion>::ID.to_string();
let family = <api::map::SubmapRequest as ContractBody>::FAMILY.to_string();
let reply = MapTest::__serve_snapshot(snapshot, "map/submap".to_string(), api, family, request)
.await
.unwrap();
let response: api::map::SubmapResponse = MessagePack::decode(&reply.payload).unwrap();
assert_eq!(response.cells, vec![1, 2, 3, 4]);
}