From 961940cc78e3b85f0b4b958dac9fb287a79c9335 Mon Sep 17 00:00:00 2001 From: Adam Cohen Date: Fri, 2 Dec 2022 04:44:14 -0500 Subject: [PATCH 1/9] MM --- .../Microsoft.StreamProcessing.Provider.csproj | 6 +++--- .../Microsoft.StreamProcessing.csproj | 6 +++--- Sources/Test/SimpleTesting/SimpleTesting.csproj | 13 ++++++++++--- Sources/Test/TrillPerf/PerformanceTesting.csproj | 11 +++++++++-- 4 files changed, 25 insertions(+), 11 deletions(-) diff --git a/Sources/Core/Microsoft.StreamProcessing.Provider/Microsoft.StreamProcessing.Provider.csproj b/Sources/Core/Microsoft.StreamProcessing.Provider/Microsoft.StreamProcessing.Provider.csproj index 1d9de4e69..b38205d12 100644 --- a/Sources/Core/Microsoft.StreamProcessing.Provider/Microsoft.StreamProcessing.Provider.csproj +++ b/Sources/Core/Microsoft.StreamProcessing.Provider/Microsoft.StreamProcessing.Provider.csproj @@ -1,7 +1,7 @@  - netstandard2.0 + net6.0;net7.0;net472 x64;AnyCPU @@ -11,11 +11,11 @@ - + - + diff --git a/Sources/Core/Microsoft.StreamProcessing/Microsoft.StreamProcessing.csproj b/Sources/Core/Microsoft.StreamProcessing/Microsoft.StreamProcessing.csproj index b96b07891..1fcb6e2c1 100644 --- a/Sources/Core/Microsoft.StreamProcessing/Microsoft.StreamProcessing.csproj +++ b/Sources/Core/Microsoft.StreamProcessing/Microsoft.StreamProcessing.csproj @@ -1,7 +1,7 @@  - netstandard2.0 + net6.0;net7.0;net472 x64;AnyCPU @@ -11,8 +11,8 @@ - - + + diff --git a/Sources/Test/SimpleTesting/SimpleTesting.csproj b/Sources/Test/SimpleTesting/SimpleTesting.csproj index 6e35f0351..9c01afb03 100644 --- a/Sources/Test/SimpleTesting/SimpleTesting.csproj +++ b/Sources/Test/SimpleTesting/SimpleTesting.csproj @@ -1,7 +1,7 @@  - net472;netcoreapp3.1 + net6.0;net7.0;net472net472;net7;net7]};net7211 AnyCPU @@ -11,14 +11,14 @@ - + - + false @@ -160,6 +160,13 @@ ShuffleStreamableTests.tt + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + diff --git a/Sources/Test/TrillPerf/PerformanceTesting.csproj b/Sources/Test/TrillPerf/PerformanceTesting.csproj index e7aae4a51..992c531ce 100644 --- a/Sources/Test/TrillPerf/PerformanceTesting.csproj +++ b/Sources/Test/TrillPerf/PerformanceTesting.csproj @@ -2,14 +2,21 @@ Exe - net472;netcoreapp3.1 + net472;net6.0;net7.0 AnyCPU - + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + From a28d04e1ec767b7142744362bda542b0168517b3 Mon Sep 17 00:00:00 2001 From: Adam Cohen Date: Fri, 2 Dec 2022 09:28:00 -0500 Subject: [PATCH 2/9] 1.GlobalSuppression file added to supress irregular naming conventions 2. Workaround to windows only thread affinity in Native32 for Linux 3. Solution updated to target Net7, Net6, Net472, and NetCoreapp3.1 --- Sources/.editorconfig | 12 ++++- ...Microsoft.StreamProcessing.Provider.csproj | 2 +- .../Microsoft.StreamProcessing.csproj | 2 +- .../Utilities/Native32.cs | 12 ++++- .../Test/SimpleTesting/GlobalSuppressions.cs | 24 +++++++++ .../Macros/LeftOuterJoinTests.cs | 16 +++--- .../Test/SimpleTesting/SimpleTesting.csproj | 2 +- .../SimpleTesting/Streamables/AfaTests.cs | 52 +++++++++---------- .../SimpleTesting/Streamables/JoinTests.cs | 16 +++--- .../Test/TrillPerf/PerformanceTesting.csproj | 2 +- 10 files changed, 91 insertions(+), 49 deletions(-) create mode 100644 Sources/Test/SimpleTesting/GlobalSuppressions.cs diff --git a/Sources/.editorconfig b/Sources/.editorconfig index 1bae2e959..116ea2776 100644 --- a/Sources/.editorconfig +++ b/Sources/.editorconfig @@ -50,4 +50,14 @@ csharp_new_line_before_catch = true csharp_new_line_before_finally = true csharp_indent_case_contents = true csharp_indent_switch_labels = true -csharp_preserve_single_line_statements = false \ No newline at end of file +csharp_preserve_single_line_statements = false +[*.cs] + +# Default severity for analyzer diagnostics with category 'StyleCop.CSharp.NamingRules' +dotnet_analyzer_diagnostic.category-StyleCop.CSharp.NamingRules.severity = none + +# Default severity for all analyzer diagnostics +dotnet_analyzer_diagnostic.severity = none + +# SA1314: Type parameter names should begin with T +dotnet_diagnostic.SA1314.severity = none diff --git a/Sources/Core/Microsoft.StreamProcessing.Provider/Microsoft.StreamProcessing.Provider.csproj b/Sources/Core/Microsoft.StreamProcessing.Provider/Microsoft.StreamProcessing.Provider.csproj index b38205d12..f60cb12a7 100644 --- a/Sources/Core/Microsoft.StreamProcessing.Provider/Microsoft.StreamProcessing.Provider.csproj +++ b/Sources/Core/Microsoft.StreamProcessing.Provider/Microsoft.StreamProcessing.Provider.csproj @@ -1,7 +1,7 @@  - net6.0;net7.0;net472 + net6.0;net7.0;net472;netcoreapp3.1 x64;AnyCPU diff --git a/Sources/Core/Microsoft.StreamProcessing/Microsoft.StreamProcessing.csproj b/Sources/Core/Microsoft.StreamProcessing/Microsoft.StreamProcessing.csproj index 1fcb6e2c1..284cb528d 100644 --- a/Sources/Core/Microsoft.StreamProcessing/Microsoft.StreamProcessing.csproj +++ b/Sources/Core/Microsoft.StreamProcessing/Microsoft.StreamProcessing.csproj @@ -1,7 +1,7 @@  - net6.0;net7.0;net472 + net6.0;net7.0;net472;netcoreapp3.1 x64;AnyCPU diff --git a/Sources/Core/Microsoft.StreamProcessing/Utilities/Native32.cs b/Sources/Core/Microsoft.StreamProcessing/Utilities/Native32.cs index f2924c0e7..d19a7ca57 100644 --- a/Sources/Core/Microsoft.StreamProcessing/Utilities/Native32.cs +++ b/Sources/Core/Microsoft.StreamProcessing/Utilities/Native32.cs @@ -74,8 +74,16 @@ internal static void AffinitizeThread(int processor) { if (utid == pt.Id) { - long AffinityMask = 1 << processor; - pt.ProcessorAffinity = (IntPtr)(AffinityMask); // Set affinity for this + if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + pt.IdealProcessor = processor; + } + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + long AffinityMask = 1 << processor; + pt.ProcessorAffinity = (IntPtr)(AffinityMask); // Set affinity for this + } } } } diff --git a/Sources/Test/SimpleTesting/GlobalSuppressions.cs b/Sources/Test/SimpleTesting/GlobalSuppressions.cs new file mode 100644 index 000000000..c89b555bf --- /dev/null +++ b/Sources/Test/SimpleTesting/GlobalSuppressions.cs @@ -0,0 +1,24 @@ +// This file is used by Code Analysis to maintain SuppressMessage +// attributes that are applied to this project. +// Project-level suppressions either have no target or are given +// a specific target and scoped to a namespace, type, member, etc. + +using System.Diagnostics.CodeAnalysis; + +[assembly: SuppressMessage("StyleCop.CSharp.NamingRules", "SA1300:Element should begin with upper-case letter", Justification = "", Scope = "member", Target = "~M:SimpleTesting.CheckpointRestoreTestsColumnar.CheckpointRegressionColumnar")] +[assembly: SuppressMessage("StyleCop.CSharp.NamingRules", "SA1300:Element should begin with upper-case letter", Justification = "", Scope = "member", Target = "~M:SimpleTesting.CheckpointRestoreTestsColumnar.MaxBug0Columnar")] +[assembly: SuppressMessage("StyleCop.CSharp.NamingRules", "SA1300:Element should begin with upper-case letter", Justification = "", Scope = "member", Target = "~M:SimpleTesting.CheckpointRestoreTestsColumnar.MaxBug1Columnar")] +[assembly: SuppressMessage("StyleCop.CSharp.NamingRules", "SA1300:Element should begin with upper-case letter", Justification = "", Scope = "member", Target = "~M:SimpleTesting.CheckpointRestoreTestsColumnar.MaxBug2Columnar")] +[assembly: SuppressMessage("StyleCop.CSharp.NamingRules", "SA1300:Element should begin with upper-case letter", Justification = "", Scope = "member", Target = "~M:SimpleTesting.CheckpointRestoreTestsColumnarSmallBatch.CheckpointRegressionColumnarSmallBatch")] +[assembly: SuppressMessage("StyleCop.CSharp.NamingRules", "SA1300:Element should begin with upper-case letter", Justification = "", Scope = "member", Target = "~M:SimpleTesting.CheckpointRestoreTestsColumnarSmallBatch.MaxBug0ColumnarSmallBatch")] +[assembly: SuppressMessage("StyleCop.CSharp.NamingRules", "SA1300:Element should begin with upper-case letter", Justification = "", Scope = "member", Target = "~M:SimpleTesting.CheckpointRestoreTestsColumnarSmallBatch.MaxBug1ColumnarSmallBatch")] +[assembly: SuppressMessage("StyleCop.CSharp.NamingRules", "SA1300:Element should begin with upper-case letter", Justification = "", Scope = "member", Target = "~M:SimpleTesting.CheckpointRestoreTestsColumnarSmallBatch.MaxBug2ColumnarSmallBatch")] +[assembly: SuppressMessage("StyleCop.CSharp.NamingRules", "SA1300:Element should begin with upper-case letter", Justification = "", Scope = "member", Target = "~M:SimpleTesting.CheckpointRestoreTestsRow.CheckpointRegressionRow")] +[assembly: SuppressMessage("StyleCop.CSharp.NamingRules", "SA1300:Element should begin with upper-case letter", Justification = "", Scope = "member", Target = "~M:SimpleTesting.CheckpointRestoreTestsRow.MaxBug0Row")] +[assembly: SuppressMessage("StyleCop.CSharp.NamingRules", "SA1300:Element should begin with upper-case letter", Justification = "", Scope = "member", Target = "~M:SimpleTesting.CheckpointRestoreTestsRow.MaxBug1Row")] +[assembly: SuppressMessage("StyleCop.CSharp.NamingRules", "SA1300:Element should begin with upper-case letter", Justification = "", Scope = "member", Target = "~M:SimpleTesting.CheckpointRestoreTestsRow.MaxBug2Row")] +[assembly: SuppressMessage("StyleCop.CSharp.NamingRules", "SA1300:Element should begin with upper-case letter", Justification = "", Scope = "member", Target = "~M:SimpleTesting.CheckpointRestoreTestsRowSmallBatch.CheckpointRegressionRowSmallBatch")] +[assembly: SuppressMessage("StyleCop.CSharp.NamingRules", "SA1300:Element should begin with upper-case letter", Justification = "", Scope = "member", Target = "~M:SimpleTesting.CheckpointRestoreTestsRowSmallBatch.MaxBug0RowSmallBatch")] +[assembly: SuppressMessage("StyleCop.CSharp.NamingRules", "SA1300:Element should begin with upper-case letter", Justification = "", Scope = "member", Target = "~M:SimpleTesting.CheckpointRestoreTestsRowSmallBatch.MaxBug1RowSmallBatch")] +[assembly: SuppressMessage("StyleCop.CSharp.NamingRules", "SA1300:Element should begin with upper-case letter", Justification = "", Scope = "member", Target = "~M:SimpleTesting.CheckpointRestoreTestsRowSmallBatch.MaxBug2RowSmallBatch")] +[assembly: SuppressMessage("StyleCop.CSharp.NamingRules", "SA1305:Field names should not use Hungarian notation", Justification = "", Scope = "member", Target = "~M:SimpleTesting.Extensions.ToEvents``1(System.Collections.Generic.IEnumerable{``0},System.Func{``0,System.Int64},System.Func{``0,System.Int64})~System.Collections.Generic.IEnumerable{Microsoft.StreamProcessing.StreamEvent{``0}}")] diff --git a/Sources/Test/SimpleTesting/Macros/LeftOuterJoinTests.cs b/Sources/Test/SimpleTesting/Macros/LeftOuterJoinTests.cs index 6b778f07d..68c8b6593 100644 --- a/Sources/Test/SimpleTesting/Macros/LeftOuterJoinTests.cs +++ b/Sources/Test/SimpleTesting/Macros/LeftOuterJoinTests.cs @@ -82,8 +82,8 @@ public void LOJ1Row() var query = leftStream.LeftOuterJoin(rightStream, e => e.field1, e => e.field3, (l, r) => l.field2 != "E", - (l) => new MyData3 { field1 = l.field1, field2 = l.field2, field3 = tmp1, field4 = tmp2 }, - (l, r) => new MyData3 { field1 = l.field1, field2 = l.field2, field3 = r.field3, field4 = r.field4 }); + (l) => new MyData3 { field1 = l.field1, field2 = l.field2, field3 = tmp1, field4 = tmp2 }, + (l, r) => new MyData3 { field1 = l.field1, field2 = l.field2, field3 = r.field3, field4 = r.field4 }); var result = container.RegisterOutput(query, ReshapingPolicy.CoalesceEndEdges).Where(e => e.IsData); var resultAsync = result.ForEachAsync(o => output.Add(o)); @@ -144,8 +144,8 @@ public void LOJ1RowSmallBatch() var query = leftStream.LeftOuterJoin(rightStream, e => e.field1, e => e.field3, (l, r) => l.field2 != "E", - (l) => new MyData3 { field1 = l.field1, field2 = l.field2, field3 = tmp1, field4 = tmp2 }, - (l, r) => new MyData3 { field1 = l.field1, field2 = l.field2, field3 = r.field3, field4 = r.field4 }); + (l) => new MyData3 { field1 = l.field1, field2 = l.field2, field3 = tmp1, field4 = tmp2 }, + (l, r) => new MyData3 { field1 = l.field1, field2 = l.field2, field3 = r.field3, field4 = r.field4 }); var result = container.RegisterOutput(query, ReshapingPolicy.CoalesceEndEdges).Where(e => e.IsData); var resultAsync = result.ForEachAsync(o => output.Add(o)); @@ -205,8 +205,8 @@ public void LOJ1Columnar() var query = leftStream.LeftOuterJoin(rightStream, e => e.field1, e => e.field3, (l, r) => l.field2 != "E", - (l) => new MyData3 { field1 = l.field1, field2 = l.field2, field3 = tmp1, field4 = tmp2 }, - (l, r) => new MyData3 { field1 = l.field1, field2 = l.field2, field3 = r.field3, field4 = r.field4 }); + (l) => new MyData3 { field1 = l.field1, field2 = l.field2, field3 = tmp1, field4 = tmp2 }, + (l, r) => new MyData3 { field1 = l.field1, field2 = l.field2, field3 = r.field3, field4 = r.field4 }); var result = container.RegisterOutput(query, ReshapingPolicy.CoalesceEndEdges).Where(e => e.IsData); var resultAsync = result.ForEachAsync(o => output.Add(o)); @@ -267,8 +267,8 @@ public void LOJ1ColumnarSmallBatch() var query = leftStream.LeftOuterJoin(rightStream, e => e.field1, e => e.field3, (l, r) => l.field2 != "E", - (l) => new MyData3 { field1 = l.field1, field2 = l.field2, field3 = tmp1, field4 = tmp2 }, - (l, r) => new MyData3 { field1 = l.field1, field2 = l.field2, field3 = r.field3, field4 = r.field4 }); + (l) => new MyData3 { field1 = l.field1, field2 = l.field2, field3 = tmp1, field4 = tmp2 }, + (l, r) => new MyData3 { field1 = l.field1, field2 = l.field2, field3 = r.field3, field4 = r.field4 }); var result = container.RegisterOutput(query, ReshapingPolicy.CoalesceEndEdges).Where(e => e.IsData); var resultAsync = result.ForEachAsync(o => output.Add(o)); diff --git a/Sources/Test/SimpleTesting/SimpleTesting.csproj b/Sources/Test/SimpleTesting/SimpleTesting.csproj index 9c01afb03..546873730 100644 --- a/Sources/Test/SimpleTesting/SimpleTesting.csproj +++ b/Sources/Test/SimpleTesting/SimpleTesting.csproj @@ -1,7 +1,7 @@  - net6.0;net7.0;net472net472;net7;net7]};net7211 + net6.0;net7.0;net472;netcoreapp3.1 AnyCPU diff --git a/Sources/Test/SimpleTesting/Streamables/AfaTests.cs b/Sources/Test/SimpleTesting/Streamables/AfaTests.cs index 68aa36026..a48bd6fdd 100644 --- a/Sources/Test/SimpleTesting/Streamables/AfaTests.cs +++ b/Sources/Test/SimpleTesting/Streamables/AfaTests.cs @@ -845,15 +845,15 @@ public void GroupedAfa() var source = new StreamEvent>[] { StreamEvent.CreateStart(0, new Tuple("A", 1)), - StreamEvent.CreateStart(1, new Tuple("A", 2)), - StreamEvent.CreateStart(2, new Tuple("B", 2)), + StreamEvent.CreateStart(1, new Tuple("A", 2)), + StreamEvent.CreateStart(2, new Tuple("B", 2)), StreamEvent.CreateStart(3, new Tuple("A", 1)), StreamEvent.CreateStart(4, new Tuple("B", 1)), - StreamEvent.CreateStart(5, new Tuple("B", 2)), + StreamEvent.CreateStart(5, new Tuple("B", 2)), StreamEvent.CreateStart(6, new Tuple("B", 1)), StreamEvent.CreateStart(7, new Tuple("C", 1)), - StreamEvent.CreateStart(8, new Tuple("B", 2)), - StreamEvent.CreateStart(9, new Tuple("A", 2)), + StreamEvent.CreateStart(8, new Tuple("B", 2)), + StreamEvent.CreateStart(9, new Tuple("A", 2)), }.ToObservable() .ToStreamable() .AlterEventDuration(7); @@ -893,18 +893,18 @@ public void GroupedAfa_IsSyncTimeSimultaneityFree() var source = new StreamEvent>[] { StreamEvent.CreateStart(0, new Tuple("A", 1)), - StreamEvent.CreateStart(1, new Tuple("A", 2)), - StreamEvent.CreateStart(1, new Tuple("B", 2)), + StreamEvent.CreateStart(1, new Tuple("A", 2)), + StreamEvent.CreateStart(1, new Tuple("B", 2)), StreamEvent.CreateStart(3, new Tuple("A", 1)), StreamEvent.CreatePunctuation>(4), StreamEvent.CreateStart(4, new Tuple("B", 1)), - StreamEvent.CreateStart(4, new Tuple("B", 2)), + StreamEvent.CreateStart(4, new Tuple("B", 2)), StreamEvent.CreateStart(5, new Tuple("B", 1)), StreamEvent.CreateStart(5, new Tuple("C", 1)), - StreamEvent.CreateStart(6, new Tuple("B", 2)), - StreamEvent.CreateStart(7, new Tuple("A", 2)), + StreamEvent.CreateStart(6, new Tuple("B", 2)), + StreamEvent.CreateStart(7, new Tuple("A", 2)), StreamEvent.CreatePunctuation>(7), }.ToObservable() @@ -959,23 +959,23 @@ public void PartitionedAfa() var source = new PartitionedStreamEvent[] { PartitionedStreamEvent.CreateStart(1, 0, "A"), - PartitionedStreamEvent.CreateStart(2, 0, "A"), + PartitionedStreamEvent.CreateStart(2, 0, "A"), PartitionedStreamEvent.CreateStart(1, 1, "B"), PartitionedStreamEvent.CreateStart(1, 2, "B"), - PartitionedStreamEvent.CreateStart(2, 2, "B"), + PartitionedStreamEvent.CreateStart(2, 2, "B"), PartitionedStreamEvent.CreateStart(1, 3, "A"), PartitionedStreamEvent.CreateStart(1, 4, "C"), - PartitionedStreamEvent.CreateStart(2, 3, "C"), - PartitionedStreamEvent.CreateStart(2, 4, "A"), + PartitionedStreamEvent.CreateStart(2, 3, "C"), + PartitionedStreamEvent.CreateStart(2, 4, "A"), PartitionedStreamEvent.CreateStart(1, 5, "A"), PartitionedStreamEvent.CreateStart(1, 6, "B"), - PartitionedStreamEvent.CreateStart(2, 5, "B"), + PartitionedStreamEvent.CreateStart(2, 5, "B"), PartitionedStreamEvent.CreateStart(1, 7, "B"), - PartitionedStreamEvent.CreateStart(2, 6, "B"), + PartitionedStreamEvent.CreateStart(2, 6, "B"), PartitionedStreamEvent.CreateStart(1, 8, "B"), PartitionedStreamEvent.CreateStart(1, 9, "A"), - PartitionedStreamEvent.CreateStart(2, 7, "A"), - PartitionedStreamEvent.CreateStart(2, 8, "B") + PartitionedStreamEvent.CreateStart(2, 7, "A"), + PartitionedStreamEvent.CreateStart(2, 8, "B") }.ToObservable() .ToStreamable() .AlterEventDuration(7); @@ -1016,23 +1016,23 @@ public void PartitionedAfa_IsSyncTimeSimultaneityFree() var source = new PartitionedStreamEvent[] { PartitionedStreamEvent.CreateStart(1, 0, "A"), - PartitionedStreamEvent.CreateStart(2, 0, "A"), + PartitionedStreamEvent.CreateStart(2, 0, "A"), PartitionedStreamEvent.CreateStart(1, 1, "B"), PartitionedStreamEvent.CreateStart(1, 1, "B"), - PartitionedStreamEvent.CreateStart(2, 0, "B"), + PartitionedStreamEvent.CreateStart(2, 0, "B"), PartitionedStreamEvent.CreateStart(1, 3, "A"), PartitionedStreamEvent.CreateStart(1, 4, "C"), - PartitionedStreamEvent.CreateStart(2, 3, "C"), - PartitionedStreamEvent.CreateStart(2, 4, "A"), + PartitionedStreamEvent.CreateStart(2, 3, "C"), + PartitionedStreamEvent.CreateStart(2, 4, "A"), PartitionedStreamEvent.CreateStart(1, 5, "A"), PartitionedStreamEvent.CreateStart(1, 6, "B"), - PartitionedStreamEvent.CreateStart(2, 4, "B"), + PartitionedStreamEvent.CreateStart(2, 4, "B"), PartitionedStreamEvent.CreateStart(1, 7, "B"), - PartitionedStreamEvent.CreateStart(2, 6, "B"), + PartitionedStreamEvent.CreateStart(2, 6, "B"), PartitionedStreamEvent.CreateStart(1, 8, "B"), PartitionedStreamEvent.CreateStart(1, 9, "A"), - PartitionedStreamEvent.CreateStart(2, 7, "A"), - PartitionedStreamEvent.CreateStart(2, 8, "B") + PartitionedStreamEvent.CreateStart(2, 7, "A"), + PartitionedStreamEvent.CreateStart(2, 8, "B") }.ToObservable() .ToStreamable() .AlterEventDuration(7); diff --git a/Sources/Test/SimpleTesting/Streamables/JoinTests.cs b/Sources/Test/SimpleTesting/Streamables/JoinTests.cs index ca4ecb8c2..b5c2fe2e4 100644 --- a/Sources/Test/SimpleTesting/Streamables/JoinTests.cs +++ b/Sources/Test/SimpleTesting/Streamables/JoinTests.cs @@ -83,7 +83,7 @@ public void IOOEJ2RowMultiString() input2, e => e.field1, e => e, - (l, r) => new GameData() { EventType = l.field1, GameId = r, }); + (l, r) => new GameData() { EventType = l.field1, GameId = r, }); var result = query .ToPayloadEnumerable() .ToArray(); @@ -446,7 +446,7 @@ public void IOOEJ2RowRegularString() input2, e => e.field1, e => e, - (l, r) => new GameData() { EventType = l.field1, GameId = r, }); + (l, r) => new GameData() { EventType = l.field1, GameId = r, }); var result = query .ToPayloadEnumerable() .ToArray(); @@ -810,7 +810,7 @@ public void IOOEJ2RowSmallBatchMultiString() input2, e => e.field1, e => e, - (l, r) => new GameData() { EventType = l.field1, GameId = r, }); + (l, r) => new GameData() { EventType = l.field1, GameId = r, }); var result = query .ToPayloadEnumerable() .ToArray(); @@ -1174,7 +1174,7 @@ public void IOOEJ2RowSmallBatchRegularString() input2, e => e.field1, e => e, - (l, r) => new GameData() { EventType = l.field1, GameId = r, }); + (l, r) => new GameData() { EventType = l.field1, GameId = r, }); var result = query .ToPayloadEnumerable() .ToArray(); @@ -1537,7 +1537,7 @@ public void IOOEJ2ColumnarMultiString() input2, e => e.field1, e => e, - (l, r) => new GameData() { EventType = l.field1, GameId = r, }); + (l, r) => new GameData() { EventType = l.field1, GameId = r, }); var result = query .ToPayloadEnumerable() .ToArray(); @@ -1900,7 +1900,7 @@ public void IOOEJ2ColumnarRegularString() input2, e => e.field1, e => e, - (l, r) => new GameData() { EventType = l.field1, GameId = r, }); + (l, r) => new GameData() { EventType = l.field1, GameId = r, }); var result = query .ToPayloadEnumerable() .ToArray(); @@ -2264,7 +2264,7 @@ public void IOOEJ2ColumnarSmallBatchMultiString() input2, e => e.field1, e => e, - (l, r) => new GameData() { EventType = l.field1, GameId = r, }); + (l, r) => new GameData() { EventType = l.field1, GameId = r, }); var result = query .ToPayloadEnumerable() .ToArray(); @@ -2628,7 +2628,7 @@ public void IOOEJ2ColumnarSmallBatchRegularString() input2, e => e.field1, e => e, - (l, r) => new GameData() { EventType = l.field1, GameId = r, }); + (l, r) => new GameData() { EventType = l.field1, GameId = r, }); var result = query .ToPayloadEnumerable() .ToArray(); diff --git a/Sources/Test/TrillPerf/PerformanceTesting.csproj b/Sources/Test/TrillPerf/PerformanceTesting.csproj index 992c531ce..a5c1f0e0f 100644 --- a/Sources/Test/TrillPerf/PerformanceTesting.csproj +++ b/Sources/Test/TrillPerf/PerformanceTesting.csproj @@ -2,7 +2,7 @@ Exe - net472;net6.0;net7.0 + net472;net6.0;net7.0;netcoreapp3.1 AnyCPU From 7fa170acb6be6e3dcab8a248ccf6d0eb72e7b75f Mon Sep 17 00:00:00 2001 From: Adam Cohen Date: Wed, 11 Jan 2023 04:28:40 -0500 Subject: [PATCH 3/9] - Removed netcoreapp3.1 - Upgraded MSTest packages with security vulerabilites - Reverted StyleCop package update from previous commit --- .../Microsoft.StreamProcessing.Provider.csproj | 2 +- .../Microsoft.StreamProcessing.csproj | 2 +- Sources/Test/SimpleTesting/SimpleTesting.csproj | 12 ++++++------ Sources/Test/TrillPerf/PerformanceTesting.csproj | 9 +-------- 4 files changed, 9 insertions(+), 16 deletions(-) diff --git a/Sources/Core/Microsoft.StreamProcessing.Provider/Microsoft.StreamProcessing.Provider.csproj b/Sources/Core/Microsoft.StreamProcessing.Provider/Microsoft.StreamProcessing.Provider.csproj index f60cb12a7..b38205d12 100644 --- a/Sources/Core/Microsoft.StreamProcessing.Provider/Microsoft.StreamProcessing.Provider.csproj +++ b/Sources/Core/Microsoft.StreamProcessing.Provider/Microsoft.StreamProcessing.Provider.csproj @@ -1,7 +1,7 @@  - net6.0;net7.0;net472;netcoreapp3.1 + net6.0;net7.0;net472 x64;AnyCPU diff --git a/Sources/Core/Microsoft.StreamProcessing/Microsoft.StreamProcessing.csproj b/Sources/Core/Microsoft.StreamProcessing/Microsoft.StreamProcessing.csproj index 284cb528d..1fcb6e2c1 100644 --- a/Sources/Core/Microsoft.StreamProcessing/Microsoft.StreamProcessing.csproj +++ b/Sources/Core/Microsoft.StreamProcessing/Microsoft.StreamProcessing.csproj @@ -1,7 +1,7 @@  - net6.0;net7.0;net472;netcoreapp3.1 + net6.0;net7.0;net472 x64;AnyCPU diff --git a/Sources/Test/SimpleTesting/SimpleTesting.csproj b/Sources/Test/SimpleTesting/SimpleTesting.csproj index 546873730..9b97824ad 100644 --- a/Sources/Test/SimpleTesting/SimpleTesting.csproj +++ b/Sources/Test/SimpleTesting/SimpleTesting.csproj @@ -1,16 +1,16 @@  - net6.0;net7.0;net472;netcoreapp3.1 + net7.0;net6.0;net472 AnyCPU - - - + + + @@ -18,7 +18,7 @@ Microsoft.NET.Test.Sdk in .NET Core injects a stub main entry point for test execution by default to convert lib projects to console apps. Since we have our own entry point to enable manually compiling OutputType of Exe, we need to tell it not to generate one automatically. --> - + false @@ -162,7 +162,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/Sources/Test/TrillPerf/PerformanceTesting.csproj b/Sources/Test/TrillPerf/PerformanceTesting.csproj index a5c1f0e0f..3df5caec3 100644 --- a/Sources/Test/TrillPerf/PerformanceTesting.csproj +++ b/Sources/Test/TrillPerf/PerformanceTesting.csproj @@ -2,7 +2,7 @@ Exe - net472;net6.0;net7.0;netcoreapp3.1 + net7.0;net6.0;net472 AnyCPU @@ -12,13 +12,6 @@ - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - true From 4cc6c5b1bef64b780a1c4a4a3b8df073d4ef08f6 Mon Sep 17 00:00:00 2001 From: Amir Burbea Date: Mon, 23 Mar 2026 17:15:27 -0700 Subject: [PATCH 4/9] Upgrade to .NET 8 and fix async-incompatible ConfigModifier locking - Target net8.0 across all projects, dropping net6.0/net7.0/net472 - Remove legacy .NET Standard packages (System.Linq.Expressions 4.3.0, Microsoft.CSharp 4.7.0, System.Diagnostics.*, etc.) now built into the runtime - Upgrade Microsoft.CodeAnalysis.Scripting 4.4.0 -> 5.3.0 - Upgrade MSTest 3.x -> 4.x, System.Reactive 5.x -> 6.x, and other packages - Fix ConfigModifier gate: replace Monitor (thread-affine) with SemaphoreSlim + AsyncLocal depth counter, making it safe for async tests that release from a different thread while remaining re-entrant for nested Modify() calls - Make T4 template import conditional so dotnet CLI builds work without VS - Add trill.runsettings with StopRunOnFirstFailure for faster test diagnosis - All 3185 tests pass on .NET 8 --- .gitignore | 2 + ...Microsoft.StreamProcessing.Provider.csproj | 16 +- .../Microsoft.StreamProcessing.csproj | 11 +- .../Utilities/Config.cs | 14 +- Sources/Test/SimpleTesting/AdHocTests.cs | 59 ++-- .../SimpleTesting/CheckpointRestoreTests.cs | 8 +- .../Collections/AbstractEventBatch.cs | 48 +-- .../SimpleTesting/Collections/FastListTest.cs | 8 +- .../SimpleTesting/Collections/FastMapTest.cs | 6 +- Sources/Test/SimpleTesting/Common.cs | 5 - .../DisorderedIngressAndEgressTests.cs | 64 ++-- .../FlushPolicyTestMatrixBase.cs | 6 +- .../Macros/LeftOuterJoinTests.cs | 16 +- .../Test/SimpleTesting/MultiStringTests.cs | 4 +- ...titionedIngressAndEgressTestMatrixBases.cs | 6 +- .../Partitioned/PartitionedStreamTests.cs | 6 +- .../Serializer/SurrogateTests.cs | 2 +- .../Test/SimpleTesting/SimpleTesting.csproj | 17 +- Sources/Test/SimpleTesting/SimpleTests.cs | 304 +++++++++--------- .../SimpleTesting/Streamables/JoinTests.cs | 96 +++--- .../Streamables/ShuffleStreamableTests.cs | 16 +- Sources/Test/SimpleTesting/trill.runsettings | 6 + .../Test/TrillPerf/PerformanceTesting.csproj | 15 +- 23 files changed, 367 insertions(+), 368 deletions(-) create mode 100644 Sources/Test/SimpleTesting/trill.runsettings diff --git a/.gitignore b/.gitignore index 809f06a76..ed8c08844 100644 --- a/.gitignore +++ b/.gitignore @@ -58,3 +58,5 @@ $tf/pendingchanges.tfb $tf/properties.tf1 project.lock.json **/.vs/ + +.claude/ \ No newline at end of file diff --git a/Sources/Core/Microsoft.StreamProcessing.Provider/Microsoft.StreamProcessing.Provider.csproj b/Sources/Core/Microsoft.StreamProcessing.Provider/Microsoft.StreamProcessing.Provider.csproj index b38205d12..b4dfea5bb 100644 --- a/Sources/Core/Microsoft.StreamProcessing.Provider/Microsoft.StreamProcessing.Provider.csproj +++ b/Sources/Core/Microsoft.StreamProcessing.Provider/Microsoft.StreamProcessing.Provider.csproj @@ -1,7 +1,7 @@  - net6.0;net7.0;net472 + net8.0 x64;AnyCPU @@ -11,19 +11,7 @@ - - - - - - - - - - - - - + diff --git a/Sources/Core/Microsoft.StreamProcessing/Microsoft.StreamProcessing.csproj b/Sources/Core/Microsoft.StreamProcessing/Microsoft.StreamProcessing.csproj index 1fcb6e2c1..f3e5fc326 100644 --- a/Sources/Core/Microsoft.StreamProcessing/Microsoft.StreamProcessing.csproj +++ b/Sources/Core/Microsoft.StreamProcessing/Microsoft.StreamProcessing.csproj @@ -1,7 +1,7 @@  - net6.0;net7.0;net472 + net8.0 x64;AnyCPU @@ -11,14 +11,7 @@ - - - - - - - - + diff --git a/Sources/Core/Microsoft.StreamProcessing/Utilities/Config.cs b/Sources/Core/Microsoft.StreamProcessing/Utilities/Config.cs index badaa164f..1f7d1cf20 100644 --- a/Sources/Core/Microsoft.StreamProcessing/Utilities/Config.cs +++ b/Sources/Core/Microsoft.StreamProcessing/Utilities/Config.cs @@ -467,8 +467,12 @@ public static string Describe() // in VSTest, which is a good thing, since Config is static and those tests may clash otherwise. internal sealed class ConfigModifier { - // lockable gate allowing only one ConfigModifier active at a time - private static readonly object gate = new object(); + // Serializes concurrent ConfigModifier usage across tests. + // SemaphoreSlim instead of Monitor so that async tests can release from a different thread. + // AsyncLocal depth counter makes it re-entrant within the same async call context (e.g. nested + // using blocks within a single test) without blocking on the semaphore a second time. + private static readonly SemaphoreSlim gate = new SemaphoreSlim(1, 1); + private static readonly AsyncLocal gateDepth = new AsyncLocal(); // collection of Config modifications private readonly List modifications = new List(); @@ -723,7 +727,8 @@ public ConfigModifier SerializationCompressionLevel(SerializationCompressionLeve public IDisposable Modify() { - Monitor.Enter(gate); + if (gateDepth.Value == 0) gate.Wait(); + gateDepth.Value++; foreach (var m in this.modifications) m.Modify(); @@ -732,7 +737,8 @@ public IDisposable Modify() foreach (var m in this.modifications) m.Modify(); - Monitor.Exit(gate); + gateDepth.Value--; + if (gateDepth.Value == 0) gate.Release(); }); } diff --git a/Sources/Test/SimpleTesting/AdHocTests.cs b/Sources/Test/SimpleTesting/AdHocTests.cs index 41c0cca20..6c11d45a8 100644 --- a/Sources/Test/SimpleTesting/AdHocTests.cs +++ b/Sources/Test/SimpleTesting/AdHocTests.cs @@ -141,11 +141,11 @@ private void TestSerialization() ms.Position = 0; ColumnBatch resultStr = s.Deserialize(ms); - Assert.IsTrue(resultStr.UsedLength == inputStr.UsedLength); + Assert.AreEqual(inputStr.UsedLength, resultStr.UsedLength); for (int j = 0; j < inputStr.UsedLength; j++) { - Assert.IsTrue(inputStr.col[j] == resultStr.col[j]); + Assert.AreEqual(resultStr.col[j], inputStr.col[j]); } resultStr.ReturnClear(); inputStr.ReturnClear(); @@ -165,9 +165,9 @@ public void StreamEventArrayIngress1() var s = input.ToObservable(); var str = s.ToStreamable(); var output = str.ToStreamMessageObservable().ToEnumerable().ToArray(); - Assert.IsTrue(output.Length == 1); // first batch with all data and one punctuation - Assert.IsTrue(output[0].Count == length + 1); - Assert.IsTrue(output[0].vother.col[output[0].Count - 1] == StreamEvent.PunctuationOtherTime); + Assert.HasCount(1, output); // first batch with all data and one punctuation + Assert.AreEqual(length + 1, output[0].Count); + Assert.AreEqual(StreamEvent.PunctuationOtherTime, output[0].vother.col[output[0].Count - 1]); for (int i = 0; i < output.Length; i++) output[i].Free(); } @@ -185,11 +185,11 @@ public void StreamEventArrayIngress2() var s = input.ToObservable(); var str = s.ToStreamable(); var output = str.ToStreamMessageObservable().ToEnumerable().ToArray(); - Assert.IsTrue(output.Length == 4); // four data batches - Assert.IsTrue(output[0].Count + output[1].Count + output[2].Count + output[3].Count == length + 1); + Assert.HasCount(4, output); // four data batches + Assert.AreEqual(length + 1, output[0].Count + output[1].Count + output[2].Count + output[3].Count); // fourth data batch should have a punctuation at the end - Assert.IsTrue(output[3].vother.col[output[3].Count - 1] == StreamEvent.PunctuationOtherTime); + Assert.AreEqual(StreamEvent.PunctuationOtherTime, output[3].vother.col[output[3].Count - 1]); for (int i = 0; i < output.Length; i++) output[i].Free(); } @@ -211,15 +211,15 @@ public void StreamEventArrayIngress3() // 10 pairs of data and punc, then one with just a punctuation at infinity int expectedDataBatches = 11; - Assert.IsTrue(output.Length == expectedDataBatches); + Assert.HasCount(expectedDataBatches, output); var dataEventCount = 0; for (int i = 0; i < output.Length; i++) { // Data batch should end with a punctuation - Assert.IsTrue(output[i].vother.col[output[i].Count - 1] == StreamEvent.PunctuationOtherTime); + Assert.AreEqual(StreamEvent.PunctuationOtherTime, output[i].vother.col[output[i].Count - 1]); dataEventCount += output[i].Count - 1; // exclude punctuation } - Assert.IsTrue(dataEventCount == length - 10); // because every 10th row was a punctuation, not a data row + Assert.AreEqual(length - 10, dataEventCount); // because every 10th row was a punctuation, not a data row for (int i = 0; i < output.Length; i++) output[i].Free(); } @@ -255,7 +255,7 @@ public void PartitionedStreamAdjustIngressPolicy() egress.Wait(); output = output.Where(o => o.IsData).ToList(); - Assert.AreEqual(2, output.Count); + Assert.HasCount(2, output); Assert.AreEqual(70, output[0].SyncTime); Assert.AreEqual(22, output[1].SyncTime); } @@ -920,11 +920,11 @@ public void SinglePunctuationBatchTimestamps() batch => { var min = batch.MinTimestamp; - Assert.IsTrue(min >= currentMin); + Assert.IsGreaterThanOrEqualTo(currentMin, min); currentMin = min; var max = batch.MaxTimestamp; - Assert.IsTrue(max >= currentMax); + Assert.IsGreaterThanOrEqualTo(currentMax, max); currentMax = max; batch.Free(); @@ -1311,8 +1311,10 @@ public async Task DisposeTest1() await inputTask; // Make sure we really got an output data event. - Assert.IsTrue(lastSeenSubscription > 0); + Assert.IsGreaterThan(0, lastSeenSubscription); } + + public TestContext TestContext { get; set; } } [TestClass] @@ -1412,7 +1414,7 @@ public struct NormalizedHttpEvent countedNE = countedNE.AlterEventDuration(1); var output2 = countedNE.ToStreamEventObservable(ReshapingPolicy.CoalesceEndEdges).ToEnumerable().ToArray(); - Assert.IsTrue(output2.Count() == 9); + Assert.AreEqual(9, output2.Count()); } } @@ -1871,7 +1873,7 @@ public void LeftJoinOutOfOrder() process.Flush(); var outputData = output.Where(o => o.IsData).ToList(); - Assert.IsTrue(outputData.Count == 2); + Assert.HasCount(2, outputData); } [TestMethod, TestCategory("Gated")] @@ -1949,7 +1951,7 @@ public void StartEdge1() .ToArray(); var x = events.Length; - Assert.IsTrue(x == inputEnumerable.Count()); + Assert.AreEqual(inputEnumerable.Count(), x); } } @@ -2133,12 +2135,14 @@ public void JoinClipTest() }); var result = successes.ToStreamEventObservable().ToEnumerable().ToArray(); - Assert.IsTrue(false); // should never reach here. + Assert.Fail(); // should never reach here. } - catch (Exception e) + catch (InvalidOperationException) { - Assert.IsTrue(e is InvalidOperationException); + // expected, because the Join should not be able to match the clipped events with the finishing events, since the clipped events have had their lifetime shifted by 1 tick, and thus should not overlap with the finishing events. + return; } + Assert.Fail(); // should never reach here. } /// @@ -2249,7 +2253,7 @@ public void Select8() .ToEnumerable() .ToArray() ; - Assert.IsTrue(expected.Count() == output.Length); + Assert.AreEqual(output.Length, expected.Count()); for (int i = 0; i < output.Length; i++) Assert.IsTrue(expected.ElementAt(i).Equals(output[i])); } @@ -2404,18 +2408,15 @@ public void JoinTestWithoutException() .ToStreamable() ; - try - { - var result = stream1 + + var result = stream1 .Join(stream2, e => e.x, e => e, (left, right) => new { LeftX = left.x, RightX = right, }) .ToStreamEventObservable() .ToEnumerable() .ToArray(); - Assert.IsTrue(true); // just test that no exception happened - } - catch (Exception) + if (object.ReferenceEquals(result, null)) { - Assert.IsTrue(false); // should never reach here. + // just to use the result and avoid "unused variable" warning } } diff --git a/Sources/Test/SimpleTesting/CheckpointRestoreTests.cs b/Sources/Test/SimpleTesting/CheckpointRestoreTests.cs index 02483aca7..1a0d6a350 100644 --- a/Sources/Test/SimpleTesting/CheckpointRestoreTests.cs +++ b/Sources/Test/SimpleTesting/CheckpointRestoreTests.cs @@ -1318,7 +1318,7 @@ public void BasicDisorderAdjustPolicyRow() postCheckpointSubject.OnCompleted(); outputAsync2.Wait(); - Assert.IsTrue(outputList.Count == 10000); + Assert.HasCount(10000, outputList); preCheckpointSubject.OnCompleted(); } @@ -2790,7 +2790,7 @@ public void BasicDisorderAdjustPolicyRowSmallBatch() postCheckpointSubject.OnCompleted(); outputAsync2.Wait(); - Assert.IsTrue(outputList.Count == 10000); + Assert.HasCount(10000, outputList); preCheckpointSubject.OnCompleted(); } @@ -4260,7 +4260,7 @@ public void BasicDisorderAdjustPolicyColumnar() postCheckpointSubject.OnCompleted(); outputAsync2.Wait(); - Assert.IsTrue(outputList.Count == 10000); + Assert.HasCount(10000, outputList); preCheckpointSubject.OnCompleted(); } @@ -5732,7 +5732,7 @@ public void BasicDisorderAdjustPolicyColumnarSmallBatch() postCheckpointSubject.OnCompleted(); outputAsync2.Wait(); - Assert.IsTrue(outputList.Count == 10000); + Assert.HasCount(10000, outputList); preCheckpointSubject.OnCompleted(); } diff --git a/Sources/Test/SimpleTesting/Collections/AbstractEventBatch.cs b/Sources/Test/SimpleTesting/Collections/AbstractEventBatch.cs index 28e73fb35..c07b95977 100644 --- a/Sources/Test/SimpleTesting/Collections/AbstractEventBatch.cs +++ b/Sources/Test/SimpleTesting/Collections/AbstractEventBatch.cs @@ -43,21 +43,21 @@ public void ComputeMinMax_Basic() // (a) message.Count = 0; - Assert.IsTrue(message.MinTimestamp == StreamEvent.MinSyncTime, "Empty message with Count=0 has MinTimestamp <> 0."); - Assert.IsTrue(message.MaxTimestamp == StreamEvent.MaxSyncTime, "Empty message with Count=0 has MaxTimestamp <> inf-1."); + Assert.AreEqual(StreamEvent.MinSyncTime, message.MinTimestamp, "Empty message with Count=0 has MinTimestamp <> 0."); + Assert.AreEqual(StreamEvent.MaxSyncTime, message.MaxTimestamp, "Empty message with Count=0 has MaxTimestamp <> inf-1."); // (b) message.Count = 1; message.vsync.col[0] = TESTVALUE; - Assert.IsTrue(message.MinTimestamp == StreamEvent.MinSyncTime, "Empty message with Count=1 has MinTimestamp <> 0."); - Assert.IsTrue(message.MaxTimestamp == StreamEvent.MaxSyncTime, "Empty message with Count=1 has MaxTimestamp <> inf-1."); + Assert.AreEqual(StreamEvent.MinSyncTime, message.MinTimestamp, "Empty message with Count=1 has MinTimestamp <> 0."); + Assert.AreEqual(StreamEvent.MaxSyncTime, message.MaxTimestamp, "Empty message with Count=1 has MaxTimestamp <> inf-1."); // (c) message.Count = 1; message.vsync.col[0] = TESTVALUE; OccupyAt(message, 0); - Assert.IsTrue(message.MinTimestamp == TESTVALUE, "Empty message with Count=1 has MinTimestamp <> TESTVALUE."); - Assert.IsTrue(message.MaxTimestamp == TESTVALUE, "Empty message with Count=1 has MaxTimestamp <> TESTVALUE"); + Assert.AreEqual(TESTVALUE, message.MinTimestamp, "Empty message with Count=1 has MinTimestamp <> TESTVALUE."); + Assert.AreEqual(TESTVALUE, message.MaxTimestamp, "Empty message with Count=1 has MaxTimestamp <> TESTVALUE"); VacateAt(message, 0); message.vsync.col[0] = 0; @@ -65,14 +65,14 @@ public void ComputeMinMax_Basic() message.Count = 100; message.vsync.col[5] = TESTVALUE - 1; message.vsync.col[42] = TESTVALUE; - Assert.IsTrue(message.MinTimestamp == StreamEvent.MinSyncTime, "Empty message with Count>1 has MinTimestamp <> 0."); - Assert.IsTrue(message.MaxTimestamp == StreamEvent.MaxSyncTime, "Empty message with Count>1 has MaxTimestamp <> inf-1"); + Assert.AreEqual(StreamEvent.MinSyncTime, message.MinTimestamp, "Empty message with Count>1 has MinTimestamp <> 0."); + Assert.AreEqual(StreamEvent.MaxSyncTime, message.MaxTimestamp, "Empty message with Count>1 has MaxTimestamp <> inf-1"); // (e) OccupyAt(message, 5); OccupyAt(message, 42); - Assert.IsTrue(message.MinTimestamp == TESTVALUE - 1, "Non-empty message with Count>1 has MinTimestamp <> TESTVALUE-1."); - Assert.IsTrue(message.MaxTimestamp == TESTVALUE, "Non-empty message with Count>1 has MaxTimestamp <> TESTVALUE"); + Assert.AreEqual(TESTVALUE - 1, message.MinTimestamp, "Non-empty message with Count>1 has MinTimestamp <> TESTVALUE-1."); + Assert.AreEqual(TESTVALUE, message.MaxTimestamp, "Non-empty message with Count>1 has MaxTimestamp <> TESTVALUE"); VacateAt(message, 5); VacateAt(message, 42); message.vsync.col[5] = 0; @@ -161,21 +161,21 @@ public void ComputeMinMax_Partitioned_Basic() // (a) message.Count = 0; - Assert.IsTrue(message.MinTimestamp == StreamEvent.MinSyncTime, "Empty message with Count=0 has MinTimestamp <> 0."); - Assert.IsTrue(message.MaxTimestamp == StreamEvent.MaxSyncTime, "Empty message with Count=0 has MaxTimestamp <> inf-1."); + Assert.AreEqual(StreamEvent.MinSyncTime, message.MinTimestamp, "Empty message with Count=0 has MinTimestamp <> 0."); + Assert.AreEqual(StreamEvent.MaxSyncTime, message.MaxTimestamp, "Empty message with Count=0 has MaxTimestamp <> inf-1."); // (b) message.Count = 1; message.vsync.col[0] = TESTVALUE; - Assert.IsTrue(message.MinTimestamp == StreamEvent.MinSyncTime, "Empty message with Count=1 has MinTimestamp <> 0."); - Assert.IsTrue(message.MaxTimestamp == StreamEvent.MaxSyncTime, "Empty message with Count=1 has MaxTimestamp <> inf-1."); + Assert.AreEqual(StreamEvent.MinSyncTime, message.MinTimestamp, "Empty message with Count=1 has MinTimestamp <> 0."); + Assert.AreEqual(StreamEvent.MaxSyncTime, message.MaxTimestamp, "Empty message with Count=1 has MaxTimestamp <> inf-1."); // (c) message.Count = 1; message.vsync.col[0] = TESTVALUE; OccupyAt(message, 0); - Assert.IsTrue(message.MinTimestamp == TESTVALUE, "Empty message with Count=1 has MinTimestamp <> TESTVALUE."); - Assert.IsTrue(message.MaxTimestamp == TESTVALUE, "Empty message with Count=1 has MaxTimestamp <> TESTVALUE"); + Assert.AreEqual(TESTVALUE, message.MinTimestamp, "Empty message with Count=1 has MinTimestamp <> TESTVALUE."); + Assert.AreEqual(TESTVALUE, message.MaxTimestamp, "Empty message with Count=1 has MaxTimestamp <> TESTVALUE"); VacateAt(message, 0); message.vsync.col[0] = 0; @@ -183,14 +183,14 @@ public void ComputeMinMax_Partitioned_Basic() message.Count = 100; message.vsync.col[5] = TESTVALUE - 1; message.vsync.col[42] = TESTVALUE; - Assert.IsTrue(message.MinTimestamp == StreamEvent.MinSyncTime, "Empty message with Count>1 has MinTimestamp <> 0."); - Assert.IsTrue(message.MaxTimestamp == StreamEvent.MaxSyncTime, "Empty message with Count>1 has MaxTimestamp <> inf-1"); + Assert.AreEqual(StreamEvent.MinSyncTime, message.MinTimestamp, "Empty message with Count>1 has MinTimestamp <> 0."); + Assert.AreEqual(StreamEvent.MaxSyncTime, message.MaxTimestamp, "Empty message with Count>1 has MaxTimestamp <> inf-1"); // (e) OccupyAt(message, 5); OccupyAt(message, 42); - Assert.IsTrue(message.MinTimestamp == TESTVALUE - 1, "Non-empty message with Count>1 has MinTimestamp <> TESTVALUE-1."); - Assert.IsTrue(message.MaxTimestamp == TESTVALUE, "Non-empty message with Count>1 has MaxTimestamp <> TESTVALUE"); + Assert.AreEqual(TESTVALUE - 1, message.MinTimestamp, "Non-empty message with Count>1 has MinTimestamp <> TESTVALUE-1."); + Assert.AreEqual(TESTVALUE, message.MaxTimestamp, "Non-empty message with Count>1 has MaxTimestamp <> TESTVALUE"); VacateAt(message, 5); VacateAt(message, 42); message.vsync.col[5] = 0; @@ -218,14 +218,14 @@ public void ComputeMinMax_Partitioned_Compound_Basic() message.Count = 100; message.vsync.col[5] = TESTVALUE; message.vsync.col[42] = TESTVALUE - 1; - Assert.IsTrue(message.MinTimestamp == StreamEvent.MinSyncTime, "Empty message with Count>1 has MinTimestamp <> 0."); - Assert.IsTrue(message.MaxTimestamp == StreamEvent.MaxSyncTime, "Empty message with Count>1 has MaxTimestamp <> inf-1"); + Assert.AreEqual(StreamEvent.MinSyncTime, message.MinTimestamp, "Empty message with Count>1 has MinTimestamp <> 0."); + Assert.AreEqual(StreamEvent.MaxSyncTime, message.MaxTimestamp, "Empty message with Count>1 has MaxTimestamp <> inf-1"); // (e) OccupyAt(message, 5); OccupyAt(message, 42); - Assert.IsTrue(message.MinTimestamp == TESTVALUE - 1, "Non-empty message with Count>1 has MinTimestamp <> TESTVALUE-1."); - Assert.IsTrue(message.MaxTimestamp == TESTVALUE, "Non-empty message with Count>1 has MaxTimestamp <> TESTVALUE"); + Assert.AreEqual(TESTVALUE - 1, message.MinTimestamp, "Non-empty message with Count>1 has MinTimestamp <> TESTVALUE-1."); + Assert.AreEqual(TESTVALUE, message.MaxTimestamp, "Non-empty message with Count>1 has MaxTimestamp <> TESTVALUE"); VacateAt(message, 5); VacateAt(message, 42); message.vsync.col[5] = 0; diff --git a/Sources/Test/SimpleTesting/Collections/FastListTest.cs b/Sources/Test/SimpleTesting/Collections/FastListTest.cs index 946f4c7c9..11c1957e0 100644 --- a/Sources/Test/SimpleTesting/Collections/FastListTest.cs +++ b/Sources/Test/SimpleTesting/Collections/FastListTest.cs @@ -39,9 +39,9 @@ private static void SimpleListTest() int indexA2 = list.Insert("a"); int indexB2 = list.Insert("b"); - Assert.IsTrue(indexA != indexA2); - Assert.IsTrue(indexA != indexB); - Assert.IsTrue(indexA2 != indexB2); + Assert.AreNotEqual(indexA2, indexA); + Assert.AreNotEqual(indexB, indexA); + Assert.AreNotEqual(indexB2, indexA2); Assert.IsFalse(list.IsEmpty); Assert.AreEqual(4, list.Count); @@ -131,7 +131,7 @@ private static void BetterListTest() { check += list.Values[index]; } - Assert.IsTrue(sum == check); + Assert.AreEqual(check, sum); } } } diff --git a/Sources/Test/SimpleTesting/Collections/FastMapTest.cs b/Sources/Test/SimpleTesting/Collections/FastMapTest.cs index 13cfb25c2..51750f2bf 100644 --- a/Sources/Test/SimpleTesting/Collections/FastMapTest.cs +++ b/Sources/Test/SimpleTesting/Collections/FastMapTest.cs @@ -40,9 +40,9 @@ private static void SimpleMapTest() int indexA5Two = map.Insert(5, "a"); int indexB5 = map.Insert(5, "b"); - Assert.IsTrue(indexA5 != indexA5Two); - Assert.IsTrue(indexA5 != indexB5); - Assert.IsTrue(indexA5Two != indexB5); + Assert.AreNotEqual(indexA5Two, indexA5); + Assert.AreNotEqual(indexB5, indexA5); + Assert.AreNotEqual(indexB5, indexA5Two); Assert.IsFalse(map.IsEmpty); Assert.AreEqual(4, map.Count); diff --git a/Sources/Test/SimpleTesting/Common.cs b/Sources/Test/SimpleTesting/Common.cs index 29a080ad0..9ef0d7ca7 100644 --- a/Sources/Test/SimpleTesting/Common.cs +++ b/Sources/Test/SimpleTesting/Common.cs @@ -183,11 +183,6 @@ public static IEnumerable> ToEvents(this IEnumerable input, yield return StreamEvent.CreateInterval(vsSelector(e), veSelector(e), e); } } - -#if NET472 - // string.Split has different signatures across .NET Framework/Core, so use an extension so we can use a single signature - public static string[] Split(this string original, char separator, StringSplitOptions options) => original.Split(separator); -#endif } public static class Helpers diff --git a/Sources/Test/SimpleTesting/IngressEgress/DisorderedIngressAndEgressTests.cs b/Sources/Test/SimpleTesting/IngressEgress/DisorderedIngressAndEgressTests.cs index a750c1dea..ea0c22f96 100644 --- a/Sources/Test/SimpleTesting/IngressEgress/DisorderedIngressAndEgressTests.cs +++ b/Sources/Test/SimpleTesting/IngressEgress/DisorderedIngressAndEgressTests.cs @@ -1186,7 +1186,7 @@ public void DisorderedStartEdgeTestRowThrow105() } catch(Exception) { - Assert.IsTrue(true); // Todo. Verify if the ingress/egress before the exception was correct. + // Todo. Verify if the ingress/egress before the exception was correct. } } @@ -1229,7 +1229,7 @@ public void DisorderedIntervalTestRowThrow105() } catch(Exception) { - Assert.IsTrue(true); // Todo. Verify if the ingress/egress before the exception was correct. + // Todo. Verify if the ingress/egress before the exception was correct. } } } @@ -1285,7 +1285,7 @@ public void DisorderedStartEdgeTestRowThrow105Diagnostic() } catch(Exception) { - Assert.IsTrue(true); // Todo. Verify if the ingress/egress before the exception was correct. + // Todo. Verify if the ingress/egress before the exception was correct. } } @@ -1332,7 +1332,7 @@ public void DisorderedIntervalTestRowThrow105Diagnostic() } catch(Exception) { - Assert.IsTrue(true); // Todo. Verify if the ingress/egress before the exception was correct. + // Todo. Verify if the ingress/egress before the exception was correct. } } } @@ -1616,7 +1616,7 @@ public void DisorderedStartEdgeTestRowThrow105Time() } catch(Exception) { - Assert.IsTrue(true); // Todo. Verify if the ingress/egress before the exception was correct. + // Todo. Verify if the ingress/egress before the exception was correct. } } @@ -1659,7 +1659,7 @@ public void DisorderedIntervalTestRowThrow105Time() } catch(Exception) { - Assert.IsTrue(true); // Todo. Verify if the ingress/egress before the exception was correct. + // Todo. Verify if the ingress/egress before the exception was correct. } } } @@ -1715,7 +1715,7 @@ public void DisorderedStartEdgeTestRowThrow105TimeDiagnostic() } catch(Exception) { - Assert.IsTrue(true); // Todo. Verify if the ingress/egress before the exception was correct. + // Todo. Verify if the ingress/egress before the exception was correct. } } @@ -1762,7 +1762,7 @@ public void DisorderedIntervalTestRowThrow105TimeDiagnostic() } catch(Exception) { - Assert.IsTrue(true); // Todo. Verify if the ingress/egress before the exception was correct. + // Todo. Verify if the ingress/egress before the exception was correct. } } } @@ -4463,7 +4463,7 @@ public void DisorderedStartEdgeTestRowSmallBatchThrow105() } catch(Exception) { - Assert.IsTrue(true); // Todo. Verify if the ingress/egress before the exception was correct. + // Todo. Verify if the ingress/egress before the exception was correct. } } @@ -4506,7 +4506,7 @@ public void DisorderedIntervalTestRowSmallBatchThrow105() } catch(Exception) { - Assert.IsTrue(true); // Todo. Verify if the ingress/egress before the exception was correct. + // Todo. Verify if the ingress/egress before the exception was correct. } } } @@ -4563,7 +4563,7 @@ public void DisorderedStartEdgeTestRowSmallBatchThrow105Diagnostic() } catch(Exception) { - Assert.IsTrue(true); // Todo. Verify if the ingress/egress before the exception was correct. + // Todo. Verify if the ingress/egress before the exception was correct. } } @@ -4610,7 +4610,7 @@ public void DisorderedIntervalTestRowSmallBatchThrow105Diagnostic() } catch(Exception) { - Assert.IsTrue(true); // Todo. Verify if the ingress/egress before the exception was correct. + // Todo. Verify if the ingress/egress before the exception was correct. } } } @@ -4897,7 +4897,7 @@ public void DisorderedStartEdgeTestRowSmallBatchThrow105Time() } catch(Exception) { - Assert.IsTrue(true); // Todo. Verify if the ingress/egress before the exception was correct. + // Todo. Verify if the ingress/egress before the exception was correct. } } @@ -4940,7 +4940,7 @@ public void DisorderedIntervalTestRowSmallBatchThrow105Time() } catch(Exception) { - Assert.IsTrue(true); // Todo. Verify if the ingress/egress before the exception was correct. + // Todo. Verify if the ingress/egress before the exception was correct. } } } @@ -4997,7 +4997,7 @@ public void DisorderedStartEdgeTestRowSmallBatchThrow105TimeDiagnostic() } catch(Exception) { - Assert.IsTrue(true); // Todo. Verify if the ingress/egress before the exception was correct. + // Todo. Verify if the ingress/egress before the exception was correct. } } @@ -5044,7 +5044,7 @@ public void DisorderedIntervalTestRowSmallBatchThrow105TimeDiagnostic() } catch(Exception) { - Assert.IsTrue(true); // Todo. Verify if the ingress/egress before the exception was correct. + // Todo. Verify if the ingress/egress before the exception was correct. } } } @@ -7746,7 +7746,7 @@ public void DisorderedStartEdgeTestColumnarThrow105() } catch(Exception) { - Assert.IsTrue(true); // Todo. Verify if the ingress/egress before the exception was correct. + // Todo. Verify if the ingress/egress before the exception was correct. } } @@ -7789,7 +7789,7 @@ public void DisorderedIntervalTestColumnarThrow105() } catch(Exception) { - Assert.IsTrue(true); // Todo. Verify if the ingress/egress before the exception was correct. + // Todo. Verify if the ingress/egress before the exception was correct. } } } @@ -7845,7 +7845,7 @@ public void DisorderedStartEdgeTestColumnarThrow105Diagnostic() } catch(Exception) { - Assert.IsTrue(true); // Todo. Verify if the ingress/egress before the exception was correct. + // Todo. Verify if the ingress/egress before the exception was correct. } } @@ -7892,7 +7892,7 @@ public void DisorderedIntervalTestColumnarThrow105Diagnostic() } catch(Exception) { - Assert.IsTrue(true); // Todo. Verify if the ingress/egress before the exception was correct. + // Todo. Verify if the ingress/egress before the exception was correct. } } } @@ -8176,7 +8176,7 @@ public void DisorderedStartEdgeTestColumnarThrow105Time() } catch(Exception) { - Assert.IsTrue(true); // Todo. Verify if the ingress/egress before the exception was correct. + // Todo. Verify if the ingress/egress before the exception was correct. } } @@ -8219,7 +8219,7 @@ public void DisorderedIntervalTestColumnarThrow105Time() } catch(Exception) { - Assert.IsTrue(true); // Todo. Verify if the ingress/egress before the exception was correct. + // Todo. Verify if the ingress/egress before the exception was correct. } } } @@ -8275,7 +8275,7 @@ public void DisorderedStartEdgeTestColumnarThrow105TimeDiagnostic() } catch(Exception) { - Assert.IsTrue(true); // Todo. Verify if the ingress/egress before the exception was correct. + // Todo. Verify if the ingress/egress before the exception was correct. } } @@ -8322,7 +8322,7 @@ public void DisorderedIntervalTestColumnarThrow105TimeDiagnostic() } catch(Exception) { - Assert.IsTrue(true); // Todo. Verify if the ingress/egress before the exception was correct. + // Todo. Verify if the ingress/egress before the exception was correct. } } } @@ -11023,7 +11023,7 @@ public void DisorderedStartEdgeTestColumnarSmallBatchThrow105() } catch(Exception) { - Assert.IsTrue(true); // Todo. Verify if the ingress/egress before the exception was correct. + // Todo. Verify if the ingress/egress before the exception was correct. } } @@ -11066,7 +11066,7 @@ public void DisorderedIntervalTestColumnarSmallBatchThrow105() } catch(Exception) { - Assert.IsTrue(true); // Todo. Verify if the ingress/egress before the exception was correct. + // Todo. Verify if the ingress/egress before the exception was correct. } } } @@ -11123,7 +11123,7 @@ public void DisorderedStartEdgeTestColumnarSmallBatchThrow105Diagnostic() } catch(Exception) { - Assert.IsTrue(true); // Todo. Verify if the ingress/egress before the exception was correct. + // Todo. Verify if the ingress/egress before the exception was correct. } } @@ -11170,7 +11170,7 @@ public void DisorderedIntervalTestColumnarSmallBatchThrow105Diagnostic() } catch(Exception) { - Assert.IsTrue(true); // Todo. Verify if the ingress/egress before the exception was correct. + // Todo. Verify if the ingress/egress before the exception was correct. } } } @@ -11457,7 +11457,7 @@ public void DisorderedStartEdgeTestColumnarSmallBatchThrow105Time() } catch(Exception) { - Assert.IsTrue(true); // Todo. Verify if the ingress/egress before the exception was correct. + // Todo. Verify if the ingress/egress before the exception was correct. } } @@ -11500,7 +11500,7 @@ public void DisorderedIntervalTestColumnarSmallBatchThrow105Time() } catch(Exception) { - Assert.IsTrue(true); // Todo. Verify if the ingress/egress before the exception was correct. + // Todo. Verify if the ingress/egress before the exception was correct. } } } @@ -11557,7 +11557,7 @@ public void DisorderedStartEdgeTestColumnarSmallBatchThrow105TimeDiagnostic() } catch(Exception) { - Assert.IsTrue(true); // Todo. Verify if the ingress/egress before the exception was correct. + // Todo. Verify if the ingress/egress before the exception was correct. } } @@ -11604,7 +11604,7 @@ public void DisorderedIntervalTestColumnarSmallBatchThrow105TimeDiagnostic() } catch(Exception) { - Assert.IsTrue(true); // Todo. Verify if the ingress/egress before the exception was correct. + // Todo. Verify if the ingress/egress before the exception was correct. } } } diff --git a/Sources/Test/SimpleTesting/IngressEgress/FlushPolicyTestMatrixBase.cs b/Sources/Test/SimpleTesting/IngressEgress/FlushPolicyTestMatrixBase.cs index e0af14413..bac4766d5 100644 --- a/Sources/Test/SimpleTesting/IngressEgress/FlushPolicyTestMatrixBase.cs +++ b/Sources/Test/SimpleTesting/IngressEgress/FlushPolicyTestMatrixBase.cs @@ -12,7 +12,7 @@ namespace SimpleTesting.Flush { - public class FlushTestBase : TestWithConfigSettingsAndMemoryLeakDetection + public abstract class FlushTestBase : TestWithConfigSettingsAndMemoryLeakDetection { private const int IntervalLength = 5; private const int BatchSize = 10; // TODO: this will be identical for FlushPolicy.None and FlushOnBatchBoundary without some filter operator @@ -55,7 +55,7 @@ public void FilterTest() OnIngress(inputSubject, StreamEvent.CreatePunctuation(i)); // Make sure we don't have any pending events we expected to be egressed at this point - Assert.IsTrue(this.expectedOutput.Count == 0); + Assert.IsEmpty(this.expectedOutput); } OnCompleted(inputSubject); @@ -115,7 +115,7 @@ private void MoveFilteredBatchBatchToOutput() private void OnEgress(StreamEvent egressEvent) { - Assert.IsTrue(this.expectedOutput.Count > 0); + Assert.IsNotEmpty(this.expectedOutput); var expectedEvent = this.expectedOutput.Dequeue(); Assert.IsTrue(expectedEvent.Equals(egressEvent)); diff --git a/Sources/Test/SimpleTesting/Macros/LeftOuterJoinTests.cs b/Sources/Test/SimpleTesting/Macros/LeftOuterJoinTests.cs index 68c8b6593..6b778f07d 100644 --- a/Sources/Test/SimpleTesting/Macros/LeftOuterJoinTests.cs +++ b/Sources/Test/SimpleTesting/Macros/LeftOuterJoinTests.cs @@ -82,8 +82,8 @@ public void LOJ1Row() var query = leftStream.LeftOuterJoin(rightStream, e => e.field1, e => e.field3, (l, r) => l.field2 != "E", - (l) => new MyData3 { field1 = l.field1, field2 = l.field2, field3 = tmp1, field4 = tmp2 }, - (l, r) => new MyData3 { field1 = l.field1, field2 = l.field2, field3 = r.field3, field4 = r.field4 }); + (l) => new MyData3 { field1 = l.field1, field2 = l.field2, field3 = tmp1, field4 = tmp2 }, + (l, r) => new MyData3 { field1 = l.field1, field2 = l.field2, field3 = r.field3, field4 = r.field4 }); var result = container.RegisterOutput(query, ReshapingPolicy.CoalesceEndEdges).Where(e => e.IsData); var resultAsync = result.ForEachAsync(o => output.Add(o)); @@ -144,8 +144,8 @@ public void LOJ1RowSmallBatch() var query = leftStream.LeftOuterJoin(rightStream, e => e.field1, e => e.field3, (l, r) => l.field2 != "E", - (l) => new MyData3 { field1 = l.field1, field2 = l.field2, field3 = tmp1, field4 = tmp2 }, - (l, r) => new MyData3 { field1 = l.field1, field2 = l.field2, field3 = r.field3, field4 = r.field4 }); + (l) => new MyData3 { field1 = l.field1, field2 = l.field2, field3 = tmp1, field4 = tmp2 }, + (l, r) => new MyData3 { field1 = l.field1, field2 = l.field2, field3 = r.field3, field4 = r.field4 }); var result = container.RegisterOutput(query, ReshapingPolicy.CoalesceEndEdges).Where(e => e.IsData); var resultAsync = result.ForEachAsync(o => output.Add(o)); @@ -205,8 +205,8 @@ public void LOJ1Columnar() var query = leftStream.LeftOuterJoin(rightStream, e => e.field1, e => e.field3, (l, r) => l.field2 != "E", - (l) => new MyData3 { field1 = l.field1, field2 = l.field2, field3 = tmp1, field4 = tmp2 }, - (l, r) => new MyData3 { field1 = l.field1, field2 = l.field2, field3 = r.field3, field4 = r.field4 }); + (l) => new MyData3 { field1 = l.field1, field2 = l.field2, field3 = tmp1, field4 = tmp2 }, + (l, r) => new MyData3 { field1 = l.field1, field2 = l.field2, field3 = r.field3, field4 = r.field4 }); var result = container.RegisterOutput(query, ReshapingPolicy.CoalesceEndEdges).Where(e => e.IsData); var resultAsync = result.ForEachAsync(o => output.Add(o)); @@ -267,8 +267,8 @@ public void LOJ1ColumnarSmallBatch() var query = leftStream.LeftOuterJoin(rightStream, e => e.field1, e => e.field3, (l, r) => l.field2 != "E", - (l) => new MyData3 { field1 = l.field1, field2 = l.field2, field3 = tmp1, field4 = tmp2 }, - (l, r) => new MyData3 { field1 = l.field1, field2 = l.field2, field3 = r.field3, field4 = r.field4 }); + (l) => new MyData3 { field1 = l.field1, field2 = l.field2, field3 = tmp1, field4 = tmp2 }, + (l, r) => new MyData3 { field1 = l.field1, field2 = l.field2, field3 = r.field3, field4 = r.field4 }); var result = container.RegisterOutput(query, ReshapingPolicy.CoalesceEndEdges).Where(e => e.IsData); var resultAsync = result.ForEachAsync(o => output.Add(o)); diff --git a/Sources/Test/SimpleTesting/MultiStringTests.cs b/Sources/Test/SimpleTesting/MultiStringTests.cs index 4477d88ec..e6d3b6618 100644 --- a/Sources/Test/SimpleTesting/MultiStringTests.cs +++ b/Sources/Test/SimpleTesting/MultiStringTests.cs @@ -609,11 +609,11 @@ public void MultiStringRegex1() { if ((result.col[i >> 6] & (1L << (i & 0x3f))) == 0) { - Assert.IsTrue(input[i].Contains(pattern)); + Assert.Contains(pattern, input[i]); } else { - Assert.IsFalse(input[i].Contains(pattern)); + Assert.DoesNotContain(pattern, input[i]); } } inBV.ReturnClear(); diff --git a/Sources/Test/SimpleTesting/Partitioned/PartitionedIngressAndEgressTestMatrixBases.cs b/Sources/Test/SimpleTesting/Partitioned/PartitionedIngressAndEgressTestMatrixBases.cs index f84057087..f67deef83 100644 --- a/Sources/Test/SimpleTesting/Partitioned/PartitionedIngressAndEgressTestMatrixBases.cs +++ b/Sources/Test/SimpleTesting/Partitioned/PartitionedIngressAndEgressTestMatrixBases.cs @@ -11,7 +11,7 @@ namespace SimpleTesting.PartitionedIngressAndEgress { - public class TriPartitionedOrderedTestsBase : TestWithConfigSettingsAndMemoryLeakDetection + public abstract class TriPartitionedOrderedTestsBase : TestWithConfigSettingsAndMemoryLeakDetection { internal TriPartitionedOrderedTestsBase( ConfigModifier config, @@ -86,8 +86,8 @@ private void ValidateOutput(IList input, IList data.Length, "Flush should push all events out."); + Assert.IsGreaterThan(data.Length, res.Count, "Flush should push all events out."); j.OnCompleted(); } @@ -748,7 +748,7 @@ public void AlterLifeTimeWithFlush() { } - Assert.IsTrue(res.Count > 0, "There should be some results."); + Assert.IsNotEmpty(res, "There should be some results."); } [TestMethod, TestCategory("Gated")] @@ -801,7 +801,7 @@ public void AlterLifeTimeWithFlushDoubles() { } - Assert.IsTrue(res.Count > 0, "There should be some results."); + Assert.IsNotEmpty(res, "There should be some results."); } [TestMethod, TestCategory("Gated")] diff --git a/Sources/Test/SimpleTesting/Serializer/SurrogateTests.cs b/Sources/Test/SimpleTesting/Serializer/SurrogateTests.cs index 975e98e97..ce2bb5b5b 100644 --- a/Sources/Test/SimpleTesting/Serializer/SurrogateTests.cs +++ b/Sources/Test/SimpleTesting/Serializer/SurrogateTests.cs @@ -108,7 +108,7 @@ public void SurrogateTest() input2.OnCompleted(); - Assert.AreEqual(2, output2.Count); + Assert.HasCount(2, output2); Assert.AreEqual(1, output2[0].Payload.GetValue()); Assert.AreEqual(StreamEvent.InfinitySyncTime, output2[1].SyncTime); } diff --git a/Sources/Test/SimpleTesting/SimpleTesting.csproj b/Sources/Test/SimpleTesting/SimpleTesting.csproj index 9b97824ad..179f2df5a 100644 --- a/Sources/Test/SimpleTesting/SimpleTesting.csproj +++ b/Sources/Test/SimpleTesting/SimpleTesting.csproj @@ -1,17 +1,17 @@  - net7.0;net6.0;net472 + net8.0 AnyCPU - - - - - - + + + + + + - - - all - runtime; build; native; contentfiles; analyzers - - - - - $(EnlistmentRoot)\Sources\Microsoft.StreamProcessing.ruleset - diff --git a/Sources/Core/Microsoft.StreamProcessing.Provider/Microsoft.StreamProcessing.Provider.csproj b/Sources/Core/Microsoft.StreamProcessing.Provider/Microsoft.StreamProcessing.Provider.csproj index b4dfea5bb..00948d43b 100644 --- a/Sources/Core/Microsoft.StreamProcessing.Provider/Microsoft.StreamProcessing.Provider.csproj +++ b/Sources/Core/Microsoft.StreamProcessing.Provider/Microsoft.StreamProcessing.Provider.csproj @@ -1,7 +1,7 @@  - net8.0 + net10.0 x64;AnyCPU diff --git a/Sources/Core/Microsoft.StreamProcessing/Microsoft.StreamProcessing.csproj b/Sources/Core/Microsoft.StreamProcessing/Microsoft.StreamProcessing.csproj index f3e5fc326..967913da3 100644 --- a/Sources/Core/Microsoft.StreamProcessing/Microsoft.StreamProcessing.csproj +++ b/Sources/Core/Microsoft.StreamProcessing/Microsoft.StreamProcessing.csproj @@ -1,7 +1,7 @@  - net8.0 + net10.0 x64;AnyCPU diff --git a/Sources/Test/Directory.Build.props b/Sources/Test/Directory.Build.props index 588c632b2..a3b945e01 100644 --- a/Sources/Test/Directory.Build.props +++ b/Sources/Test/Directory.Build.props @@ -28,7 +28,7 @@ - + diff --git a/Sources/Test/Microsoft.StreamProcessing.Test.ruleset b/Sources/Test/Microsoft.StreamProcessing.Test.ruleset index ca4f78706..c656edfee 100644 --- a/Sources/Test/Microsoft.StreamProcessing.Test.ruleset +++ b/Sources/Test/Microsoft.StreamProcessing.Test.ruleset @@ -4,6 +4,6 @@ - + \ No newline at end of file diff --git a/Sources/Test/SimpleTesting/AdHocTests.cs b/Sources/Test/SimpleTesting/AdHocTests.cs index 6c11d45a8..a78baca5e 100644 --- a/Sources/Test/SimpleTesting/AdHocTests.cs +++ b/Sources/Test/SimpleTesting/AdHocTests.cs @@ -44,7 +44,7 @@ public void Properties() .ToObservable() .ToStreamable(DisorderPolicy.Throw(), FlushPolicy.FlushOnPunctuation, PeriodicPunctuationPolicy.None(), OnCompletedPolicy.None); - var q2 = q1.Select(x => string.Join(",", x.A, x.B, x.C, x.D, x.E)); + var q2 = q1.Select(x => string.Join(",", new object[] { x.A, x.B, x.C, x.D, x.E })); int count = 0; q2.ToStreamEventObservable().ForEachAsync(x => count++).Wait(); @@ -67,7 +67,7 @@ public void Fields() .ToObservable() .ToStreamable(DisorderPolicy.Throw(), FlushPolicy.FlushOnPunctuation, PeriodicPunctuationPolicy.None(), OnCompletedPolicy.None); - var q2 = q1.Select(x => string.Join(",", x.A, x.B, x.C, x.D, x.E)); + var q2 = q1.Select(x => string.Join(",", new object[] { x.A, x.B, x.C, x.D, x.E })); int count = 0; q2.ToStreamEventObservable().ForEachAsync(x => count++).Wait(); diff --git a/Sources/Test/SimpleTesting/SimpleTesting.csproj b/Sources/Test/SimpleTesting/SimpleTesting.csproj index 179f2df5a..cff611c29 100644 --- a/Sources/Test/SimpleTesting/SimpleTesting.csproj +++ b/Sources/Test/SimpleTesting/SimpleTesting.csproj @@ -1,7 +1,7 @@  - net8.0 + net10.0 AnyCPU @@ -162,7 +162,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/Sources/Test/TrillPerf/PerformanceTesting.csproj b/Sources/Test/TrillPerf/PerformanceTesting.csproj index df3472d8d..5268654f5 100644 --- a/Sources/Test/TrillPerf/PerformanceTesting.csproj +++ b/Sources/Test/TrillPerf/PerformanceTesting.csproj @@ -2,7 +2,7 @@ Exe - net8.0 + net10.0 AnyCPU From b4e281fc5c87d9a434c89f02a0ef1297e37a9ad4 Mon Sep 17 00:00:00 2001 From: Amir Burbea Date: Mon, 23 Mar 2026 21:18:55 -0700 Subject: [PATCH 7/9] Eliminate heap allocations in BinaryDecoder/BinaryEncoder hot paths MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BinaryDecoder: - DecodeFloat, DecodeDouble, DecodeGuid, ReadIntFixed: replace new byte[] with stackalloc Span; add Span overload of ReadAllRequiredBytes - DecodeString: bypass DecodeByteArray, rent from ArrayPool, decode string, return buffer — avoids a heap allocation per string field BinaryEncoder: - Encode(float): replace BitConverter.GetBytes (allocates) with stackalloc + BitConverter.TryWriteBytes - Encode(Guid): replace ToByteArray() (allocates) with stackalloc + TryWriteBytes - Encode(string): replace Encoding.UTF8.GetBytes(string) (allocates) with ArrayPool rent, encode into span, delegate to Encode(ReadOnlySpan) --- .../Serializer/Encoders/BinaryDecoder.cs | 53 +++++++++++++------ .../Serializer/Encoders/BinaryEncoder.cs | 44 +++++++++++---- 2 files changed, 73 insertions(+), 24 deletions(-) diff --git a/Sources/Core/Microsoft.StreamProcessing/Serializer/Encoders/BinaryDecoder.cs b/Sources/Core/Microsoft.StreamProcessing/Serializer/Encoders/BinaryDecoder.cs index 8392f8475..35880a25c 100644 --- a/Sources/Core/Microsoft.StreamProcessing/Serializer/Encoders/BinaryDecoder.cs +++ b/Sources/Core/Microsoft.StreamProcessing/Serializer/Encoders/BinaryDecoder.cs @@ -3,6 +3,7 @@ // Licensed under the MIT License // ********************************************************************* using System; +using System.Buffers; using System.IO; using System.Runtime.Serialization; using System.Text; @@ -110,18 +111,15 @@ public ulong DecodeULong() public float DecodeFloat() { - var value = new byte[4]; + Span value = stackalloc byte[4]; ReadAllRequiredBytes(value); - if (!BitConverter.IsLittleEndian) - { - Array.Reverse(value); - } - return BitConverter.ToSingle(value, 0); + if (!BitConverter.IsLittleEndian) value.Reverse(); + return BitConverter.ToSingle(value); } public double DecodeDouble() { - var value = new byte[8]; + Span value = stackalloc byte[8]; ReadAllRequiredBytes(value); long longValue = value[0] | (long)value[1] << 0x8 @@ -142,7 +140,21 @@ public byte[] DecodeByteArray() return array; } - public string DecodeString() => Encoding.UTF8.GetString(DecodeByteArray()); + public string DecodeString() + { + int byteCount = DecodeInt(); + if (byteCount == 0) return string.Empty; + var rented = ArrayPool.Shared.Rent(byteCount); + try + { + ReadAllRequiredBytes(rented.AsSpan(0, byteCount)); + return Encoding.UTF8.GetString(rented, 0, byteCount); + } + finally + { + ArrayPool.Shared.Return(rented); + } + } public int DecodeArrayChunk() { @@ -157,9 +169,9 @@ public int DecodeArrayChunk() public Guid DecodeGuid() { - var array = new byte[16]; - ReadAllRequiredBytes(array); - return new Guid(array); + Span value = stackalloc byte[16]; + ReadAllRequiredBytes(value); + return new Guid(value); } private void ReadAllRequiredBytes(byte[] array) @@ -172,15 +184,26 @@ private void ReadAllRequiredBytes(byte[] array) } } + private void ReadAllRequiredBytes(Span span) + { + int totalRead = 0; + while (totalRead < span.Length) + { + int read = this.stream.Read(span.Slice(totalRead)); + if (read == 0) + throw new SerializationException($"Unexpected end of stream: '{span.Length - totalRead}' bytes missing."); + totalRead += read; + } + } + private int ReadIntFixed() { - var value = new byte[4]; - this.stream.ReadAllRequiredBytes(value, 0, value.Length); - int intValue = value[0] + Span value = stackalloc byte[4]; + ReadAllRequiredBytes(value); + return value[0] | value[1] << 0x8 | value[2] << 0x10 | value[3] << 0x18; - return intValue; } public unsafe T[] DecodeArray() where T : struct diff --git a/Sources/Core/Microsoft.StreamProcessing/Serializer/Encoders/BinaryEncoder.cs b/Sources/Core/Microsoft.StreamProcessing/Serializer/Encoders/BinaryEncoder.cs index dd944275e..902c15699 100644 --- a/Sources/Core/Microsoft.StreamProcessing/Serializer/Encoders/BinaryEncoder.cs +++ b/Sources/Core/Microsoft.StreamProcessing/Serializer/Encoders/BinaryEncoder.cs @@ -3,6 +3,7 @@ // Licensed under the MIT License // ********************************************************************* using System; +using System.Buffers; using System.IO; using System.Text; using Microsoft.StreamProcessing.Internal; @@ -83,13 +84,10 @@ public void Encode(ulong value) public void Encode(float value) { - byte[] bytes = BitConverter.GetBytes(value); - if (!BitConverter.IsLittleEndian) - { - Array.Reverse(bytes); - } - - this.stream.Write(bytes, 0, bytes.Length); + Span bytes = stackalloc byte[4]; + BitConverter.TryWriteBytes(bytes, value); + if (!BitConverter.IsLittleEndian) bytes.Reverse(); + this.stream.Write(bytes); } public void Encode(double value) @@ -113,12 +111,40 @@ public void Encode(byte[] value) if (value.Length > 0) this.stream.Write(value, 0, value.Length); } + public void Encode(ReadOnlySpan span) + { + int count = span.Length; + Encode(count); + if (count > 0) + { + this.stream.Write(span); + } + } + public void Encode(string value) - => Encode(Encoding.UTF8.GetBytes(value ?? throw new ArgumentNullException(nameof(value)))); + { + if (value == null) throw new ArgumentNullException(nameof(value)); + int byteCount = Encoding.UTF8.GetByteCount(value); + var rented = ArrayPool.Shared.Rent(byteCount); + try + { + int written = Encoding.UTF8.GetBytes(value, rented); + Encode(rented.AsSpan(0, written)); + } + finally + { + ArrayPool.Shared.Return(rented); + } + } public void EncodeArrayChunk(int size) => Encode(size); - public void Encode(Guid value) => this.stream.Write(value.ToByteArray(), 0, 16); + public void Encode(Guid value) + { + Span bytes = stackalloc byte[16]; + value.TryWriteBytes(bytes); + this.stream.Write(bytes); + } private void WriteIntFixed(int encodedValue) { From e86158af7e28f43000d1eb8f72fb604775cf19a9 Mon Sep 17 00:00:00 2001 From: Amir Burbea Date: Mon, 23 Mar 2026 23:03:31 -0700 Subject: [PATCH 8/9] Fix JoinTestWithException to be deterministic across test orderings The codegen cache (EquiJoinStreamable.cachedPipes) persisted across tests in the same process, causing JoinTestWithException to silently succeed (no exception thrown) when a compatible join had already been compiled by an earlier test. Fix: add internal Clear() to SafeConcurrentDictionary, expose cachedPipes as internal on EquiJoinStreamable, and clear the exact cache instance in [TestInitialize] before each run. The test now uses a named JoinResult struct so the closed generic type can be referenced at compile time, and asserts the StreamProcessingException is always thrown. --- .../Collections/SafeConcurrentDictionary.cs | 12 ++++++ .../Operators/EquiJoin/EquiJoinStreamable.cs | 6 ++- Sources/Test/SimpleTesting/AdHocTests.cs | 41 ++++++++++++------- 3 files changed, 43 insertions(+), 16 deletions(-) diff --git a/Sources/Core/Microsoft.StreamProcessing/Collections/SafeConcurrentDictionary.cs b/Sources/Core/Microsoft.StreamProcessing/Collections/SafeConcurrentDictionary.cs index 9b04f7206..153890de3 100644 --- a/Sources/Core/Microsoft.StreamProcessing/Collections/SafeConcurrentDictionary.cs +++ b/Sources/Core/Microsoft.StreamProcessing/Collections/SafeConcurrentDictionary.cs @@ -44,6 +44,18 @@ public TValue GetOrAdd(CacheKey key, Func valueFactory) [MethodImpl(MethodImplOptions.AggressiveInlining)] public IEnumerator> GetEnumerator() => this.dictionary.GetEnumerator(); + /// + /// Clears all entries from the dictionary and the per-key lock table. + /// Marked internal (not private) so that test code can clear the codegen cache + /// (e.g. EquiJoinStreamable.cachedPipes) to ensure deterministic test behavior + /// without relying on reflection. + /// + internal void Clear() + { + this.dictionary.Clear(); + this.keyLocks.Clear(); + } + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); /// diff --git a/Sources/Core/Microsoft.StreamProcessing/Operators/EquiJoin/EquiJoinStreamable.cs b/Sources/Core/Microsoft.StreamProcessing/Operators/EquiJoin/EquiJoinStreamable.cs index 4624db258..9c049504f 100644 --- a/Sources/Core/Microsoft.StreamProcessing/Operators/EquiJoin/EquiJoinStreamable.cs +++ b/Sources/Core/Microsoft.StreamProcessing/Operators/EquiJoin/EquiJoinStreamable.cs @@ -11,8 +11,10 @@ namespace Microsoft.StreamProcessing { internal sealed class EquiJoinStreamable : BinaryStreamable { - private static readonly SafeConcurrentDictionary> cachedPipes - = new SafeConcurrentDictionary>(); + // Internal (not private) so test code can call cachedPipes.Clear() to ensure + // deterministic behavior in tests that depend on a fresh codegen compile. + internal static readonly SafeConcurrentDictionary> cachedPipes + = new SafeConcurrentDictionary>(); private readonly JoinKind joinKind; private readonly Func> columnarGenerator; diff --git a/Sources/Test/SimpleTesting/AdHocTests.cs b/Sources/Test/SimpleTesting/AdHocTests.cs index a78baca5e..f201a7204 100644 --- a/Sources/Test/SimpleTesting/AdHocTests.cs +++ b/Sources/Test/SimpleTesting/AdHocTests.cs @@ -2325,6 +2325,21 @@ public class LeftComparerPayload_WithCodegen : TestWithConfigSettingsAndMemoryLe public LeftComparerPayload_WithCodegen() : base(new ConfigModifier().DontFallBackToRowBasedExecution(true)) { } + // Named result type so the full closed generic EquiJoinStreamable<,,,,> can be + // referenced at compile time (anonymous types cannot be named in typeof/generic arguments). + public struct JoinResult { public int LeftX; public int RightX; } + + [TestInitialize] + public void ClearCodegenCache() + { + // Clear the EquiJoin codegen cache before each test so that JoinTestWithException + // always triggers a fresh compile and deterministically throws StreamProcessingException, + // regardless of which tests ran before it in the same process. + // The join is built via Map+Reduce, so the inner EquiJoinStreamable uses TKey=CompoundGroupKey. + EquiJoinStreamable, ClassOverridingEquals, int, JoinResult> + .cachedPipes.Clear(); + } + public class ClassOverridingEquals { public int x; @@ -2334,9 +2349,10 @@ public class ClassOverridingEquals } /// - /// This test has a left comparer which has a reference to the left - /// payload instead of just to its fields. This causes the streamable - /// to thrown an exception. + /// This test has a left comparer which has a reference to the left payload instead of + /// just to its fields. Codegen should always throw StreamProcessingException when + /// compiling this join fresh. The [TestInitialize] method clears the codegen cache + /// before this test runs to ensure deterministic behavior in the full test suite. /// [TestMethod] public void JoinTestWithException() @@ -2353,20 +2369,17 @@ public void JoinTestWithException() .ToStreamable() ; - bool exceptionHappened = false; + bool threw = false; try { - var result = stream1 - .Join(stream2, e => e.x, e => e, (left, right) => new { LeftX = left.x, RightX = right, }) - .ToStreamEventObservable() - .ToEnumerable() - .ToArray(); - } - catch (StreamProcessingException) - { - exceptionHappened = true; + stream1 + .Join(stream2, e => e.x, e => e, (left, right) => new JoinResult { LeftX = left.x, RightX = right }) + .ToStreamEventObservable() + .ToEnumerable() + .ToArray(); } - Assert.IsTrue(exceptionHappened); + catch (StreamProcessingException) { threw = true; } + Assert.IsTrue(threw, "Expected StreamProcessingException from codegen failure on ClassOverridingEquals"); } } From f05cf2dc34205985f3c97b4e1a66b025c913f872 Mon Sep 17 00:00:00 2001 From: Amir Burbea Date: Thu, 26 Mar 2026 15:07:49 -0700 Subject: [PATCH 9/9] Fix long standing bug in CountAggregate where Sum was accidentally implemented with - instead of +. SimpleTesting does not have a test for this. --- .../Microsoft.StreamProcessing/Aggregates/CountAggregate.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/Core/Microsoft.StreamProcessing/Aggregates/CountAggregate.cs b/Sources/Core/Microsoft.StreamProcessing/Aggregates/CountAggregate.cs index db3e0ab86..d4ab16d42 100644 --- a/Sources/Core/Microsoft.StreamProcessing/Aggregates/CountAggregate.cs +++ b/Sources/Core/Microsoft.StreamProcessing/Aggregates/CountAggregate.cs @@ -21,7 +21,7 @@ internal sealed class CountAggregate : ISummableAggregate> diff = (leftCount, rightCount) => leftCount - rightCount; public Expression> Difference() => diff; - private static readonly Expression> sum = (leftCount, rightCount) => leftCount - rightCount; + private static readonly Expression> sum = (leftCount, rightCount) => leftCount + rightCount; public Expression> Sum() => sum; private static readonly Expression> res = count => count;