feat(simulation): T-1152 server half — WindowGranularity enum, derive_orbital_at_metres, Region rung on the same carrier
R1 measured first: a capped Region tile through the real production path (build_district_window_layer + T-1151 par_iter) at the 64x64 wire cap costs 0.40-0.48ms — faster than the shipped district n=64 window, so Jeroen's progressive capped-density tiling ruling is comfortably interactive on-demand. Raw orbital derive ~0.9µs/cell (~2.3x faster than full derive; region_baseline dominates, not invent_primitives). R5 redesign: WindowGranularity enum (Quarter/District/Region), serde named-variant per the RoadNodeKind precedent, spacing from D-243 scale:: constants — the single source of truth. Additive serde-default window_granularity_v2 request field (None = legacy u32 path; v2 wins when Some); DistrictWindowLayer.granularity_v2 always echoed. Legacy u32 echo for Region uses reserved WINDOW_GRANULARITY_REGION_KEY = u32::MAX (never a legal input) so the old slot cannot lie about aliasing. Cache and coalescing keys carry the enum itself (Ord by declaration order, D-010). n stays district-extent at every rung; Region's cell grid is a DIVISION (round(n/100), min 1) with its own per-axis ceiling DISTRICT_WINDOW_MAX_N_REGION=6400 and a bounded halving-loop clamp (no closed form under the rounding division — the client mirror must replicate the loop). derive_orbital_at_metres: bilinear envelope reads + region_baseline temperature, NO invent_primitives (proven by test — slope_q pinned 0), routed through the shared build_district_profile classification tail so the existing colorizer family renders orbital cells unchanged. R2 stepped-categorical behavior documented at the function, not implied. Region aliasing + clamp/echo tests mirror the T-1150 discipline. 1813 lib tests green; clippy clean; fixture regenerated (254->278 bytes, new echoed field).
This commit is contained in:
@@ -1569,6 +1569,128 @@ pub fn derive_at_metres(
|
||||
)
|
||||
}
|
||||
|
||||
/// The orbital-rung derivation (T-1152, zoom ladder design doc §2/§4): the
|
||||
/// coarse-granularity twin of [`derive_at_metres`] that skips [`invent_primitives`]
|
||||
/// entirely — **no coastline warp, no detail-scatter octave sum, no classification
|
||||
/// noise call of any kind**. Per the design doc's orbital row: "`region_baseline_at_district`
|
||||
/// only — bilinear blend of 4 region baselines, no `invent_primitives`, no
|
||||
/// classification [driver]." Orbital sample spacing (≥205 km, D-243's region rung
|
||||
/// and coarser) sits below `detail_scatter`'s own octave floor
|
||||
/// (`OCTAVE_WAVELENGTHS_M`'s coarsest entry is 32,768 m ≈ 32.8 km — an order of
|
||||
/// magnitude finer than a region), so the invented terrain has nothing left to
|
||||
/// contribute at this spacing; calling it would burn cycles synthesizing detail
|
||||
/// no orbital pixel can resolve. What DOES vary at orbital spacing is the
|
||||
/// **envelope** the heightmap itself carries (the `TerrainAnalysis` continental
|
||||
/// shape) and the **region climate baseline** — this function samples exactly
|
||||
/// those two, nothing else.
|
||||
///
|
||||
/// **Cost model (design doc R1 — measure first):** one `bilinear` (elevation),
|
||||
/// one `bilinear_bool` (ocean mask), one `region_baseline_at_district` call (its
|
||||
/// own cost is 4×`derive_region_baseline_c` on a cache miss, O(1) on a cache hit)
|
||||
/// — no octave sum, no coast-warp trig, no character/envelope computation. See
|
||||
/// `server/tests/zoom_ladder_bench.rs`'s `bench_derive_orbital_at_metres` for the
|
||||
/// measured per-cell figure this claim rests on.
|
||||
///
|
||||
/// Produces the SAME six-field tail every other rung produces (`morphology_zone`,
|
||||
/// `elev_q`, `temperature_c`, `moisture_q`, `vegetation_class`, `glaciation_grade`)
|
||||
/// by routing the bilinear-only primitives through the same
|
||||
/// [`build_district_profile`] classification tail every other rung uses — one
|
||||
/// classification pipeline, never a second orbital-only decision tree (D-227:
|
||||
/// classification thresholds don't get a coarse-rung variant any more than the
|
||||
/// quarter rung got its own "quarter mode" thresholds, design doc §6).
|
||||
///
|
||||
/// **R2 (stepped fields):** `moisture_q`/`temperature_c`/`morphology_zone`/etc.
|
||||
/// are exactly as stepped here as at every other rung — `region_baseline_at_district`
|
||||
/// floor-divides to the containing `DistrictPos` regardless of caller spacing (see
|
||||
/// [`derive_at_metres`]'s own doc on this), so this function does not make
|
||||
/// temperature MORE continuous at orbital scale; it inherits the same
|
||||
/// district-tier step the design doc documents as permanent, by construction.
|
||||
///
|
||||
/// **`slope_q` is fixed at 0`** — the bilinear-only envelope carries no
|
||||
/// per-cell slope signal at orbital spacing (`ta.slope_deg` is a district-scale
|
||||
/// proxy; sampling it here would imply a precision the coarse envelope doesn't
|
||||
/// have). `slope_q` only affects morphology gates 3–6 (FjordWall/CliffCoast/
|
||||
/// BraidedDelta/DuneStrand) and the invented-primitives `carve` term this
|
||||
/// function never runs — passing 0 means those gates fall through to their
|
||||
/// low-slope alternatives, which is the correct behavior for a coastline sampled
|
||||
/// at coarser-than-detail-scatter resolution (no invented ruggedness to report).
|
||||
pub fn derive_orbital_at_metres(
|
||||
seed: SeedChain,
|
||||
body_id: &str,
|
||||
body_params: &BodyParams,
|
||||
ta: &TerrainAnalysis,
|
||||
wx: f64,
|
||||
wy: f64,
|
||||
climate: &ClimateConstants,
|
||||
) -> DistrictProfile {
|
||||
// Same world-metres -> fractional heightmap pixel + latitude mapping
|
||||
// derive_at_metres uses — the envelope is the SAME TerrainAnalysis grid at
|
||||
// every rung, only the sampling density differs.
|
||||
let (px, py, _world_x_m, _world_y_m, lat_deg) = match body_params.body_radius_km {
|
||||
Some(r_km) if r_km > 0.0 => {
|
||||
let circumference_m = std::f64::consts::TAU * r_km * 1000.0;
|
||||
let meridian_m = std::f64::consts::PI * r_km * 1000.0;
|
||||
let px = (wx / circumference_m).rem_euclid(1.0) * ta.w as f64;
|
||||
let lat_frac = (wy / meridian_m).clamp(-0.5, 0.5);
|
||||
let py = (0.5 + lat_frac) * ta.h.saturating_sub(1) as f64;
|
||||
(px, py, wx, wy, -lat_frac * 180.0)
|
||||
}
|
||||
_ => {
|
||||
let dm = scale::DISTRICT_M as f64;
|
||||
let px = (wx / dm).clamp(0.0, ta.w.saturating_sub(1) as f64);
|
||||
let py = (wy / dm).clamp(0.0, ta.h.saturating_sub(1) as f64);
|
||||
let lat_deg = if ta.h > 1 {
|
||||
90.0 - (py / (ta.h - 1) as f64) * 180.0
|
||||
} else {
|
||||
0.0
|
||||
};
|
||||
(px, py, px * dm, py * dm, lat_deg)
|
||||
}
|
||||
};
|
||||
|
||||
let params = BodyParams {
|
||||
latitude_deg: lat_deg,
|
||||
..body_params.clone()
|
||||
};
|
||||
|
||||
// The envelope only — no coast-warp, no detail-scatter. This is exactly
|
||||
// `invent_primitives`' step-1 "driver tier" raw bilinear reads, promoted to
|
||||
// be the FINAL primitives instead of a one-step-stale input to invention.
|
||||
let elev_q =
|
||||
((bilinear(&ta.elev_pct, ta.w, ta.h, px, py) as f64 * 100.0).round() as i32).clamp(0, 100);
|
||||
let ocean_fraction_q = ((bilinear_bool(&ta.ocean_mask, ta.w, ta.h, px, py) as f64 * 100.0)
|
||||
.round() as i32)
|
||||
.clamp(0, 100);
|
||||
// No invented ruggedness at orbital spacing (see the function doc's note
|
||||
// on slope_q) — the envelope carries no per-cell slope signal this coarse.
|
||||
let slope_q = 0;
|
||||
|
||||
let district_pos: DistrictPos = (
|
||||
(wx / scale::DISTRICT_M as f64).floor() as i32,
|
||||
(wy / scale::DISTRICT_M as f64).floor() as i32,
|
||||
);
|
||||
let region_baseline_c = region_profile::region_baseline_at_district(
|
||||
seed.seed(),
|
||||
body_id,
|
||||
district_pos,
|
||||
¶ms,
|
||||
climate,
|
||||
seed,
|
||||
None, // no pre-built cache; derive on-the-fly, same posture as derive_at_metres
|
||||
);
|
||||
|
||||
build_district_profile(
|
||||
seed,
|
||||
¶ms,
|
||||
climate,
|
||||
slope_q,
|
||||
elev_q,
|
||||
ocean_fraction_q,
|
||||
region_baseline_c,
|
||||
BasinDirection::default(),
|
||||
)
|
||||
}
|
||||
|
||||
/// Bilinear interpolation of a row-major `f32` field at fractional `(px, py)`.
|
||||
/// Columns wrap (equirectangular); rows clamp at the poles.
|
||||
fn bilinear(field: &[f32], w: usize, h: usize, px: f64, py: f64) -> f32 {
|
||||
@@ -2066,6 +2188,153 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// derive_orbital_at_metres (T-1152, design doc §2/§4 orbital row)
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
/// Determinism (D-010/D-227): two independent orbital derives at the same
|
||||
/// position produce a bit-identical `DistrictProfile`, mirroring
|
||||
/// `derive_district_is_deterministic`'s pattern for the finer rungs.
|
||||
#[test]
|
||||
fn derive_orbital_at_metres_is_deterministic() {
|
||||
let hm = test_hm();
|
||||
let ta = test_ta(&hm);
|
||||
let climate = ClimateConstants::default();
|
||||
let p = earth_params();
|
||||
let dm = scale::REGION_M as f64;
|
||||
|
||||
let a = derive_orbital_at_metres(
|
||||
test_seed(),
|
||||
"test_body",
|
||||
&p,
|
||||
&ta,
|
||||
3.0 * dm,
|
||||
2.0 * dm,
|
||||
&climate,
|
||||
);
|
||||
let b = derive_orbital_at_metres(
|
||||
test_seed(),
|
||||
"test_body",
|
||||
&p,
|
||||
&ta,
|
||||
3.0 * dm,
|
||||
2.0 * dm,
|
||||
&climate,
|
||||
);
|
||||
assert_district_profiles_eq(&a, &b);
|
||||
}
|
||||
|
||||
/// The orbital path must NOT run `invent_primitives` — the design doc's
|
||||
/// central constraint (§2: "no invent_primitives at orbital wavelengths").
|
||||
/// Direct proof: `slope_q` is always exactly 0 (invention is the only
|
||||
/// source of nonzero slope_q at this call depth — see
|
||||
/// `derive_orbital_at_metres`'s doc on why slope_q is fixed), sampled
|
||||
/// across enough distinct positions that a nonzero value appearing even
|
||||
/// once would falsify the claim.
|
||||
#[test]
|
||||
fn derive_orbital_at_metres_never_invents_slope() {
|
||||
let hm = test_hm();
|
||||
let ta = test_ta(&hm);
|
||||
let climate = ClimateConstants::default();
|
||||
let p = earth_params();
|
||||
let dm = scale::REGION_M as f64;
|
||||
|
||||
for i in 0..25 {
|
||||
let wx = (i * 7) as f64 * dm * 0.37;
|
||||
let wy = (i * 11) as f64 * dm * 0.29;
|
||||
let prof =
|
||||
derive_orbital_at_metres(test_seed(), "test_body", &p, &ta, wx, wy, &climate);
|
||||
assert_eq!(
|
||||
prof.slope_q, 0,
|
||||
"orbital derive must never report invented slope (position {i})"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// The orbital derive's `elev_q`/`temperature_c` must come from the SAME
|
||||
/// envelope + region-baseline sources `derive_at_metres` reads — not an
|
||||
/// independent/divergent computation. At a position where the invented
|
||||
/// scatter happens to contribute exactly zero (impossible to guarantee by
|
||||
/// construction, so this test instead checks the WEAKER, always-true
|
||||
/// property: both paths' `elev_q` derive from the same underlying
|
||||
/// bilinear envelope, so they must be close — within the invented
|
||||
/// scatter's own bounded contribution range, not arbitrarily different).
|
||||
/// This guards against the orbital path silently reading a different
|
||||
/// terrain field entirely (a copy-paste bug this refactor is exactly the
|
||||
/// kind of change that could introduce).
|
||||
#[test]
|
||||
fn derive_orbital_at_metres_elevation_tracks_the_same_envelope() {
|
||||
let hm = test_hm();
|
||||
let ta = test_ta(&hm);
|
||||
let climate = ClimateConstants::default();
|
||||
let p = earth_params();
|
||||
let dm = scale::DISTRICT_M as f64;
|
||||
|
||||
// Sample at a DISTRICT-aligned position (within the orbital function's
|
||||
// legal domain — it accepts any world position, this just makes the
|
||||
// district-mode comparison call meaningful) so both paths read the
|
||||
// exact same fractional heightmap pixel.
|
||||
let wx = 40.0 * dm;
|
||||
let wy = 20.0 * dm;
|
||||
let orbital = derive_orbital_at_metres(test_seed(), "test_body", &p, &ta, wx, wy, &climate);
|
||||
let full = derive_at_metres(test_seed(), "test_body", &p, &ta, wx, wy, &climate, 0.0);
|
||||
|
||||
// The invented scatter is a bounded perturbation on top of the raw
|
||||
// envelope (detail_scatter's amplitude is capped well under 100 elev_q
|
||||
// points) — the two must be in the same ballpark, not exactly equal
|
||||
// (that would defeat the point of invention existing at all at the
|
||||
// finer rung) and not wildly different (that would mean the orbital
|
||||
// path is reading a different field).
|
||||
let elev_diff = (orbital.elev_q - full.elev_q).abs();
|
||||
assert!(
|
||||
elev_diff <= 50,
|
||||
"orbital elev_q ({}) and full-derive elev_q ({}) must come from the \
|
||||
same envelope, not diverge arbitrarily",
|
||||
orbital.elev_q,
|
||||
full.elev_q
|
||||
);
|
||||
}
|
||||
|
||||
/// Orbital-scale windows must still fill all six dense wire arrays the
|
||||
/// client's colorizer family reads (T-1152: "the orbital cells must fill
|
||||
/// the same six dense arrays the DistrictWindowLayer carries") — this is
|
||||
/// checked at the `DistrictProfile` level (the pre-packing source of
|
||||
/// those six fields): every field the packer reads
|
||||
/// (`morphology_zone`/`elev_q`/`temperature_c`/`moisture_q`/
|
||||
/// `vegetation_class`/`glaciation_grade`) must be populated the same way
|
||||
/// regardless of rung — this test asserts the orbital output is a
|
||||
/// legitimate `DistrictProfile`, not a partially-filled stand-in.
|
||||
#[test]
|
||||
fn derive_orbital_at_metres_populates_all_six_wire_fields() {
|
||||
let hm = test_hm();
|
||||
let ta = test_ta(&hm);
|
||||
let climate = ClimateConstants::default();
|
||||
let p = earth_params();
|
||||
let dm = scale::REGION_M as f64;
|
||||
|
||||
let prof = derive_orbital_at_metres(
|
||||
test_seed(),
|
||||
"test_body",
|
||||
&p,
|
||||
&ta,
|
||||
5.0 * dm,
|
||||
3.0 * dm,
|
||||
&climate,
|
||||
);
|
||||
assert!((0..=100).contains(&prof.elev_q));
|
||||
assert!((0..=100).contains(&prof.moisture_q));
|
||||
// temperature_c is Some for a breathable-atmosphere body (earth_params).
|
||||
assert!(prof.temperature_c.is_some());
|
||||
// morphology_zone/vegetation_class/glaciation_grade are enums with no
|
||||
// "unset" state — successfully constructing the DistrictProfile at
|
||||
// all (no panic) is the actual assertion; the field reads below just
|
||||
// confirm they're reachable typed values, matching the discipline
|
||||
// `derive_district_is_deterministic` and neighbours already use.
|
||||
let _ = prof.morphology_zone;
|
||||
let _ = prof.vegetation_class;
|
||||
let _ = prof.glaciation_grade;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn derive_district_profile_is_deterministic() {
|
||||
let hm = test_hm();
|
||||
|
||||
@@ -34,7 +34,9 @@ use crate::atlas::cascade::{run_cascade_from_heightmap, CascadeLayer};
|
||||
use crate::atlas::district_profile::{BodyParams, ClimateConstants, DistrictPos};
|
||||
use crate::atlas::features::TerrainAnalysis;
|
||||
use crate::atlas::heightmap::{load_heightmap_png, GRID_H, GRID_W};
|
||||
use crate::atlas::layer_proxy::{build_district_window_layer, DistrictWindowLayer};
|
||||
use crate::atlas::layer_proxy::{
|
||||
build_district_window_layer, DistrictWindowLayer, WindowGranularity,
|
||||
};
|
||||
use crate::atlas::shell::{fill_chunk, FilledChunk};
|
||||
use crate::atlas::skeleton_gen::{assign_all_block_tags, generate_quarter_skeleton};
|
||||
use crate::atlas::trait_catalog_reader::ExteriorCatalog;
|
||||
@@ -208,11 +210,18 @@ pub enum GenWorkItem {
|
||||
/// before this item is built — never trusted from the wire again here.
|
||||
center: DistrictPos,
|
||||
n: u32,
|
||||
/// Derivation granularity (T-1150) — `WINDOW_GRANULARITY_DISTRICT` (1)
|
||||
/// or `WINDOW_GRANULARITY_QUARTER` (4). Already resolved via
|
||||
/// `resolve_window_granularity` by the caller.
|
||||
granularity: u32,
|
||||
/// Derivation granularity (T-1150, widened T-1152 to the full
|
||||
/// [`WindowGranularity`] vocabulary — `District`/`Quarter` (finer)
|
||||
/// plus `Region` (coarser, T-1152)). Already resolved via
|
||||
/// `resolve_window_granularity_v2` by the caller — this is a
|
||||
/// concrete rung, never a raw wire value.
|
||||
granularity: WindowGranularity,
|
||||
/// Octave cutoff in whole metres (T-1149/T-1150), `0` = no cutoff.
|
||||
/// Meaningless for `granularity: Region` (`derive_orbital_at_metres`
|
||||
/// never calls the octave-scatter path this cuts off) but still
|
||||
/// carried and echoed uniformly — see `derive_orbital_at_metres`'s
|
||||
/// doc for why the field is harmless-but-unused there, not
|
||||
/// special-cased away.
|
||||
min_wl_m: u32,
|
||||
},
|
||||
}
|
||||
@@ -227,13 +236,17 @@ impl GenWorkItem {
|
||||
|
||||
/// Coalescing key for `DeriveWindow` items only — `(connection, body,
|
||||
/// granularity)` (T-1150, design doc §3 [SOFT] recommendation, extending
|
||||
/// T-1137's `(connection, body)`). `granularity` is part of the key so an
|
||||
/// in-flight district-spacing (granularity 1) pan-burst is never
|
||||
/// superseded by an unrelated quarter-spacing (granularity 4) request for
|
||||
/// the same connection+body, and vice versa — the two rungs are separate
|
||||
/// in-flight derives, not competing updates to the same one.
|
||||
/// T-1137's `(connection, body)`; widened T-1152 to carry the full
|
||||
/// [`WindowGranularity`] enum rather than the legacy `u32`, so `Region`
|
||||
/// occupies its own coalescing slot exactly like `District`/`Quarter` do
|
||||
/// — this is one of the five T-1150 touch points the R5 redesign must
|
||||
/// carry the new representation through). `granularity` is part of the
|
||||
/// key so an in-flight district-spacing pan-burst is never superseded by
|
||||
/// an unrelated quarter- or region-spacing request for the same
|
||||
/// connection+body, and vice versa — every rung is a separate in-flight
|
||||
/// derive, not a competing update to the same one.
|
||||
/// `None` for every other variant (they don't coalesce this way).
|
||||
pub fn window_supersede_key(&self) -> Option<(ConnectionId, &str, u32)> {
|
||||
pub fn window_supersede_key(&self) -> Option<(ConnectionId, &str, WindowGranularity)> {
|
||||
if let GenWorkItem::DeriveWindow {
|
||||
body_id,
|
||||
conn_id,
|
||||
@@ -1150,19 +1163,14 @@ mod tests {
|
||||
/// coalescing tests can exercise the granularity axis of
|
||||
/// `window_supersede_key()` without a second near-duplicate helper.
|
||||
fn derive_window(body_id: &str, conn_id: ConnectionId, center: DistrictPos) -> GenWorkItem {
|
||||
derive_window_at(
|
||||
body_id,
|
||||
conn_id,
|
||||
center,
|
||||
crate::atlas::layer_proxy::WINDOW_GRANULARITY_DISTRICT,
|
||||
)
|
||||
derive_window_at(body_id, conn_id, center, WindowGranularity::District)
|
||||
}
|
||||
|
||||
fn derive_window_at(
|
||||
body_id: &str,
|
||||
conn_id: ConnectionId,
|
||||
center: DistrictPos,
|
||||
granularity: u32,
|
||||
granularity: WindowGranularity,
|
||||
) -> GenWorkItem {
|
||||
GenWorkItem::DeriveWindow {
|
||||
body_id: body_id.to_string(),
|
||||
@@ -1316,21 +1324,11 @@ mod tests {
|
||||
|
||||
let conn = ConnectionId(9);
|
||||
q.submit_window(
|
||||
derive_window_at(
|
||||
"GranBody",
|
||||
conn,
|
||||
(0, 0),
|
||||
crate::atlas::layer_proxy::WINDOW_GRANULARITY_DISTRICT,
|
||||
),
|
||||
derive_window_at("GranBody", conn, (0, 0), WindowGranularity::District),
|
||||
GenPriority::Immediate,
|
||||
);
|
||||
q.submit_window(
|
||||
derive_window_at(
|
||||
"GranBody",
|
||||
conn,
|
||||
(0, 0),
|
||||
crate::atlas::layer_proxy::WINDOW_GRANULARITY_QUARTER,
|
||||
),
|
||||
derive_window_at("GranBody", conn, (0, 0), WindowGranularity::Quarter),
|
||||
GenPriority::Immediate,
|
||||
);
|
||||
assert_eq!(
|
||||
@@ -1352,21 +1350,11 @@ mod tests {
|
||||
|
||||
let conn = ConnectionId(11);
|
||||
q.submit_window(
|
||||
derive_window_at(
|
||||
"SameGranBody",
|
||||
conn,
|
||||
(0, 0),
|
||||
crate::atlas::layer_proxy::WINDOW_GRANULARITY_QUARTER,
|
||||
),
|
||||
derive_window_at("SameGranBody", conn, (0, 0), WindowGranularity::Quarter),
|
||||
GenPriority::Immediate,
|
||||
);
|
||||
q.submit_window(
|
||||
derive_window_at(
|
||||
"SameGranBody",
|
||||
conn,
|
||||
(5, 5),
|
||||
crate::atlas::layer_proxy::WINDOW_GRANULARITY_QUARTER,
|
||||
),
|
||||
derive_window_at("SameGranBody", conn, (5, 5), WindowGranularity::Quarter),
|
||||
GenPriority::Immediate,
|
||||
);
|
||||
assert_eq!(
|
||||
|
||||
+661
-88
File diff suppressed because it is too large
Load Diff
@@ -418,7 +418,7 @@ fn drain_generation_completions(
|
||||
body_id,
|
||||
layer.center,
|
||||
layer.n,
|
||||
layer.granularity,
|
||||
layer.granularity_v2,
|
||||
layer.min_wl_m,
|
||||
),
|
||||
*layer,
|
||||
@@ -914,6 +914,7 @@ mod tests {
|
||||
window_center: None,
|
||||
window_n: 0,
|
||||
window_granularity: 0,
|
||||
window_granularity_v2: None,
|
||||
window_min_wl_m: 0,
|
||||
},
|
||||
)]));
|
||||
|
||||
@@ -1202,6 +1202,7 @@ mod inbound_tests {
|
||||
window_center: None,
|
||||
window_n: 0,
|
||||
window_granularity: 0,
|
||||
window_granularity_v2: None,
|
||||
window_min_wl_m: 0,
|
||||
};
|
||||
let frame = rmp_serde::to_vec_named(&req).unwrap();
|
||||
@@ -1249,6 +1250,7 @@ mod inbound_tests {
|
||||
window_center: None,
|
||||
window_n: 0,
|
||||
window_granularity: 0,
|
||||
window_granularity_v2: None,
|
||||
window_min_wl_m: 0,
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
Reference in New Issue
Block a user