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
51 changes: 28 additions & 23 deletions Darling/Darling.Tests/AgGroupIdRungTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,9 @@ namespace Darling.Tests;
/// <c>group_id IS NULL</c> rather than erroring, and an INSERT in the collector's own column order round
/// trips a GUID string end to end.
///
/// <para>This file's "I am the top rung" claim takes over from
/// <c>CollectionLogWatermarkAndJobHistoryIndexesRungTests</c> (V150) now that V151 has landed.</para>
/// <para>This file's "I am the top rung" claim moved to <c>CaggGroupIndexDropRungTests</c> (V152) now
/// that V152 has landed; this file's own rung/probe facts below keep asserting what stays true forever
/// (present, in-order, gated behind the arm above it) rather than "is exactly the top".</para>
/// </summary>
/* #1776 own-store: each fact mints its own scratch database through ScratchPostgres and never touches the
shared store's tables, so it cannot race the live collection and serializing it would be pure slowdown. */
Expand All @@ -37,64 +38,68 @@ public sealed class AgGroupIdRungTests
private const int RungVersion = 151;
private const int PreviousVersion = 150;

/// <summary>This rung's sentinel ordinal in the viewer probe — the newest, so the last argument.</summary>
/// <summary>This rung's sentinel ordinal in the viewer probe — no longer the newest, since V152
/// landed above it.</summary>
private const int ProbeOrdinal = 126;

private static string? ConnectionString => Environment.GetEnvironmentVariable("DARLING_TEST_PG");

/// <summary>
/// The rung is registered and is the new top of the ladder — the claim this class takes over from
/// <c>CollectionLogWatermarkAndJobHistoryIndexesRungTests</c> (V150) now that V151 has landed.
/// The rung is registered, and the ladder stays dense above the historical gap — the claim this class
/// took over from <c>CollectionLogWatermarkAndJobHistoryIndexesRungTests</c> (V150) moved on again to
/// <c>CaggGroupIndexDropRungTests</c> (V152) now that V152 has landed.
/// </summary>
[Fact]
public void TheRungIsRegisteredAtTheTopOfADenseLadder()
public void TheRungIsRegistered_AndTheLadderIsDenseAboveTheHistoricalGap()
{
var versions = PgMigrations.Scripts.Select(s => s.Version).ToList();

Assert.Equal("ag-group-id", PgMigrations.Scripts.Single(s => s.Version == RungVersion).Name);
Assert.Equal(StorageVersion.SchemaVersion, PgMigrations.Scripts[^1].Version);
Assert.Equal(StorageVersion.SchemaVersion, versions.Max());
Assert.Equal(RungVersion, StorageVersion.SchemaVersion);
Assert.Equal(versions.Distinct().OrderBy(v => v), versions);

var above = versions.Where(v => v > 45).OrderBy(v => v).ToList();
Assert.Equal(Enumerable.Range(above[0], above.Count), above);
}

/// <summary>
/// The viewer probe's sentinel carries this rung, and the map treats it as the TOP arm: a missing top arm
/// maps a fully-migrated store one rung short, permanently, because
/// The viewer probe's sentinel carries this rung, and the map treats it as an arm gated below the
/// current top's arm — a missing arm maps a fully-migrated store one rung short, permanently, because
/// <see cref="ViewerDataService.RequiredStoreSchemaVersion"/> is <see cref="StorageVersion.SchemaVersion"/>.
/// </summary>
[Fact]
public void TheProbeMapsAFullyMigratedStoreToThisTopRung()
public void TheProbeCarriesThisRungsSentinel_AndTheArmSitsBelowTheCurrentTop()
{
var probe = ViewerDataService.StoreSchemaProbeSql.Replace("\r\n", "\n", StringComparison.Ordinal);
Assert.Contains("table_name = 'ag_replica_states'", probe, StringComparison.Ordinal);
Assert.Contains("column_name = 'group_id'", probe, StringComparison.Ordinal);

var viewer = RepoFile.ReadRepoFile("Darling", "PerformanceMonitor.Darling.Viewer", "ViewerDataService.cs");
Assert.Contains($"reader.GetBoolean({ProbeOrdinal})", viewer, StringComparison.Ordinal);
Assert.DoesNotContain($"reader.GetBoolean({ProbeOrdinal + 1})", viewer, StringComparison.Ordinal);

Assert.Equal(StorageVersion.SchemaVersion, ViewerDataService.RequiredStoreSchemaVersion);

var method = typeof(ViewerDataService).GetMethod("MapProbedSchemaVersion", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static)!;
var arity = method.GetParameters().Length;
Assert.Equal(ProbeOrdinal, arity - 1);
Assert.Equal("hasAgGroupId", method.GetParameters()[ProbeOrdinal].Name);

/* Every rung above this one (V152's hasCaggGroupIndexDrop) must also be false, or the map finds
the newer arm first and this assertion is checking the wrong rung's fallthrough. */
var all = Enumerable.Repeat((object)true, arity).ToArray();
Assert.Equal(StorageVersion.SchemaVersion, (int)method.Invoke(null, all)!);

var behind = (object[])all.Clone();
behind[ProbeOrdinal] = false;
for (var i = ProbeOrdinal; i < arity; i++)
{
behind[i] = false;
}
Assert.Equal(PreviousVersion, (int)method.Invoke(null, behind)!);

/* V152 (#4503) is now the top rung, so this arm no longer needs to be the LAST one — it only has to
sit below the current top's arm, which is what the ladder-dense invariant above already
guarantees is registered ahead of it. */
var thisArm = viewer.IndexOf("if (hasAgGroupId)", StringComparison.Ordinal);
var previousArm = viewer.IndexOf("if (hasCollectionLogWatermarkAndJobHistoryIndexes)", StringComparison.Ordinal);
var topArm = viewer.IndexOf("if (hasCaggGroupIndexDrop)", StringComparison.Ordinal);
Assert.True(thisArm >= 0, "the viewer has no V151 sentinel arm — a fully-migrated store would map one rung short");
Assert.True(thisArm < previousArm, "the V151 arm sits below V150's, so a current store maps one rung short");
Assert.True(topArm >= 0 && topArm < thisArm, "the current top rung's arm must sit above the V151 arm");
Assert.Contains(
"return " + StorageVersion.SchemaVersion.ToString(CultureInfo.InvariantCulture) + ";",
viewer[thisArm..previousArm], StringComparison.Ordinal);
"return " + RungVersion.ToString(CultureInfo.InvariantCulture) + ";",
viewer[thisArm..viewer.IndexOf("if (hasCollectionLogWatermarkAndJobHistoryIndexes)", StringComparison.Ordinal)], StringComparison.Ordinal);
}

/// <summary>
Expand Down
Loading
Loading