## Summary Many tests proved a specific change when it landed but don't need to run on every CI build forever. This removes **202 test methods and 9 files: 313 test cases, 2,247 → 1,934**. UOContent.Tests drops from about 14s to about 5s locally. Removed: - **Tautologies.** Asserting a constant, a constructor readback or a trivial getter, or testing BCL behavior. - **Exact duplicates** of a surviving test on the same code path. - **Obsolete regressions** whose failure can no longer be expressed. - **Game-content values** shard owners customize (era drop rates, loot and skill tables, single-creature tuning). Each customization would otherwise force a test fix. ## How it was decided 1. Every test was classified, with a reason, by a per-shard sweep over all 287 test files. 2. Each proposed deletion was then checked by a second, adversarial reviewer against the surviving tests and the production code. 3. Anything that was the only coverage of a separate code path was **kept**, even where it looked like a duplicate. Examples: the unsigned `SpanReader`/`SpanWriter` methods, the at-location versus bounds enumerators, null-map enumerables, the security filters, archive-journal state transitions. About 130 proposed deletions were rejected this way. Whole files removed: - `FishingTests`, apart from 3 tests: the map-edge scan, serpent cleanup, and SOS chest consumption. The SOS test now stops at the first chest instead of measuring a catch rate. The multi-million-cast rate simulations are gone. - `LordOaksTests` and `MeerEnragedTests` (single-creature tests). - `AutoArchiveHelperTests`, `JsonDiscoverableTypeAttributeTests`, `DecimalSerializationTests` and `EnumConversionTests` (tautologies, or tests of their own local helpers). - `NetworkStatsTests`. - `MigratedDataLoadTests` (a subset of `AllSpawnFilesLoadTests`). - `SpawnerFixtureCapture`: a capture tool, not a test, and its `version == 12` assert can no longer pass. The `.bin` fixtures it produced stay. ## Tests - Server.Tests: 811 pass. - UOContent.Tests: 1,123 pass. A follow-up PR, stacked on this one, fixes how the remaining tests behave: shared state, CI-vacuous tests, harness duplication.
321 lines
9.3 KiB
C#
321 lines
9.3 KiB
C#
using System.Collections.Generic;
|
|
using Server.Items;
|
|
using Xunit;
|
|
|
|
namespace Server.Tests.Maps;
|
|
|
|
[Collection("Sequential Server Tests")]
|
|
public class StaticTileEnumeratorTests
|
|
{
|
|
[Fact]
|
|
public void StaticTileEnumerator_IncludeStaticsOnlyWorks()
|
|
{
|
|
var map = Map.Felucca;
|
|
var location = new Point2D(200, 200);
|
|
|
|
TestMulti multi = null;
|
|
try
|
|
{
|
|
// Create a multi at the location
|
|
multi = CreateMultiWithComponents(map, new Point3D(200, 200, 0));
|
|
|
|
// Get tiles with statics only (no multis)
|
|
var tiles = new List<StaticTile>();
|
|
foreach (var tile in new Map.StaticTileEnumerable(map, location, includeStatics: true, includeMultis: false))
|
|
{
|
|
tiles.Add(tile);
|
|
}
|
|
|
|
// Should not include multi tiles
|
|
Assert.Empty(tiles);
|
|
}
|
|
finally
|
|
{
|
|
multi?.Delete();
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public void StaticTileEnumerator_IncludeMultisOnlyWorks()
|
|
{
|
|
var map = Map.Felucca;
|
|
var location = new Point2D(300, 300);
|
|
|
|
TestMulti multi = null;
|
|
try
|
|
{
|
|
// Create a multi at the location with components
|
|
multi = CreateMultiWithComponents(map, new Point3D(300, 300, 0));
|
|
|
|
// Get tiles with multis only (no statics)
|
|
var tiles = new List<StaticTile>();
|
|
foreach (var tile in new Map.StaticTileEnumerable(map, location, includeStatics: false, includeMultis: true))
|
|
{
|
|
tiles.Add(tile);
|
|
}
|
|
|
|
// Should include multi tiles
|
|
Assert.NotEmpty(tiles);
|
|
}
|
|
finally
|
|
{
|
|
multi?.Delete();
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public void StaticTileEnumerator_IncludeBothStaticsAndMultisWorks()
|
|
{
|
|
var map = Map.Felucca;
|
|
var location = new Point2D(400, 400);
|
|
|
|
TestMulti multi = null;
|
|
try
|
|
{
|
|
// Create a multi at the location
|
|
multi = CreateMultiWithComponents(map, new Point3D(400, 400, 0));
|
|
|
|
// Get all tiles (statics and multis)
|
|
var tiles = new List<StaticTile>();
|
|
foreach (var tile in new Map.StaticTileEnumerable(map, location, includeStatics: true, includeMultis: true))
|
|
{
|
|
tiles.Add(tile);
|
|
}
|
|
|
|
// Should include multi tiles (statics would be empty without map files)
|
|
Assert.NotEmpty(tiles);
|
|
}
|
|
finally
|
|
{
|
|
multi?.Delete();
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public void StaticTileEnumerator_MultiTileZOffsetApplied()
|
|
{
|
|
var map = Map.Felucca;
|
|
var location = new Point2D(500, 500);
|
|
var multiZ = 10;
|
|
|
|
TestMulti multi = null;
|
|
try
|
|
{
|
|
// Create a multi at Z=10
|
|
multi = CreateMultiWithComponents(map, new Point3D(500, 500, multiZ));
|
|
|
|
// Get multi tiles
|
|
var tiles = new List<StaticTile>();
|
|
foreach (var tile in new Map.StaticTileEnumerable(map, location, includeStatics: false, includeMultis: true))
|
|
{
|
|
tiles.Add(tile);
|
|
}
|
|
|
|
// All tiles should have Z offset by the multi's Z position
|
|
Assert.NotEmpty(tiles);
|
|
Assert.All(tiles, tile => Assert.True(tile.Z >= multiZ));
|
|
}
|
|
finally
|
|
{
|
|
multi?.Delete();
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public void StaticTileEnumerator_TileMatrixGetStaticAndMultiTilesWorks()
|
|
{
|
|
var map = Map.Felucca;
|
|
var x = 700;
|
|
var y = 700;
|
|
|
|
TestMulti multi = null;
|
|
try
|
|
{
|
|
// Create a multi at the location
|
|
multi = CreateMultiWithComponents(map, new Point3D(700, 700, 0));
|
|
|
|
// Test the TileMatrix.GetStaticAndMultiTiles method
|
|
var tiles = new List<StaticTile>();
|
|
foreach (var tile in map.Tiles.GetStaticAndMultiTiles(x, y))
|
|
{
|
|
tiles.Add(tile);
|
|
}
|
|
|
|
// Should include multi tiles
|
|
Assert.NotEmpty(tiles);
|
|
}
|
|
finally
|
|
{
|
|
multi?.Delete();
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public void StaticTileEnumerator_TileMatrixGetMultiTilesWorks()
|
|
{
|
|
var map = Map.Felucca;
|
|
var x = 800;
|
|
var y = 800;
|
|
|
|
TestMulti multi = null;
|
|
try
|
|
{
|
|
// Create a multi at the location
|
|
multi = CreateMultiWithComponents(map, new Point3D(800, 800, 0));
|
|
|
|
// Test the TileMatrix.GetMultiTiles method
|
|
var tiles = new List<StaticTile>();
|
|
foreach (var tile in map.Tiles.GetMultiTiles(x, y))
|
|
{
|
|
tiles.Add(tile);
|
|
}
|
|
|
|
// Should include multi tiles
|
|
Assert.NotEmpty(tiles);
|
|
}
|
|
finally
|
|
{
|
|
multi?.Delete();
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public void StaticTileEnumerator_MultipleMultisAtSameLocation()
|
|
{
|
|
var map = Map.Felucca;
|
|
var location = new Point2D(900, 900);
|
|
|
|
var multis = new TestMulti[2];
|
|
try
|
|
{
|
|
// Create two multis at the same location
|
|
multis[0] = CreateMultiWithComponents(map, new Point3D(900, 900, 0));
|
|
multis[1] = CreateMultiWithComponents(map, new Point3D(900, 900, 5));
|
|
|
|
// Get all multi tiles
|
|
var tiles = new List<StaticTile>();
|
|
foreach (var tile in new Map.StaticTileEnumerable(map, location, includeStatics: false, includeMultis: true))
|
|
{
|
|
tiles.Add(tile);
|
|
}
|
|
|
|
// Should include tiles from both multis
|
|
Assert.NotEmpty(tiles);
|
|
// We expect at least tiles from both multis
|
|
Assert.True(tiles.Count >= 2);
|
|
}
|
|
finally
|
|
{
|
|
multis[0]?.Delete();
|
|
multis[1]?.Delete();
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public void StaticTileEnumerator_DeletedMultiSkipped()
|
|
{
|
|
var map = Map.Felucca;
|
|
var location = new Point2D(1000, 1000);
|
|
|
|
var multis = new TestMulti[2];
|
|
try
|
|
{
|
|
// Create two multis
|
|
multis[0] = CreateMultiWithComponents(map, new Point3D(1000, 1000, 0));
|
|
multis[1] = CreateMultiWithComponents(map, new Point3D(1000, 1000, 5));
|
|
|
|
// Delete the first multi
|
|
multis[0].Delete();
|
|
|
|
// Get all multi tiles
|
|
var tiles = new List<StaticTile>();
|
|
foreach (var tile in new Map.StaticTileEnumerable(map, location, includeStatics: false, includeMultis: true))
|
|
{
|
|
tiles.Add(tile);
|
|
}
|
|
|
|
// Should only include tiles from the second multi
|
|
Assert.NotEmpty(tiles);
|
|
Assert.All(tiles, tile => Assert.True(tile.Z >= 5));
|
|
}
|
|
finally
|
|
{
|
|
multis[0]?.Delete();
|
|
multis[1]?.Delete();
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public void StaticTileEnumerator_MultiWithEmptyCellDoesNotHideLaterMultis()
|
|
{
|
|
var map = Map.Felucca;
|
|
var location = new Point2D(1101, 1100);
|
|
|
|
TestMulti outer = null;
|
|
TestMulti inner = null;
|
|
try
|
|
{
|
|
// Outer's bounds cover the probe cell but it has no tile there; placing it first puts it
|
|
// ahead of inner in the sector's multi list
|
|
outer = new TestMulti(World.NewItem, GappedComponents);
|
|
outer.MoveToWorld(new Point3D(1100, 1100, 0), map);
|
|
|
|
inner = new TestMulti(World.NewItem, SingleTileComponents);
|
|
inner.MoveToWorld(new Point3D(location.X, location.Y, 20), map);
|
|
|
|
var tiles = new List<StaticTile>();
|
|
foreach (var tile in new Map.StaticTileEnumerable(map, location, includeStatics: false, includeMultis: true))
|
|
{
|
|
tiles.Add(tile);
|
|
}
|
|
|
|
// Only inner sits at z 20; item ids are masked by tiledata, which CI does not have
|
|
var single = Assert.Single(tiles);
|
|
Assert.Equal(20, single.Z);
|
|
}
|
|
finally
|
|
{
|
|
outer?.Delete();
|
|
inner?.Delete();
|
|
}
|
|
}
|
|
|
|
// Entries after the first need non-zero flags or MultiComponentList drops them
|
|
private static readonly MultiComponentList GappedComponents = new(
|
|
[
|
|
new MultiTileEntry(0x1, 0, 0, 0, TileFlag.Background),
|
|
new MultiTileEntry(0x2, 2, 0, 0, TileFlag.Background)
|
|
]
|
|
);
|
|
|
|
private static readonly MultiComponentList SingleTileComponents = new(
|
|
[
|
|
new MultiTileEntry(0x3, 0, 0, 0, TileFlag.Background)
|
|
]
|
|
);
|
|
|
|
private static TestMulti CreateMultiWithComponents(Map map, Point3D location)
|
|
{
|
|
var multi = new TestMulti(World.NewItem);
|
|
multi.MoveToWorld(location, map);
|
|
return multi;
|
|
}
|
|
|
|
private class TestMulti : BaseMulti
|
|
{
|
|
private readonly MultiComponentList _components;
|
|
|
|
public TestMulti(Serial serial, MultiComponentList components = null) : base(serial) =>
|
|
_components = components ?? DefaultComponents;
|
|
|
|
public override MultiComponentList Components => _components;
|
|
|
|
private static readonly MultiComponentList DefaultComponents = new(
|
|
[
|
|
new MultiTileEntry(0x1, 0, 0, 0, 0x0),
|
|
new MultiTileEntry(0x2, 1, 0, 0, 0x0)
|
|
]
|
|
);
|
|
}
|
|
}
|
|
|