198 lines
6.6 KiB
C#
198 lines
6.6 KiB
C#
// Copyright (C) 2026 SharpEmu Emulator Project
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
using SharpEmu.GUI;
|
|
using Xunit;
|
|
|
|
namespace SharpEmu.Libs.Tests.GUI;
|
|
|
|
public sealed class PerGameSettingsTests
|
|
{
|
|
[Fact]
|
|
public void GuestResolutionDefaultsToHdAndCanBeOverriddenPerGame()
|
|
{
|
|
var global = new GuiSettings { Resolution = "3840x2160" };
|
|
Assert.Equal("1920x1080", EffectiveLaunchSettings.Resolve(global, null).GuestResolution);
|
|
var game = new PerGameSettings { GuestResolution = "3840x2160" };
|
|
game.RemoveInheritedValues(global);
|
|
Assert.False(game.IsEmpty);
|
|
var restored = PerGameSettings.NormalizeFromJson(System.Text.Json.JsonSerializer.Serialize(game));
|
|
Assert.Equal("3840x2160", EffectiveLaunchSettings.Resolve(global, restored).GuestResolution);
|
|
global.GuestResolution = "3840x2160";
|
|
game.RemoveInheritedValues(global);
|
|
Assert.True(game.IsEmpty);
|
|
Assert.Equal("3840x2160", EffectiveLaunchSettings.Resolve(global, game).GuestResolution);
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(null)]
|
|
[InlineData("")]
|
|
[InlineData("invalid")]
|
|
[InlineData("7680x4320")]
|
|
public void InvalidGuestResolutionFallsBackToHd(string? value)
|
|
{
|
|
Assert.Equal("1920x1080", EffectiveLaunchSettings.Resolve(
|
|
new GuiSettings(), new PerGameSettings { GuestResolution = value }).GuestResolution);
|
|
}
|
|
|
|
[Fact]
|
|
public void NewGameInheritsWritableApp0AndGlobalCrashCapture()
|
|
{
|
|
var global = new GuiSettings();
|
|
global.EnvironmentToggles.Add("SHARPEMU_CRASH_CAPTURE");
|
|
var effective = EffectiveLaunchSettings.Resolve(global, new PerGameSettings());
|
|
Assert.Contains("SHARPEMU_WRITABLE_APP0", effective.EnvironmentToggles);
|
|
Assert.Contains("SHARPEMU_CRASH_CAPTURE", effective.EnvironmentToggles);
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(false)]
|
|
[InlineData(true)]
|
|
public void GameCrashDumpOverrideSurvivesReload(bool enabled)
|
|
{
|
|
var global = new GuiSettings();
|
|
if (!enabled)
|
|
global.EnvironmentToggles.Add("SHARPEMU_CRASH_CAPTURE");
|
|
var perGame = new PerGameSettings { EnvironmentToggles = ["SHARPEMU_WRITABLE_APP0"] };
|
|
if (enabled)
|
|
perGame.EnvironmentToggles.Add("SHARPEMU_CRASH_CAPTURE");
|
|
perGame.RemoveInheritedValues(global);
|
|
var restored = PerGameSettings.NormalizeFromJson(System.Text.Json.JsonSerializer.Serialize(perGame));
|
|
var effective = EffectiveLaunchSettings.Resolve(global, restored);
|
|
Assert.Equal(enabled, effective.EnvironmentToggles.Contains("SHARPEMU_CRASH_CAPTURE"));
|
|
Assert.Contains("SHARPEMU_WRITABLE_APP0", effective.EnvironmentToggles);
|
|
}
|
|
|
|
// Invalid entries must not reach Environment.SetEnvironmentVariable.
|
|
[Fact]
|
|
public void NormalizeFromJson_NullOrEmptyToggleEntries_AreFilteredOut()
|
|
{
|
|
const string json = """
|
|
{ "EnvironmentToggles": [null, "SHARPEMU_TRACE", ""] }
|
|
""";
|
|
|
|
var settings = PerGameSettings.NormalizeFromJson(json);
|
|
|
|
Assert.NotNull(settings);
|
|
Assert.Equal(["SHARPEMU_TRACE"], settings.EnvironmentToggles);
|
|
}
|
|
|
|
// A null list means that the global setting should be inherited.
|
|
[Fact]
|
|
public void NormalizeFromJson_NullToggleList_StaysNull()
|
|
{
|
|
const string json = """{ "EnvironmentToggles": null }""";
|
|
|
|
var settings = PerGameSettings.NormalizeFromJson(json);
|
|
|
|
Assert.NotNull(settings);
|
|
Assert.Null(settings.EnvironmentToggles);
|
|
}
|
|
|
|
[Fact]
|
|
public void NormalizeFromJson_EmptyToggleList_StaysEmpty()
|
|
{
|
|
const string json = """{ "EnvironmentToggles": [] }""";
|
|
|
|
var settings = PerGameSettings.NormalizeFromJson(json);
|
|
|
|
Assert.NotNull(settings);
|
|
Assert.Empty(Assert.IsType<List<string>>(settings.EnvironmentToggles));
|
|
}
|
|
|
|
[Fact]
|
|
public void NormalizeFromJson_ValidToggles_ArePreserved()
|
|
{
|
|
const string json = """
|
|
{ "EnvironmentToggles": ["SHARPEMU_TRACE", "SHARPEMU_NO_JIT"] }
|
|
""";
|
|
|
|
var settings = PerGameSettings.NormalizeFromJson(json);
|
|
|
|
Assert.NotNull(settings);
|
|
Assert.Equal(["SHARPEMU_TRACE", "SHARPEMU_NO_JIT"], settings.EnvironmentToggles);
|
|
}
|
|
|
|
[Fact]
|
|
public void RemoveInheritedValues_AllMatchingValues_ProducesEmptySettings()
|
|
{
|
|
var global = new GuiSettings
|
|
{
|
|
LogLevel = "Info",
|
|
ImportTraceLimit = 32,
|
|
StrictDynlibResolution = true,
|
|
LogToFile = false,
|
|
WindowMode = "Borderless",
|
|
Resolution = "2560x1440",
|
|
DisplayIndex = 1,
|
|
RefreshRate = 144,
|
|
ScalingMode = "Fit",
|
|
VSync = true,
|
|
HdrMode = "Auto",
|
|
EnvironmentToggles = ["SHARPEMU_LOG_IO", "SHARPEMU_VK_VALIDATION"],
|
|
};
|
|
var perGame = new PerGameSettings
|
|
{
|
|
LogLevel = "info",
|
|
ImportTraceLimit = 32,
|
|
StrictDynlibResolution = true,
|
|
LogToFile = false,
|
|
WindowMode = "borderless",
|
|
Resolution = "2560x1440",
|
|
DisplayIndex = 1,
|
|
RefreshRate = 144,
|
|
ScalingMode = "fit",
|
|
VSync = true,
|
|
HdrMode = "auto",
|
|
EnvironmentToggles = ["SHARPEMU_VK_VALIDATION=1", "sharpemu_log_io"],
|
|
};
|
|
|
|
perGame.RemoveInheritedValues(global);
|
|
|
|
Assert.True(perGame.IsEmpty);
|
|
}
|
|
|
|
[Fact]
|
|
public void RemoveInheritedValues_DifferentValues_RemainOverrides()
|
|
{
|
|
var global = new GuiSettings
|
|
{
|
|
LogLevel = "Info",
|
|
Resolution = "1920x1080",
|
|
VSync = true,
|
|
EnvironmentToggles = ["SHARPEMU_LOG_IO"],
|
|
};
|
|
var perGame = new PerGameSettings
|
|
{
|
|
LogLevel = "Debug",
|
|
Resolution = "2560x1440",
|
|
VSync = false,
|
|
EnvironmentToggles = ["SHARPEMU_VK_VALIDATION"],
|
|
};
|
|
|
|
perGame.RemoveInheritedValues(global);
|
|
|
|
Assert.Equal("Debug", perGame.LogLevel);
|
|
Assert.Equal("2560x1440", perGame.Resolution);
|
|
Assert.False(perGame.VSync);
|
|
Assert.Equal(["SHARPEMU_VK_VALIDATION"], perGame.EnvironmentToggles);
|
|
}
|
|
|
|
[Fact]
|
|
public void RemoveInheritedValues_DisabledEnvironmentEntry_MatchesMissingEntry()
|
|
{
|
|
var global = new GuiSettings
|
|
{
|
|
EnvironmentToggles = ["SHARPEMU_LOG_IO=0"],
|
|
};
|
|
var perGame = new PerGameSettings
|
|
{
|
|
EnvironmentToggles = [],
|
|
};
|
|
|
|
perGame.RemoveInheritedValues(global);
|
|
|
|
Assert.Null(perGame.EnvironmentToggles);
|
|
}
|
|
}
|