public void TestFalseOwnership() { // This test tries to make sure a RWList doesn't get confused about what // blocks it owns. It's possible for a RWList to share a partially-mutable // block that contains mutable items with another RWList, but only one // RWList owns the items. // Case 1: two WLists point to the same block but only one owns it: // // block 0 // owned by A // |____3| block 1 // |____2| unowned // A,B--->|Imm_1|--->|Imm_1| // |____0| |____0| // // (The location of "Imm" in each block denotes the highest immutable // item; this diagram shows there are two immutable items in each // block) RWList <int> A = new RWList <int>(); A.Resize(4); for (int i = 0; i < 4; i++) { A[i] = i; } RWList <int> B = A.Clone(); // B can't add to the second block because it's not the owner, so a // third block is created when we Add(1). B.Add(4); A.Add(-4); ExpectList(A, 0, 1, 2, 3, -4); ExpectList(B, 0, 1, 2, 3, 4); Assert.AreEqual(2, A.BlockChainLength); Assert.AreEqual(3, B.BlockChainLength); // Case 2: two WLists point to different blocks but they share a common // tail, where one list owns part of the tail and the other does not: // // block 0 // owned by B // |____8| // |____7| // |____6| // |____5| block 1 // |____4| owned by A // |____3| A |____3| block 2 // |____2| | |____2| unowned // |____1|---+---->|Imm_1|---->|Imm_1| // B--->|____0| |____0| |____0| // mutable // // Actually the previous test puts us in just this state. // // I can't think of a test that uses the public interface to detect bugs // in this case. The most important thing is that B._block.PriorIsOwned // returns false. Assert.That(B.IsOwner && !B.Block.PriorIsOwned); Assert.That(A.IsOwner); Assert.That(B.Block.Prior.ToRVList() == A.WithoutLast(1)); }