Skip to content

Commit 99df454

Browse files
committed
test: cover l4 join relay finish flags
1 parent 132ff95 commit 99df454

2 files changed

Lines changed: 55 additions & 1 deletion

File tree

CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2323
partial Finish retry without resending already-finished JoinResult questions,
2424
malformed/exception JoinResult cleanup that Finishes the affected question
2525
without restoring it, Accept-exception cleanup that still Finishes JoinResult
26-
lifetimes, and proxy-relay pickup through the real `JoinCoordinator`.
26+
lifetimes, proxy-relay pickup through the real `JoinCoordinator`, and
27+
`releaseResultCaps` propagation when upstream Finish drains a relayed
28+
JoinResult lifetime after Return.
2729

2830
- **RPC Level-4 Join state insertion is rollback-safe.** Fresh Join buckets now
2931
roll back if allocation fails before the first part is fully indexed, avoiding

tests/rpc/peer/rpc_join_readiness_test.zig

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1904,6 +1904,58 @@ test "L4 Join proxy relay source teardown after Return drains on upstream Finish
19041904
try harness.expectNoJoinState(&owner);
19051905
}
19061906

1907+
test "L4 Join proxy relay preserves releaseResultCaps on upstream Finish after Return" {
1908+
const allocator = std.testing.allocator;
1909+
1910+
var owner_capture = ReturnCapture{ .allocator = allocator };
1911+
defer owner_capture.deinit();
1912+
var source_capture = ReturnCapture{ .allocator = allocator };
1913+
defer source_capture.deinit();
1914+
1915+
var owner = Peer.initDetached(allocator);
1916+
owner.disableThreadAffinity();
1917+
defer owner.deinit();
1918+
owner.setSendFrameOverride(&owner_capture, ReturnCapture.onFrame);
1919+
1920+
var source = Peer.initDetached(allocator);
1921+
source.disableThreadAffinity();
1922+
defer source.deinit();
1923+
source.setSendFrameOverride(&source_capture, ReturnCapture.onFrame);
1924+
1925+
const proxy_export = try peer_test_hooks.addCrossPeerProxyExport(
1926+
&owner,
1927+
&source,
1928+
.{ .imported = .{ .id = 781 } },
1929+
null,
1930+
);
1931+
1932+
const join_frame = try buildJoinFrame(allocator, 59, proxy_export, 0x4c11, 1, 0);
1933+
defer allocator.free(join_frame);
1934+
try owner.handleFrame(join_frame);
1935+
const downstream_qid = (owner.pending_join_relays.get(59) orelse return error.MissingJoinRelay).source_question_id;
1936+
try std.testing.expect(source.questions.contains(downstream_qid));
1937+
try std.testing.expectEqual(@as(usize, 1), source.cross_peer_join_relay_links.items.len);
1938+
1939+
const downstream_return = try buildReturnResultsFrame(allocator, downstream_qid);
1940+
defer allocator.free(downstream_return);
1941+
try source.handleFrame(downstream_return);
1942+
1943+
try std.testing.expectEqual(@as(usize, 1), owner_capture.countReturns(59, .results));
1944+
try std.testing.expectEqual(@as(usize, 1), owner.pending_join_relays.count());
1945+
try std.testing.expectEqual(@as(usize, 1), source.cross_peer_join_relay_links.items.len);
1946+
try std.testing.expect(!source.questions.contains(downstream_qid));
1947+
1948+
const finish_frame = try buildFinishFrame(allocator, 59, true);
1949+
defer allocator.free(finish_frame);
1950+
try owner.handleFrame(finish_frame);
1951+
1952+
try source_capture.expectFinish(downstream_qid, true);
1953+
try std.testing.expectEqual(@as(usize, 0), owner.pending_join_relays.count());
1954+
try std.testing.expectEqual(@as(usize, 0), source.cross_peer_join_relay_links.items.len);
1955+
try harness.expectNoJoinState(&owner);
1956+
try harness.expectNoJoinState(&source);
1957+
}
1958+
19071959
test "L4 Join proxy relay propagates downstream target mismatch" {
19081960
const allocator = std.testing.allocator;
19091961

0 commit comments

Comments
 (0)