Fix exchange-only process continuation with explicit append path
This commit is contained in:
@@ -848,3 +848,123 @@ fn direct_process_real_picker_stays_bounded_and_search_keeps_selection() {
|
||||
assert_eq!(state.draft.as_ref().unwrap().target, Some(f.work[0]));
|
||||
assert_eq!(state.draft.as_ref().unwrap().browsers[0].page, 0);
|
||||
}
|
||||
|
||||
pub(crate) fn empty_exchange_fixture(layer: Layer) -> (Fixture, Id) {
|
||||
let mut f = fixture(layer);
|
||||
let mut commands = f.nodes.into_iter().map(Command::Delete).collect::<Vec<_>>();
|
||||
commands.push(Command::Connect(
|
||||
f.p.relations[&f.exchange].kind(),
|
||||
"Response".into(),
|
||||
f.work[1],
|
||||
f.work[2],
|
||||
));
|
||||
f.p = execute_batch(&f.p, &commands).unwrap();
|
||||
let next =
|
||||
f.p.relations
|
||||
.values()
|
||||
.find(|r| r.name == "Response")
|
||||
.unwrap()
|
||||
.id;
|
||||
assert!(f.p.elements[&f.owner].steps().unwrap().is_empty());
|
||||
(f, next)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn direct_process_append_preserves_existing_order_and_rejects_incompatible_exchange() {
|
||||
for layer in [Layer::Oa, Layer::Sa] {
|
||||
let (mut f, next) = empty_exchange_fixture(layer);
|
||||
let kind = f.p.relations[&f.exchange].kind();
|
||||
f.p = execute_batch(
|
||||
&f.p,
|
||||
&[Command::Connect(
|
||||
kind,
|
||||
"Recovery".into(),
|
||||
f.work[2],
|
||||
f.work[0],
|
||||
)],
|
||||
)
|
||||
.unwrap();
|
||||
let final_exchange =
|
||||
f.p.relations
|
||||
.values()
|
||||
.find(|r| r.name == "Recovery")
|
||||
.unwrap()
|
||||
.id;
|
||||
for exchange in [f.exchange, next] {
|
||||
let e = occurrence(
|
||||
&f.p,
|
||||
f.owner,
|
||||
"Ordered contribution",
|
||||
OccurrenceBody::Exchange {
|
||||
exchange: Some(exchange),
|
||||
sender: None,
|
||||
receiver: None,
|
||||
message_kind: MessageKind::default(),
|
||||
reply_to: None,
|
||||
values: vec![],
|
||||
},
|
||||
);
|
||||
f.p = execute_batch(&f.p, &[Command::CreateElement(e)]).unwrap();
|
||||
}
|
||||
let before = f.p.elements[&f.owner].steps().unwrap().clone();
|
||||
assert_eq!(legacy_order(&f.p, f.owner), before);
|
||||
assert!(sequence_links(&f.p, f.owner).is_empty());
|
||||
let mut state = State::default();
|
||||
state.append_exchange(&f.p, f.owner).unwrap();
|
||||
let draft = state.draft.as_ref().unwrap();
|
||||
assert!(draft.fixed);
|
||||
assert_eq!(draft.before, before.last().copied());
|
||||
assert_eq!(draft.after, None);
|
||||
assert!(!compatible_source(&f.p, draft, f.exchange));
|
||||
assert!(compatible_source(&f.p, draft, final_exchange));
|
||||
state
|
||||
.update(
|
||||
&f.p,
|
||||
Event::Target(Choice {
|
||||
id: f.exchange,
|
||||
label: "Incompatible".into(),
|
||||
}),
|
||||
)
|
||||
.unwrap();
|
||||
assert!(state.prepare_pending(&f.p).is_err());
|
||||
assert!(state.draft.is_some());
|
||||
state
|
||||
.update(
|
||||
&f.p,
|
||||
Event::Target(Choice {
|
||||
id: final_exchange,
|
||||
label: "Recovery".into(),
|
||||
}),
|
||||
)
|
||||
.unwrap();
|
||||
let command = state.prepare_pending(&f.p).unwrap();
|
||||
let Command::Batch(commands) = &command else {
|
||||
panic!("one ordinary batch")
|
||||
};
|
||||
assert_eq!(
|
||||
commands.len(),
|
||||
4,
|
||||
"materialize old path + occurrence + append link + order"
|
||||
);
|
||||
let serialized = serde_json::to_value(command).unwrap();
|
||||
let result = execute_batch(&f.p, &[serde_json::from_value(serialized).unwrap()]).unwrap();
|
||||
let after = result.elements[&f.owner].steps().unwrap();
|
||||
assert_eq!(&after[..2], &before);
|
||||
assert_eq!(after.len(), 3);
|
||||
let links = sequence_links(&result, f.owner);
|
||||
assert_eq!(links.len(), 2);
|
||||
for pair in after.windows(2) {
|
||||
assert_eq!(
|
||||
links
|
||||
.iter()
|
||||
.filter(|r| r.source() == pair[0] && r.target() == pair[1])
|
||||
.count(),
|
||||
1
|
||||
);
|
||||
}
|
||||
assert!(uses_explicit_topology(&result, f.owner));
|
||||
for (id, relation) in &f.p.relations {
|
||||
assert_eq!(result.relations[id], *relation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user