using MeterVault.Infrastructure.Options; using MeterVault.Infrastructure.Update; using Microsoft.Extensions.Logging.Abstractions; namespace MeterVault.Integration.Tests; /// /// The gate in front of the in-app update. AllowInAppUpdate is the whole gate by explicit /// operator choice — no key — so the flag defaulting off is the only thing standing between an /// upgrade and a network-triggerable rebuild-and-restart as root. /// /// /// None of these launch anything: they assert the conditions that must hold before a launch /// is even attempted, which is the part worth pinning. The launch itself needs systemd and a real /// /usr/bin/update. /// public sealed class UpdateRunnerTests { [Fact] public void Disabled_by_default() { // The single most important assertion in this file: with no key required, an operator who // upgrades without reading the notes must not silently acquire an open trigger. Assert.False(new MeterVaultOptions().AllowInAppUpdate); Assert.Equal(UpdateAvailability.NotEnabled, NewRunner(new MeterVaultOptions()).Availability); } [Fact] public void Configuring_api_keys_alone_does_not_enable_it() { // The two settings are independent: having an API key for the REST API is not consent to // rebuild the host. var options = new MeterVaultOptions(); options.ApiKeys.Add("some-key"); Assert.Equal(UpdateAvailability.NotEnabled, NewRunner(options).Availability); } [Fact] public async Task Refuses_to_launch_when_not_allowed_even_if_asked_directly() { // Defence in depth: LaunchAsync re-checks rather than trusting its caller to have done so. var launch = await NewRunner(new MeterVaultOptions()).LaunchAsync(); Assert.False(launch.Started); Assert.Contains("NotEnabled", launch.Message, StringComparison.Ordinal); } [Fact] public void Reports_unsupported_where_there_is_no_in_place_updater() { // On a dev box or in a container there is no /usr/bin/update, so an enabled runner still // declines rather than half-running something. if (UpdateRunner.IsSupportedHere) { return; // running on a provisioned LXC; the negative case cannot be observed here } Assert.Equal(UpdateAvailability.NotSupportedHere, NewRunner(Enabled()).Availability); } private static MeterVaultOptions Enabled() => new() { AllowInAppUpdate = true }; private static UpdateRunner NewRunner(MeterVaultOptions options) => new(Microsoft.Extensions.Options.Options.Create(options), NullLogger.Instance); }