public void TestFork() { FWList <int> A = new FWList <int>(); A.AddRange(new int[] { 5, 6, 7 }); FWList <int> B = A.Clone(); A.Push(4); ExpectList(B, 5, 6, 7); ExpectList(A, 4, 5, 6, 7); B.Push(-4); ExpectList(B, -4, 5, 6, 7); Assert.That(A.WithoutFirst(2) == B.WithoutFirst(2)); }
public void TestFalseOwnership() { // This test tries to make sure a FWList doesn't get confused about what // blocks it owns. It's possible for a FWList to share a partially-mutable // block that contains mutable items with another FWList, but only one // FWList 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) FWList <int> A = new FWList <int>(4); for (int i = 0; i < 4; i++) { A[i] = i; } FWList <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(1); A.Add(-1); ExpectList(A, -1, 0, 1, 2, 3); ExpectList(B, 1, 0, 1, 2, 3); 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 == A.WithoutFirst(1)); }