mirror of https://github.com/icsharpcode/ILSpy.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
313 lines
10 KiB
313 lines
10 KiB
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) |
|
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) |
|
|
|
using System; |
|
using NUnit.Framework; |
|
using System.Collections.Generic; |
|
|
|
namespace ICSharpCode.AvalonEdit.Document |
|
{ |
|
[TestFixture] |
|
public class TextAnchorTest |
|
{ |
|
TextDocument document; |
|
|
|
[SetUp] |
|
public void SetUp() |
|
{ |
|
document = new TextDocument(); |
|
} |
|
|
|
[Test] |
|
public void AnchorInEmptyDocument() |
|
{ |
|
TextAnchor a1 = document.CreateAnchor(0); |
|
TextAnchor a2 = document.CreateAnchor(0); |
|
a1.MovementType = AnchorMovementType.BeforeInsertion; |
|
a2.MovementType = AnchorMovementType.AfterInsertion; |
|
Assert.AreEqual(0, a1.Offset); |
|
Assert.AreEqual(0, a2.Offset); |
|
document.Insert(0, "x"); |
|
Assert.AreEqual(0, a1.Offset); |
|
Assert.AreEqual(1, a2.Offset); |
|
} |
|
|
|
[Test] |
|
public void AnchorsSurviveDeletion() |
|
{ |
|
document.Text = new string(' ', 10); |
|
TextAnchor[] a1 = new TextAnchor[11]; |
|
TextAnchor[] a2 = new TextAnchor[11]; |
|
for (int i = 0; i < 11; i++) { |
|
//Console.WriteLine("Insert first at i = " + i); |
|
a1[i] = document.CreateAnchor(i); |
|
a1[i].SurviveDeletion = true; |
|
//Console.WriteLine(document.GetTextAnchorTreeAsString()); |
|
//Console.WriteLine("Insert second at i = " + i); |
|
a2[i] = document.CreateAnchor(i); |
|
a2[i].SurviveDeletion = false; |
|
//Console.WriteLine(document.GetTextAnchorTreeAsString()); |
|
} |
|
for (int i = 0; i < 11; i++) { |
|
Assert.AreEqual(i, a1[i].Offset); |
|
Assert.AreEqual(i, a2[i].Offset); |
|
} |
|
document.Remove(1, 8); |
|
for (int i = 0; i < 11; i++) { |
|
if (i <= 1) { |
|
Assert.IsFalse(a1[i].IsDeleted); |
|
Assert.IsFalse(a2[i].IsDeleted); |
|
Assert.AreEqual(i, a1[i].Offset); |
|
Assert.AreEqual(i, a2[i].Offset); |
|
} else if (i <= 8) { |
|
Assert.IsFalse(a1[i].IsDeleted); |
|
Assert.IsTrue(a2[i].IsDeleted); |
|
Assert.AreEqual(1, a1[i].Offset); |
|
} else { |
|
Assert.IsFalse(a1[i].IsDeleted); |
|
Assert.IsFalse(a2[i].IsDeleted); |
|
Assert.AreEqual(i - 8, a1[i].Offset); |
|
Assert.AreEqual(i - 8, a2[i].Offset); |
|
} |
|
} |
|
} |
|
|
|
|
|
Random rnd; |
|
|
|
[TestFixtureSetUp] |
|
public void FixtureSetup() |
|
{ |
|
int seed = Environment.TickCount; |
|
Console.WriteLine("TextAnchorTest Seed: " + seed); |
|
rnd = new Random(seed); |
|
} |
|
|
|
[Test] |
|
public void CreateAnchors() |
|
{ |
|
List<TextAnchor> anchors = new List<TextAnchor>(); |
|
List<int> expectedOffsets = new List<int>(); |
|
document.Text = new string(' ', 1000); |
|
for (int i = 0; i < 1000; i++) { |
|
int offset = rnd.Next(1000); |
|
anchors.Add(document.CreateAnchor(offset)); |
|
expectedOffsets.Add(offset); |
|
} |
|
for (int i = 0; i < anchors.Count; i++) { |
|
Assert.AreEqual(expectedOffsets[i], anchors[i].Offset); |
|
} |
|
GC.KeepAlive(anchors); |
|
} |
|
|
|
[Test] |
|
public void CreateAndGCAnchors() |
|
{ |
|
List<TextAnchor> anchors = new List<TextAnchor>(); |
|
List<int> expectedOffsets = new List<int>(); |
|
document.Text = new string(' ', 1000); |
|
for (int t = 0; t < 250; t++) { |
|
int c = rnd.Next(50); |
|
if (rnd.Next(2) == 0) { |
|
for (int i = 0; i < c; i++) { |
|
int offset = rnd.Next(1000); |
|
anchors.Add(document.CreateAnchor(offset)); |
|
expectedOffsets.Add(offset); |
|
} |
|
} else if (c <= anchors.Count) { |
|
anchors.RemoveRange(0, c); |
|
expectedOffsets.RemoveRange(0, c); |
|
GC.Collect(); |
|
} |
|
for (int j = 0; j < anchors.Count; j++) { |
|
Assert.AreEqual(expectedOffsets[j], anchors[j].Offset); |
|
} |
|
} |
|
GC.KeepAlive(anchors); |
|
} |
|
|
|
[Test] |
|
public void MoveAnchorsDuringReplace() |
|
{ |
|
document.Text = "abcd"; |
|
TextAnchor start = document.CreateAnchor(1); |
|
TextAnchor middleDeletable = document.CreateAnchor(2); |
|
TextAnchor middleSurvivorLeft = document.CreateAnchor(2); |
|
middleSurvivorLeft.SurviveDeletion = true; |
|
middleSurvivorLeft.MovementType = AnchorMovementType.BeforeInsertion; |
|
TextAnchor middleSurvivorRight = document.CreateAnchor(2); |
|
middleSurvivorRight.SurviveDeletion = true; |
|
middleSurvivorRight.MovementType = AnchorMovementType.AfterInsertion; |
|
TextAnchor end = document.CreateAnchor(3); |
|
document.Replace(1, 2, "BxC"); |
|
|
|
Assert.AreEqual(1, start.Offset); |
|
Assert.IsTrue(middleDeletable.IsDeleted); |
|
Assert.AreEqual(1, middleSurvivorLeft.Offset); |
|
Assert.AreEqual(4, middleSurvivorRight.Offset); |
|
Assert.AreEqual(4, end.Offset); |
|
} |
|
|
|
[Test] |
|
public void CreateAndMoveAnchors() |
|
{ |
|
List<TextAnchor> anchors = new List<TextAnchor>(); |
|
List<int> expectedOffsets = new List<int>(); |
|
document.Text = new string(' ', 1000); |
|
for (int t = 0; t < 250; t++) { |
|
//Console.Write("t = " + t + " "); |
|
int c = rnd.Next(50); |
|
switch (rnd.Next(5)) { |
|
case 0: |
|
//Console.WriteLine("Add c=" + c + " anchors"); |
|
for (int i = 0; i < c; i++) { |
|
int offset = rnd.Next(document.TextLength); |
|
TextAnchor anchor = document.CreateAnchor(offset); |
|
if (rnd.Next(2) == 0) |
|
anchor.MovementType = AnchorMovementType.BeforeInsertion; |
|
else |
|
anchor.MovementType = AnchorMovementType.AfterInsertion; |
|
anchor.SurviveDeletion = rnd.Next(2) == 0; |
|
anchors.Add(anchor); |
|
expectedOffsets.Add(offset); |
|
} |
|
break; |
|
case 1: |
|
if (c <= anchors.Count) { |
|
//Console.WriteLine("Remove c=" + c + " anchors"); |
|
anchors.RemoveRange(0, c); |
|
expectedOffsets.RemoveRange(0, c); |
|
GC.Collect(); |
|
} |
|
break; |
|
case 2: |
|
int insertOffset = rnd.Next(document.TextLength); |
|
int insertLength = rnd.Next(1000); |
|
//Console.WriteLine("insertOffset=" + insertOffset + " insertLength="+insertLength); |
|
document.Insert(insertOffset, new string(' ', insertLength)); |
|
for (int i = 0; i < anchors.Count; i++) { |
|
if (anchors[i].MovementType == AnchorMovementType.BeforeInsertion) { |
|
if (expectedOffsets[i] > insertOffset) |
|
expectedOffsets[i] += insertLength; |
|
} else { |
|
if (expectedOffsets[i] >= insertOffset) |
|
expectedOffsets[i] += insertLength; |
|
} |
|
} |
|
break; |
|
case 3: |
|
int removalOffset = rnd.Next(document.TextLength); |
|
int removalLength = rnd.Next(document.TextLength - removalOffset); |
|
//Console.WriteLine("RemovalOffset=" + removalOffset + " RemovalLength="+removalLength); |
|
document.Remove(removalOffset, removalLength); |
|
for (int i = anchors.Count - 1; i >= 0; i--) { |
|
if (expectedOffsets[i] > removalOffset && expectedOffsets[i] < removalOffset + removalLength) { |
|
if (anchors[i].SurviveDeletion) { |
|
expectedOffsets[i] = removalOffset; |
|
} else { |
|
Assert.IsTrue(anchors[i].IsDeleted); |
|
anchors.RemoveAt(i); |
|
expectedOffsets.RemoveAt(i); |
|
} |
|
} else if (expectedOffsets[i] > removalOffset) { |
|
expectedOffsets[i] -= removalLength; |
|
} |
|
} |
|
break; |
|
case 4: |
|
int replaceOffset = rnd.Next(document.TextLength); |
|
int replaceRemovalLength = rnd.Next(document.TextLength - replaceOffset); |
|
int replaceInsertLength = rnd.Next(1000); |
|
//Console.WriteLine("ReplaceOffset=" + replaceOffset + " RemovalLength="+replaceRemovalLength + " InsertLength=" + replaceInsertLength); |
|
document.Replace(replaceOffset, replaceRemovalLength, new string(' ', replaceInsertLength)); |
|
for (int i = anchors.Count - 1; i >= 0; i--) { |
|
if (expectedOffsets[i] > replaceOffset && expectedOffsets[i] < replaceOffset + replaceRemovalLength) { |
|
if (anchors[i].SurviveDeletion) { |
|
if (anchors[i].MovementType == AnchorMovementType.AfterInsertion) |
|
expectedOffsets[i] = replaceOffset + replaceInsertLength; |
|
else |
|
expectedOffsets[i] = replaceOffset; |
|
} else { |
|
Assert.IsTrue(anchors[i].IsDeleted); |
|
anchors.RemoveAt(i); |
|
expectedOffsets.RemoveAt(i); |
|
} |
|
} else if (expectedOffsets[i] > replaceOffset) { |
|
expectedOffsets[i] += replaceInsertLength - replaceRemovalLength; |
|
} else if (expectedOffsets[i] == replaceOffset && replaceRemovalLength == 0 && anchors[i].MovementType == AnchorMovementType.AfterInsertion) { |
|
expectedOffsets[i] += replaceInsertLength - replaceRemovalLength; |
|
} |
|
} |
|
break; |
|
} |
|
Assert.AreEqual(anchors.Count, expectedOffsets.Count); |
|
for (int j = 0; j < anchors.Count; j++) { |
|
Assert.AreEqual(expectedOffsets[j], anchors[j].Offset); |
|
} |
|
} |
|
GC.KeepAlive(anchors); |
|
} |
|
|
|
[Test] |
|
public void RepeatedTextDragDrop() |
|
{ |
|
document.Text = new string(' ', 1000); |
|
for (int i = 0; i < 20; i++) { |
|
TextAnchor a = document.CreateAnchor(144); |
|
TextAnchor b = document.CreateAnchor(157); |
|
document.Insert(128, new string('a', 13)); |
|
document.Remove(157, 13); |
|
a = document.CreateAnchor(128); |
|
b = document.CreateAnchor(141); |
|
|
|
document.Insert(157, new string('b', 13)); |
|
document.Remove(128, 13); |
|
|
|
a = null; |
|
b = null; |
|
if ((i % 5) == 0) |
|
GC.Collect(); |
|
} |
|
} |
|
|
|
[Test] |
|
public void ReplaceSpacesWithTab() |
|
{ |
|
document.Text = "a b"; |
|
TextAnchor before = document.CreateAnchor(1); |
|
before.MovementType = AnchorMovementType.AfterInsertion; |
|
TextAnchor after = document.CreateAnchor(5); |
|
TextAnchor survivingMiddle = document.CreateAnchor(2); |
|
TextAnchor deletedMiddle = document.CreateAnchor(3); |
|
|
|
document.Replace(1, 4, "\t", OffsetChangeMappingType.CharacterReplace); |
|
Assert.AreEqual("a\tb", document.Text); |
|
// yes, the movement is a bit strange; but that's how CharacterReplace works when the text gets shorter |
|
Assert.AreEqual(1, before.Offset); |
|
Assert.AreEqual(2, after.Offset); |
|
Assert.AreEqual(2, survivingMiddle.Offset); |
|
Assert.AreEqual(2, deletedMiddle.Offset); |
|
} |
|
|
|
[Test] |
|
public void ReplaceTwoCharactersWithThree() |
|
{ |
|
document.Text = "a12b"; |
|
TextAnchor before = document.CreateAnchor(1); |
|
before.MovementType = AnchorMovementType.AfterInsertion; |
|
TextAnchor after = document.CreateAnchor(3); |
|
before.MovementType = AnchorMovementType.BeforeInsertion; |
|
TextAnchor middleB = document.CreateAnchor(2); |
|
before.MovementType = AnchorMovementType.BeforeInsertion; |
|
TextAnchor middleA = document.CreateAnchor(2); |
|
before.MovementType = AnchorMovementType.AfterInsertion; |
|
|
|
document.Replace(1, 2, "123", OffsetChangeMappingType.CharacterReplace); |
|
Assert.AreEqual("a123b", document.Text); |
|
Assert.AreEqual(1, before.Offset); |
|
Assert.AreEqual(4, after.Offset); |
|
Assert.AreEqual(2, middleA.Offset); |
|
Assert.AreEqual(2, middleB.Offset); |
|
} |
|
} |
|
}
|
|
|