Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2638,7 +2638,8 @@ jobs:
- 'Darling/Darling.Tests/McpArgumentTypeRows.cs'
- 'Darling/Darling.Tests/StatementScrubCanary.cs'
- 'Darling/Darling.Tests/GuardStageScanner.cs'
- 'Darling/Darling.Tests/WpfStaGate.cs'
- 'Darling/Darling.Tests/StaTestThread.cs'
- 'Darling/Darling.Tests/TimingTestScanner.cs'
- 'Darling/Darling.Tests/WpfExitSwitchTests.cs'
# How much of the Lite suite THIS leg runs, decided from the filter answers alone (no build needed):
# full - a Lite, Lite.Tests, core or root path changed, or a Darling.Tests file that Lite.Tests
Expand Down
27 changes: 4 additions & 23 deletions Darling/Darling.Tests/AvailabilityGroupsTabRefreshTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public void Render_SameRowsAcrossTwoCalls_KeepsTheSameCardInstances()
/* The pin the ruling asks for: two refreshes over identical rows must not hand the ItemsControl a new
object per card. Before the fix, Render assigns a brand new List<AgTopologyCard> (brand new instances)
every call, so this fails on the pre-#4238 code — proven once, below. */
OnStaThread(() =>
StaTestThread.Run(() =>
{
var tab = new AvailabilityGroupsTab();

Expand All @@ -56,7 +56,7 @@ public void Render_SameRowsAcrossTwoCalls_KeepsTheSameCardInstances()
[Fact]
public void Render_ChangedValue_UpdatesInPlace_SameInstanceNewValue()
{
OnStaThread(() =>
StaTestThread.Run(() =>
{
var tab = new AvailabilityGroupsTab();

Expand All @@ -80,7 +80,7 @@ public void Render_ChangedValue_UpdatesInPlace_SameInstanceNewValue()
[Fact]
public void Render_AddedOrRemovedAg_AddsOrRemovesExactlyOneCard()
{
OnStaThread(() =>
StaTestThread.Run(() =>
{
var tab = new AvailabilityGroupsTab();

Expand Down Expand Up @@ -129,7 +129,7 @@ public void Render_UnchangedRows_ReplacesNoCardReplicaOrDatabaseInstances()
reconcile every card, replica and database IN PLACE and never rebuild any of them. A regression that
tears down and rebuilds rows -- or an O(n^2) loop that amounts to the same thing -- shows up here as a
nonzero replaced count, independent of how loaded the runner is. */
OnStaThread(() =>
StaTestThread.Run(() =>
{
var tab = new AvailabilityGroupsTab();
var topology = BuildTopology(agCount: 42, replicasPerAg: 2, dbRowsPerAg: 9, extraDbRowsOnFirst: 20);
Expand Down Expand Up @@ -253,23 +253,4 @@ private static AgTopologyDatabaseRow Database(int serverId, string serverName, s
RedoRateKbPerSec = 0,
};

/// <summary>WPF objects require STA; same shape as RawWindowFloorViewerPortTests / Lite.Tests' MainWindowAccessKeyTests.</summary>
private static void OnStaThread(Action body)
{
Exception? error = null;
using var staGate = WpfStaGate.Enter();
var thread = new Thread(() =>
{
try { body(); }
catch (Exception ex) { error = ex; }
});
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
thread.Join();

if (error is not null)
{
throw error;
}
}
}
1 change: 1 addition & 0 deletions Darling/Darling.Tests/BoundedCompressionDdlTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ namespace Darling.Tests;
/// failed settings read.
/// </summary>
/* #1776 own-store: each live fact mints its own scratch database through ScratchPostgres. */
[Collection("timing")]
public sealed class BoundedCompressionDdlTests
{
private static string Storage() =>
Expand Down
44 changes: 13 additions & 31 deletions Darling/Darling.Tests/ColumnFilterPersistenceTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -509,24 +509,6 @@ private sealed class LoginRow
public string? Detail { get; set; }
}

private static T OnStaThread<T>(Func<T> body)
{
T result = default!;
Exception? error = null;
using var staGate = WpfStaGate.Enter();
var thread = new Thread(() =>
{
try { result = body(); }
catch (Exception ex) { error = ex; }
});
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
thread.Join();
if (error is not null)
throw error;
return result;
}

private static DataGrid NewGrid(string? name, string? server)
{
var grid = new DataGrid { AutoGenerateColumns = false };
Expand Down Expand Up @@ -555,7 +537,7 @@ private static void Untick(IDataGridFilterManager manager, string column, string
[Fact]
public void A_text_match_on_a_query_text_column_lasts_the_session_but_is_not_stored()
{
var kept = OnStaThread(() =>
var kept = StaTestThread.Run(() =>
{
var store = NewStore();
ColumnFilterStore.Current = store;
Expand Down Expand Up @@ -591,7 +573,7 @@ public void A_text_match_on_a_query_text_column_lasts_the_session_but_is_not_sto
[Fact]
public void A_filter_survives_a_refresh_and_a_value_that_first_appears_later_still_shows()
{
OnStaThread(() =>
StaTestThread.Run(() =>
{
var grid = NewGrid("G", null);
var manager = new DataGridFilterManager<LoginRow>(grid);
Expand All @@ -610,7 +592,7 @@ public void A_filter_survives_a_refresh_and_a_value_that_first_appears_later_sti
[Fact]
public void The_value_list_comes_from_the_unfiltered_rows_not_the_ones_shown()
{
OnStaThread(() =>
StaTestThread.Run(() =>
{
var grid = NewGrid("G", null);
var manager = new DataGridFilterManager<LoginRow>(grid);
Expand All @@ -626,7 +608,7 @@ public void The_value_list_comes_from_the_unfiltered_rows_not_the_ones_shown()
[Fact]
public void Number_query_text_and_prose_columns_and_columns_the_row_lacks_get_no_list()
{
OnStaThread(() =>
StaTestThread.Run(() =>
{
var grid = NewGrid("G", null);
var manager = new DataGridFilterManager<LoginRow>(grid);
Expand All @@ -645,7 +627,7 @@ public void Number_query_text_and_prose_columns_and_columns_the_row_lacks_get_no
[Fact]
public void A_text_column_that_sorts_by_another_member_gets_no_list()
{
OnStaThread(() =>
StaTestThread.Run(() =>
{
var grid = NewGrid("G", null);
((DataGridTextColumn)grid.Columns[0]).SortMemberPath = "SessionId";
Expand All @@ -660,7 +642,7 @@ public void A_text_column_that_sorts_by_another_member_gets_no_list()
[Fact]
public void A_column_with_a_value_over_256_characters_gets_no_list()
{
OnStaThread(() =>
StaTestThread.Run(() =>
{
var grid = NewGrid("G", null);
var manager = new DataGridFilterManager<LoginRow>(grid);
Expand All @@ -674,7 +656,7 @@ public void A_column_with_a_value_over_256_characters_gets_no_list()
[Fact]
public void A_filter_set_in_one_session_is_loaded_by_the_next_on_its_first_refresh()
{
var shown = OnStaThread(() =>
var shown = StaTestThread.Run(() =>
{
var store = NewStore();
ColumnFilterStore.Current = store;
Expand All @@ -700,7 +682,7 @@ public void A_filter_set_in_one_session_is_loaded_by_the_next_on_its_first_refre
[Fact]
public void A_cross_server_list_under_the_all_servers_scope_keeps_its_filters_across_a_restart()
{
var shown = OnStaThread(() =>
var shown = StaTestThread.Run(() =>
{
var store = NewStore();
ColumnFilterStore.Current = store;
Expand All @@ -723,7 +705,7 @@ public void A_cross_server_list_under_the_all_servers_scope_keeps_its_filters_ac
[Fact]
public void Another_servers_filters_do_not_apply_and_a_grid_without_a_name_or_scope_is_not_stored()
{
OnStaThread(() =>
StaTestThread.Run(() =>
{
var store = NewStore();
ColumnFilterStore.Current = store;
Expand Down Expand Up @@ -757,7 +739,7 @@ public void Another_servers_filters_do_not_apply_and_a_grid_without_a_name_or_sc
[Fact]
public void A_stored_filter_on_a_column_the_grid_no_longer_has_is_ignored()
{
OnStaThread(() =>
StaTestThread.Run(() =>
{
var store = NewStore();
store.Save("srv-a", "G", new[] { Hide("RetiredColumn", "x"), Hide("LoginName", "job_svc") });
Expand All @@ -776,7 +758,7 @@ public void A_stored_filter_on_a_column_the_grid_no_longer_has_is_ignored()
[Fact]
public void Clear_all_filters_clears_the_grid_and_the_stored_copy_but_a_server_switch_does_not()
{
OnStaThread(() =>
StaTestThread.Run(() =>
{
var store = NewStore();
ColumnFilterStore.Current = store;
Expand Down Expand Up @@ -806,7 +788,7 @@ public void Clear_all_filters_clears_the_grid_and_the_stored_copy_but_a_server_s
[Fact]
public void A_server_switch_loads_the_new_servers_own_filters()
{
OnStaThread(() =>
StaTestThread.Run(() =>
{
var store = NewStore();
store.Save("srv-b", "G", new[] { Hide("LoginName", "sa") });
Expand All @@ -828,7 +810,7 @@ public void A_server_switch_loads_the_new_servers_own_filters()
[Fact]
public void A_store_that_fails_never_blocks_the_grid()
{
OnStaThread(() =>
StaTestThread.Run(() =>
{
File.WriteAllText(FilePath, "garbage");
ColumnFilterStore.Current = NewStore();
Expand Down
40 changes: 11 additions & 29 deletions Darling/Darling.Tests/ColumnFilterPopupTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,24 +26,6 @@ namespace Darling.Tests;
/// </summary>
public sealed class ColumnFilterPopupTests
{
private static T OnStaThread<T>(Func<T> body)
{
T result = default!;
Exception? error = null;
using var staGate = WpfStaGate.Enter();
var thread = new Thread(() =>
{
try { result = body(); }
catch (Exception ex) { error = ex; }
});
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
thread.Join();
if (error is not null)
throw error;
return result;
}

private static T Find<T>(DependencyObject root, Func<T, bool> where) where T : DependencyObject
{
foreach (var child in LogicalTreeHelper.GetChildren(root).OfType<DependencyObject>())
Expand All @@ -65,7 +47,7 @@ private static Button ButtonNamed(ColumnFilterPopup popup, string content) =>
[Fact]
public void The_list_section_shows_only_for_a_column_with_a_catalog()
{
OnStaThread(() =>
StaTestThread.Run(() =>
{
var popup = new ColumnFilterPopup();
var panel = Find<StackPanel>(popup, p => p.Name == "ValueListPanel");
Expand All @@ -84,7 +66,7 @@ public void The_list_section_shows_only_for_a_column_with_a_catalog()
[Fact]
public void The_search_box_narrows_the_list_and_Select_All_covers_what_it_shows()
{
OnStaThread(() =>
StaTestThread.Run(() =>
{
var popup = new ColumnFilterPopup();
popup.Initialize("LoginName", null, Catalog("sa", "app", "job_svc", null));
Expand Down Expand Up @@ -113,7 +95,7 @@ public void The_search_box_narrows_the_list_and_Select_All_covers_what_it_shows(
[Fact]
public void Nothing_ticked_shows_the_note_and_the_cap_note_shows_for_a_long_list()
{
OnStaThread(() =>
StaTestThread.Run(() =>
{
var popup = new ColumnFilterPopup();
popup.Initialize("LoginName", null, Catalog("a", "b"));
Expand All @@ -134,7 +116,7 @@ public void Nothing_ticked_shows_the_note_and_the_cap_note_shows_for_a_long_list
[Fact]
public void An_existing_value_filter_comes_back_as_the_ticks_and_the_text_match_beside_it()
{
OnStaThread(() =>
StaTestThread.Run(() =>
{
var existing = new ColumnFilterState { ColumnName = "LoginName", ValueMode = ColumnValueMode.Hide, Operator = FilterOperator.StartsWith, Value = "s" };
existing.Values.Add("job_svc");
Expand All @@ -158,7 +140,7 @@ public void An_existing_value_filter_comes_back_as_the_ticks_and_the_text_match_
[Fact]
public void A_column_without_a_list_keeps_a_stored_value_filter_when_the_text_match_is_applied()
{
OnStaThread(() =>
StaTestThread.Run(() =>
{
var existing = new ColumnFilterState { ColumnName = "LoginName", ValueMode = ColumnValueMode.ShowOnly };
existing.Values.Add("sa");
Expand All @@ -178,7 +160,7 @@ public void A_column_without_a_list_keeps_a_stored_value_filter_when_the_text_ma
[Fact]
public void A_text_only_apply_keeps_the_stored_value_part_even_when_todays_rows_have_drifted_from_it()
{
OnStaThread(() =>
StaTestThread.Run(() =>
{
/* Scenario A: stored ShowOnly {sa}, but the rows now hold only sa. Re-deriving the mode would find nothing
unticked, give None, and drop the filter. */
Expand Down Expand Up @@ -214,7 +196,7 @@ public void A_text_only_apply_keeps_the_stored_value_part_even_when_todays_rows_
[Fact]
public void Select_All_unticked_shows_the_no_values_note_at_once()
{
OnStaThread(() =>
StaTestThread.Run(() =>
{
var popup = new ColumnFilterPopup();
popup.Initialize("LoginName", null, Catalog("a", "b"));
Expand All @@ -234,7 +216,7 @@ public void Select_All_unticked_shows_the_no_values_note_at_once()
[Fact]
public void A_stored_value_part_on_a_column_with_no_list_shows_read_only_with_a_way_to_clear_it()
{
OnStaThread(() =>
StaTestThread.Run(() =>
{
var existing = new ColumnFilterState { ColumnName = "LoginName", ValueMode = ColumnValueMode.Hide };
existing.Values.Add("a");
Expand Down Expand Up @@ -276,7 +258,7 @@ public void A_stored_value_part_on_a_column_with_no_list_shows_read_only_with_a_
[Fact]
public void Clear_all_filters_shows_only_when_the_grid_has_a_filter_and_raises_its_event()
{
OnStaThread(() =>
StaTestThread.Run(() =>
{
var popup = new ColumnFilterPopup();
var button = ButtonNamed(popup, "Clear all filters");
Expand All @@ -297,7 +279,7 @@ public void Clear_all_filters_shows_only_when_the_grid_has_a_filter_and_raises_i
[Fact]
public void Clear_applies_an_empty_filter_including_the_value_part()
{
OnStaThread(() =>
StaTestThread.Run(() =>
{
var existing = new ColumnFilterState { ColumnName = "LoginName", ValueMode = ColumnValueMode.Hide };
existing.Values.Add("a");
Expand All @@ -316,7 +298,7 @@ public void Clear_applies_an_empty_filter_including_the_value_part()
[Fact]
public void Esc_closes_the_popup_from_anywhere_in_it_and_the_list_is_virtualised_and_tab_stops_once()
{
OnStaThread(() =>
StaTestThread.Run(() =>
{
var popup = new ColumnFilterPopup();
popup.Initialize("LoginName", null, Catalog("a", "b"));
Expand Down
Loading
Loading