| 110 | /// Ops routed to shard 1 appear only in shard 1's log. |
| 111 | #[test] |
| 112 | fn per_shard_logs_are_isolated() { |
| 113 | let log0 = InMemoryOpLog::new(); |
| 114 | let log1 = InMemoryOpLog::new(); |
| 115 | |
| 116 | // Route ops to the correct shard log. |
| 117 | let op_tile0 = put_op("arr", 5, 100); // tile 0 → shard 0 |
| 118 | let op_tile1 = put_op("arr", 15, 200); // tile 1 → shard 1 |
| 119 | |
| 120 | let s_op0 = shard_id(5, 10, 2); |
| 121 | let s_op1 = shard_id(15, 10, 2); |
| 122 | assert_ne!(s_op0, s_op1, "must route to different shards"); |
| 123 | |
| 124 | if s_op0 == 0 { |
| 125 | log0.append(&op_tile0).expect("append to shard0"); |
| 126 | log1.append(&op_tile1).expect("append to shard1"); |
| 127 | } else { |
| 128 | log1.append(&op_tile0).expect("append to shard1"); |
| 129 | log0.append(&op_tile1).expect("append to shard0"); |
| 130 | } |
| 131 | |
| 132 | assert_eq!(log0.len().expect("len"), 1, "shard0 must have exactly 1 op"); |
| 133 | assert_eq!(log1.len().expect("len"), 1, "shard1 must have exactly 1 op"); |
| 134 | |
| 135 | // Verify shard0 does NOT contain shard1's op. |
| 136 | let shard0_ops: Vec<_> = log0 |
| 137 | .scan_from(Hlc::ZERO) |
| 138 | .expect("scan") |
| 139 | .collect::<Result<_, _>>() |
| 140 | .expect("collect"); |
| 141 | let shard1_ops: Vec<_> = log1 |
| 142 | .scan_from(Hlc::ZERO) |
| 143 | .expect("scan") |
| 144 | .collect::<Result<_, _>>() |
| 145 | .expect("collect"); |
| 146 | |
| 147 | // The op in shard0 must not have the same coord as the one in shard1. |
| 148 | let coord0 = match shard0_ops[0].coord.first() { |
| 149 | Some(CoordValue::Int64(x)) => *x, |
| 150 | _ => panic!("unexpected coord type"), |
| 151 | }; |
| 152 | let coord1 = match shard1_ops[0].coord.first() { |
| 153 | Some(CoordValue::Int64(x)) => *x, |
| 154 | _ => panic!("unexpected coord type"), |
| 155 | }; |
| 156 | assert_ne!(coord0, coord1, "shards must hold different coords"); |
| 157 | } |
| 158 | |
| 159 | // ── Cross-shard GC independence ─────────────────────────────────────────────── |
| 160 | |