Skip to content
This repository was archived by the owner on Aug 26, 2022. It is now read-only.

Commit 1c71600

Browse files
akashlalpdeligia
authored andcommitted
Fix coverage reporting across multiple invocations of the testing engine (#450)
1 parent 613c185 commit 1c71600

File tree

4 files changed

+78
-35
lines changed

4 files changed

+78
-35
lines changed

Source/Core/Runtime/Machines/MachineFactory.cs

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ internal static class MachineFactory
1717
/// <summary>
1818
/// Cache storing machine constructors.
1919
/// </summary>
20-
private static Dictionary<Type, Func<Machine>> MachineConstructorCache =
20+
private static readonly Dictionary<Type, Func<Machine>> MachineConstructorCache =
2121
new Dictionary<Type, Func<Machine>>();
2222

2323
/// <summary>
@@ -39,18 +39,5 @@ public static Machine Create(Type type)
3939
return constructor();
4040
}
4141
}
42-
43-
/// <summary>
44-
/// Checks if the constructor of the specified machine type exists in the cache.
45-
/// </summary>
46-
/// <param name="type">Type of the machine.</param>
47-
/// <returns>True if the constructor exists, else false.</returns>
48-
internal static bool IsCached(Type type)
49-
{
50-
lock (MachineConstructorCache)
51-
{
52-
return MachineConstructorCache.ContainsKey(type);
53-
}
54-
}
5542
}
5643
}

Source/TestingServices/Runtime/SystematicTestingRuntime.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -495,7 +495,6 @@ private Machine CreateMachine(MachineId mid, Type type, string machineName, Mach
495495
opGroupId = creator.OperationGroupId;
496496
}
497497

498-
var isMachineTypeCached = MachineFactory.IsCached(type);
499498
Machine machine = MachineFactory.Create(type);
500499
this.MachineOperations.GetOrAdd(mid.Value, new AsyncOperation(mid));
501500
IMachineStateManager stateManager = new SerializedMachineStateManager(this, machine, opGroupId);
@@ -504,7 +503,7 @@ private Machine CreateMachine(MachineId mid, Type type, string machineName, Mach
504503
machine.Initialize(this, mid, stateManager, eventQueue);
505504
machine.InitializeStateInformation();
506505

507-
if (this.Configuration.ReportActivityCoverage && !isMachineTypeCached)
506+
if (this.Configuration.ReportActivityCoverage)
508507
{
509508
this.ReportActivityCoverageOfMachine(machine);
510509
}
@@ -1474,18 +1473,20 @@ private void ReportActivityCoverageOfMonitorEvent(AsyncMachine sender, Monitor m
14741473
private void ReportActivityCoverageOfMachine(Machine machine)
14751474
{
14761475
var machineName = machine.GetType().FullName;
1476+
if (this.CoverageInfo.IsMachineDeclared(machineName))
1477+
{
1478+
return;
1479+
}
14771480

14781481
// Fetch states.
14791482
var states = machine.GetAllStates();
1480-
14811483
foreach (var state in states)
14821484
{
14831485
this.CoverageInfo.DeclareMachineState(machineName, state);
14841486
}
14851487

14861488
// Fetch registered events.
14871489
var pairs = machine.GetAllStateEventPairs();
1488-
14891490
foreach (var tup in pairs)
14901491
{
14911492
this.CoverageInfo.DeclareStateEvent(machineName, tup.Item1, tup.Item2);

Source/TestingServices/Statistics/Coverage/CoverageInfo.cs

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,14 @@ public CoverageInfo()
4444
this.Transitions = new HashSet<Transition>();
4545
}
4646

47+
/// <summary>
48+
/// Checks if the machine type has already been registered for coverage.
49+
/// </summary>
50+
public bool IsMachineDeclared(string machineName) => this.MachinesToStates.ContainsKey(machineName);
51+
4752
/// <summary>
4853
/// Adds a new transition.
4954
/// </summary>
50-
/// <param name="machineOrigin">Origin machine</param>
51-
/// <param name="stateOrigin">Origin state</param>
52-
/// <param name="edgeLabel">Edge label</param>
53-
/// <param name="machineTarget">Target machine</param>
54-
/// <param name="stateTarget">Target state</param>
5555
public void AddTransition(string machineOrigin, string stateOrigin, string edgeLabel,
5656
string machineTarget, string stateTarget)
5757
{
@@ -64,19 +64,11 @@ public void AddTransition(string machineOrigin, string stateOrigin, string edgeL
6464
/// <summary>
6565
/// Declares a state.
6666
/// </summary>
67-
/// <param name="machine">Machine name</param>
68-
/// <param name="state">state name</param>
69-
public void DeclareMachineState(string machine, string state)
70-
{
71-
this.AddState(machine, state);
72-
}
67+
public void DeclareMachineState(string machine, string state) => this.AddState(machine, state);
7368

7469
/// <summary>
7570
/// Declares a registered state, event pair.
7671
/// </summary>
77-
/// <param name="machine">Machine name</param>
78-
/// <param name="state">state name</param>
79-
/// <param name="eventName">Event name that the state is prepared to handle</param>
8072
public void DeclareStateEvent(string machine, string state, string eventName)
8173
{
8274
this.AddState(machine, state);
@@ -87,7 +79,6 @@ public void DeclareStateEvent(string machine, string state, string eventName)
8779
/// Merges the information from the specified
8880
/// coverage info. This is not thread-safe.
8981
/// </summary>
90-
/// <param name="coverageInfo">CoverageInfo</param>
9182
public void Merge(CoverageInfo coverageInfo)
9283
{
9384
foreach (var machine in coverageInfo.MachinesToStates)
@@ -113,8 +104,6 @@ public void Merge(CoverageInfo coverageInfo)
113104
/// <summary>
114105
/// Adds a new state.
115106
/// </summary>
116-
/// <param name="machineName">Machine name</param>
117-
/// <param name="stateName">State name</param>
118107
private void AddState(string machineName, string stateName)
119108
{
120109
if (!this.MachinesToStates.ContainsKey(machineName))

Tests/TestingServices.Tests/Coverage/ActivityCoverageTest.cs

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,5 +220,71 @@ public void TestMachineSendEventActivityCoverage()
220220
expected = RemoveExcessiveEmptySpaceFromReport(expected);
221221
Assert.Equal(expected, result);
222222
}
223+
224+
internal class M4 : Machine
225+
{
226+
[Start]
227+
[OnEventGotoState(typeof(E), typeof(Done))]
228+
internal class Init : MachineState
229+
{
230+
}
231+
232+
internal class Done : MachineState
233+
{
234+
}
235+
}
236+
237+
[Fact(Timeout = 5000)]
238+
public void TestCoverageOnMultipleTests()
239+
{
240+
var configuration = Configuration.Create().WithVerbosityEnabled();
241+
configuration.ReportActivityCoverage = true;
242+
243+
ITestingEngine testingEngine1 = this.Test(r =>
244+
{
245+
var m = r.CreateMachine(typeof(M4));
246+
r.SendEvent(m, new E());
247+
},
248+
configuration);
249+
250+
// Assert that the coverage is as expected.
251+
var coverage1 = testingEngine1.TestReport.CoverageInfo;
252+
Assert.Contains(typeof(M4).FullName, coverage1.MachinesToStates.Keys);
253+
Assert.Contains(typeof(M4.Init).Name, coverage1.MachinesToStates[typeof(M4).FullName]);
254+
Assert.Contains(typeof(M4.Done).Name, coverage1.MachinesToStates[typeof(M4).FullName]);
255+
Assert.Contains(coverage1.RegisteredEvents, tup => tup.Item3 == typeof(E).FullName);
256+
257+
ITestingEngine testingEngine2 = this.Test(r =>
258+
{
259+
var m = r.CreateMachine(typeof(M4));
260+
r.SendEvent(m, new E());
261+
},
262+
configuration);
263+
264+
// Assert that the coverage is the same as before.
265+
var coverage2 = testingEngine2.TestReport.CoverageInfo;
266+
Assert.Contains(typeof(M4).FullName, coverage2.MachinesToStates.Keys);
267+
Assert.Contains(typeof(M4.Init).Name, coverage2.MachinesToStates[typeof(M4).FullName]);
268+
Assert.Contains(typeof(M4.Done).Name, coverage2.MachinesToStates[typeof(M4).FullName]);
269+
Assert.Contains(coverage2.RegisteredEvents, tup => tup.Item3 == typeof(E).FullName);
270+
271+
string coverageReport1, coverageReport2;
272+
273+
var activityCoverageReporter = new ActivityCoverageReporter(coverage1);
274+
using (var writer = new StringWriter())
275+
{
276+
activityCoverageReporter.WriteCoverageText(writer);
277+
coverageReport1 = writer.ToString();
278+
}
279+
280+
activityCoverageReporter = new ActivityCoverageReporter(coverage2);
281+
using (var writer = new StringWriter())
282+
{
283+
activityCoverageReporter.WriteCoverageText(writer);
284+
coverageReport2 = writer.ToString();
285+
}
286+
287+
Assert.Equal(coverageReport1, coverageReport2);
288+
}
223289
}
224290
}

0 commit comments

Comments
 (0)