Skip to content

Commit 98dd544

Browse files
committed
Added Declined signal -- currently unused but logged to aid in uncovering edge cases
Added more unit tests
1 parent 7f83b67 commit 98dd544

File tree

4 files changed

+285
-79
lines changed

4 files changed

+285
-79
lines changed

Rubberduck.Core/UnitTesting/TestEngine.cs

Lines changed: 80 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -101,104 +101,106 @@ private void RunInternal(IEnumerable<TestMethod> tests)
101101
return;
102102
}
103103

104-
_state.OnSuspendParser(this, () =>
104+
_state.OnSuspendParser(this, () => RunWhileSuspended(tests));
105+
}
106+
107+
private void RunWhileSuspended(IEnumerable<TestMethod> tests)
108+
{
109+
var testMethods = tests as IList<TestMethod> ?? tests.ToList();
110+
if (!testMethods.Any())
105111
{
106-
var testMethods = tests as IList<TestMethod> ?? tests.ToList();
107-
if (!testMethods.Any())
108-
{
109-
return;
110-
}
112+
return;
113+
}
111114

112-
try
115+
try
116+
{
117+
var modules = testMethods.GroupBy(test => test.Declaration.QualifiedName.QualifiedModuleName);
118+
foreach (var module in modules)
113119
{
114-
var modules = testMethods.GroupBy(test => test.Declaration.QualifiedName.QualifiedModuleName);
115-
foreach (var module in modules)
116-
{
117-
var testInitialize = module.Key.FindTestInitializeMethods(_state).ToList();
118-
var testCleanup = module.Key.FindTestCleanupMethods(_state).ToList();
120+
var testInitialize = module.Key.FindTestInitializeMethods(_state).ToList();
121+
var testCleanup = module.Key.FindTestCleanupMethods(_state).ToList();
119122

120-
var capturedModule = module;
121-
var moduleTestMethods = testMethods
122-
.Where(test =>
123-
{
124-
var qmn = test.Declaration.QualifiedName.QualifiedModuleName;
123+
var capturedModule = module;
124+
var moduleTestMethods = testMethods
125+
.Where(test =>
126+
{
127+
var qmn = test.Declaration.QualifiedName.QualifiedModuleName;
125128

126-
return qmn.ProjectId == capturedModule.Key.ProjectId
127-
&& qmn.ComponentName == capturedModule.Key.ComponentName;
128-
});
129+
return qmn.ProjectId == capturedModule.Key.ProjectId
130+
&& qmn.ComponentName == capturedModule.Key.ComponentName;
131+
});
129132

130-
var fakes = _fakesFactory.Create();
131-
var initializeMethods = module.Key.FindModuleInitializeMethods(_state);
132-
try
133+
var fakes = _fakesFactory.Create();
134+
var initializeMethods = module.Key.FindModuleInitializeMethods(_state);
135+
try
136+
{
137+
RunInternal(initializeMethods);
138+
}
139+
catch (COMException ex)
140+
{
141+
Logger.Error(ex,
142+
"Unexpected COM exception while initializing tests for module {0}. The module will be skipped.",
143+
module.Key.Name);
144+
foreach (var method in moduleTestMethods)
133145
{
134-
RunInternal(initializeMethods);
146+
method.UpdateResult(TestOutcome.Unknown, AssertMessages.Assert_ComException);
135147
}
136-
catch (COMException ex)
148+
continue;
149+
}
150+
foreach (var test in moduleTestMethods)
151+
{
152+
// no need to run setup/teardown for ignored tests
153+
if (test.Declaration.Annotations.Any(a => a.AnnotationType == AnnotationType.IgnoreTest))
137154
{
138-
Logger.Error(ex,
139-
"Unexpected COM exception while initializing tests for module {0}. The module will be skipped.",
140-
module.Key.Name);
141-
foreach (var method in moduleTestMethods)
142-
{
143-
method.UpdateResult(TestOutcome.Unknown, AssertMessages.Assert_ComException);
144-
}
155+
test.UpdateResult(TestOutcome.Ignored);
156+
OnTestCompleted();
145157
continue;
146158
}
147-
foreach (var test in moduleTestMethods)
148-
{
149-
// no need to run setup/teardown for ignored tests
150-
if (test.Declaration.Annotations.Any(a => a.AnnotationType == AnnotationType.IgnoreTest))
151-
{
152-
test.UpdateResult(TestOutcome.Ignored);
153-
OnTestCompleted();
154-
continue;
155-
}
156-
157-
var stopwatch = new Stopwatch();
158-
stopwatch.Start();
159-
160-
try
161-
{
162-
fakes.StartTest();
163-
RunInternal(testInitialize);
164-
test.Run();
165-
RunInternal(testCleanup);
166-
}
167-
catch (COMException ex)
168-
{
169-
Logger.Error(ex, "Unexpected COM exception while running tests.");
170-
test.UpdateResult(TestOutcome.Inconclusive, AssertMessages.Assert_ComException);
171-
}
172-
finally
173-
{
174-
fakes.StopTest();
175-
}
176-
177-
stopwatch.Stop();
178-
test.Result.SetDuration(stopwatch.ElapsedMilliseconds);
179159

180-
OnTestCompleted();
181-
Model.AddExecutedTest(test);
182-
}
183-
var cleanupMethods = module.Key.FindModuleCleanupMethods(_state);
160+
var stopwatch = new Stopwatch();
161+
stopwatch.Start();
162+
184163
try
185164
{
186-
RunInternal(cleanupMethods);
165+
fakes.StartTest();
166+
RunInternal(testInitialize);
167+
test.Run();
168+
RunInternal(testCleanup);
187169
}
188170
catch (COMException ex)
189171
{
190-
Logger.Error(ex,
191-
"Unexpected COM exception while cleaning up tests for module {0}. Aborting any further unit tests",
192-
module.Key.Name);
193-
break;
172+
Logger.Error(ex, "Unexpected COM exception while running tests.");
173+
test.UpdateResult(TestOutcome.Inconclusive, AssertMessages.Assert_ComException);
194174
}
175+
finally
176+
{
177+
fakes.StopTest();
178+
}
179+
180+
stopwatch.Stop();
181+
test.Result.SetDuration(stopwatch.ElapsedMilliseconds);
182+
183+
OnTestCompleted();
184+
Model.AddExecutedTest(test);
185+
}
186+
var cleanupMethods = module.Key.FindModuleCleanupMethods(_state);
187+
try
188+
{
189+
RunInternal(cleanupMethods);
190+
}
191+
catch (COMException ex)
192+
{
193+
Logger.Error(ex,
194+
"Unexpected COM exception while cleaning up tests for module {0}. Aborting any further unit tests",
195+
module.Key.Name);
196+
break;
195197
}
196198
}
197-
catch (Exception ex)
198-
{
199-
Logger.Error(ex, "Unexpected expection while running unit tests; unit tests will be aborted");
200-
}
201-
});
199+
}
200+
catch (Exception ex)
201+
{
202+
Logger.Error(ex, "Unexpected expection while running unit tests; unit tests will be aborted");
203+
}
202204
}
203205

204206
private void RunInternal(IEnumerable<Declaration> members)

Rubberduck.Parsing/VBA/ParseCoordinator.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,12 @@ public void SuspendRequested(object sender, RubberduckStatusSuspendParserEventAr
123123

124124
try
125125
{
126+
if (_parsingSuspendLock.IsReadLockHeld)
127+
{
128+
Logger.Warn("A suspension action was attempted while a read lock was held.");
129+
e.Declined = true;
130+
return;
131+
}
126132
_parsingSuspendLock.EnterWriteLock();
127133
Interlocked.Add(ref _suspensionIteration, 1);
128134
var originalStatus = State.Status;

Rubberduck.Parsing/VBA/RubberduckParserState.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ public RubberduckStatusSuspendParserEventArgs(object requestor, Action busyActio
6565
BusyAction = busyAction;
6666
}
6767

68+
public bool Declined { get; set; }
6869
public object Requestor { get; }
6970
public Action BusyAction { get; }
7071
}
@@ -931,14 +932,17 @@ public void OnParseRequested(object requestor)
931932
}
932933
}
933934

934-
public void OnSuspendParser(object requestor, Action busyAction)
935+
public bool OnSuspendParser(object requestor, Action busyAction)
935936
{
936937
var handler = SuspendRequest;
937938
if (handler != null && IsEnabled)
938939
{
939940
var args = new RubberduckStatusSuspendParserEventArgs(requestor, busyAction);
940941
handler.Invoke(requestor, args);
942+
return !args.Declined;
941943
}
944+
945+
return false;
942946
}
943947

944948
public bool IsNewOrModified(IVBComponent component)

0 commit comments

Comments
 (0)