Renames AssemblyName to LlamaCasty before the first Steam depot — Steamworks is explicit that renaming a live exe is painful, so this had to land first, not later. Four assembly-qualified pack URIs carried the old name, not three: MainWindow (window icon), OverlayHost (logo), RenameRecordingDialog and KeepBroadcastDialog. Pack URIs resolve by assembly name at runtime, so a stale one compiles, passes every test and then silently renders nothing the first time that view opens. AssemblyIdentityTests guards both halves — the assembly name, and no source XAML still naming the legacy assembly. Packaging/Package.appxmanifest and package-msix.sh carry the exe name too. scripts/publish.sh replaces the by-hand publish: single-file win-x64, ReadyToRun, ffmpeg beside the exe, and it refuses to finish if ffmpeg, LICENSE, PRIVACY.md or THIRD-PARTY-NOTICES.txt are missing, or if a test assembly leaked in. That last guard exists because the first publish was wrong in a way no test could see: PublishSingleFile + IncludeNativeLibrariesForSelfExtract bundled the libav*.dll family into the exe — a 9-file output with no ffmpeg folder and a 182 MB binary, so the locator would have found nothing at runtime. ExcludeFromSingleFile="true" on the content keeps the folder a folder. Diffing against a control publish without the single-file flags found it; guessing at item globs wasted two attempts first (recorded in MyMistakes.md). Measured: 127 MB exe + 129 MB ffmpeg = 257 MB depot. Tests: AssemblyIdentity, StorePackaging, BuildStamp, BundledFonts all pass; app builds with 0 warnings.
72 lines
3.2 KiB
C#
72 lines
3.2 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using Xunit;
|
|
|
|
namespace ytLive.Tests;
|
|
|
|
/// <summary>
|
|
/// The shipped binary is <c>LlamaCasty.exe</c> (renamed 2026-11-01, before the first Steam
|
|
/// depot). Two things have to agree for that to be true, and neither fails the build when it
|
|
/// doesn't:
|
|
///
|
|
/// <list type="number">
|
|
/// <item>The assembly name comes from <c>ytLive.csproj</c> and silently reverting it produces
|
|
/// <c>ytLive.exe</c> again — which is why the rename lands before a depot upload rather than
|
|
/// after (Steamworks: renaming a live exe is painful).</item>
|
|
/// <item>Assembly-qualified WPF pack URIs (<c>/Assembly;component/path</c>) resolve by that
|
|
/// same name. A stale <c>/ytLive;component/…</c> compiles, runs, and then fails <b>silently</b>
|
|
/// the moment that particular view opens — a blank window icon, a missing logo in the overlay
|
|
/// host. Nobody notices until a dialog is opened at the wrong time, so the rename is exactly the
|
|
/// kind of change that needs a source-level guard.</item>
|
|
/// </list>
|
|
///
|
|
/// <para>The C# namespaces stay <c>ytLive</c>: they are not user-visible, and the file churn
|
|
/// would buy nothing. Only the assembly name and the URIs that quote it move.</para>
|
|
/// </summary>
|
|
public class AssemblyIdentityTests
|
|
{
|
|
private const string ShipName = "LlamaCasty";
|
|
private const string LegacyName = "ytLive";
|
|
|
|
[Fact]
|
|
public void The_assembly_is_LlamaCasty_and_no_pack_uri_still_names_the_legacy_assembly()
|
|
{
|
|
Assert.Equal(ShipName, typeof(MainWindow).Assembly.GetName().Name);
|
|
|
|
var root = RepoRoot();
|
|
var stale = Directory.EnumerateFiles(root, "*.xaml", SearchOption.AllDirectories)
|
|
.Where(path => !IsBuildOutput(path))
|
|
.Where(path => File.ReadAllText(path).Contains("/" + LegacyName + ";component/", StringComparison.Ordinal))
|
|
.Select(path => Path.GetRelativePath(root, path))
|
|
.ToArray();
|
|
|
|
Assert.True(stale.Length == 0,
|
|
"These XAML files still point at the legacy assembly name in a pack URI, which " +
|
|
"fails silently at runtime: " + string.Join(", ", stale));
|
|
}
|
|
|
|
/// <summary>Walks up from the test output directory to the repo root (the folder holding
|
|
/// <c>ytLive.csproj</c>).</summary>
|
|
private static string RepoRoot()
|
|
{
|
|
var dir = new DirectoryInfo(AppContext.BaseDirectory);
|
|
while (dir != null)
|
|
{
|
|
if (File.Exists(Path.Combine(dir.FullName, "ytLive.csproj"))) return dir.FullName;
|
|
dir = dir.Parent;
|
|
}
|
|
throw new InvalidOperationException("Could not locate the repo root from " + AppContext.BaseDirectory);
|
|
}
|
|
|
|
/// <summary>Publish and compile output carry copies of the XAML (and old generated XAML);
|
|
/// only the source tree is the thing under test.</summary>
|
|
private static bool IsBuildOutput(string path)
|
|
{
|
|
var parts = path.Split(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
|
|
return parts.Any(part => part.Equals("bin", StringComparison.OrdinalIgnoreCase)
|
|
|| part.Equals("obj", StringComparison.OrdinalIgnoreCase)
|
|
|| part.Equals("artifacts", StringComparison.OrdinalIgnoreCase));
|
|
}
|
|
}
|