From dbbb6b3fad032aabbe4ca072f966ee7660a9bb8d Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Sun, 6 Dec 2015 07:14:36 -0800 Subject: [PATCH] Actually make trait filter work and get rid of lots unnecessary allocation --- xunit.runner.wpf/ITestUtil.cs | 11 +-- xunit.runner.wpf/Impl/RemoteTestUtil.cs | 10 +-- xunit.runner.wpf/ViewModel/MainViewModel.cs | 69 ++++++++----------- .../ViewModel/TraitCollectionView.cs | 17 ++++- xunit.runner.wpf/ViewModel/TraitViewModel.cs | 14 ++++ 5 files changed, 63 insertions(+), 58 deletions(-) diff --git a/xunit.runner.wpf/ITestUtil.cs b/xunit.runner.wpf/ITestUtil.cs index e6566ba..35f786a 100644 --- a/xunit.runner.wpf/ITestUtil.cs +++ b/xunit.runner.wpf/ITestUtil.cs @@ -1,14 +1,9 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; -using System.Collections.ObjectModel; -using System.Linq; -using System.Text; using System.Threading; using System.Threading.Tasks; -using System.Windows.Threading; using xunit.runner.data; -using xunit.runner.wpf.ViewModel; namespace xunit.runner.wpf { @@ -17,16 +12,16 @@ namespace xunit.runner.wpf /// /// Discover the list of test cases which are available in the specified assembly. /// - Task Discover(string assemblyPath, Action> callback, CancellationToken cancellationToken = default(CancellationToken)); + Task Discover(string assemblyPath, Action> callback, CancellationToken cancellationToken = default(CancellationToken)); /// /// Begin a run of all unit tests for the given assembly. /// - Task RunAll(string assemblyPath, Action> callback, CancellationToken cancellationToken = default(CancellationToken)); + Task RunAll(string assemblyPath, Action> callback, CancellationToken cancellationToken = default(CancellationToken)); /// /// Begin a run of specific unit tests for the given assembly. /// - Task RunSpecific(string assemblyPath, ImmutableArray testCaseDisplayNames, Action> callback, CancellationToken cancellationToken = default(CancellationToken)); + Task RunSpecific(string assemblyPath, ImmutableArray testCaseDisplayNames, Action> callback, CancellationToken cancellationToken = default(CancellationToken)); } } diff --git a/xunit.runner.wpf/Impl/RemoteTestUtil.cs b/xunit.runner.wpf/Impl/RemoteTestUtil.cs index aa94034..64dbabe 100644 --- a/xunit.runner.wpf/Impl/RemoteTestUtil.cs +++ b/xunit.runner.wpf/Impl/RemoteTestUtil.cs @@ -3,15 +3,11 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; -using System.IO; using System.IO.Pipes; -using System.Linq; -using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Threading; using xunit.runner.data; -using xunit.runner.wpf.ViewModel; namespace xunit.runner.wpf.Impl { @@ -137,17 +133,17 @@ namespace xunit.runner.wpf.Impl #region ITestUtil - Task ITestUtil.Discover(string assemblyPath, Action> callback, CancellationToken cancellationToken) + Task ITestUtil.Discover(string assemblyPath, Action> callback, CancellationToken cancellationToken) { return Discover(assemblyPath, callback, cancellationToken); } - Task ITestUtil.RunAll(string assemblyPath, Action> callback, CancellationToken cancellationToken) + Task ITestUtil.RunAll(string assemblyPath, Action> callback, CancellationToken cancellationToken) { return RunCore(Constants.ActionRunAll, assemblyPath, ImmutableArray.Empty, callback, cancellationToken); } - Task ITestUtil.RunSpecific(string assemblyPath, ImmutableArray testCaseDisplayNames, Action> callback, CancellationToken cancellationToken) + Task ITestUtil.RunSpecific(string assemblyPath, ImmutableArray testCaseDisplayNames, Action> callback, CancellationToken cancellationToken) { return RunCore(Constants.ActionRunSpecific, assemblyPath, testCaseDisplayNames, callback, cancellationToken); } diff --git a/xunit.runner.wpf/ViewModel/MainViewModel.cs b/xunit.runner.wpf/ViewModel/MainViewModel.cs index c79b0f9..1d1f249 100644 --- a/xunit.runner.wpf/ViewModel/MainViewModel.cs +++ b/xunit.runner.wpf/ViewModel/MainViewModel.cs @@ -477,57 +477,42 @@ namespace xunit.runner.wpf.ViewModel } } - private void OnTestDiscovered(List testCaseDataList) + private void OnTestDiscovered(IEnumerable testCases) { - var allTraits = new SortedDictionary>(); - foreach (var data in testCaseDataList) + var traitWorkerList = new List(); + + foreach (var testCase in testCases) { - AddTraits(allTraits, data); - } + traitWorkerList.Clear(); - this.allTestCases.AddRange(testCaseDataList.Select(d => - new TestCaseViewModel(d.DisplayName, d.AssemblyPath, Convert(CreateSortedTraits(d))))); - - this.traitCollectionView.AddRange(Convert(allTraits)); - } - - private SortedDictionary> CreateSortedTraits(TestCaseData data) - { - var traits = new SortedDictionary>(); - AddTraits(traits, data); - return traits; - } - - private static IEnumerable Convert(SortedDictionary> allTraits) - { - foreach (var trait in allTraits) - { - var name = trait.Key; - var values = trait.Value; - - var viewModel = new TraitViewModel(name); - viewModel.AddValues(values); - - yield return viewModel; - } - } - - private static void AddTraits(SortedDictionary> allTraits, TestCaseData data) - { - foreach (var kvp in data.TraitMap) - { - SortedSet values; - if (!allTraits.TryGetValue(kvp.Key, out values)) + // Get or create traits. + if (testCase.TraitMap?.Count > 0) { - values = new SortedSet(); - allTraits.Add(kvp.Key, values); + foreach (var kvp in testCase.TraitMap) + { + var name = kvp.Key; + var values = kvp.Value; + + var parentTraitViewModel = traitCollectionView.GetOrAdd(name); + + foreach (var value in values) + { + var traitViewModel = parentTraitViewModel.GetOrAdd(value); + traitWorkerList.Add(traitViewModel); + } + } } - values.AddRange(kvp.Value); + var testCaseViewModel = new TestCaseViewModel( + testCase.DisplayName, + testCase.AssemblyPath, + traitWorkerList); + + this.allTestCases.Add(testCaseViewModel); } } - private void OnTestFinished(List testResultData) + private void OnTestFinished(IEnumerable testResultData) { foreach (var data in testResultData) { diff --git a/xunit.runner.wpf/ViewModel/TraitCollectionView.cs b/xunit.runner.wpf/ViewModel/TraitCollectionView.cs index fb5610b..ef5297b 100644 --- a/xunit.runner.wpf/ViewModel/TraitCollectionView.cs +++ b/xunit.runner.wpf/ViewModel/TraitCollectionView.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; @@ -26,6 +27,20 @@ namespace xunit.runner.wpf.ViewModel } } + public TraitViewModel GetOrAdd(string text) + { + var index = this.Collection.BinarySearch(text, StringComparer.Ordinal, vm => vm.Text); + + if (index < 0) + { + var viewModel = new TraitViewModel(text); + this.Collection.Insert(~index, viewModel); + return viewModel; + } + + return this.Collection[index]; + } + public ISet GetCheckedTraits() { return new HashSet( diff --git a/xunit.runner.wpf/ViewModel/TraitViewModel.cs b/xunit.runner.wpf/ViewModel/TraitViewModel.cs index 526bfdd..8854415 100644 --- a/xunit.runner.wpf/ViewModel/TraitViewModel.cs +++ b/xunit.runner.wpf/ViewModel/TraitViewModel.cs @@ -87,6 +87,20 @@ namespace xunit.runner.wpf.ViewModel } } + public TraitViewModel GetOrAdd(string text) + { + var index = this.Children.BinarySearch(text, StringComparer.Ordinal, vm => vm.Text); + + if (index < 0) + { + var viewModel = new TraitViewModel(this, text); + this.Children.Insert(~index, viewModel); + return viewModel; + } + + return this.Children[index]; + } + public bool? IsChecked { get { return _isChecked; }