lib/machine/src/fabric/test.zig

daab053ee43316e1809a84551d573ddd1e5bf3d2

   1 const admission = @import("../admission/root.zig");
   2 const fabric = @import("root.zig");
   3 const fault = @import("../fault/root.zig");
   4 const instance = @import("../instance/root.zig");
   5 const os = @import("os");
   6 const profile = @import("../profile/root.zig");
   7 const std = @import("std");
   8 
   9 const k0_elf = @embedFile("machine-k0-elf");
  10 const k0_manifest = @embedFile("machine-k0-manifest");
  11 const world: [16]u8 = @splat(0x44);
  12 const source_id: fabric.NodeId = .{ .bytes = @splat(0x11) };
  13 const destination_id: fabric.NodeId = .{ .bytes = @splat(0x22) };
  14 const receiver_id: fabric.NodeId = .{ .bytes = @splat(0x33) };
  15 
  16 const SnapshotMutation = struct {
  17     offset: usize,
  18     mask: u8,
  19     expected: anyerror,
  20 };
  21 
  22 const connected_transition_count: usize = 5;
  23 const transition_count_max: usize = 6;
  24 
  25 var first_ram: [instance.ram_bytes]u8 align(instance.ram_alignment) = undefined;
  26 var second_ram: [instance.ram_bytes]u8 align(instance.ram_alignment) = undefined;
  27 var third_ram: [instance.ram_bytes]u8 align(instance.ram_alignment) = undefined;
  28 var snapshot_stream: [fabric.snapshot.stream_bytes + 1]u8 = undefined;
  29 var transition_streams: [transition_count_max][fabric.transition.stream_bytes]u8 = undefined;
  30 var transition_roots: [transition_count_max]fabric.Root = undefined;
  31 
  32 test "fabric snapshot reconstructs exact connected state" {
  33     const execution = try os.boot.kernel.manifest.parse(k0_manifest);
  34     const first_fence = activationFence(1, 0xf1);
  35     const second_fence = activationFence(1, 0xf2);
  36     const receiver_fence = activationFence(1, 0xf3);
  37     var first_storage = instance.Storage.init();
  38     var first = try start(
  39         &first_storage,
  40         &first_ram,
  41         machineInput(execution, first_fence, 0xd1, effectRequest(0xa1)),
  42     );
  43     defer first.deinit();
  44     var second_storage = instance.Storage.init();
  45     var second = try start(
  46         &second_storage,
  47         &second_ram,
  48         machineInput(execution, second_fence, 0xd2, effectRequest(0xa2)),
  49     );
  50     defer second.deinit();
  51     var receiver_storage = instance.Storage.init();
  52     var receiver = try start(
  53         &receiver_storage,
  54         &third_ram,
  55         machineInput(execution, receiver_fence, 0xd3, effectRequest(0xa3)),
  56     );
  57     defer receiver.deinit();
  58     const connected = try snapshotFixture(
  59         &first,
  60         &second,
  61         &receiver,
  62         first_fence,
  63         second_fence,
  64     );
  65     try expectSnapshotRoundTrip(connected);
  66 }
  67 
  68 test "fabric snapshot rejects framing tampering aliases and pending turns" {
  69     const execution = try os.boot.kernel.manifest.parse(k0_manifest);
  70     const first_fence = activationFence(1, 0xf4);
  71     const second_fence = activationFence(1, 0xf5);
  72     var first_storage = instance.Storage.init();
  73     var first = try start(
  74         &first_storage,
  75         &first_ram,
  76         machineInput(execution, first_fence, 0xe1, effectRequest(0xb1)),
  77     );
  78     defer first.deinit();
  79     var second_storage = instance.Storage.init();
  80     var second = try start(
  81         &second_storage,
  82         &second_ram,
  83         machineInput(execution, second_fence, 0xe2, effectRequest(0xb2)),
  84     );
  85     defer second.deinit();
  86     const initial = try twoNodeFabric(&first, &second);
  87     try expectSnapshotRejections(initial, &first, first_fence);
  88 }
  89 
  90 test "fabric transitions reopen one authenticated connected history" {
  91     const execution = try os.boot.kernel.manifest.parse(k0_manifest);
  92     const source_fence = activationFence(1, 0x91);
  93     const destination_fence = activationFence(1, 0x92);
  94     var source_storage = instance.Storage.init();
  95     var source = try start(
  96         &source_storage,
  97         &first_ram,
  98         machineInput(execution, source_fence, 0x61, effectRequest(0xc1)),
  99     );
 100     defer source.deinit();
 101     var destination_storage = instance.Storage.init();
 102     var destination = try start(
 103         &destination_storage,
 104         &second_ram,
 105         machineInput(execution, destination_fence, 0x71, effectRequest(0xc2)),
 106     );
 107     defer destination.deinit();
 108     const initial = try twoNodeFabric(&source, &destination);
 109     try encodeSnapshot(&initial);
 110     var connected = initial;
 111     try recordConnectedTransitions(
 112         &connected,
 113         &source,
 114         &destination,
 115         source_fence,
 116         destination_fence,
 117     );
 118     try expectTransitionReplay(initial, connected.root());
 119     try expectTransitionRejections(initial);
 120     try expectFaultTransitionVariants(initial);
 121 }
 122 
 123 test "fabric transitions preserve direct input and admission fault variants" {
 124     const execution = try os.boot.kernel.manifest.parse(k0_manifest);
 125     const initial_fence = activationFence(1, 0x93);
 126     var storage = instance.Storage.init();
 127     var machine = try start(
 128         &storage,
 129         &first_ram,
 130         machineInput(execution, initial_fence, 0x81, null),
 131     );
 132     defer machine.deinit();
 133     const initial = try singleNodeFabric(&machine);
 134     var connected = initial;
 135     try recordDirectTransitions(&connected, &machine, initial_fence);
 136     try expectTransitionFrames(initial, transition_count_max, connected.root());
 137 }
 138 
 139 test "connected packet turns are write-ahead settled and replayable" {
 140     const execution = try os.boot.kernel.manifest.parse(k0_manifest);
 141     const source_fence = activationFence(1, 0x51);
 142     const destination_fence = activationFence(1, 0x61);
 143     var source_storage = instance.Storage.init();
 144     var source = try start(
 145         &source_storage,
 146         &first_ram,
 147         machineInput(execution, source_fence, 0x31, effectRequest(0x71)),
 148     );
 149     defer source.deinit();
 150     var destination_storage = instance.Storage.init();
 151     var destination = try start(
 152         &destination_storage,
 153         &second_ram,
 154         machineInput(execution, destination_fence, 0x41, effectRequest(0x81)),
 155     );
 156     defer destination.deinit();
 157     const initial = try twoNodeFabric(&source, &destination);
 158     try expectRootHex(
 159         initial.root(),
 160         "f90d9b4855abe5e4927604b39405eb0fb48c8bcda853ee80d0720bfdea393fee",
 161     );
 162     try exercisePacketReplay(
 163         initial,
 164         &source,
 165         &destination,
 166         source_fence,
 167         destination_fence,
 168     );
 169 }
 170 
 171 test "virtual time entropy and terminal choices share the fabric ledger" {
 172     const execution = try os.boot.kernel.manifest.parse(k0_manifest);
 173     var current_fence = activationFence(1, 0xa1);
 174     var storage = instance.Storage.init();
 175     var machine = try start(
 176         &storage,
 177         &first_ram,
 178         machineInput(execution, current_fence, 0x51, null),
 179     );
 180     defer machine.deinit();
 181     const nodes = [_]fabric.Node{
 182         .{ .id = source_id, .basis = try machine.admissionBasis() },
 183     };
 184     const initial = try fabric.Fabric.init(.{
 185         .profile = profile.interpretedContinuationTestV1(),
 186         .world = world,
 187         .virtual_time_tick = 7,
 188         .nodes = &nodes,
 189     });
 190 
 191     var replay = initial;
 192     var connected = try advanceAndSettleTime(
 193         initial,
 194         &machine,
 195         current_fence,
 196         &replay,
 197     );
 198     current_fence = activationFence(2, 0xa2);
 199     try machine.reactivate(current_fence);
 200     try activate(&machine);
 201     try std.testing.expectError(
 202         error.VirtualTimeRegression,
 203         connected.advanceTime(source_id, &machine, current_fence, 7),
 204     );
 205     connected = try injectAndSettleEntropy(
 206         connected,
 207         &machine,
 208         current_fence,
 209         &replay,
 210     );
 211     current_fence = activationFence(3, 0xa3);
 212     try machine.reactivate(current_fence);
 213     try activate(&machine);
 214     const admission_frontier = connected.root().admission_frontier;
 215     const terminal = try connected.terminal(
 216         source_id,
 217         &machine,
 218         current_fence,
 219         os.k0.request_bytes,
 220     );
 221     try std.testing.expectEqual(
 222         @as(u64, admission_frontier + 1),
 223         terminal.root.admission_frontier,
 224     );
 225 }
 226 
 227 test "packet selection is an explicit connected schedule choice" {
 228     const execution = try os.boot.kernel.manifest.parse(k0_manifest);
 229     const first_fence = activationFence(1, 0xc1);
 230     const second_fence = activationFence(1, 0xc2);
 231     const receiver_fence = activationFence(1, 0xc3);
 232     var first_storage = instance.Storage.init();
 233     var first = try start(
 234         &first_storage,
 235         &first_ram,
 236         machineInput(execution, first_fence, 0x71, effectRequest(0xd1)),
 237     );
 238     defer first.deinit();
 239     var second_storage = instance.Storage.init();
 240     var second = try start(
 241         &second_storage,
 242         &second_ram,
 243         machineInput(execution, second_fence, 0x81, effectRequest(0xd2)),
 244     );
 245     defer second.deinit();
 246     var receiver_storage = instance.Storage.init();
 247     var receiver = try start(
 248         &receiver_storage,
 249         &third_ram,
 250         machineInput(execution, receiver_fence, 0x91, effectRequest(0xd3)),
 251     );
 252     defer receiver.deinit();
 253     try expectPacketSelection(
 254         &first,
 255         &second,
 256         &receiver,
 257         first_fence,
 258         second_fence,
 259         receiver_fence,
 260     );
 261 }
 262 
 263 test "fabric initialization rejects every noncanonical topology" {
 264     const execution = try os.boot.kernel.manifest.parse(k0_manifest);
 265     const current_fence = activationFence(1, 0xb1);
 266     var storage = instance.Storage.init();
 267     var machine = try start(
 268         &storage,
 269         &first_ram,
 270         machineInput(execution, current_fence, 0x61, null),
 271     );
 272     defer machine.deinit();
 273     const basis = try machine.admissionBasis();
 274     const reversed = [_]fabric.Node{
 275         .{ .id = destination_id, .basis = basis },
 276         .{ .id = source_id, .basis = basis },
 277     };
 278     try expectInitError(error.NodesNotCanonical, world, 7, &reversed);
 279     const duplicate = [_]fabric.Node{
 280         .{ .id = source_id, .basis = basis },
 281         .{ .id = source_id, .basis = basis },
 282     };
 283     try expectInitError(error.NodesNotCanonical, world, 7, &duplicate);
 284     const invalid_id = [_]fabric.Node{
 285         .{ .id = .{ .bytes = @splat(0) }, .basis = basis },
 286     };
 287     try expectInitError(error.InvalidNode, world, 7, &invalid_id);
 288     const one = [_]fabric.Node{
 289         .{ .id = source_id, .basis = basis },
 290     };
 291     try expectInitError(error.InvalidWorld, @splat(0), 7, &one);
 292     try expectInitError(error.NodeStateMismatch, world, 6, &one);
 293     const too_many = [_]fabric.Node{
 294         .{ .id = .{ .bytes = @splat(1) }, .basis = basis },
 295         .{ .id = .{ .bytes = @splat(2) }, .basis = basis },
 296         .{ .id = .{ .bytes = @splat(3) }, .basis = basis },
 297         .{ .id = .{ .bytes = @splat(4) }, .basis = basis },
 298         .{ .id = .{ .bytes = @splat(5) }, .basis = basis },
 299     };
 300     try expectInitError(error.NodeCapacityExceeded, world, 7, &too_many);
 301     const exact = too_many[0..fabric.node_limit];
 302     const initialized = try fabric.Fabric.init(.{
 303         .profile = profile.interpretedContinuationTestV1(),
 304         .world = world,
 305         .virtual_time_tick = 7,
 306         .nodes = exact,
 307     });
 308     try std.testing.expectEqual(@as(u64, 0), initialized.root().entry_frontier);
 309     try std.testing.expectEqual(
 310         fabric.Dialect.ordered_effect_fabric_v3,
 311         initialized.root().dialect,
 312     );
 313     const accelerated = try fabric.Fabric.init(.{
 314         .profile = profile.kvmContinuationTestV1(),
 315         .world = world,
 316         .virtual_time_tick = 7,
 317         .nodes = exact,
 318     });
 319     try expectBackendNeutralFault(initialized, accelerated);
 320     var wrong_limit = initialized;
 321     wrong_limit.state.admission_limit += 1;
 322     try std.testing.expectError(
 323         error.FabricStateInvalid,
 324         wrong_limit.packet(1),
 325     );
 326 }
 327 
 328 fn expectBackendNeutralFault(
 329     interpreted: fabric.Fabric,
 330     accelerated: fabric.Fabric,
 331 ) !void {
 332     try std.testing.expectEqualDeep(interpreted.root(), accelerated.root());
 333     var interpreted_fault = interpreted;
 334     var accelerated_fault = accelerated;
 335     const fault_input: fabric.FaultInput = .{
 336         .effect = .{ .clock_jump = 8 },
 337         .choice = .inject,
 338     };
 339     const interpreted_result = try interpreted_fault.applyFault(fault_input);
 340     const accelerated_result = try accelerated_fault.applyFault(fault_input);
 341     try std.testing.expectEqualDeep(
 342         interpreted_result.decision,
 343         accelerated_result.decision,
 344     );
 345     try std.testing.expectEqualDeep(
 346         interpreted_result.root,
 347         accelerated_result.root,
 348     );
 349 }
 350 
 351 test "direct fault choices are stable replayable and enforced" {
 352     const execution = try os.boot.kernel.manifest.parse(k0_manifest);
 353     const current_fence = activationFence(1, 0xe1);
 354     var storage = instance.Storage.init();
 355     var machine = try start(
 356         &storage,
 357         &first_ram,
 358         machineInput(execution, current_fence, 0xa1, null),
 359     );
 360     defer machine.deinit();
 361     const initial = try singleNodeFabric(&machine);
 362     try expectNodeFaultChoices(initial, &machine, current_fence);
 363     try expectClockAndCapacityFaults(initial, &machine, current_fence);
 364 }
 365 
 366 test "network faults control delivery without ambient network state" {
 367     const execution = try os.boot.kernel.manifest.parse(k0_manifest);
 368     const first_fence = activationFence(1, 0xe2);
 369     const second_fence = activationFence(1, 0xe3);
 370     const receiver_fence = activationFence(1, 0xe4);
 371     var first_storage = instance.Storage.init();
 372     var first = try start(
 373         &first_storage,
 374         &first_ram,
 375         machineInput(execution, first_fence, 0xb1, effectRequest(0xe1)),
 376     );
 377     defer first.deinit();
 378     var second_storage = instance.Storage.init();
 379     var second = try start(
 380         &second_storage,
 381         &second_ram,
 382         machineInput(execution, second_fence, 0xb2, effectRequest(0xe2)),
 383     );
 384     defer second.deinit();
 385     var receiver_storage = instance.Storage.init();
 386     var receiver = try start(
 387         &receiver_storage,
 388         &third_ram,
 389         machineInput(execution, receiver_fence, 0xb3, effectRequest(0xe3)),
 390     );
 391     defer receiver.deinit();
 392     const connected = try readyPackets(
 393         &first,
 394         &second,
 395         &receiver,
 396         first_fence,
 397         second_fence,
 398     );
 399     try expectNetworkFaultChoices(connected, &receiver, receiver_fence);
 400 }
 401 
 402 test "fault alternatives bind entropy and service admissions" {
 403     const execution = try os.boot.kernel.manifest.parse(k0_manifest);
 404     const entropy_fence = activationFence(1, 0xe5);
 405     const service_fence = activationFence(1, 0xe6);
 406     var entropy_storage = instance.Storage.init();
 407     var entropy_machine = try start(
 408         &entropy_storage,
 409         &first_ram,
 410         machineInput(execution, entropy_fence, 0xc1, null),
 411     );
 412     defer entropy_machine.deinit();
 413     var service_storage = instance.Storage.init();
 414     var service_machine = try start(
 415         &service_storage,
 416         &second_ram,
 417         machineInput(execution, service_fence, 0xc2, effectRequest(0xe4)),
 418     );
 419     defer service_machine.deinit();
 420     const initial = try twoNodeFabric(&entropy_machine, &service_machine);
 421     const connected = try expectEntropyFaultChoices(
 422         initial,
 423         &entropy_machine,
 424         entropy_fence,
 425     );
 426     try expectServiceFaultChoices(connected, &service_machine, service_fence);
 427 }
 428 
 429 fn singleNodeFabric(machine: *const instance.Instance) !fabric.Fabric {
 430     const nodes = [_]fabric.Node{
 431         .{ .id = source_id, .basis = try machine.admissionBasis() },
 432     };
 433     return fabric.Fabric.init(.{
 434         .profile = profile.interpretedContinuationTestV1(),
 435         .world = world,
 436         .virtual_time_tick = 7,
 437         .nodes = &nodes,
 438     });
 439 }
 440 
 441 fn expectNodeFaultChoices(
 442     initial: fabric.Fabric,
 443     machine: *const instance.Instance,
 444     fence: os.abi.ActivationFence,
 445 ) !void {
 446     const effect: fabric.FaultEffect = .{ .machine_crash = source_id };
 447     var bypass_branch = initial;
 448     const bypassed = try bypass_branch.applyFault(.{
 449         .effect = effect,
 450         .choice = .bypass,
 451     });
 452     var inject_branch = initial;
 453     const injected = try inject_branch.applyFault(.{
 454         .effect = effect,
 455         .choice = .inject,
 456     });
 457     try std.testing.expectEqualDeep(
 458         bypassed.decision.point,
 459         injected.decision.point,
 460     );
 461     try expectDifferentRoots(bypassed.root, injected.root);
 462     try std.testing.expect(try bypass_branch.nodeAvailable(source_id));
 463     try std.testing.expect(!try inject_branch.nodeAvailable(source_id));
 464     try std.testing.expectEqual(@as(u64, 1), injected.root.fault_frontier);
 465     try std.testing.expectEqual(@as(u64, 1), injected.root.admission_frontier);
 466     try std.testing.expectError(
 467         error.NodeUnavailable,
 468         inject_branch.terminal(source_id, machine, fence, "blocked"),
 469     );
 470     try expectFaultReplayMutation(initial, injected);
 471     try expectProcessFaultCommand(initial);
 472 }
 473 
 474 fn expectFaultReplayMutation(
 475     initial: fabric.Fabric,
 476     injected: fabric.Faulted,
 477 ) !void {
 478     var replay = initial;
 479     try std.testing.expectEqualDeep(injected.root, try replay.replay(injected.entry));
 480     var changed = injected.entry;
 481     changed.value.fault.decision.choice = .bypass;
 482     var invalid = initial;
 483     const before = invalid.root();
 484     try std.testing.expectError(
 485         error.InvalidFaultDecision,
 486         invalid.replay(changed),
 487     );
 488     try std.testing.expectEqualDeep(before, invalid.root());
 489     var changed_effect = injected.entry;
 490     changed_effect.value.fault.effect = .{ .clock_jump = 12 };
 491     var invalid_effect = initial;
 492     const effect_before = invalid_effect.root();
 493     try std.testing.expectError(
 494         error.InvalidFaultPoint,
 495         invalid_effect.replay(changed_effect),
 496     );
 497     try std.testing.expectEqualDeep(effect_before, invalid_effect.root());
 498 }
 499 
 500 fn expectProcessFaultCommand(initial: fabric.Fabric) !void {
 501     var process_branch = initial;
 502     const command = try process_branch.applyFault(.{
 503         .effect = .{ .process_crash = .{ .node = source_id, .process = 7 } },
 504         .choice = .inject,
 505     });
 506     try std.testing.expectEqual(fault.Kind.process_crash, command.decision.point.kind);
 507     try std.testing.expect(try process_branch.nodeAvailable(source_id));
 508     var invalid = initial;
 509     try std.testing.expectError(
 510         error.ProcessIdentityInvalid,
 511         invalid.applyFault(.{
 512             .effect = .{ .process_crash = .{ .node = source_id, .process = 0 } },
 513             .choice = .inject,
 514         }),
 515     );
 516 }
 517 
 518 fn expectClockAndCapacityFaults(
 519     initial: fabric.Fabric,
 520     machine: *const instance.Instance,
 521     fence: os.abi.ActivationFence,
 522 ) !void {
 523     const jump_effect: fabric.FaultEffect = .{ .clock_jump = 12 };
 524     var bypass_branch = initial;
 525     const bypassed = try bypass_branch.applyFault(.{
 526         .effect = jump_effect,
 527         .choice = .bypass,
 528     });
 529     var jump_branch = initial;
 530     const jumped = try jump_branch.applyFault(.{
 531         .effect = jump_effect,
 532         .choice = .inject,
 533     });
 534     try std.testing.expectEqualDeep(bypassed.decision.point, jumped.decision.point);
 535     try std.testing.expectEqual(@as(u64, 12), jump_branch.state.virtual_time_tick);
 536     try std.testing.expectError(
 537         error.VirtualTimeRegression,
 538         jump_branch.advanceTime(source_id, machine, fence, 8),
 539     );
 540     var capacity = initial;
 541     _ = try capacity.applyFault(.{
 542         .effect = .{ .capacity_exhaustion = .{
 543             .resource = .admission,
 544             .active = true,
 545         } },
 546         .choice = .inject,
 547     });
 548     try std.testing.expectError(
 549         error.AdmissionCapacityExceeded,
 550         capacity.terminal(source_id, machine, fence, "blocked"),
 551     );
 552     _ = try capacity.applyFault(.{
 553         .effect = .{ .capacity_exhaustion = .{
 554             .resource = .admission,
 555             .active = false,
 556         } },
 557         .choice = .inject,
 558     });
 559     _ = try capacity.terminal(source_id, machine, fence, "restored");
 560 }
 561 
 562 fn expectNetworkFaultChoices(
 563     connected: fabric.Fabric,
 564     receiver: *const instance.Instance,
 565     fence: os.abi.ActivationFence,
 566 ) !void {
 567     try expectPacketReorderFault(connected, receiver, fence);
 568     try expectPacketLossAndDelay(connected, receiver, fence);
 569     try expectPartitionFault(connected, receiver, fence);
 570 }
 571 
 572 fn expectPacketReorderFault(
 573     connected: fabric.Fabric,
 574     receiver: *const instance.Instance,
 575     fence: os.abi.ActivationFence,
 576 ) !void {
 577     var reversed = connected;
 578     try std.testing.expectError(
 579         error.PacketOrderInvalid,
 580         reversed.applyFault(.{
 581             .effect = .{ .packet_reorder = .{ .first = 2, .second = 1 } },
 582             .choice = .inject,
 583         }),
 584     );
 585     const effect: fabric.FaultEffect = .{ .packet_reorder = .{
 586         .first = 1,
 587         .second = 2,
 588     } };
 589     var bypass_branch = connected;
 590     const bypassed = try bypass_branch.applyFault(.{
 591         .effect = effect,
 592         .choice = .bypass,
 593     });
 594     var inject_branch = connected;
 595     const injected = try inject_branch.applyFault(.{
 596         .effect = effect,
 597         .choice = .inject,
 598     });
 599     try std.testing.expectEqualDeep(
 600         bypassed.decision.point,
 601         injected.decision.point,
 602     );
 603     try expectDifferentRoots(bypassed.root, injected.root);
 604     const first = try bypass_branch.receiveNextPacket(receiver_id, receiver, fence);
 605     const second = try inject_branch.receiveNextPacket(receiver_id, receiver, fence);
 606     try std.testing.expectEqual(
 607         @as(u64, 1),
 608         first.entry.value.admission.effect.packet_delivery,
 609     );
 610     try std.testing.expectEqual(
 611         @as(u64, 2),
 612         second.entry.value.admission.effect.packet_delivery,
 613     );
 614 }
 615 
 616 fn expectPacketLossAndDelay(
 617     connected: fabric.Fabric,
 618     receiver: *const instance.Instance,
 619     fence: os.abi.ActivationFence,
 620 ) !void {
 621     var lost = connected;
 622     const dropped = try lost.applyFault(.{
 623         .effect = .{ .packet_loss = 1 },
 624         .choice = .inject,
 625     });
 626     try std.testing.expectEqual(@as(u8, 1), lost.packetCount());
 627     try std.testing.expectError(error.PacketUnknown, lost.packet(1));
 628     var replay = connected;
 629     try std.testing.expectEqualDeep(dropped.root, try replay.replay(dropped.entry));
 630     var delayed = connected;
 631     try std.testing.expectError(
 632         error.PacketDelayed,
 633         delayed.applyFault(.{
 634             .effect = .{ .packet_delay = .{ .packet = 1, .until_tick = 7 } },
 635             .choice = .inject,
 636         }),
 637     );
 638     _ = try delayed.applyFault(.{
 639         .effect = .{ .packet_delay = .{ .packet = 1, .until_tick = 12 } },
 640         .choice = .inject,
 641     });
 642     try std.testing.expectError(
 643         error.PacketDelayed,
 644         delayed.receivePacket(receiver_id, receiver, fence, 1),
 645     );
 646     _ = try delayed.applyFault(.{
 647         .effect = .{ .clock_jump = 12 },
 648         .choice = .inject,
 649     });
 650     _ = try delayed.receivePacket(receiver_id, receiver, fence, 1);
 651 }
 652 
 653 fn expectPartitionFault(
 654     connected: fabric.Fabric,
 655     receiver: *const instance.Instance,
 656     fence: os.abi.ActivationFence,
 657 ) !void {
 658     var partition = connected;
 659     try std.testing.expectError(
 660         error.InvalidNode,
 661         partition.applyFault(.{
 662             .effect = .{ .partition = .{
 663                 .first = receiver_id,
 664                 .second = source_id,
 665                 .active = true,
 666             } },
 667             .choice = .inject,
 668         }),
 669     );
 670     _ = try partition.applyFault(.{
 671         .effect = .{ .partition = .{
 672             .first = source_id,
 673             .second = receiver_id,
 674             .active = true,
 675         } },
 676         .choice = .inject,
 677     });
 678     try std.testing.expect(try partition.partitioned(source_id, receiver_id));
 679     try std.testing.expectError(
 680         error.LinkPartitioned,
 681         partition.receivePacket(receiver_id, receiver, fence, 1),
 682     );
 683     _ = try partition.applyFault(.{
 684         .effect = .{ .partition = .{
 685             .first = source_id,
 686             .second = receiver_id,
 687             .active = false,
 688         } },
 689         .choice = .inject,
 690     });
 691     try std.testing.expect(!try partition.partitioned(source_id, receiver_id));
 692     _ = try partition.receivePacket(receiver_id, receiver, fence, 1);
 693 }
 694 
 695 fn expectEntropyFaultChoices(
 696     initial: fabric.Fabric,
 697     machine: *instance.Instance,
 698     fence: os.abi.ActivationFence,
 699 ) !fabric.Fabric {
 700     var equal_branch = initial;
 701     const equal_before = equal_branch.root();
 702     try std.testing.expectError(
 703         error.FaultAlternativesEqual,
 704         equal_branch.chooseEntropy(
 705             source_id,
 706             machine,
 707             fence,
 708             &.{ 1, 2, 3 },
 709             &.{ 1, 2, 3 },
 710             .inject,
 711         ),
 712     );
 713     try std.testing.expectEqualDeep(equal_before, equal_branch.root());
 714     var bypass_branch = initial;
 715     const bypassed = try bypass_branch.chooseEntropy(
 716         source_id,
 717         machine,
 718         fence,
 719         &.{ 1, 2, 3 },
 720         &.{ 4, 5, 6 },
 721         .bypass,
 722     );
 723     var inject_branch = initial;
 724     const injected = try inject_branch.chooseEntropy(
 725         source_id,
 726         machine,
 727         fence,
 728         &.{ 1, 2, 3 },
 729         &.{ 4, 5, 6 },
 730         .inject,
 731     );
 732     try std.testing.expectEqualDeep(
 733         admissionFaultDecision(bypassed).point,
 734         admissionFaultDecision(injected).point,
 735     );
 736     try expectDifferentRoots(bypassed.root, injected.root);
 737     try std.testing.expectEqual(@as(u64, 1), injected.root.fault_frontier);
 738     var replay = initial;
 739     try std.testing.expectEqualDeep(injected.root, try replay.replay(injected.entry));
 740     try expectAdmissionFaultMutation(initial, injected);
 741     const settled = try inject_branch.settle(
 742         source_id,
 743         try completeTurn(machine, injected.delivery),
 744     );
 745     try std.testing.expectEqualDeep(settled.root, try replay.replay(settled.entry));
 746     return inject_branch;
 747 }
 748 
 749 fn expectAdmissionFaultMutation(
 750     initial: fabric.Fabric,
 751     admitted: fabric.Admitted,
 752 ) !void {
 753     var changed = admitted.entry;
 754     changed.value.admission.fault.?.decision.choice = .bypass;
 755     var replay = initial;
 756     const before = replay.root();
 757     try std.testing.expectError(
 758         error.InvalidFaultDecision,
 759         replay.replay(changed),
 760     );
 761     try std.testing.expectEqualDeep(before, replay.root());
 762     var changed_effect = admitted.entry;
 763     changed_effect.value.admission.fault.?.effect.entropy_choice.inject[0] ^= 1;
 764     var effect_replay = initial;
 765     const effect_before = effect_replay.root();
 766     try std.testing.expectError(
 767         error.InvalidFaultPoint,
 768         effect_replay.replay(changed_effect),
 769     );
 770     try std.testing.expectEqualDeep(effect_before, effect_replay.root());
 771 }
 772 
 773 fn expectServiceFaultChoices(
 774     connected: fabric.Fabric,
 775     machine: *const instance.Instance,
 776     fence: os.abi.ActivationFence,
 777 ) !void {
 778     const normal: fabric.ServiceResult = .{
 779         .status = .ok,
 780         .output_root = @splat(0xf1),
 781         .bytes = "normal",
 782     };
 783     const io_failure: fabric.ServiceResult = .{
 784         .status = .failed,
 785         .output_root = @splat(0xf2),
 786         .bytes = "io-error",
 787     };
 788     var bypass_branch = connected;
 789     const bypassed = try bypass_branch.chooseService(
 790         destination_id,
 791         machine,
 792         fence,
 793         .io_error,
 794         normal,
 795         io_failure,
 796         .bypass,
 797     );
 798     var inject_branch = connected;
 799     const injected = try inject_branch.chooseService(
 800         destination_id,
 801         machine,
 802         fence,
 803         .io_error,
 804         normal,
 805         io_failure,
 806         .inject,
 807     );
 808     try std.testing.expectEqualDeep(
 809         admissionFaultDecision(bypassed).point,
 810         admissionFaultDecision(injected).point,
 811     );
 812     try expectDifferentRoots(bypassed.root, injected.root);
 813     try std.testing.expectEqual(
 814         os.abi.EffectStatus.failed,
 815         injected.entry.value.admission.admission.record.effect_result.status,
 816     );
 817     try expectHostServiceFault(connected, machine, fence, normal);
 818 }
 819 
 820 fn expectHostServiceFault(
 821     connected: fabric.Fabric,
 822     machine: *const instance.Instance,
 823     fence: os.abi.ActivationFence,
 824     normal: fabric.ServiceResult,
 825 ) !void {
 826     const unavailable: fabric.ServiceResult = .{
 827         .status = .unavailable,
 828         .output_root = @splat(0xf3),
 829         .bytes = "offline",
 830     };
 831     var branch = connected;
 832     const admitted = try branch.chooseService(
 833         destination_id,
 834         machine,
 835         fence,
 836         .host_service_failure,
 837         normal,
 838         unavailable,
 839         .inject,
 840     );
 841     try std.testing.expectEqual(
 842         fault.Kind.host_service_failure,
 843         admissionFaultDecision(admitted).point.kind,
 844     );
 845     var invalid = connected;
 846     try std.testing.expectError(
 847         error.FaultStatusInvalid,
 848         invalid.chooseService(
 849             destination_id,
 850             machine,
 851             fence,
 852             .host_service_failure,
 853             normal,
 854             .{ .status = .failed, .output_root = @splat(0xf4), .bytes = "bad" },
 855             .inject,
 856         ),
 857     );
 858 }
 859 
 860 fn admissionFaultDecision(admitted: fabric.Admitted) fault.Decision {
 861     return admitted.entry.value.admission.fault.?.decision;
 862 }
 863 
 864 fn advanceAndSettleTime(
 865     initial: fabric.Fabric,
 866     machine: *instance.Instance,
 867     fence: os.abi.ActivationFence,
 868     replay: *fabric.Fabric,
 869 ) !fabric.Fabric {
 870     var time_eight = initial;
 871     const advanced = try time_eight.advanceTime(source_id, machine, fence, 8);
 872     var time_nine = initial;
 873     const later = try time_nine.advanceTime(source_id, machine, fence, 9);
 874     try expectDifferentRoots(advanced.root, later.root);
 875     try std.testing.expectEqualDeep(advanced.root, try replay.replay(advanced.entry));
 876     const settled = try time_eight.settle(
 877         source_id,
 878         try completeTurn(machine, advanced.delivery),
 879     );
 880     try std.testing.expectEqualDeep(settled.root, try replay.replay(settled.entry));
 881     return time_eight;
 882 }
 883 
 884 fn injectAndSettleEntropy(
 885     initial: fabric.Fabric,
 886     machine: *instance.Instance,
 887     fence: os.abi.ActivationFence,
 888     replay: *fabric.Fabric,
 889 ) !fabric.Fabric {
 890     var first_branch = initial;
 891     const first = try first_branch.injectEntropy(
 892         source_id,
 893         machine,
 894         fence,
 895         &.{ 1, 2, 3 },
 896     );
 897     var second_branch = initial;
 898     const second = try second_branch.injectEntropy(
 899         source_id,
 900         machine,
 901         fence,
 902         &.{ 1, 2, 4 },
 903     );
 904     try expectDifferentRoots(first.root, second.root);
 905     try std.testing.expectEqualDeep(first.root, try replay.replay(first.entry));
 906     const settled = try first_branch.settle(
 907         source_id,
 908         try completeTurn(machine, first.delivery),
 909     );
 910     try std.testing.expectEqualDeep(settled.root, try replay.replay(settled.entry));
 911     return first_branch;
 912 }
 913 
 914 fn expectPacketSelection(
 915     first: *instance.Instance,
 916     second: *instance.Instance,
 917     receiver: *const instance.Instance,
 918     first_fence: os.abi.ActivationFence,
 919     second_fence: os.abi.ActivationFence,
 920     receiver_fence: os.abi.ActivationFence,
 921 ) !void {
 922     const connected = try readyPackets(
 923         first,
 924         second,
 925         receiver,
 926         first_fence,
 927         second_fence,
 928     );
 929     try std.testing.expectEqual(@as(u8, 2), connected.packetCount());
 930     try expectPacketBranches(connected, receiver, receiver_fence);
 931 }
 932 
 933 fn readyPackets(
 934     first: *instance.Instance,
 935     second: *instance.Instance,
 936     receiver: *const instance.Instance,
 937     first_fence: os.abi.ActivationFence,
 938     second_fence: os.abi.ActivationFence,
 939 ) !fabric.Fabric {
 940     const nodes = [_]fabric.Node{
 941         .{ .id = source_id, .basis = try first.admissionBasis() },
 942         .{ .id = destination_id, .basis = try second.admissionBasis() },
 943         .{ .id = receiver_id, .basis = try receiver.admissionBasis() },
 944     };
 945     var connected = try fabric.Fabric.init(.{
 946         .profile = profile.interpretedContinuationTestV1(),
 947         .world = world,
 948         .virtual_time_tick = 7,
 949         .nodes = &nodes,
 950     });
 951     const first_send = try connected.sendPacket(
 952         source_id,
 953         first,
 954         first_fence,
 955         .{ .destination = receiver_id, .channel = 9, .bytes = "first" },
 956     );
 957     _ = try connected.settle(
 958         source_id,
 959         try completeTurn(first, first_send.delivery),
 960     );
 961     const second_send = try connected.sendPacket(
 962         destination_id,
 963         second,
 964         second_fence,
 965         .{ .destination = receiver_id, .channel = 9, .bytes = "second" },
 966     );
 967     _ = try connected.settle(
 968         destination_id,
 969         try completeTurn(second, second_send.delivery),
 970     );
 971     return connected;
 972 }
 973 
 974 fn expectPacketBranches(
 975     connected: fabric.Fabric,
 976     receiver: *const instance.Instance,
 977     fence: os.abi.ActivationFence,
 978 ) !void {
 979     var choose_first = connected;
 980     const first = try choose_first.receivePacket(receiver_id, receiver, fence, 1);
 981     var choose_second = connected;
 982     const second = try choose_second.receivePacket(receiver_id, receiver, fence, 2);
 983     try expectDifferentRoots(first.root, second.root);
 984     try std.testing.expectEqual(@as(u8, 1), choose_first.packetCount());
 985     try std.testing.expectEqual(@as(u8, 1), choose_second.packetCount());
 986     try std.testing.expectError(error.PacketUnknown, choose_first.packet(1));
 987     try std.testing.expectError(error.PacketUnknown, choose_second.packet(2));
 988     try std.testing.expectEqualStrings("second", (try choose_first.packet(2)).bytes());
 989     try std.testing.expectEqualStrings("first", (try choose_second.packet(1)).bytes());
 990 }
 991 
 992 fn twoNodeFabric(
 993     source: *const instance.Instance,
 994     destination: *const instance.Instance,
 995 ) !fabric.Fabric {
 996     const nodes = [_]fabric.Node{
 997         .{ .id = source_id, .basis = try source.admissionBasis() },
 998         .{ .id = destination_id, .basis = try destination.admissionBasis() },
 999     };
1000     return fabric.Fabric.init(.{
1001         .profile = profile.interpretedContinuationTestV1(),
1002         .world = world,
1003         .virtual_time_tick = 7,
1004         .nodes = &nodes,
1005     });
1006 }
1007 
1008 fn exercisePacketReplay(
1009     initial: fabric.Fabric,
1010     source: *instance.Instance,
1011     destination: *instance.Instance,
1012     source_fence: os.abi.ActivationFence,
1013     destination_fence: os.abi.ActivationFence,
1014 ) !void {
1015     try expectPacketPayloadCapacity(initial, source, source_fence);
1016     try expectPacketCapacityFault(initial, source, source_fence);
1017     try expectServiceBranching(initial, source, source_fence);
1018     var connected = initial;
1019     const sent = try connected.sendPacket(
1020         source_id,
1021         source,
1022         source_fence,
1023         .{ .destination = destination_id, .channel = 7, .bytes = "packet" },
1024     );
1025     try expectPendingSafety(
1026         initial,
1027         &connected,
1028         destination,
1029         source_fence,
1030         destination_fence,
1031         sent,
1032     );
1033     var replay = initial;
1034     try std.testing.expectEqualDeep(sent.root, try replay.replay(sent.entry));
1035     const source_settled = try connected.settle(
1036         source_id,
1037         try completeTurn(source, sent.delivery),
1038     );
1039     try std.testing.expectEqualDeep(
1040         source_settled.root,
1041         try replay.replay(source_settled.entry),
1042     );
1043     try std.testing.expect(!connected.turnPending());
1044     try expectReceiptDivergence(initial, sent, source_settled);
1045     const received = try connected.receivePacket(
1046         destination_id,
1047         destination,
1048         destination_fence,
1049         1,
1050     );
1051     try std.testing.expectEqual(@as(u8, 0), connected.packetCount());
1052     try std.testing.expectEqualDeep(received.root, try replay.replay(received.entry));
1053     const destination_settled = try connected.settle(
1054         destination_id,
1055         try completeTurn(destination, received.delivery),
1056     );
1057     try std.testing.expectEqualDeep(
1058         destination_settled.root,
1059         try replay.replay(destination_settled.entry),
1060     );
1061     try std.testing.expectEqualDeep(connected.root(), replay.root());
1062     try expectRootHex(
1063         connected.root(),
1064         "09f26db64cd8b9a5abbf87e264a00e12c8eb35e14172ed9d64e11a3544e22952",
1065     );
1066 }
1067 
1068 fn recordConnectedTransitions(
1069     connected: *fabric.Fabric,
1070     source: *instance.Instance,
1071     destination: *instance.Instance,
1072     source_fence: os.abi.ActivationFence,
1073     destination_fence: os.abi.ActivationFence,
1074 ) !void {
1075     const before_send = connected.*;
1076     const sent = try connected.sendPacket(
1077         source_id,
1078         source,
1079         source_fence,
1080         .{ .destination = destination_id, .channel = 9, .bytes = "durable" },
1081     );
1082     try recordTransition(0, &before_send, sent.entry, sent.root);
1083     const source_receipt = try completeTurn(source, sent.delivery);
1084     const before_source_settle = connected.*;
1085     const source_settled = try connected.settle(source_id, source_receipt);
1086     try recordTransition(
1087         1,
1088         &before_source_settle,
1089         source_settled.entry,
1090         source_settled.root,
1091     );
1092     const before_receive = connected.*;
1093     const received = try connected.receivePacket(
1094         destination_id,
1095         destination,
1096         destination_fence,
1097         1,
1098     );
1099     try recordTransition(2, &before_receive, received.entry, received.root);
1100     const destination_receipt = try completeTurn(destination, received.delivery);
1101     const before_destination_settle = connected.*;
1102     const destination_settled = try connected.settle(
1103         destination_id,
1104         destination_receipt,
1105     );
1106     try recordTransition(
1107         3,
1108         &before_destination_settle,
1109         destination_settled.entry,
1110         destination_settled.root,
1111     );
1112     const before_fault = connected.*;
1113     const faulted = try connected.applyFault(.{
1114         .effect = .{ .clock_jump = 19 },
1115         .choice = .inject,
1116     });
1117     try recordTransition(4, &before_fault, faulted.entry, faulted.root);
1118 }
1119 
1120 fn recordTransition(
1121     index: usize,
1122     before: *const fabric.Fabric,
1123     entry: fabric.Entry,
1124     root: fabric.Root,
1125 ) !void {
1126     std.debug.assert(index < transition_count_max);
1127     const value: fabric.Transition = .{ .entry = entry, .root = root };
1128     var writer = std.Io.Writer.fixed(&transition_streams[index]);
1129     try fabric.transition.encodeDisjoint(before, &value, &writer);
1130     try std.testing.expectEqual(fabric.transition.stream_bytes, writer.end);
1131     transition_roots[index] = root;
1132 }
1133 
1134 fn recordDirectTransitions(
1135     connected: *fabric.Fabric,
1136     machine: *instance.Instance,
1137     initial_fence: os.abi.ActivationFence,
1138 ) !void {
1139     const before_time = connected.*;
1140     const advanced = try connected.advanceTime(
1141         source_id,
1142         machine,
1143         initial_fence,
1144         11,
1145     );
1146     try recordTransition(0, &before_time, advanced.entry, advanced.root);
1147     const time_receipt = try completeTurn(machine, advanced.delivery);
1148     const before_time_settle = connected.*;
1149     const time_settled = try connected.settle(source_id, time_receipt);
1150     try recordTransition(1, &before_time_settle, time_settled.entry, time_settled.root);
1151     const entropy_fence = activationFence(2, 0x94);
1152     try machine.reactivate(entropy_fence);
1153     try activate(machine);
1154     const before_entropy = connected.*;
1155     const entropy = try connected.chooseEntropy(
1156         source_id,
1157         machine,
1158         entropy_fence,
1159         &.{ 1, 2, 3 },
1160         &.{ 4, 5, 6 },
1161         .inject,
1162     );
1163     try recordTransition(2, &before_entropy, entropy.entry, entropy.root);
1164     const entropy_receipt = try completeTurn(machine, entropy.delivery);
1165     const before_entropy_settle = connected.*;
1166     const entropy_settled = try connected.settle(source_id, entropy_receipt);
1167     try recordTransition(
1168         3,
1169         &before_entropy_settle,
1170         entropy_settled.entry,
1171         entropy_settled.root,
1172     );
1173     const terminal_fence = activationFence(3, 0x95);
1174     try machine.reactivate(terminal_fence);
1175     try activate(machine);
1176     const before_terminal = connected.*;
1177     const terminal = try connected.terminal(
1178         source_id,
1179         machine,
1180         terminal_fence,
1181         os.k0.request_bytes,
1182     );
1183     try recordTransition(4, &before_terminal, terminal.entry, terminal.root);
1184     const terminal_receipt = try completeTurn(machine, terminal.delivery);
1185     const before_terminal_settle = connected.*;
1186     const terminal_settled = try connected.settle(source_id, terminal_receipt);
1187     try recordTransition(
1188         5,
1189         &before_terminal_settle,
1190         terminal_settled.entry,
1191         terminal_settled.root,
1192     );
1193 }
1194 
1195 fn expectTransitionReplay(
1196     initial: fabric.Fabric,
1197     final_root: fabric.Root,
1198 ) !void {
1199     try std.testing.expectEqualSlices(u8, &.{
1200         'M', 'C', 'H', 'F', 'T', 'R', '1', 0,
1201         1,   0,   0,   4,   0,   0,   1,   0,
1202         3,   0,   1,   0,   32,  0,   96,  0,
1203         208, 0,   240, 0,   88,  0,   136, 0,
1204         192, 1,
1205     }, transition_streams[0][0..34]);
1206     var snapshot_reader = std.Io.Reader.fixed(
1207         snapshot_stream[0..fabric.snapshot.stream_bytes],
1208     );
1209     const replay = try fabric.snapshot.decodeDisjoint(
1210         &snapshot_reader,
1211         initial.root(),
1212     );
1213     try expectTransitionFrames(
1214         replay,
1215         connected_transition_count,
1216         final_root,
1217     );
1218 }
1219 
1220 fn expectTransitionFrames(
1221     initial: fabric.Fabric,
1222     count: usize,
1223     final_root: fabric.Root,
1224 ) !void {
1225     std.debug.assert(count > 0);
1226     std.debug.assert(count <= transition_count_max);
1227     var replay = initial;
1228     for (0..count) |index| {
1229         const before = replay;
1230         var reader = std.Io.Reader.fixed(&transition_streams[index]);
1231         const value = try fabric.transition.replayDisjoint(
1232             &replay,
1233             &reader,
1234             transition_roots[index],
1235         );
1236         try std.testing.expectEqualDeep(transition_roots[index], value.root);
1237         var repeated: [fabric.transition.stream_bytes]u8 = undefined;
1238         var writer = std.Io.Writer.fixed(&repeated);
1239         try fabric.transition.encodeDisjoint(&before, &value, &writer);
1240         try std.testing.expectEqualSlices(
1241             u8,
1242             &transition_streams[index],
1243             &repeated,
1244         );
1245     }
1246     try std.testing.expectEqualDeep(final_root, replay.root());
1247 }
1248 
1249 fn expectTransitionRejections(initial: fabric.Fabric) !void {
1250     var decoded_owner = initial;
1251     var first_reader = std.Io.Reader.fixed(&transition_streams[0]);
1252     const first = try fabric.transition.replayDisjoint(
1253         &decoded_owner,
1254         &first_reader,
1255         transition_roots[0],
1256     );
1257     var short_output: [fabric.transition.stream_bytes - 1]u8 = undefined;
1258     var short_writer = std.Io.Writer.fixed(&short_output);
1259     try std.testing.expectError(
1260         error.WriteFailed,
1261         fabric.transition.encodeDisjoint(&initial, &first, &short_writer),
1262     );
1263     var wrong = first;
1264     wrong.root = transition_roots[1];
1265     var output: [fabric.transition.stream_bytes]u8 = undefined;
1266     var wrong_writer = std.Io.Writer.fixed(&output);
1267     try std.testing.expectError(
1268         error.TransitionMismatch,
1269         fabric.transition.encodeDisjoint(&initial, &wrong, &wrong_writer),
1270     );
1271     try expectTransitionAliases(initial, first);
1272     try expectTransitionFraming(initial);
1273     try expectEveryTransitionByteBound(initial);
1274 }
1275 
1276 fn expectFaultTransitionVariants(initial: fabric.Fabric) !void {
1277     try expectFaultTransitionRoundTrip(initial, .{
1278         .machine_crash = source_id,
1279     });
1280     try expectFaultTransitionRoundTrip(initial, .{ .process_crash = .{
1281         .node = source_id,
1282         .process = 7,
1283     } });
1284     try expectFaultTransitionRoundTrip(initial, .{ .partition = .{
1285         .first = source_id,
1286         .second = destination_id,
1287         .active = true,
1288     } });
1289     try expectFaultTransitionRoundTrip(initial, .{ .capacity_exhaustion = .{
1290         .resource = .packet,
1291         .active = true,
1292     } });
1293     var packet_ready = initial;
1294     for (0..2) |index| {
1295         var reader = std.Io.Reader.fixed(&transition_streams[index]);
1296         _ = try fabric.transition.replayDisjoint(
1297             &packet_ready,
1298             &reader,
1299             transition_roots[index],
1300         );
1301     }
1302     try expectFaultTransitionRoundTrip(packet_ready, .{ .packet_loss = 1 });
1303     try expectFaultTransitionRoundTrip(packet_ready, .{ .packet_delay = .{
1304         .packet = 1,
1305         .until_tick = 23,
1306     } });
1307 }
1308 
1309 fn expectFaultTransitionRoundTrip(
1310     initial: fabric.Fabric,
1311     effect: fabric.FaultEffect,
1312 ) !void {
1313     var connected = initial;
1314     const faulted = try connected.applyFault(.{
1315         .effect = effect,
1316         .choice = .bypass,
1317     });
1318     const value: fabric.Transition = .{
1319         .entry = faulted.entry,
1320         .root = faulted.root,
1321     };
1322     var bytes: [fabric.transition.stream_bytes]u8 = undefined;
1323     var writer = std.Io.Writer.fixed(&bytes);
1324     try fabric.transition.encodeDisjoint(&initial, &value, &writer);
1325     var replay = initial;
1326     var reader = std.Io.Reader.fixed(&bytes);
1327     const reopened = try fabric.transition.replayDisjoint(
1328         &replay,
1329         &reader,
1330         faulted.root,
1331     );
1332     try std.testing.expectEqualDeep(value, reopened);
1333     try std.testing.expectEqualDeep(connected, replay);
1334 }
1335 
1336 fn expectTransitionAliases(
1337     initial: fabric.Fabric,
1338     value: fabric.Transition,
1339 ) !void {
1340     var aliased_fabric = initial;
1341     var fabric_writer = std.Io.Writer.fixed(std.mem.asBytes(&aliased_fabric));
1342     try std.testing.expectError(
1343         error.SinkAliasesFabric,
1344         fabric.transition.encodeDisjoint(&aliased_fabric, &value, &fabric_writer),
1345     );
1346     var aliased_transition = value;
1347     var transition_writer = std.Io.Writer.fixed(std.mem.asBytes(&aliased_transition));
1348     try std.testing.expectError(
1349         error.SinkAliasesTransition,
1350         fabric.transition.encodeDisjoint(
1351             &initial,
1352             &aliased_transition,
1353             &transition_writer,
1354         ),
1355     );
1356     var source_alias = initial;
1357     var reader = std.Io.Reader.fixed(std.mem.asBytes(&source_alias));
1358     try std.testing.expectError(
1359         error.SourceAliasesFabric,
1360         fabric.transition.replayDisjoint(
1361             &source_alias,
1362             &reader,
1363             transition_roots[0],
1364         ),
1365     );
1366     try std.testing.expectEqualDeep(initial, source_alias);
1367 }
1368 
1369 fn expectTransitionFraming(initial: fabric.Fabric) !void {
1370     try expectTransitionReplayFailure(
1371         error.TruncatedStream,
1372         initial,
1373         transition_streams[0][0 .. fabric.transition.stream_bytes - 1],
1374         transition_roots[0],
1375     );
1376     var trailing: [fabric.transition.stream_bytes + 1]u8 = undefined;
1377     @memcpy(trailing[0..fabric.transition.stream_bytes], &transition_streams[0]);
1378     trailing[fabric.transition.stream_bytes] = 0xa5;
1379     try expectTransitionReplayFailure(
1380         error.TrailingData,
1381         initial,
1382         &trailing,
1383         transition_roots[0],
1384     );
1385     try expectTransitionReplayFailure(
1386         error.ResultRootMismatch,
1387         initial,
1388         &transition_streams[0],
1389         transition_roots[1],
1390     );
1391     try expectTransitionReplayFailure(
1392         error.PreviousRootMismatch,
1393         initial,
1394         &transition_streams[1],
1395         transition_roots[1],
1396     );
1397 }
1398 
1399 fn expectEveryTransitionByteBound(initial: fabric.Fabric) !void {
1400     var basis = initial;
1401     for (0..connected_transition_count) |index| {
1402         try expectEveryTransitionFrameByteBound(basis, index);
1403         var reader = std.Io.Reader.fixed(&transition_streams[index]);
1404         _ = try fabric.transition.replayDisjoint(
1405             &basis,
1406             &reader,
1407             transition_roots[index],
1408         );
1409     }
1410 }
1411 
1412 fn expectEveryTransitionFrameByteBound(
1413     initial: fabric.Fabric,
1414     index: usize,
1415 ) !void {
1416     std.debug.assert(index < connected_transition_count);
1417     for (0..fabric.transition.stream_bytes) |offset| {
1418         transition_streams[index][offset] ^= 1;
1419         var replay = initial;
1420         var reader = std.Io.Reader.fixed(&transition_streams[index]);
1421         if (fabric.transition.replayDisjoint(
1422             &replay,
1423             &reader,
1424             transition_roots[index],
1425         )) |_| {
1426             transition_streams[index][offset] ^= 1;
1427             return error.TestAcceptedTransitionMutation;
1428         } else |_| {}
1429         try std.testing.expectEqualDeep(initial, replay);
1430         transition_streams[index][offset] ^= 1;
1431     }
1432 }
1433 
1434 fn expectTransitionReplayFailure(
1435     expected: anyerror,
1436     initial: fabric.Fabric,
1437     bytes: []const u8,
1438     root: fabric.Root,
1439 ) !void {
1440     var replay = initial;
1441     var reader = std.Io.Reader.fixed(bytes);
1442     try std.testing.expectError(
1443         expected,
1444         fabric.transition.replayDisjoint(&replay, &reader, root),
1445     );
1446     try std.testing.expectEqualDeep(initial, replay);
1447 }
1448 
1449 fn expectPacketPayloadCapacity(
1450     initial: fabric.Fabric,
1451     source: *const instance.Instance,
1452     fence: os.abi.ActivationFence,
1453 ) !void {
1454     const full_payload: [fabric.packet_bytes_max]u8 = @splat(0x5a);
1455     var full = initial;
1456     _ = try full.sendPacket(
1457         source_id,
1458         source,
1459         fence,
1460         .{ .destination = destination_id, .channel = 1, .bytes = &full_payload },
1461     );
1462     const oversized_payload: [fabric.packet_bytes_max + 1]u8 = @splat(0x5a);
1463     var oversized = initial;
1464     try std.testing.expectError(
1465         error.PayloadCapacityExceeded,
1466         oversized.sendPacket(
1467             source_id,
1468             source,
1469             fence,
1470             .{
1471                 .destination = destination_id,
1472                 .channel = 1,
1473                 .bytes = &oversized_payload,
1474             },
1475         ),
1476     );
1477 }
1478 
1479 fn expectPacketCapacityFault(
1480     initial: fabric.Fabric,
1481     source: *const instance.Instance,
1482     fence: os.abi.ActivationFence,
1483 ) !void {
1484     const effect: fabric.FaultEffect = .{ .capacity_exhaustion = .{
1485         .resource = .packet,
1486         .active = true,
1487     } };
1488     var bypass_branch = initial;
1489     const bypassed = try bypass_branch.applyFault(.{
1490         .effect = effect,
1491         .choice = .bypass,
1492     });
1493     var inject_branch = initial;
1494     const injected = try inject_branch.applyFault(.{
1495         .effect = effect,
1496         .choice = .inject,
1497     });
1498     try std.testing.expectEqualDeep(
1499         bypassed.decision.point,
1500         injected.decision.point,
1501     );
1502     _ = try bypass_branch.sendPacket(
1503         source_id,
1504         source,
1505         fence,
1506         .{ .destination = destination_id, .channel = 1, .bytes = "allowed" },
1507     );
1508     try std.testing.expectError(
1509         error.PacketCapacityExceeded,
1510         inject_branch.sendPacket(
1511             source_id,
1512             source,
1513             fence,
1514             .{ .destination = destination_id, .channel = 1, .bytes = "blocked" },
1515         ),
1516     );
1517 }
1518 
1519 fn expectServiceBranching(
1520     initial: fabric.Fabric,
1521     source: *const instance.Instance,
1522     fence: os.abi.ActivationFence,
1523 ) !void {
1524     var service_ok = initial;
1525     const modeled_ok = try service_ok.settleService(
1526         source_id,
1527         source,
1528         fence,
1529         .{ .status = .ok, .output_root = @splat(0x91), .bytes = "modeled" },
1530     );
1531     var service_failed = initial;
1532     const modeled_failed = try service_failed.settleService(
1533         source_id,
1534         source,
1535         fence,
1536         .{ .status = .unavailable, .output_root = @splat(0x91), .bytes = "modeled" },
1537     );
1538     try expectDifferentRoots(modeled_ok.root, modeled_failed.root);
1539 }
1540 
1541 fn expectPendingSafety(
1542     initial: fabric.Fabric,
1543     connected: *fabric.Fabric,
1544     destination: *const instance.Instance,
1545     source_fence: os.abi.ActivationFence,
1546     destination_fence: os.abi.ActivationFence,
1547     sent: fabric.Admitted,
1548 ) !void {
1549     try std.testing.expect(connected.turnPending());
1550     try std.testing.expectEqual(@as(u8, 1), connected.packetCount());
1551     try std.testing.expectEqualStrings("packet", (try connected.packet(1)).bytes());
1552     try std.testing.expectError(
1553         error.TurnPending,
1554         connected.receivePacket(destination_id, destination, destination_fence, 1),
1555     );
1556     var stale = initial;
1557     try std.testing.expectError(
1558         error.MachineBasisMismatch,
1559         stale.settleService(
1560             source_id,
1561             destination,
1562             destination_fence,
1563             .{ .status = .ok, .output_root = @splat(0x92), .bytes = "wrong" },
1564         ),
1565     );
1566     try expectInvalidReplays(initial, sent);
1567     try expectFenceRebinding(connected, source_fence, sent);
1568 }
1569 
1570 fn expectInvalidReplays(initial: fabric.Fabric, sent: fabric.Admitted) !void {
1571     var changed_payload = sent.entry;
1572     changed_payload.value.admission.effect.packet_send.storage[0] ^= 1;
1573     var invalid_replay = initial;
1574     const invalid_root = invalid_replay.root();
1575     try std.testing.expectError(error.InvalidPacket, invalid_replay.replay(changed_payload));
1576     try std.testing.expectEqualDeep(invalid_root, invalid_replay.root());
1577     var changed_sequence = sent.entry;
1578     changed_sequence.sequence += 1;
1579     try std.testing.expectError(
1580         error.EntrySequenceMismatch,
1581         invalid_replay.replay(changed_sequence),
1582     );
1583     try std.testing.expectEqualDeep(invalid_root, invalid_replay.root());
1584 }
1585 
1586 fn expectFenceRebinding(
1587     connected: *const fabric.Fabric,
1588     source_fence: os.abi.ActivationFence,
1589     sent: fabric.Admitted,
1590 ) !void {
1591     var rotated_fence = source_fence;
1592     rotated_fence.generation += 1;
1593     rotated_fence.token = @splat(0x52);
1594     const rebound = try connected.pendingDelivery(source_id, rotated_fence);
1595     try std.testing.expectEqualDeep(sent.delivery.admission, rebound.admission);
1596     try std.testing.expectEqualSlices(
1597         u8,
1598         &sent.delivery.next_source_root,
1599         &rebound.next_source_root,
1600     );
1601     try std.testing.expect(!std.meta.eql(sent.delivery.receipt, rebound.receipt));
1602     try std.testing.expectEqualDeep(sent.root, connected.root());
1603 }
1604 
1605 fn expectReceiptDivergence(
1606     initial: fabric.Fabric,
1607     sent: fabric.Admitted,
1608     settled: fabric.Settled,
1609 ) !void {
1610     var changed = settled.entry;
1611     changed.value.settlement.receipt.semantic_transcript_digest[0] ^= 1;
1612     var replay = initial;
1613     _ = try replay.replay(sent.entry);
1614     try expectDifferentRoots(settled.root, try replay.replay(changed));
1615 }
1616 
1617 fn snapshotFixture(
1618     first: *instance.Instance,
1619     second: *instance.Instance,
1620     receiver: *const instance.Instance,
1621     first_fence: os.abi.ActivationFence,
1622     second_fence: os.abi.ActivationFence,
1623 ) !fabric.Fabric {
1624     var connected = try readyPackets(
1625         first,
1626         second,
1627         receiver,
1628         first_fence,
1629         second_fence,
1630     );
1631     _ = try connected.applyFault(.{
1632         .effect = .{ .packet_delay = .{ .packet = 1, .until_tick = 12 } },
1633         .choice = .inject,
1634     });
1635     _ = try connected.applyFault(.{
1636         .effect = .{ .partition = .{
1637             .first = source_id,
1638             .second = receiver_id,
1639             .active = true,
1640         } },
1641         .choice = .inject,
1642     });
1643     _ = try connected.applyFault(.{
1644         .effect = .{ .capacity_exhaustion = .{
1645             .resource = .packet,
1646             .active = true,
1647         } },
1648         .choice = .inject,
1649     });
1650     _ = try connected.applyFault(.{
1651         .effect = .{ .machine_crash = destination_id },
1652         .choice = .inject,
1653     });
1654     return connected;
1655 }
1656 
1657 fn expectSnapshotRoundTrip(connected: fabric.Fabric) !void {
1658     try encodeSnapshot(&connected);
1659     try std.testing.expectEqualSlices(u8, &.{
1660         'M', 'C', 'H', 'F', 'A', 'B', '1', 0,
1661         1,   0,   0,   32,  0,   0,   1,   0,
1662         3,   0,   4,   0,   15,  0,   208, 0,
1663         0,   1,   120, 0,   32,  0,   96,  0,
1664         160, 0,
1665     }, snapshot_stream[0..34]);
1666     var reader = std.Io.Reader.fixed(
1667         snapshot_stream[0..fabric.snapshot.stream_bytes],
1668     );
1669     const reopened = try fabric.snapshot.decodeDisjoint(
1670         &reader,
1671         connected.root(),
1672     );
1673     try std.testing.expectEqualDeep(try connected.cut(), try reopened.cut());
1674     try std.testing.expectEqualStrings("first", (try reopened.packet(1)).bytes());
1675     try std.testing.expectEqualStrings("second", (try reopened.packet(2)).bytes());
1676     try std.testing.expect(try reopened.partitioned(source_id, receiver_id));
1677     try std.testing.expect(!try reopened.nodeAvailable(destination_id));
1678     var repeated: [fabric.snapshot.stream_bytes]u8 = undefined;
1679     var writer = std.Io.Writer.fixed(&repeated);
1680     try fabric.snapshot.encodeDisjoint(&reopened, &writer);
1681     try std.testing.expectEqual(fabric.snapshot.stream_bytes, writer.end);
1682     try std.testing.expectEqualSlices(
1683         u8,
1684         snapshot_stream[0..fabric.snapshot.stream_bytes],
1685         &repeated,
1686     );
1687 }
1688 
1689 fn expectSnapshotRejections(
1690     initial: fabric.Fabric,
1691     machine: *const instance.Instance,
1692     fence: os.abi.ActivationFence,
1693 ) !void {
1694     try encodeSnapshot(&initial);
1695     var short_writer = std.Io.Writer.fixed(
1696         snapshot_stream[0 .. fabric.snapshot.stream_bytes - 1],
1697     );
1698     try std.testing.expectError(
1699         error.WriteFailed,
1700         fabric.snapshot.encodeDisjoint(&initial, &short_writer),
1701     );
1702     try expectSnapshotDecodeFailure(
1703         error.TruncatedStream,
1704         snapshot_stream[0 .. fabric.snapshot.stream_bytes - 1],
1705         initial.root(),
1706     );
1707     snapshot_stream[fabric.snapshot.stream_bytes] = 0xa5;
1708     try expectSnapshotDecodeFailure(error.TrailingData, &snapshot_stream, initial.root());
1709     try expectSnapshotMutations(initial.root());
1710     try expectEverySnapshotByteBound(initial.root());
1711     var wrong_root = initial.root();
1712     wrong_root.digest[0] ^= 1;
1713     try expectSnapshotDecodeFailure(
1714         error.FabricRootMismatch,
1715         snapshot_stream[0..fabric.snapshot.stream_bytes],
1716         wrong_root,
1717     );
1718     var pending = initial;
1719     _ = try pending.sendPacket(
1720         source_id,
1721         machine,
1722         fence,
1723         .{ .destination = destination_id, .channel = 1, .bytes = "pending" },
1724     );
1725     var pending_writer = std.Io.Writer.fixed(
1726         snapshot_stream[0..fabric.snapshot.stream_bytes],
1727     );
1728     try std.testing.expectError(
1729         error.TurnPending,
1730         fabric.snapshot.encodeDisjoint(&pending, &pending_writer),
1731     );
1732     try std.testing.expectEqual(@as(usize, 0), pending_writer.end);
1733     var aliased = initial;
1734     var alias_writer = std.Io.Writer.fixed(std.mem.asBytes(&aliased));
1735     try std.testing.expectError(
1736         error.SinkAliasesFabric,
1737         fabric.snapshot.encodeDisjoint(&aliased, &alias_writer),
1738     );
1739 }
1740 
1741 fn expectSnapshotMutations(expected_root: fabric.Root) !void {
1742     const mutations = [_]SnapshotMutation{
1743         .{ .offset = 0, .mask = 1, .expected = error.BadMagic },
1744         .{ .offset = 8, .mask = 1, .expected = error.UnsupportedVersion },
1745         .{ .offset = 10, .mask = 1, .expected = error.StreamBytesMismatch },
1746         .{ .offset = 12, .mask = 1, .expected = error.UnsupportedFlags },
1747         .{ .offset = 14, .mask = 1, .expected = error.SnapshotFormatMismatch },
1748         .{ .offset = 16, .mask = 1, .expected = error.UnknownSnapshotField },
1749         .{ .offset = 18, .mask = 1, .expected = error.MetadataShapeMismatch },
1750         .{ .offset = 34, .mask = 1, .expected = error.ReservedNonzero },
1751         .{ .offset = 154, .mask = 1, .expected = error.ReservedNonzero },
1752         .{ .offset = 180, .mask = 1, .expected = error.ReservedNonzero },
1753         .{ .offset = 440, .mask = 3, .expected = error.NonCanonicalBoolean },
1754         .{ .offset = 488, .mask = 0xff, .expected = error.UnknownSnapshotField },
1755         .{ .offset = 736, .mask = 1, .expected = error.ReservedNonzero },
1756         .{ .offset = 1152, .mask = 1, .expected = error.ReservedNonzero },
1757         .{ .offset = 4992, .mask = 1, .expected = error.ReservedNonzero },
1758         .{ .offset = 160, .mask = 1, .expected = error.RootMismatch },
1759     };
1760     for (mutations) |mutation| {
1761         snapshot_stream[mutation.offset] ^= mutation.mask;
1762         try expectSnapshotDecodeFailure(
1763             mutation.expected,
1764             snapshot_stream[0..fabric.snapshot.stream_bytes],
1765             expected_root,
1766         );
1767         snapshot_stream[mutation.offset] ^= mutation.mask;
1768     }
1769 }
1770 
1771 fn expectEverySnapshotByteBound(expected_root: fabric.Root) !void {
1772     for (0..fabric.snapshot.stream_bytes) |offset| {
1773         snapshot_stream[offset] ^= 1;
1774         var reader = std.Io.Reader.fixed(
1775             snapshot_stream[0..fabric.snapshot.stream_bytes],
1776         );
1777         if (fabric.snapshot.decodeDisjoint(&reader, expected_root)) |_| {
1778             snapshot_stream[offset] ^= 1;
1779             return error.TestAcceptedSnapshotMutation;
1780         } else |_| {}
1781         snapshot_stream[offset] ^= 1;
1782     }
1783 }
1784 
1785 fn encodeSnapshot(value: *const fabric.Fabric) !void {
1786     var writer = std.Io.Writer.fixed(
1787         snapshot_stream[0..fabric.snapshot.stream_bytes],
1788     );
1789     try fabric.snapshot.encodeDisjoint(value, &writer);
1790     try std.testing.expectEqual(fabric.snapshot.stream_bytes, writer.end);
1791 }
1792 
1793 fn expectSnapshotDecodeFailure(
1794     expected: anyerror,
1795     bytes: []const u8,
1796     root: fabric.Root,
1797 ) !void {
1798     var reader = std.Io.Reader.fixed(bytes);
1799     try std.testing.expectError(
1800         expected,
1801         fabric.snapshot.decodeDisjoint(&reader, root),
1802     );
1803 }
1804 
1805 fn start(
1806     storage: *instance.Storage,
1807     ram: []align(instance.ram_alignment) u8,
1808     input: instance.Input,
1809 ) !instance.Instance {
1810     var machine = switch (instance.Instance.init(storage, ram, input)) {
1811         .ready => |value| value,
1812         .unavailable => return error.UnexpectedBackendUnavailable,
1813         .rejected => |failure| return failure,
1814     };
1815     try activate(&machine);
1816     return machine;
1817 }
1818 
1819 fn activate(machine: *instance.Instance) !void {
1820     try std.testing.expectEqualDeep(
1821         instance.Exit{ .doorbell = .{ .code = .ready } },
1822         try machine.run(),
1823     );
1824     var events: instance.EventBatch = undefined;
1825     try machine.takeEvents(&events);
1826     try std.testing.expectEqual(instance.RunPhase.awaiting_input, machine.phase());
1827 }
1828 
1829 fn completeTurn(
1830     machine: *instance.Instance,
1831     delivery: admission.Delivery,
1832 ) !instance.QuiescenceReceipt {
1833     try machine.deliverAdmitted(&delivery);
1834     try std.testing.expectEqualDeep(
1835         instance.Exit{ .doorbell = .{ .code = .quiescent } },
1836         try machine.run(),
1837     );
1838     var events: instance.EventBatch = undefined;
1839     try machine.takeEvents(&events);
1840     try machine.acknowledge(delivery.receipt);
1841     return machine.quiescenceReceipt();
1842 }
1843 
1844 fn machineInput(
1845     execution: os.boot.kernel.manifest.View,
1846     fence: os.abi.ActivationFence,
1847     root_byte: u8,
1848     outstanding_effect: ?admission.EffectRequest,
1849 ) instance.Input {
1850     return .{
1851         .profile = profile.interpretedContinuationTestV1(),
1852         .elf = k0_elf,
1853         .execution_manifest = k0_manifest,
1854         .expected_execution_fingerprint = execution.header.fingerprint,
1855         .fence = fence,
1856         .initial_time_tick = 7,
1857         .entropy_generation = 1,
1858         .terminal_offset = 0,
1859         .effect_frontier = 0,
1860         .block_root = @splat(root_byte),
1861         .source_root = @splat(root_byte + 1),
1862         .input_frontier = 0,
1863         .terminal_input_offset = 0,
1864         .outstanding_effect = outstanding_effect,
1865     };
1866 }
1867 
1868 fn activationFence(generation: u64, token: u8) os.abi.ActivationFence {
1869     return .{ .world = world, .generation = generation, .token = @splat(token) };
1870 }
1871 
1872 fn effectRequest(byte: u8) admission.EffectRequest {
1873     return .{
1874         .receipt = .{ .digest = @splat(byte) },
1875         .correlation = 1,
1876     };
1877 }
1878 
1879 fn expectInitError(
1880     expected: fabric.Error,
1881     selected_world: [16]u8,
1882     tick: u64,
1883     nodes: []const fabric.Node,
1884 ) !void {
1885     try std.testing.expectError(expected, fabric.Fabric.init(.{
1886         .profile = profile.interpretedContinuationTestV1(),
1887         .world = selected_world,
1888         .virtual_time_tick = tick,
1889         .nodes = nodes,
1890     }));
1891 }
1892 
1893 fn expectDifferentRoots(left: fabric.Root, right: fabric.Root) !void {
1894     try std.testing.expect(!std.mem.eql(u8, &left.digest, &right.digest));
1895 }
1896 
1897 fn expectRootHex(root: fabric.Root, expected: []const u8) !void {
1898     const actual = std.fmt.bytesToHex(root.digest, .lower);
1899     try std.testing.expectEqualStrings(expected, &actual);
1900 }