PageRenderTime 45ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/Tests/FindResultsClassifierTests.cs

#
C# | 365 lines | 271 code | 94 blank | 0 comment | 7 complexity | 3388a9089ab8acfbf311033f87ef9192 MD5 | raw file
Possible License(s): Apache-2.0, BSD-3-Clause, GPL-2.0
  1. using System;
  2. using System.Collections.Generic;
  3. using BlueOnionSoftware;
  4. using Microsoft.VisualStudio.Text;
  5. using Microsoft.VisualStudio.Text.Classification;
  6. using Moq;
  7. using NUnit.Framework;
  8. using FluentAssertions;
  9. using System.Linq;
  10. namespace Tests
  11. {
  12. [TestFixture]
  13. public class FindResultsClassifierTests
  14. {
  15. private FindResultsClassifier classifier;
  16. private const string ResultsPreamble = "Find all \"";
  17. private const string ResultsPreambleEnd = "\"";
  18. private const string ResultsMatchCase = "Match case";
  19. private const string ResultsMatchWord = "Whole word";
  20. private const string ResultsUsingRegex = "Regular expressions";
  21. private const string ResultsUsingWildcards = "Wildcards";
  22. private const string ResultsSubfolders = "SubFolders";
  23. private const string ResultsFilenamesOnly = "List filenames only";
  24. private const string ResultsLookIn = "\"Entire Solution\"";
  25. private const string ResultsFileTypes = "\"*.cs\"";
  26. private const string UsingResultsLine1 = @" C:\Projects\App\Program.cs(1):using System;";
  27. private const string UsingResultsLine2 = @" C:\Projects\App\Program.cs(20):using System.Collections.Generic;";
  28. private const string UsingResultsLineWithMultipleHits = @" C:\Projects\App\Program.cs(2):using System.Collections.Generic; // using UnusedStuff;";
  29. private const string MixedCaseResults = @" C:\Projects\App\Program.cs(366): // casing Casing CASING casing";
  30. private const string CaseInsensitiveWholeWordResults = @" C:\Projects\App\Program.cs(200):public class Classifier // subclass";
  31. [SetUp]
  32. public void Setup()
  33. {
  34. var mockSearchTermClassification = new Mock<IClassificationType>();
  35. mockSearchTermClassification.Setup(c => c.IsOfType(OutputClassificationDefinitions.FindResultsSearchTerm)).
  36. Returns(true);
  37. var mockClassificationTypeRegistryService = new Mock<IClassificationTypeRegistryService>();
  38. mockClassificationTypeRegistryService
  39. .Setup(c => c.GetClassificationType(It.IsAny<string>()))
  40. .Returns((string classificationType) => new FakeClassificationType(classificationType));
  41. classifier = new FindResultsClassifier(mockClassificationTypeRegistryService.Object);
  42. }
  43. [Test]
  44. public void GetClassificationSpansNullSnapShot()
  45. {
  46. classifier.GetClassificationSpans(new SnapshotSpan()).Should().BeEmpty();
  47. }
  48. [Test]
  49. public void GetClassificationSpansZeroLengthSnapShot()
  50. {
  51. var mockSnapshot = new Mock<ITextSnapshot>();
  52. mockSnapshot.SetupGet(s => s.Length).Returns(0);
  53. var snapshotSpan = new SnapshotSpan(mockSnapshot.Object, 0, 0);
  54. classifier.GetClassificationSpans(snapshotSpan).Should().BeEmpty();
  55. }
  56. [Test]
  57. public void ClassifiesSearchTermInSearchResultsBanner()
  58. {
  59. const string searchTerm = "using";
  60. var text = GetCaseInsensitiveResultsText(searchTerm, UsingResultsLine1, UsingResultsLine2);
  61. var offset1 = text.IndexOf(searchTerm, StringComparison.OrdinalIgnoreCase);
  62. var snapshotSpan = BuildSnapshotSpanFromLineNumber(text, 0);
  63. var spans = classifier.GetClassificationSpans(snapshotSpan);
  64. spans = spans.Where(IsSearchTerm).ToList();
  65. spans.Count.Should().Be(1);
  66. AssertSearchTermClassified(spans[0], snapshotSpan, searchTerm, offset1);
  67. }
  68. [Test]
  69. public void SearchTermContainingRegularExpressionCharactersDoesNotThrowException()
  70. {
  71. const string searchTerm = @"\P][^";
  72. var text = GetCaseInsensitiveResultsText(searchTerm, UsingResultsLine1, UsingResultsLine2);
  73. var snapshotSpan = BuildSnapshotSpanFromLineNumber(text, 1);
  74. var spans = classifier.GetClassificationSpans(snapshotSpan);
  75. spans = spans.Where(IsSearchTerm).ToList();
  76. spans.Count.Should().Be(0);
  77. }
  78. [Test]
  79. public void ClassifiesSearchTermInFirstLineOfResults()
  80. {
  81. const string searchTerm = "using";
  82. var text = GetCaseInsensitiveResultsText(searchTerm, UsingResultsLine1, UsingResultsLine2);
  83. var offset1 = UsingResultsLine1.IndexOf(searchTerm, StringComparison.OrdinalIgnoreCase);
  84. PrimeClassifierSearchOptionsWithFirstLine(text);
  85. var snapshotSpan = BuildSnapshotSpanFromLineNumber(text, 1);
  86. var spans = classifier.GetClassificationSpans(snapshotSpan);
  87. spans = spans.Where(IsSearchTerm).ToList();
  88. spans.Count.Should().Be(1);
  89. AssertSearchTermClassified(spans[0], snapshotSpan, searchTerm, offset1);
  90. }
  91. [Test]
  92. public void ClassifiesSearchTermInSubsequentLinesOfResults()
  93. {
  94. const string searchTerm = "using";
  95. var text = GetCaseInsensitiveResultsText(searchTerm, UsingResultsLine1, UsingResultsLine2);
  96. var offset1 = UsingResultsLine2.IndexOf(searchTerm, StringComparison.OrdinalIgnoreCase);
  97. PrimeClassifierSearchOptionsWithFirstLine(text);
  98. var snapshotSpan = BuildSnapshotSpanFromLineNumber(text, 2);
  99. var spans = classifier.GetClassificationSpans(snapshotSpan);
  100. spans = spans.Where(IsSearchTerm).ToList();
  101. spans.Count.Should().Be(1);
  102. AssertSearchTermClassified(spans[0], snapshotSpan, searchTerm, offset1);
  103. }
  104. [Test]
  105. public void ClassifiesSearchTermMultipleTimesInText()
  106. {
  107. const string searchTerm = "using";
  108. var text = GetCaseInsensitiveResultsText(searchTerm, UsingResultsLineWithMultipleHits);
  109. var offset1 = UsingResultsLineWithMultipleHits.IndexOf(searchTerm, StringComparison.OrdinalIgnoreCase);
  110. var offset2 = UsingResultsLineWithMultipleHits.IndexOf(searchTerm, offset1 + searchTerm.Length, StringComparison.OrdinalIgnoreCase);
  111. PrimeClassifierSearchOptionsWithFirstLine(text);
  112. var snapshotSpan = BuildSnapshotSpanFromLineNumber(text, 1);
  113. var spans = classifier.GetClassificationSpans(snapshotSpan);
  114. spans = spans.Where(IsSearchTerm).ToList();
  115. spans.Count.Should().Be(2);
  116. AssertSearchTermClassified(spans[0], snapshotSpan, searchTerm, offset1);
  117. AssertSearchTermClassified(spans[1], snapshotSpan, searchTerm, offset2);
  118. }
  119. [Test]
  120. public void ClassifiesAllSearchTermsCaseInsensitive()
  121. {
  122. const string searchTerm = "casing";
  123. var text = GetCaseInsensitiveResultsText(searchTerm, MixedCaseResults);
  124. var offset1 = MixedCaseResults.IndexOf(searchTerm, StringComparison.OrdinalIgnoreCase);
  125. var offset2 = MixedCaseResults.IndexOf(searchTerm, offset1 + searchTerm.Length, StringComparison.OrdinalIgnoreCase);
  126. var offset3 = MixedCaseResults.IndexOf(searchTerm, offset2 + searchTerm.Length, StringComparison.OrdinalIgnoreCase);
  127. var offset4 = MixedCaseResults.IndexOf(searchTerm, offset3 + searchTerm.Length, StringComparison.OrdinalIgnoreCase);
  128. PrimeClassifierSearchOptionsWithFirstLine(text);
  129. var snapshotSpan = BuildSnapshotSpanFromLineNumber(text, 1);
  130. var spans = classifier.GetClassificationSpans(snapshotSpan);
  131. spans = spans.Where(IsSearchTerm).ToList();
  132. spans.Count.Should().Be(4);
  133. AssertSearchTermClassified(spans[0], snapshotSpan, searchTerm, offset1);
  134. AssertSearchTermClassified(spans[1], snapshotSpan, searchTerm, offset2);
  135. AssertSearchTermClassified(spans[2], snapshotSpan, searchTerm, offset3);
  136. AssertSearchTermClassified(spans[3], snapshotSpan, searchTerm, offset4);
  137. }
  138. [Test]
  139. public void ClassifiesOnlySearchTermsMatchingCase()
  140. {
  141. const string searchTerm = "Casing";
  142. var text = GetCaseSensitiveResultsText(searchTerm, MixedCaseResults);
  143. var offset1 = MixedCaseResults.IndexOf(searchTerm, StringComparison.Ordinal);
  144. PrimeClassifierSearchOptionsWithFirstLine(text);
  145. var snapshotSpan = BuildSnapshotSpanFromLineNumber(text, 1);
  146. var spans = classifier.GetClassificationSpans(snapshotSpan);
  147. spans = spans.Where(IsSearchTerm).ToList();
  148. spans.Count.Should().Be(1);
  149. AssertSearchTermClassified(spans[0], snapshotSpan, searchTerm, offset1);
  150. }
  151. [Test]
  152. public void ClassifiesWholeWordsOnly()
  153. {
  154. const string searchTerm = "class";
  155. var text = GetCaseInsensitiveWholeWordResultsText(searchTerm, CaseInsensitiveWholeWordResults);
  156. var offset1 = CaseInsensitiveWholeWordResults.IndexOf(searchTerm, StringComparison.OrdinalIgnoreCase);
  157. PrimeClassifierSearchOptionsWithFirstLine(text);
  158. var snapshotSpan = BuildSnapshotSpanFromLineNumber(text, 1);
  159. var spans = classifier.GetClassificationSpans(snapshotSpan);
  160. spans = spans.Where(IsSearchTerm).ToList();
  161. spans.Count.Should().Be(1);
  162. AssertSearchTermClassified(spans[0], snapshotSpan, searchTerm, offset1);
  163. }
  164. [Test]
  165. public void ClassifiesFilename()
  166. {
  167. const string searchTerm = "not found";
  168. var text = GetCaseInsensitiveResultsText(searchTerm, UsingResultsLine1, UsingResultsLine2);
  169. PrimeClassifierSearchOptionsWithFirstLine(text);
  170. var snapshotSpan = BuildSnapshotSpanFromLineNumber(text, 1);
  171. var spans = classifier.GetClassificationSpans(snapshotSpan);
  172. spans.Count.Should().Be(1);
  173. AssertFilenameClassified(spans[0], snapshotSpan);
  174. }
  175. [Test]
  176. public void DoesNotClassifySearchTermInFilename()
  177. {
  178. const string searchTerm = @"C:\Projects";
  179. var text = GetCaseInsensitiveResultsText(searchTerm, UsingResultsLine1, UsingResultsLine2);
  180. PrimeClassifierSearchOptionsWithFirstLine(text);
  181. var snapshotSpan = BuildSnapshotSpanFromLineNumber(text, 1);
  182. var spans = classifier.GetClassificationSpans(snapshotSpan);
  183. var searchSpans = spans.Where(IsSearchTerm);
  184. searchSpans.Count().Should().Be(0);
  185. spans.Count.Should().Be(1);
  186. AssertFilenameClassified(spans[0], snapshotSpan);
  187. }
  188. [Test]
  189. public void DoesNotClassifyAnythingWhenListingFilenamesOnly()
  190. {
  191. const string searchTerm = "using";
  192. var intro = BuildFindResultsBanner(searchTerm, filenamesOnly: true);
  193. var text = BuildResultsLines(intro, UsingResultsLine1, UsingResultsLine2);
  194. PrimeClassifierSearchOptionsWithFirstLine(text);
  195. var snapshotSpan = BuildSnapshotSpanFromLineNumber(text, 1);
  196. var spans = classifier.GetClassificationSpans(snapshotSpan);
  197. spans.Count.Should().Be(0);
  198. }
  199. private static bool IsSearchTerm(ClassificationSpan s)
  200. {
  201. return s.ClassificationType.Classification == OutputClassificationDefinitions.FindResultsSearchTerm;
  202. }
  203. private static void AssertFilenameClassified(ClassificationSpan classificationSpan, SnapshotSpan snapshotSpan)
  204. {
  205. var text = snapshotSpan.GetText();
  206. var index = text.IndexOf(':');
  207. index = text.IndexOf(':', index + 1);
  208. AssertClassification(classificationSpan, OutputClassificationDefinitions.FindResultsFilename, snapshotSpan.Start.Position, index + 1);
  209. }
  210. private static void AssertSearchTermClassified(ClassificationSpan classificationSpan, SnapshotSpan snapshotSpan, string searchTerm, int searchTermStart)
  211. {
  212. AssertClassification(classificationSpan, OutputClassificationDefinitions.FindResultsSearchTerm, snapshotSpan.Start.Position + searchTermStart, searchTerm.Length);
  213. }
  214. private static void AssertClassification(ClassificationSpan classificationSpan, string classificationType, int spanStart, int spanLength)
  215. {
  216. classificationSpan.ClassificationType.Classification.Should().Match(classificationType);
  217. classificationSpan.Span.Start.Position.Should().Be(spanStart);
  218. classificationSpan.Span.Length.Should().Be(spanLength);
  219. }
  220. private void PrimeClassifierSearchOptionsWithFirstLine(string text)
  221. {
  222. var introSnapshotSpan = BuildSnapshotSpanFromLineNumber(text, 0);
  223. classifier.GetClassificationSpans(introSnapshotSpan);
  224. }
  225. private static string GetCaseInsensitiveResultsText(string searchTerm, params string[] resultLines)
  226. {
  227. var intro = BuildFindResultsBanner(searchTerm);
  228. return BuildResultsLines(intro, resultLines);
  229. }
  230. private static string GetCaseSensitiveResultsText(string searchTerm, params string[] resultLines)
  231. {
  232. var intro = BuildFindResultsBanner(searchTerm, caseSensitive: true);
  233. return BuildResultsLines(intro, resultLines);
  234. }
  235. private static string GetCaseInsensitiveWholeWordResultsText(string searchTerm, params string[] resultLines)
  236. {
  237. var intro = BuildFindResultsBanner(searchTerm, matchWord: true);
  238. return BuildResultsLines(intro, resultLines);
  239. }
  240. private static string BuildFindResultsBanner(string searchTerm, bool caseSensitive = false, bool matchWord = false,
  241. bool usingRegularExpressions = false, bool usingWildcards = false, bool filenamesOnly = false, bool filterByFiles = false)
  242. {
  243. var strings = new List<string> {ResultsPreamble + searchTerm + ResultsPreambleEnd};
  244. if (caseSensitive)
  245. strings.Add(ResultsMatchCase);
  246. if (matchWord)
  247. strings.Add(ResultsMatchWord);
  248. if (usingRegularExpressions)
  249. strings.Add(ResultsUsingRegex);
  250. if (usingWildcards)
  251. strings.Add(ResultsUsingWildcards);
  252. strings.Add(ResultsSubfolders);
  253. if (filenamesOnly)
  254. strings.Add(ResultsFilenamesOnly);
  255. strings.Add(ResultsLookIn);
  256. if (filterByFiles)
  257. strings.Add(ResultsFileTypes);
  258. return string.Join(", ", strings.ToArray());
  259. }
  260. private static string BuildResultsLines(string firstLine, params string[] lines)
  261. {
  262. return firstLine + Environment.NewLine + string.Join(Environment.NewLine, lines);
  263. }
  264. private static SnapshotSpan BuildSnapshotSpanFromLineNumber(string text, int lineNumber)
  265. {
  266. var textSnapshot = new FakeTextSnapshot(text);
  267. var textSnapshotLine = textSnapshot.GetLineFromLineNumber(lineNumber);
  268. return new SnapshotSpan(textSnapshot, textSnapshotLine.Start, textSnapshotLine.Length);
  269. }
  270. }
  271. }