[7.0] Address flaky DEBUG assertions#4143
Conversation
There was a problem hiding this comment.
Pull request overview
Ports PR #4085 to the release/7.0 branch by refactoring the ManualTests assertion helpers to correctly validate inner exception types and updating race-prone async-disposal tests to accept known alternate exception types, reducing DEBUG-mode flakiness on Linux/.NET.
Changes:
- Replaced
DataTestUtility.AssertThrowsWrapper*overloads with newAssertThrows*helpers that properly validate inner exception types and support “alternate inner exception” races. - Refactored
DataStreamTestto remove duplicatedTask.Wait()/AggregateExceptionhandling and updated race-sensitive assertions to tolerate expected alternate exception types. - Renamed assertion helper call sites across the manual test suite to the new APIs (plus minor whitespace/format cleanups).
Reviewed changes
Copilot reviewed 24 out of 24 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/DataTestUtility.cs | Introduces new AssertThrows* helpers (with proper inner-type validation) and updates nullable scoping. |
| src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/DataStreamTest/DataStreamTest.cs | Consolidates flaky Task.Wait() handling and updates assertions for known race-condition exception variability. |
| src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/UdtTest/UdtTest2.cs | Renames assertion helper usages to AssertThrows. |
| src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/TransactionTest/TransactionTest.cs | Renames assertion helper usages to AssertThrows. |
| src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlNotificationTest/SqlNotificationTest.cs | Renames assertion helper usages to AssertThrows. |
| src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlCommand/SqlCommandCancelTest.cs | Renames assertion helper usages to AssertThrows; minor comment whitespace cleanup. |
| src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/TransactionTestAsync.cs | Switches to AssertThrowsInner for validating AggregateException inner type. |
| src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/Transaction4.cs | Renames assertion helper usage to AssertThrows. |
| src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/Transaction3.cs | Renames assertion helper usages to AssertThrows. |
| src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/Transaction1.cs | Renames assertion helper usage to AssertThrows. |
| src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/Transaction.cs | Renames assertion helper usage to AssertThrows. |
| src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/OrderHintMissingTargetColumn.cs | Renames assertion helper usages to AssertThrows. |
| src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/OrderHintDuplicateColumn.cs | Renames assertion helper usage to AssertThrows. |
| src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/MissingTargetColumns.cs | Renames assertion helper usage to AssertThrows. |
| src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/MissingTargetColumn.cs | Renames assertion helper usage to AssertThrows. |
| src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/CopyWithEvent1.cs | Renames assertion helper usage to AssertThrows. |
| src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/CopyAllFromReaderConnectionCloseOnEventAsync.cs | Adds System.IO and uses AssertThrowsInnerWithAlternate to handle race-dependent inner exception types. |
| src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/CopyAllFromReaderConnectionCloseAsync.cs | Switches to AssertThrowsInner for validating AggregateException inner type. |
| src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/CopyAllFromReaderCancelAsync.cs | Switches to AssertThrowsInner for validating AggregateException inner type. |
| src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ParameterTest/ParametersTest.cs | Renames assertion helper usages to AssertThrows. |
| src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ParallelTransactionsTest/ParallelTransactionsTest.cs | Renames assertion helper usages to AssertThrows. |
| src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/MARSTest/MARSTest.cs | Renames assertion helper usages to AssertThrows. |
| src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/LocalDBTest/LocalDBTest.cs | Renames assertion helper usage to AssertThrows. |
| src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/AdapterTest/AdapterTest.cs | Renames assertion helper usages to AssertThrows. |
Codecov Report✅ All modified and coverable lines are covered by tests.
Additional details and impacted files@@ Coverage Diff @@
## release/7.0 #4143 +/- ##
===============================================
- Coverage 73.07% 65.58% -7.50%
===============================================
Files 280 275 -5
Lines 42997 65822 +22825
===============================================
+ Hits 31422 43171 +11749
- Misses 11575 22651 +11076
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Description
Port of #4085 to release/7.0.
Refactors the
DataTestUtility.AssertThrowsWrapperassertion helpers and fixes race condition test failures across the manual test suite.Problem
DataStreamTest(see SqlDataReader async read throws inconsistent exception types on disposal (IOException vs InvalidOperationException) #4088, Fix commented-out Debug.Assert()s that are failing #3604).PendAsyncReadsScopeis disposed while an asyncReadAsyncis in-flight, the inner exception type varies depending on timing — it may beIOException,InvalidOperationException,ObjectDisposedException, orTaskCanceledException. The existing assertion helpers only accepted a single expected type and would fail intermittently.AssertThrowsWrapperaccepted generic type parameters for inner/inner-inner exceptions but never validated them with actual type checks. It also had unused parameters (innerExceptionMustBeNull,customExceptionVerifier,innerInnerInnerExceptionMustBeNull) that no callers were passing.try { t.Wait(); } catch (AggregateException) { ... }blocks were scattered throughoutDataStreamTest.cs.Changes
DataTestUtility.cs— Assertion helper redesignReplaced the three
AssertThrowsWrapperoverloads with four properly-typed, well-documented helpers:AssertThrowsWrapper<T>(...)AssertThrows<T>(...)innerExceptionMustBeNull,customExceptionVerifier)AssertThrowsWrapper<T, TInner>(...)AssertThrowsInner<T, TInner>(...)Assert.IsAssignableFrom<TInnerException>AssertThrowsWrapper<T, TInner, TInnerInner>(...)AssertThrowsInnerWithAlternate<T, TInner, TAlt>(...)All helpers are wrapped in a
#nullable enableblock with XML documentation.DataStreamTest.cs— Race condition fixesWaitIgnoringFlakyException(Task): Replaces 6 duplicatedtry/catchblocks. Callstask.Wait()and ignoresAggregateExceptiononly for faulted tasks (with a comment explaining that a faultedTaskpermanently stores its exception, so re-waiting always rethrows).AssertThrowsInnerWithAlternate:IOException↔InvalidOperationExceptiondepending on reader disposal timingTaskCanceledException↔InvalidOperationExceptiondepending onPendAsyncReadsScopedisposal timingIOException→SqlExceptionorObjectDisposedExceptionalternate pathTODO(GH-3604)comments — replaced with proper alternate-type assertions that handle the race correctly.22 other test files — Assertion renames
All call sites across the manual test suite updated from
AssertThrowsWrapperto the new names:AssertThrowsWrapper<T>(...)→AssertThrows<T>(...)AssertThrowsWrapper<T, TInner>(...)→AssertThrowsInner<T, TInner>(...)Files: AdapterTest, LocalDBTest, MARSTest, ParallelTransactionsTest, ParametersTest, 10 SqlBulkCopy tests, SqlCommandCancelTest, SqlNotificationTest, TransactionTest, UdtTest2, CopyAllFromReaderConnectionCloseOnEventAsync.
Minor cleanups
#pragma warningindentation inDataTestUtility.cs#nullable disable→#nullable restorefor proper nullable context scopingTesting
ReadStream_ReadsStreamDataCorrectlyline 1828) is fixed by theAssertThrowsInnerWithAlternatechange