PageRenderTime 37ms CodeModel.GetById 17ms app.highlight 16ms RepoModel.GetById 1ms app.codeStats 0ms

/AvalonEdit/ICSharpCode.AvalonEdit.Tests/Document/TextSegmentTreeTest.cs

http://github.com/icsharpcode/ILSpy
C# | 368 lines | 311 code | 31 blank | 26 comment | 16 complexity | 063c8360b18aca23263bc391fe74ce87 MD5 | raw file
  1// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
  2// 
  3// Permission is hereby granted, free of charge, to any person obtaining a copy of this
  4// software and associated documentation files (the "Software"), to deal in the Software
  5// without restriction, including without limitation the rights to use, copy, modify, merge,
  6// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
  7// to whom the Software is furnished to do so, subject to the following conditions:
  8// 
  9// The above copyright notice and this permission notice shall be included in all copies or
 10// substantial portions of the Software.
 11// 
 12// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
 13// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
 14// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
 15// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 16// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 17// DEALINGS IN THE SOFTWARE.
 18
 19using System;
 20using System.Collections.Generic;
 21#if NREFACTORY
 22using ICSharpCode.NRefactory.Editor;
 23#endif
 24using NUnit.Framework;
 25
 26namespace ICSharpCode.AvalonEdit.Document
 27{
 28	[TestFixture]
 29	public class TextSegmentTreeTest
 30	{
 31		Random rnd;
 32		
 33		[TestFixtureSetUp]
 34		public void FixtureSetup()
 35		{
 36			int seed = Environment.TickCount;
 37			Console.WriteLine("TextSegmentTreeTest Seed: " + seed);
 38			rnd = new Random(seed);
 39		}
 40		
 41		class TestTextSegment : TextSegment
 42		{
 43			internal int ExpectedOffset, ExpectedLength;
 44			
 45			public TestTextSegment(int expectedOffset, int expectedLength)
 46			{
 47				this.ExpectedOffset = expectedOffset;
 48				this.ExpectedLength = expectedLength;
 49				this.StartOffset = expectedOffset;
 50				this.Length = expectedLength;
 51			}
 52		}
 53		
 54		TextSegmentCollection<TestTextSegment> tree;
 55		List<TestTextSegment> expectedSegments;
 56		
 57		[SetUp]
 58		public void SetUp()
 59		{
 60			tree = new TextSegmentCollection<TestTextSegment>();
 61			expectedSegments = new List<TestTextSegment>();
 62		}
 63		
 64		[Test]
 65		public void FindInEmptyTree()
 66		{
 67			Assert.AreSame(null, tree.FindFirstSegmentWithStartAfter(0));
 68			Assert.AreEqual(0, tree.FindSegmentsContaining(0).Count);
 69			Assert.AreEqual(0, tree.FindOverlappingSegments(10, 20).Count);
 70		}
 71		
 72		[Test]
 73		public void FindFirstSegmentWithStartAfter()
 74		{
 75			var s1 = new TestTextSegment(5, 10);
 76			var s2 = new TestTextSegment(10, 10);
 77			tree.Add(s1);
 78			tree.Add(s2);
 79			Assert.AreSame(s1, tree.FindFirstSegmentWithStartAfter(-100));
 80			Assert.AreSame(s1, tree.FindFirstSegmentWithStartAfter(0));
 81			Assert.AreSame(s1, tree.FindFirstSegmentWithStartAfter(4));
 82			Assert.AreSame(s1, tree.FindFirstSegmentWithStartAfter(5));
 83			Assert.AreSame(s2, tree.FindFirstSegmentWithStartAfter(6));
 84			Assert.AreSame(s2, tree.FindFirstSegmentWithStartAfter(9));
 85			Assert.AreSame(s2, tree.FindFirstSegmentWithStartAfter(10));
 86			Assert.AreSame(null, tree.FindFirstSegmentWithStartAfter(11));
 87			Assert.AreSame(null, tree.FindFirstSegmentWithStartAfter(100));
 88		}
 89		
 90		[Test]
 91		public void FindFirstSegmentWithStartAfterWithDuplicates()
 92		{
 93			var s1 = new TestTextSegment(5, 10);
 94			var s1b = new TestTextSegment(5, 7);
 95			var s2 = new TestTextSegment(10, 10);
 96			var s2b = new TestTextSegment(10, 7);
 97			tree.Add(s1);
 98			tree.Add(s1b);
 99			tree.Add(s2);
100			tree.Add(s2b);
101			Assert.AreSame(s1b, tree.GetNextSegment(s1));
102			Assert.AreSame(s2b, tree.GetNextSegment(s2));
103			Assert.AreSame(s1, tree.FindFirstSegmentWithStartAfter(-100));
104			Assert.AreSame(s1, tree.FindFirstSegmentWithStartAfter(0));
105			Assert.AreSame(s1, tree.FindFirstSegmentWithStartAfter(4));
106			Assert.AreSame(s1, tree.FindFirstSegmentWithStartAfter(5));
107			Assert.AreSame(s2, tree.FindFirstSegmentWithStartAfter(6));
108			Assert.AreSame(s2, tree.FindFirstSegmentWithStartAfter(9));
109			Assert.AreSame(s2, tree.FindFirstSegmentWithStartAfter(10));
110			Assert.AreSame(null, tree.FindFirstSegmentWithStartAfter(11));
111			Assert.AreSame(null, tree.FindFirstSegmentWithStartAfter(100));
112		}
113		
114		[Test]
115		public void FindFirstSegmentWithStartAfterWithDuplicates2()
116		{
117			var s1 = new TestTextSegment(5, 1);
118			var s2 = new TestTextSegment(5, 2);
119			var s3 = new TestTextSegment(5, 3);
120			var s4 = new TestTextSegment(5, 4);
121			tree.Add(s1);
122			tree.Add(s2);
123			tree.Add(s3);
124			tree.Add(s4);
125			Assert.AreSame(s1, tree.FindFirstSegmentWithStartAfter(0));
126			Assert.AreSame(s1, tree.FindFirstSegmentWithStartAfter(1));
127			Assert.AreSame(s1, tree.FindFirstSegmentWithStartAfter(4));
128			Assert.AreSame(s1, tree.FindFirstSegmentWithStartAfter(5));
129			Assert.AreSame(null, tree.FindFirstSegmentWithStartAfter(6));
130		}
131		
132		TestTextSegment AddSegment(int offset, int length)
133		{
134//			Console.WriteLine("Add " + offset + ", " + length);
135			TestTextSegment s = new TestTextSegment(offset, length);
136			tree.Add(s);
137			expectedSegments.Add(s);
138			return s;
139		}
140		
141		void RemoveSegment(TestTextSegment s)
142		{
143//			Console.WriteLine("Remove " + s);
144			expectedSegments.Remove(s);
145			tree.Remove(s);
146		}
147		
148		void TestRetrieval(int offset, int length)
149		{
150			HashSet<TestTextSegment> actual = new HashSet<TestTextSegment>(tree.FindOverlappingSegments(offset, length));
151			HashSet<TestTextSegment> expected = new HashSet<TestTextSegment>();
152			foreach (TestTextSegment e in expectedSegments) {
153				if (e.ExpectedOffset + e.ExpectedLength < offset)
154					continue;
155				if (e.ExpectedOffset > offset + length)
156					continue;
157				expected.Add(e);
158			}
159			Assert.IsTrue(actual.IsSubsetOf(expected));
160			Assert.IsTrue(expected.IsSubsetOf(actual));
161		}
162		
163		void CheckSegments()
164		{
165			Assert.AreEqual(expectedSegments.Count, tree.Count);
166			foreach (TestTextSegment s in expectedSegments) {
167				Assert.AreEqual(s.ExpectedOffset, s.StartOffset /*, "startoffset for " + s*/);
168				Assert.AreEqual(s.ExpectedLength, s.Length /*, "length for " + s*/);
169			}
170		}
171		
172		[Test]
173		public void AddSegments()
174		{
175			TestTextSegment s1 = AddSegment(10, 20);
176			TestTextSegment s2 = AddSegment(15, 10);
177			CheckSegments();
178		}
179		
180		void ChangeDocument(OffsetChangeMapEntry change)
181		{
182			tree.UpdateOffsets(change);
183			foreach (TestTextSegment s in expectedSegments) {
184				int endOffset = s.ExpectedOffset + s.ExpectedLength;
185				s.ExpectedOffset = change.GetNewOffset(s.ExpectedOffset, AnchorMovementType.AfterInsertion);
186				s.ExpectedLength = Math.Max(0, change.GetNewOffset(endOffset, AnchorMovementType.BeforeInsertion) - s.ExpectedOffset);
187			}
188		}
189		
190		[Test]
191		public void InsertionBeforeAllSegments()
192		{
193			TestTextSegment s1 = AddSegment(10, 20);
194			TestTextSegment s2 = AddSegment(15, 10);
195			ChangeDocument(new OffsetChangeMapEntry(5, 0, 2));
196			CheckSegments();
197		}
198		
199		[Test]
200		public void ReplacementBeforeAllSegmentsTouchingFirstSegment()
201		{
202			TestTextSegment s1 = AddSegment(10, 20);
203			TestTextSegment s2 = AddSegment(15, 10);
204			ChangeDocument(new OffsetChangeMapEntry(5, 5, 2));
205			CheckSegments();
206		}
207		
208		[Test]
209		public void InsertionAfterAllSegments()
210		{
211			TestTextSegment s1 = AddSegment(10, 20);
212			TestTextSegment s2 = AddSegment(15, 10);
213			ChangeDocument(new OffsetChangeMapEntry(45, 0, 2));
214			CheckSegments();
215		}
216		
217		[Test]
218		public void ReplacementOverlappingWithStartOfSegment()
219		{
220			TestTextSegment s1 = AddSegment(10, 20);
221			TestTextSegment s2 = AddSegment(15, 10);
222			ChangeDocument(new OffsetChangeMapEntry(9, 7, 2));
223			CheckSegments();
224		}
225		
226		[Test]
227		public void ReplacementOfWholeSegment()
228		{
229			TestTextSegment s1 = AddSegment(10, 20);
230			TestTextSegment s2 = AddSegment(15, 10);
231			ChangeDocument(new OffsetChangeMapEntry(10, 20, 30));
232			CheckSegments();
233		}
234		
235		[Test]
236		public void ReplacementAtEndOfSegment()
237		{
238			TestTextSegment s1 = AddSegment(10, 20);
239			TestTextSegment s2 = AddSegment(15, 10);
240			ChangeDocument(new OffsetChangeMapEntry(24, 6, 10));
241			CheckSegments();
242		}
243		
244		[Test]
245		public void RandomizedNoDocumentChanges()
246		{
247			for (int i = 0; i < 1000; i++) {
248//				Console.WriteLine(tree.GetTreeAsString());
249//				Console.WriteLine("Iteration " + i);
250				
251				switch (rnd.Next(3)) {
252					case 0:
253						AddSegment(rnd.Next(500), rnd.Next(30));
254						break;
255					case 1:
256						AddSegment(rnd.Next(500), rnd.Next(300));
257						break;
258					case 2:
259						if (tree.Count > 0) {
260							RemoveSegment(expectedSegments[rnd.Next(tree.Count)]);
261						}
262						break;
263				}
264				CheckSegments();
265			}
266		}
267		
268		[Test]
269		public void RandomizedCloseNoDocumentChanges()
270		{
271			// Lots of segments in a short document. Tests how the tree copes with multiple identical segments.
272			for (int i = 0; i < 1000; i++) {
273				switch (rnd.Next(3)) {
274					case 0:
275						AddSegment(rnd.Next(20), rnd.Next(10));
276						break;
277					case 1:
278						AddSegment(rnd.Next(20), rnd.Next(20));
279						break;
280					case 2:
281						if (tree.Count > 0) {
282							RemoveSegment(expectedSegments[rnd.Next(tree.Count)]);
283						}
284						break;
285				}
286				CheckSegments();
287			}
288		}
289		
290		[Test]
291		public void RandomizedRetrievalTest()
292		{
293			for (int i = 0; i < 1000; i++) {
294				AddSegment(rnd.Next(500), rnd.Next(300));
295			}
296			CheckSegments();
297			for (int i = 0; i < 1000; i++) {
298				TestRetrieval(rnd.Next(1000) - 100, rnd.Next(500));
299			}
300		}
301		
302		[Test]
303		public void RandomizedWithDocumentChanges()
304		{
305			for (int i = 0; i < 500; i++) {
306//				Console.WriteLine(tree.GetTreeAsString());
307//				Console.WriteLine("Iteration " + i);
308				
309				switch (rnd.Next(6)) {
310					case 0:
311						AddSegment(rnd.Next(500), rnd.Next(30));
312						break;
313					case 1:
314						AddSegment(rnd.Next(500), rnd.Next(300));
315						break;
316					case 2:
317						if (tree.Count > 0) {
318							RemoveSegment(expectedSegments[rnd.Next(tree.Count)]);
319						}
320						break;
321					case 3:
322						ChangeDocument(new OffsetChangeMapEntry(rnd.Next(800), rnd.Next(50), rnd.Next(50)));
323						break;
324					case 4:
325						ChangeDocument(new OffsetChangeMapEntry(rnd.Next(800), 0, rnd.Next(50)));
326						break;
327					case 5:
328						ChangeDocument(new OffsetChangeMapEntry(rnd.Next(800), rnd.Next(50), 0));
329						break;
330				}
331				CheckSegments();
332			}
333		}
334		
335		[Test]
336		public void RandomizedWithDocumentChangesClose()
337		{
338			for (int i = 0; i < 500; i++) {
339//				Console.WriteLine(tree.GetTreeAsString());
340//				Console.WriteLine("Iteration " + i);
341				
342				switch (rnd.Next(6)) {
343					case 0:
344						AddSegment(rnd.Next(50), rnd.Next(30));
345						break;
346					case 1:
347						AddSegment(rnd.Next(50), rnd.Next(3));
348						break;
349					case 2:
350						if (tree.Count > 0) {
351							RemoveSegment(expectedSegments[rnd.Next(tree.Count)]);
352						}
353						break;
354					case 3:
355						ChangeDocument(new OffsetChangeMapEntry(rnd.Next(80), rnd.Next(10), rnd.Next(10)));
356						break;
357					case 4:
358						ChangeDocument(new OffsetChangeMapEntry(rnd.Next(80), 0, rnd.Next(10)));
359						break;
360					case 5:
361						ChangeDocument(new OffsetChangeMapEntry(rnd.Next(80), rnd.Next(10), 0));
362						break;
363				}
364				CheckSegments();
365			}
366		}
367	}
368}