Ejemplo n.º 1
0
Archivo: VList.cs Proyecto: murven/Loyc
        public void TestSublistProblem()
        {
            // This problem affects FVList.PreviousIn(), VList.NextIn(),
            // AddRange(list, excludeSubList), VList.Enumerator when used with a
            // range.

            // Normally this works fine:
            VList <int> subList = new VList <int>(), list;

            subList.AddRange(new int[] { 1, 2, 3, 4, 5, 6, 7 });
            list = subList;
            list.Add(8);
            Assert.That(subList.NextIn(list).Last == 8);

            // But try it a second time and the problem arises, without some special
            // code in VListBlock<T>.FindNextBlock() that has been added to
            // compensate. I call the problem copy-causing-sharing-failure. You see,
            // right now subList is formed from three blocks: a size-8 block that
            // contains {7}, a size-4 block {3, 4, 5, 6} and a size-2 block {1, 2}.
            // But the size-8 block actually has two items {7, 8} and when we
            // attempt to add 9, a new array must be created. It might waste a lot
            // of memory to make a new block {9} that links to the size-8 block that
            // contains {7}, so instead a new size-8 block {7, 9} is created that
            // links directly to {3, 4, 5, 6}. That way, the block {7, 8} can be
            // garbage-collected if it is no longer in use. But a side effect is
            // that subList no longer appears to be a part of list. The fix is to
            // notice that list (block {7, 9}) and subList (block that contains {7})
            // have the same prior list, {3, 4, 5, 6}, and that the remaining
            // item(s) in subList (just one item, {7}, in this case) are also
            // present in list.
            list = subList;
            list.Add(9);
            Assert.AreEqual(9, subList.NextIn(list).Last);
        }
Ejemplo n.º 2
0
Archivo: VList.cs Proyecto: murven/Loyc
        public void TestEmptyListOperations()
        {
            VList <int> a = new VList <int>();
            VList <int> b = new VList <int>();

            a.AddRange(b);
            a.InsertRange(0, b);
            a.RemoveRange(0, 0);
            Assert.That(!a.Remove(0));
            Assert.That(a.IsEmpty);

            a.Add(1);
            b.AddRange(a);
            ExpectList(b, 1);
            b.RemoveAt(0);
            Assert.That(b.IsEmpty);
            b.InsertRange(0, a);
            ExpectList(b, 1);
            b.RemoveRange(0, 1);
            Assert.That(b.IsEmpty);
            b.Insert(0, a[0]);
            ExpectList(b, 1);
            b.Remove(a.Last);
            Assert.That(b.IsEmpty);

            AssertThrows <InvalidOperationException>(delegate() { a.NextIn(b); });
        }
Ejemplo n.º 3
0
Archivo: VList.cs Proyecto: murven/Loyc
        public void SimpleTests()
        {
            // In this simple test, I only add and remove items from the back
            // of a VList, but forking is also tested.

            VList <int> list = new VList <int>();

            Assert.That(list.IsEmpty);

            // Adding to VListBlockOfTwo
            list = new VList <int>(10, 20);
            ExpectList(list, 10, 20);

            list = new VList <int>();
            list.Add(1);
            Assert.That(!list.IsEmpty);
            list.Add(2);
            ExpectList(list, 1, 2);

            // A fork in VListBlockOfTwo. Note that list2 will use two VListBlocks
            // here but list will only use one.
            VList <int> list2 = list.WithoutLast(1);

            list2.Add(3);
            ExpectList(list, 1, 2);
            ExpectList(list2, 1, 3);

            // Try doubling list2
            list2.AddRange(list2);
            ExpectList(list2, 1, 3, 1, 3);

            // list now uses two arrays
            list.Add(4);
            ExpectList(list, 1, 2, 4);

            // Try doubling list using a different overload of AddRange()
            list.AddRange((IList <int>)list);
            ExpectList(list, 1, 2, 4, 1, 2, 4);
            list = list.WithoutLast(3);
            ExpectList(list, 1, 2, 4);

            // Remove(), Pop()
            Assert.AreEqual(3, list2.Pop());
            ExpectList(list2, 1, 3, 1);
            Assert.That(!list2.Remove(0));
            Assert.AreEqual(1, list2.Pop());
            Assert.That(list2.Remove(3));
            ExpectList(list2, 1);
            Assert.That(list2.Remove(1));
            ExpectList(list2);
            AssertThrows <Exception>(delegate() { list2.Pop(); });

            // Add many, SubList(). This will fill 3 arrays (sizes 8, 4, 2) and use
            // 1 element of a size-16 array. Oh, and test the enumerator.
            for (int i = 5; i <= 16; i++)
            {
                list.Add(i);
            }
            ExpectList(list, 1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
            list2 = list.WithoutLast(6);
            ExpectListByEnumerator(list2, 1, 2, 4, 5, 6, 7, 8, 9, 10);
            AssertThrows <IndexOutOfRangeException>(delegate() { int i = list[-1]; });
            AssertThrows <IndexOutOfRangeException>(delegate() { int i = list[15]; });

            // IndexOf, contains
            Assert.That(list.Contains(11));
            Assert.That(!list2.Contains(11));
            Assert.That(list[list.IndexOf(2)] == 2);
            Assert.That(list[list.IndexOf(1)] == 1);
            Assert.That(list[list.IndexOf(15)] == 15);
            Assert.That(list.IndexOf(3) == -1);

            // PreviousIn(), Back
            VList <int> list3 = list2;

            Assert.AreEqual(11, (list3 = list3.NextIn(list)).Last);
            Assert.AreEqual(12, (list3 = list3.NextIn(list)).Last);
            Assert.AreEqual(13, (list3 = list3.NextIn(list)).Last);
            Assert.AreEqual(14, (list3 = list3.NextIn(list)).Last);
            Assert.AreEqual(15, (list3 = list3.NextIn(list)).Last);
            Assert.AreEqual(16, (list3 = list3.NextIn(list)).Last);
            AssertThrows <Exception>(delegate() { list3.NextIn(list); });

            // Next
            Assert.AreEqual(10, (list3 = list3.WithoutLast(6)).Last);
            Assert.AreEqual(9, (list3 = list3.Tail).Last);
            Assert.AreEqual(8, (list3 = list3.Tail).Last);
            Assert.AreEqual(7, (list3 = list3.Tail).Last);
            Assert.AreEqual(6, (list3 = list3.Tail).Last);
            Assert.AreEqual(5, (list3 = list3.Tail).Last);
            Assert.AreEqual(4, (list3 = list3.Tail).Last);
            Assert.AreEqual(2, (list3 = list3.Tail).Last);
            Assert.AreEqual(1, (list3 = list3.Tail).Last);
            Assert.That((list3 = list3.Tail).IsEmpty);

            // list2 is still the same
            ExpectList(list2, 1, 2, 4, 5, 6, 7, 8, 9, 10);

            // ==, !=, Equals(), AddRange(a, b)
            Assert.That(!list2.Equals("hello"));
            list3 = list2;
            Assert.That(list3.Equals(list2));
            Assert.That(list3 == list2);
            // This AddRange forks the list. List2 ends up with block sizes 8 (3
            // used), 8 (3 used), 4, 2.
            list2.AddRange(list2, list2.WithoutLast(3));
            ExpectList(list2, 1, 2, 4, 5, 6, 7, 8, 9, 10, 8, 9, 10);
            Assert.That(list3 != list2);

            // List3 is a sublist of list, but list2 no longer is
            Assert.That(list3.NextIn(list).Last == 11);
            AssertThrows <InvalidOperationException>(delegate() { list2.NextIn(list); });

            list2 = list2.WithoutLast(3);
            Assert.That(list3 == list2);
        }