dcapwell commented on code in PR #65:
URL: https://github.com/apache/cassandra-accord/pull/65#discussion_r1309191845


##########
accord-core/src/test/java/accord/topology/TopologyManagerTest.java:
##########
@@ -277,4 +304,280 @@ void truncateTopologyCantTruncateUnsyncedEpochs()
     {
 
     }
+
+    @Test
+    void removeRanges()
+    {
+        qt().withExamples(100).check(rs -> {
+            long epochCounter = rs.nextInt(1, 42);
+            boolean withUnchange = rs.nextBoolean();
+            List<Topology> topologies = new ArrayList<>(withUnchange ? 3 : 2);
+            topologies.add(topology(epochCounter++,
+                                    shard(PrefixedIntHashKey.range(0, 0, 100), 
idList(1, 2, 3), idSet(1, 2)),
+                                    shard(PrefixedIntHashKey.range(1, 0, 100), 
idList(1, 2, 3), idSet(1, 2))));
+            if (withUnchange)
+                topologies.add(topology(epochCounter++,
+                                        shard(PrefixedIntHashKey.range(0, 0, 
100), idList(1, 2, 3), idSet(1, 2)),
+                                        shard(PrefixedIntHashKey.range(1, 0, 
100), idList(1, 2, 3), idSet(1, 2))));
+            topologies.add(topology(epochCounter++,
+                                    shard(PrefixedIntHashKey.range(1, 0, 100), 
idList(1, 2, 3), idSet(1, 2))));;
+            History history = new History(new TopologyManager(SUPPLIER, ID), 
topologies.iterator()) {
+
+                @Override
+                protected void postTopologyUpdate(int id, Topology t)
+                {
+                    test(t);
+                }
+
+                @Override
+                protected void postEpochSyncComplete(int id, long epoch, 
Node.Id node)
+                {
+                    test(tm.globalForEpoch(epoch));
+                }
+
+                private void test(Topology topology)
+                {
+                    Ranges ranges = topology.ranges();
+                    for (int i = 0; i < 10; i++)
+                    {
+                        Unseekables<?> unseekables = 
TopologyUtils.select(ranges, rs);
+                        long maxEpoch = topology.epoch();
+                        long minEpoch = tm.minEpoch() == maxEpoch ? maxEpoch : 
rs.nextLong(tm.minEpoch(), maxEpoch + 1);
+                        assertThat(tm.preciseEpochs(unseekables, minEpoch, 
maxEpoch))
+                                .isNotEmpty()
+                                .epochsBetween(minEpoch, maxEpoch)
+                                .containsAll(unseekables)
+                                .topology(maxEpoch, a -> a.isNotEmpty());
+
+                        assertThat(tm.withUnsyncedEpochs(unseekables, 
minEpoch, maxEpoch))
+                                .isNotEmpty()
+                                .epochsBetween(minEpoch, maxEpoch, false) // 
older epochs are allowed
+                                .containsAll(unseekables)
+                                .topology(maxEpoch, a -> a.isNotEmpty());
+                    }
+                }
+            };
+            history.run(rs);
+        });
+    }
+
+    /**
+     * The ABA problem is a problem with registers where you set the value A, 
then B, then A again; when you observe you see A... which A?
+     */
+    @Test
+    void aba()
+    {
+        TopologyManager service = new TopologyManager(SUPPLIER, ID);
+        List<Node.Id> dc1Nodes = idList(1, 2, 3);
+        Set<Node.Id> dc1Fp = idSet(1, 2);
+        List<Node.Id> dc2Nodes = idList(4, 5, 6);
+        Set<Node.Id> dc2Fp = idSet(4, 5);
+        addAndMarkSynced(service, topology(1,
+                shard(PrefixedIntHashKey.range(0, 0, 100), dc2Nodes, dc2Fp),
+                shard(PrefixedIntHashKey.range(1, 0, 100), dc1Nodes, dc1Fp)));
+        addAndMarkSynced(service, topology(2,
+                shard(PrefixedIntHashKey.range(1, 0, 100), dc1Nodes, dc1Fp)));
+        addAndMarkSynced(service, topology(3,
+                shard(PrefixedIntHashKey.range(0, 0, 100), dc2Nodes, dc2Fp),
+                shard(PrefixedIntHashKey.range(1, 0, 100), dc1Nodes, dc1Fp)));
+
+        // prefix=0 was added in epoch=1, removed in epoch=2, and added back 
to epoch=3; the ABA problem
+        RoutingKeys unseekables = RoutingKeys.of(PrefixedIntHashKey.forHash(0, 
42));
+
+        for (Supplier<Topologies> fn : Arrays.<Supplier<Topologies>>asList(() 
-> service.preciseEpochs(unseekables, 1, 3),
+                                                                           () 
-> service.withUnsyncedEpochs(unseekables, 1, 3)))
+        {
+            assertThat(fn.get())
+                    .isNotEmpty()
+                    .epochsBetween(1, 3)
+                    .containsAll(unseekables)
+                    .topology(1, a -> a.isEmpty())
+                    .topology(2, a -> a.isEmpty())
+                    .topology(3, a -> a.isNotEmpty()
+                                       
.isRangesEqualTo(PrefixedIntHashKey.range(0, 0, 100))
+                                       .isHostsEqualTo(dc2Nodes));
+        }
+    }
+
+    @Test
+    void fuzz()

Review Comment:
   this test was very useful to make sure the different mutations work with 
add/remove prefix.  I believe I got some of the fixes into earlier commits [1] 
so you don't see them there... this test is old for me...  I found that it was 
far faster to hit issues here than in `BurnTest`
   
   
   [1]
   
   ```
   commit 7c15f3a6203939bc6cb398e538df1ca3557cbe03
   Author: Benedict Elliott Smith <[email protected]>
   Date:   Tue Aug 15 16:51:22 2023 +0100
   
       State Eviction (#50)
   
       Permit the state machine to erase transactions that are known to be 
applied across the cluster.
   ```



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to