diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 6d075d55..11ac349f 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -27,7 +27,7 @@ jobs:
- name: Create packages
run: dotnet pack --configuration Release --output ./packages
- name: Upload a Build Artifact
- uses: actions/upload-artifact@v5
+ uses: actions/upload-artifact@v6
with:
name: NuGet packages
path: packages/*.*
@@ -45,7 +45,7 @@ jobs:
fetch-depth: 0
- name: Setup .NET
uses: actions/setup-dotnet@v5
- - uses: actions/download-artifact@v6
+ - uses: actions/download-artifact@v7
with:
name: NuGet packages
path: packages
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index ecb52d5c..362dc9aa 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -26,4 +26,8 @@ jobs:
dotnet-version: '10.0.x'
- name: Build & Test in Release Mode
- run: dotnet test --configuration Release --logger "GitHubActions"
\ No newline at end of file
+ run: dotnet test --configuration Release --report-github
+ # Ignore exit code 8 on Linux (zero tests are now allowed)
+ # TODO: Remove this when linux is supported
+ env:
+ TESTINGPLATFORM_EXITCODE_IGNORE: ${{ matrix.os == 'ubuntu-latest' && '8' || '' }}
\ No newline at end of file
diff --git a/Directory.Build.props b/Directory.Build.props
index b10fafc0..aec3b0e0 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -8,7 +8,7 @@
Alamo Engine Tools and Contributors
- Copyright © 2025 Alamo Engine Tools and contributors. All rights reserved.
+ Copyright © 2026 Alamo Engine Tools and contributors. All rights reserved.
Alamo Engine Tools
petroglyph, alamo, glyphx, foc, eaw
https://github.com/AlamoEngine-Tools/PetroglyphGameInfrastructure
@@ -32,8 +32,7 @@
3.9.50
-
- runtime; build; native; contentfiles; analyzers; buildtransitive
+
all
diff --git a/LICENSE b/LICENSE
index 10fdbec7..23fe8695 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
MIT License
-Copyright (c) 2025 Alamo Engine Tools
+Copyright (c) 2026 Alamo Engine Tools
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/PetroGlyphGameInfrastructure.slnx b/PetroGlyphGameInfrastructure.slnx
index c29d09ef..d5941e25 100644
--- a/PetroGlyphGameInfrastructure.slnx
+++ b/PetroGlyphGameInfrastructure.slnx
@@ -6,11 +6,12 @@
-
+
+
+
-
diff --git a/global.json b/global.json
new file mode 100644
index 00000000..8f73781c
--- /dev/null
+++ b/global.json
@@ -0,0 +1,5 @@
+{
+ "test": {
+ "runner": "Microsoft.Testing.Platform"
+ }
+}
\ No newline at end of file
diff --git a/sampleApp/SampleApplication.csproj b/sampleApp/SampleApplication.csproj
index e8b2d631..032d5a8c 100644
--- a/sampleApp/SampleApplication.csproj
+++ b/sampleApp/SampleApplication.csproj
@@ -7,7 +7,7 @@
-
+
diff --git a/src/AET.SteamAbstraction/AET.SteamAbstraction.csproj b/src/AET.SteamAbstraction/AET.SteamAbstraction.csproj
index 35deee25..64387ab8 100644
--- a/src/AET.SteamAbstraction/AET.SteamAbstraction.csproj
+++ b/src/AET.SteamAbstraction/AET.SteamAbstraction.csproj
@@ -1,6 +1,6 @@
-
+
- netstandard2.0
+ netstandard2.0;netstandard2.1
AET.SteamAbstraction
@@ -21,16 +21,16 @@
true
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
diff --git a/src/AET.SteamAbstraction/Library/SteamLibrary.cs b/src/AET.SteamAbstraction/Library/SteamLibrary.cs
index 8be9d434..dbcbdfa8 100644
--- a/src/AET.SteamAbstraction/Library/SteamLibrary.cs
+++ b/src/AET.SteamAbstraction/Library/SteamLibrary.cs
@@ -19,9 +19,12 @@ internal class SteamLibrary : ISteamLibrary
TrailingDirectorySeparatorBehavior = TrailingDirectorySeparatorBehavior.Trim
};
+ private readonly string _normalizedLocation;
private readonly ILogger? _logger;
private readonly ConcurrentDictionary _locations = new();
+ private protected readonly IFileSystem FileSystem;
+
private readonly Dictionary _locationsNames = new()
{
{ KnownLibraryLocations.SteamApps, ["steamapps"] },
@@ -29,9 +32,6 @@ internal class SteamLibrary : ISteamLibrary
{ KnownLibraryLocations.Workshops, ["steamapps", "workshop"] }
};
- private readonly string _normalizedLocation;
- private readonly IFileSystem _fileSystem;
-
public IDirectoryInfo LibraryLocation { get; }
public IDirectoryInfo SteamAppsLocation => GetKnownLibraryLocation(KnownLibraryLocations.SteamApps);
@@ -46,9 +46,9 @@ public SteamLibrary(IDirectoryInfo libraryLocation, IServiceProvider serviceProv
throw new ArgumentNullException(nameof(libraryLocation));
if (serviceProvider == null)
throw new ArgumentNullException(nameof(serviceProvider));
- _fileSystem = serviceProvider.GetRequiredService();
+ FileSystem = serviceProvider.GetRequiredService();
_logger = serviceProvider.GetService()?.CreateLogger(GetType());
- _normalizedLocation = PathNormalizer.Normalize(_fileSystem.Path.GetFullPath(libraryLocation.FullName), SteamLibraryPathNormalizeOptions);
+ _normalizedLocation = PathNormalizer.Normalize(FileSystem.Path.GetFullPath(libraryLocation.FullName), SteamLibraryPathNormalizeOptions);
LibraryLocation = libraryLocation;
}
@@ -91,7 +91,7 @@ public bool Equals(ISteamLibrary? other)
if (ReferenceEquals(this, other))
return true;
- var normalizedOtherPath = PathNormalizer.Normalize(_fileSystem.Path.GetFullPath(other.LibraryLocation.FullName), SteamLibraryPathNormalizeOptions);
+ var normalizedOtherPath = PathNormalizer.Normalize(FileSystem.Path.GetFullPath(other.LibraryLocation.FullName), SteamLibraryPathNormalizeOptions);
return _normalizedLocation.Equals(normalizedOtherPath);
}
diff --git a/src/AET.SteamAbstraction/Linux/LinuxSteamRegistry.cs b/src/AET.SteamAbstraction/Linux/LinuxSteamRegistry.cs
index 2cf0585d..f02d947e 100644
--- a/src/AET.SteamAbstraction/Linux/LinuxSteamRegistry.cs
+++ b/src/AET.SteamAbstraction/Linux/LinuxSteamRegistry.cs
@@ -3,6 +3,7 @@
using System.IO.Abstractions;
using AET.SteamAbstraction.Registry;
using AnakinRaW.CommonUtilities;
+using AnakinRaW.CommonUtilities.Registry;
namespace AET.SteamAbstraction;
@@ -16,4 +17,9 @@ internal class LinuxSteamRegistry(IServiceProvider serviceProvider) : Disposable
public IDirectoryInfo? InstallationDirectory { get; }
public int? ProcessId { get; }
+
+ public IRegistryKey? OpenSteamRegistryKey()
+ {
+ throw new NotImplementedException();
+ }
}
\ No newline at end of file
diff --git a/src/AET.SteamAbstraction/Properties/AssemblyInfo.cs b/src/AET.SteamAbstraction/Properties/AssemblyInfo.cs
index 372482c9..333fabca 100644
--- a/src/AET.SteamAbstraction/Properties/AssemblyInfo.cs
+++ b/src/AET.SteamAbstraction/Properties/AssemblyInfo.cs
@@ -1,7 +1,7 @@
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("AET.SteamAbstraction.Test")]
-[assembly: InternalsVisibleTo("AET.SteamAbstraction.TestingUtilities")]
+[assembly: InternalsVisibleTo("AET.SteamAbstraction.Testing")]
[assembly: InternalsVisibleTo("PG.StarWarsGame.Infrastructure.Clients.Steam.Test")]
diff --git a/src/AET.SteamAbstraction/Registry/ISteamRegistry.cs b/src/AET.SteamAbstraction/Registry/ISteamRegistry.cs
index b640d4ca..d03dba69 100644
--- a/src/AET.SteamAbstraction/Registry/ISteamRegistry.cs
+++ b/src/AET.SteamAbstraction/Registry/ISteamRegistry.cs
@@ -1,4 +1,5 @@
-using System;
+using AnakinRaW.CommonUtilities.Registry;
+using System;
using System.IO.Abstractions;
namespace AET.SteamAbstraction.Registry;
@@ -22,4 +23,10 @@ internal interface ISteamRegistry : IDisposable
/// The PID of the current Steam Process. 0 or if Steam is not running.
///
int? ProcessId { get; }
+
+ ///
+ /// Opens the Steam registry and returns a writeable key.
+ ///
+ /// The steam registry key.
+ IRegistryKey? OpenSteamRegistryKey();
}
\ No newline at end of file
diff --git a/src/AET.SteamAbstraction/Utilities/IProcessHelper.cs b/src/AET.SteamAbstraction/Utilities/IProcessHelper.cs
index d5698aa0..74a95f1b 100644
--- a/src/AET.SteamAbstraction/Utilities/IProcessHelper.cs
+++ b/src/AET.SteamAbstraction/Utilities/IProcessHelper.cs
@@ -1,10 +1,33 @@
-using System.Diagnostics;
+using System;
+using System.Diagnostics;
namespace AET.SteamAbstraction.Utilities;
+///
+/// Provides utility methods for managing and interacting with system processes.
+///
internal interface IProcessHelper
{
+ ///
+ /// Determines whether a process with the specified process identifier (PID) is currently running.
+ ///
+ /// The process identifier (PID) to check.
+ ///
+ /// if a process with the specified PID is running; otherwise, .
+ ///
+ ///
+ /// This method attempts to retrieve the process by its PID. If the process does not exist or cannot be accessed,
+ /// it returns .
+ ///
bool IsProcessRunning(int pid);
+ ///
+ /// Starts a new process using the specified configuration.
+ ///
+ /// The object that specifies the configuration for the process to be started.
+ /// A object that represents the started process, or if the process could not be started.
+ /// Thrown if is .
+ /// Thrown if no file name is specified in .
+ /// Thrown if an error occurs when opening the associated file.
Process? StartProcess(ProcessStartInfo startInfo);
}
\ No newline at end of file
diff --git a/src/AET.SteamAbstraction/Windows/WindowsSteamRegistry.cs b/src/AET.SteamAbstraction/Windows/WindowsSteamRegistry.cs
index 7f707d4b..3a4559e2 100644
--- a/src/AET.SteamAbstraction/Windows/WindowsSteamRegistry.cs
+++ b/src/AET.SteamAbstraction/Windows/WindowsSteamRegistry.cs
@@ -74,6 +74,12 @@ public IDirectoryInfo? InstallationDirectory
}
}
+ public IRegistryKey? OpenSteamRegistryKey()
+ {
+ ThrowIfDisposed();
+ return _registryKey!.OpenSubKey(string.Empty, true);
+ }
+
protected override void DisposeResources()
{
_registryKey?.Dispose();
@@ -95,10 +101,4 @@ private void WriteToSubKey(string subKeyName, Action keyAction)
if (subKey is not null)
keyAction(subKey);
}
-
- internal IRegistryKey GetSteamRegistryKey()
- {
- ThrowIfDisposed();
- return _registryKey!.OpenSubKey(string.Empty, true)!;
- }
}
\ No newline at end of file
diff --git a/src/PG.StarWarsGame.Infrastructure/PG.StarWarsGame.Infrastructure.csproj b/src/PG.StarWarsGame.Infrastructure/PG.StarWarsGame.Infrastructure.csproj
index 08e22e06..b736e5ab 100644
--- a/src/PG.StarWarsGame.Infrastructure/PG.StarWarsGame.Infrastructure.csproj
+++ b/src/PG.StarWarsGame.Infrastructure/PG.StarWarsGame.Infrastructure.csproj
@@ -22,10 +22,16 @@
true
-
-
-
-
+
+
+
+
+
+
+
+
+
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
@@ -34,11 +40,5 @@
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/PG.StarWarsGame.Infrastructure/Services/Detection/Games/CompositeGameDetector.cs b/src/PG.StarWarsGame.Infrastructure/Services/Detection/Games/CompositeGameDetector.cs
index 0634c9b8..6ef268ab 100644
--- a/src/PG.StarWarsGame.Infrastructure/Services/Detection/Games/CompositeGameDetector.cs
+++ b/src/PG.StarWarsGame.Infrastructure/Services/Detection/Games/CompositeGameDetector.cs
@@ -29,7 +29,7 @@ public sealed class CompositeGameDetector : IGameDetector
/// The sorted list of detectors which shall get used.
/// The service provider.
///
- /// When after a detector was used, it will get disposed if it implements .
+ /// If , a detector that implements gets disposed after usage.
/// Default is
///
public CompositeGameDetector(IList sortedDetectors, IServiceProvider serviceProvider, bool disposeDetectors = false)
@@ -49,7 +49,10 @@ public CompositeGameDetector(IList sortedDetectors, IServiceProvi
/// The game type to detect.
/// Collection of the platforms to search for.
/// Data which holds the game's location or error information.
- ///
+ ///
+ /// All exceptions that occurred during an unsuccessful game detection.
+ /// The exception is not thrown when any detector returns an installed game result.
+ ///
public GameDetectionResult Detect(GameType gameType, params ICollection platforms)
{
var errors = new List();
diff --git a/src/PG.StarWarsGame.Infrastructure/Services/Detection/Games/GameDetectorBase.cs b/src/PG.StarWarsGame.Infrastructure/Services/Detection/Games/GameDetectorBase.cs
index 8dafee05..3f6cced8 100644
--- a/src/PG.StarWarsGame.Infrastructure/Services/Detection/Games/GameDetectorBase.cs
+++ b/src/PG.StarWarsGame.Infrastructure/Services/Detection/Games/GameDetectorBase.cs
@@ -151,7 +151,6 @@ internal static bool DataAndMegaFilesXmlExists(IDirectoryInfo directory)
///
/// The game type to detect.
/// Information about a found game installation.
- /// This method may throw arbitrary exceptions.
protected abstract GameLocationData FindGameLocation(GameType gameType);
private static bool MatchesOptionsPlatform(ICollection platforms, GamePlatform identifiedPlatform)
diff --git a/src/PG.StarWarsGame.Infrastructure/Services/Detection/Mods/IModGameTypeResolver.cs b/src/PG.StarWarsGame.Infrastructure/Services/Detection/Mods/IModGameTypeResolver.cs
index f6502b16..bd966fc4 100644
--- a/src/PG.StarWarsGame.Infrastructure/Services/Detection/Mods/IModGameTypeResolver.cs
+++ b/src/PG.StarWarsGame.Infrastructure/Services/Detection/Mods/IModGameTypeResolver.cs
@@ -21,7 +21,7 @@ public interface IModGameTypeResolver
/// When this method returns , the assured game types will be stored in this variable.
/// when the game type could be determined; if there is no clear evidence of the actual game type.
/// is .
- public bool TryGetGameType(DetectedModReference modInformation, out ReadOnlyFrugalList gameTypes);
+ public bool TryGetGameType(DetectedModReference modInformation, out ImmutableFrugalList gameTypes);
///
/// Tries to determine the from a specified modinfo data.
@@ -32,7 +32,7 @@ public interface IModGameTypeResolver
/// The modinfo data.
/// When this method returns , the assured game types will be stored in this variable.
/// when the game type could be determined; if there is no clear evidence of the actual game type.
- public bool TryGetGameType(IModinfo? modinfo, out ReadOnlyFrugalList gameTypes);
+ public bool TryGetGameType(IModinfo? modinfo, out ImmutableFrugalList gameTypes);
///
/// Determines whether the specified mod information are definitely not compatible to a game type.
diff --git a/src/PG.StarWarsGame.Infrastructure/Services/Detection/Mods/ModFinder.cs b/src/PG.StarWarsGame.Infrastructure/Services/Detection/Mods/ModFinder.cs
index ba2cfbf0..3c159ef1 100644
--- a/src/PG.StarWarsGame.Infrastructure/Services/Detection/Mods/ModFinder.cs
+++ b/src/PG.StarWarsGame.Infrastructure/Services/Detection/Mods/ModFinder.cs
@@ -3,7 +3,6 @@
using System.IO.Abstractions;
using System.Linq;
using AET.Modinfo.File;
-using AET.Modinfo.Spec;
using AET.Modinfo.Utilities;
using AnakinRaW.CommonUtilities.FileSystem;
using Microsoft.Extensions.DependencyInjection;
@@ -83,8 +82,7 @@ private IEnumerable GetModsFromDirectory(
_logger?.LogTrace("Searching for mods at location '{Location}'", modDirectory.FullName);
- ModinfoFinderCollection modinfoFiles;
- modinfoFiles = ModinfoFileFinder.FindModinfoFiles(modDirectory);
+ var modinfoFiles = ModinfoFileFinder.FindModinfoFiles(modDirectory);
foreach (var modRef in ModReferenceBuilder.CreateIdentifiers(modinfoFiles, locationKind))
{
diff --git a/src/PG.StarWarsGame.Infrastructure/Services/Detection/Mods/ModGameTypeResolver.cs b/src/PG.StarWarsGame.Infrastructure/Services/Detection/Mods/ModGameTypeResolver.cs
index 5ace74a3..29a370a7 100644
--- a/src/PG.StarWarsGame.Infrastructure/Services/Detection/Mods/ModGameTypeResolver.cs
+++ b/src/PG.StarWarsGame.Infrastructure/Services/Detection/Mods/ModGameTypeResolver.cs
@@ -37,7 +37,7 @@ protected ModGameTypeResolver(IServiceProvider serviceProvider)
}
///
- public bool TryGetGameType(DetectedModReference modInformation, out ReadOnlyFrugalList gameTypes)
+ public bool TryGetGameType(DetectedModReference modInformation, out ImmutableFrugalList gameTypes)
{
if (modInformation == null)
throw new ArgumentNullException(nameof(modInformation));
@@ -56,10 +56,10 @@ public bool TryGetGameType(DetectedModReference modInformation, out ReadOnlyFrug
/// The information of the mod.
/// When this method returns , the assured game types will be stored in this variable.
/// when the game type could be determined; if there is no clear evidence of the actual game type.
- protected internal abstract bool TryGetGameTypeCore(DetectedModReference modInformation, out ReadOnlyFrugalList gameTypes);
+ protected internal abstract bool TryGetGameTypeCore(DetectedModReference modInformation, out ImmutableFrugalList gameTypes);
///
- public virtual bool TryGetGameType(IModinfo? modinfo, out ReadOnlyFrugalList gameTypes)
+ public virtual bool TryGetGameType(IModinfo? modinfo, out ImmutableFrugalList gameTypes)
{
return GetGameType(modinfo?.SteamData, out gameTypes);
}
@@ -82,14 +82,14 @@ public bool IsDefinitelyNotCompatibleToGame(IModinfo? modinfo, GameType expected
return TryGetGameType(modinfo, out var gameTypes) && !gameTypes.Contains(expectedGameType);
}
- private bool GetGameType(ISteamData? steamData, out ReadOnlyFrugalList gameTypes)
+ private bool GetGameType(ISteamData? steamData, out ImmutableFrugalList gameTypes)
{
gameTypes = default;
- Logger?.LogTrace($"Try getting game type from steam data '[{string.Join(",", steamData?.Tags ?? ["tags n/a"])}]'");
+ Logger?.LogTrace("Try getting game type from steam data '[{Tags}]'", string.Join(",", steamData?.Tags ?? ["tags n/a"]));
return steamData is not null && GetGameTypesFromTags(steamData.Tags, out gameTypes);
}
- internal static bool GetGameTypesFromTags(IEnumerable tags, out ReadOnlyFrugalList gameTypes)
+ internal static bool GetGameTypesFromTags(IEnumerable tags, out ImmutableFrugalList gameTypes)
{
var mutableGameTypes = new FrugalList();
@@ -104,7 +104,7 @@ internal static bool GetGameTypesFromTags(IEnumerable tags, out ReadOnly
mutableGameTypes.Add(GameType.Foc);
}
- gameTypes = mutableGameTypes.AsReadOnly();
+ gameTypes = mutableGameTypes.ToImmutableList();
return gameTypes.Count > 0;
}
}
\ No newline at end of file
diff --git a/src/PG.StarWarsGame.Infrastructure/Services/Detection/Mods/OfflineModGameTypeResolver.cs b/src/PG.StarWarsGame.Infrastructure/Services/Detection/Mods/OfflineModGameTypeResolver.cs
index cfb2fd01..abed607f 100644
--- a/src/PG.StarWarsGame.Infrastructure/Services/Detection/Mods/OfflineModGameTypeResolver.cs
+++ b/src/PG.StarWarsGame.Infrastructure/Services/Detection/Mods/OfflineModGameTypeResolver.cs
@@ -23,7 +23,7 @@ public sealed class OfflineModGameTypeResolver(IServiceProvider serviceProvider)
///
- protected internal override bool TryGetGameTypeCore(DetectedModReference modInformation, out ReadOnlyFrugalList gameTypes)
+ protected internal override bool TryGetGameTypeCore(DetectedModReference modInformation, out ImmutableFrugalList gameTypes)
{
gameTypes = default;
@@ -47,21 +47,21 @@ protected internal override bool TryGetGameTypeCore(DetectedModReference modInfo
if (detector.Detect(GameType.Foc, GamePlatform.Undefined).Installed)
{
Logger?.LogTrace("{ModRef} is located in FoC's Mods directory.", modInformation.ModReference);
- gameTypes = new ReadOnlyFrugalList(GameType.Foc);
+ gameTypes = ImmutableFrugalList.Single(GameType.Foc);
return true;
}
if (detector.Detect(GameType.Eaw, GamePlatform.Undefined).Installed)
{
Logger?.LogTrace("{ModRef} is located in EaW's Mods directory.", modInformation.ModReference);
- gameTypes = new ReadOnlyFrugalList(GameType.Eaw);
+ gameTypes = ImmutableFrugalList.Single(GameType.Eaw);
return true;
}
return false;
}
- private bool HandleWorkshop(DetectedModReference modInformation, out ReadOnlyFrugalList gameTypes)
+ private bool HandleWorkshop(DetectedModReference modInformation, out ImmutableFrugalList gameTypes)
{
gameTypes = default;
if (modInformation.ModReference.Type == ModType.Workshops)
@@ -69,15 +69,14 @@ private bool HandleWorkshop(DetectedModReference modInformation, out ReadOnlyFru
if (!_steamGameHelpers.ToSteamWorkshopsId(modInformation.Directory.Name, out var steamId))
return false;
- // Modinfo is superior to cache, because this value can change faster,
- // than new distribution of this library might release.
- // so that the cache would then be invalid.
+ // Modinfo is superior to cache, because a modinfo file can change more frequently
+ // than new release of this library (and therefore the cache).
if (TryGetGameType(modInformation.Modinfo, out gameTypes))
return true;
if (_cache.ContainsMod(steamId))
{
- gameTypes = new ReadOnlyFrugalList(_cache.GetGameTypes(steamId));
+ gameTypes = ImmutableFrugalList.Create(_cache.GetGameTypes(steamId));
return true;
}
}
diff --git a/src/PG.StarWarsGame.Infrastructure/Services/Detection/Mods/OnlineModGameTypeResolver.cs b/src/PG.StarWarsGame.Infrastructure/Services/Detection/Mods/OnlineModGameTypeResolver.cs
index b0c6ffd2..4174d29e 100644
--- a/src/PG.StarWarsGame.Infrastructure/Services/Detection/Mods/OnlineModGameTypeResolver.cs
+++ b/src/PG.StarWarsGame.Infrastructure/Services/Detection/Mods/OnlineModGameTypeResolver.cs
@@ -5,6 +5,7 @@
using AET.Modinfo.Spec;
using AET.Modinfo.Utilities;
using AnakinRaW.CommonUtilities.Collections;
+using HtmlAgilityPack;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using PG.StarWarsGame.Infrastructure.Games;
@@ -24,14 +25,14 @@ public sealed class OnlineModGameTypeResolver(IServiceProvider serviceProvider)
private readonly ISteamWorkshopWebpageDownloader _steamWebpageDownloader = serviceProvider.GetRequiredService();
///
- protected internal override bool TryGetGameTypeCore(DetectedModReference modInformation, out ReadOnlyFrugalList gameTypes)
+ protected internal override bool TryGetGameTypeCore(DetectedModReference modInformation, out ImmutableFrugalList gameTypes)
{
if (_offlineResolver.TryGetGameTypeCore(modInformation, out gameTypes))
return true;
return modInformation.ModReference.Type == ModType.Workshops && GetGameTypeFromSteamPage(modInformation.Directory.Name, out gameTypes);
}
- private bool GetGameTypeFromSteamPage(string steamIdValue, out ReadOnlyFrugalList gameTypes)
+ private bool GetGameTypeFromSteamPage(string steamIdValue, out ImmutableFrugalList gameTypes)
{
gameTypes = default;
if (!_steamGameHelpers.ToSteamWorkshopsId(steamIdValue, out var steamId))
@@ -39,10 +40,19 @@ private bool GetGameTypeFromSteamPage(string steamIdValue, out ReadOnlyFrugalLis
Logger?.LogTrace("Getting steam tags from Steam's webpage for mod '{SteamId}'", steamId);
- var webPage = _steamWebpageDownloader.GetSteamWorkshopsPageHtmlAsync(steamId, CultureInfo.InvariantCulture)
- .GetAwaiter().GetResult();
- if (webPage is null)
+ HtmlDocument webPage;
+ try
+ {
+ webPage = _steamWebpageDownloader.GetSteamWorkshopsPageHtmlAsync(steamId, CultureInfo.InvariantCulture)
+ .GetAwaiter().GetResult();
+ if (webPage is null)
+ return false;
+ }
+ catch (Exception e)
+ {
+ Logger?.LogTrace(e, "Failed to get steam tags from Steam's webpage for mod '{SteamId}'", steamId);
return false;
+ }
var tagNodes = webPage.DocumentNode.SelectNodes("//div[@class='workshopTags']/a/text()");
if (tagNodes is null || tagNodes.Count == 0)
diff --git a/src/PG.StarWarsGame.Infrastructure/Services/Name/Mods/OnlineWorkshopNameResolver.cs b/src/PG.StarWarsGame.Infrastructure/Services/Name/Mods/OnlineWorkshopNameResolver.cs
index 91514eba..bc3d7628 100644
--- a/src/PG.StarWarsGame.Infrastructure/Services/Name/Mods/OnlineWorkshopNameResolver.cs
+++ b/src/PG.StarWarsGame.Infrastructure/Services/Name/Mods/OnlineWorkshopNameResolver.cs
@@ -3,6 +3,7 @@
using System.Globalization;
using AET.Modinfo.Spec;
using AET.Modinfo.Utilities;
+using HtmlAgilityPack;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using PG.StarWarsGame.Infrastructure.Services.Steam;
@@ -50,12 +51,21 @@ protected internal override string ResolveCore(DetectedModReference detectedMod,
private string? GetNameFromOnline(ulong modId, CultureInfo culture)
{
- var modsWorkshopWebpage = _steamWebpageDownloader.GetSteamWorkshopsPageHtmlAsync(modId, culture)
- .GetAwaiter().GetResult();
+ HtmlDocument modsWorkshopWebpage;
+ try
+ {
+ modsWorkshopWebpage = _steamWebpageDownloader.GetSteamWorkshopsPageHtmlAsync(modId, culture)
+ .GetAwaiter().GetResult();
- if (modsWorkshopWebpage == null)
+ if (modsWorkshopWebpage == null)
+ {
+ Logger?.LogTrace("Unable to download website for Steam ID '{ModId}'.", modId);
+ return null;
+ }
+ }
+ catch (Exception e)
{
- Logger?.LogTrace("Unable to download website for Steam ID '{ModId}'.", modId);
+ Logger?.LogTrace(e, "Unable to download website for Steam ID '{ModId}'.", modId);
return null;
}
diff --git a/src/PG.StarWarsGame.Infrastructure/Services/Steam/ISteamWorkshopWebpageDownloader.cs b/src/PG.StarWarsGame.Infrastructure/Services/Steam/ISteamWorkshopWebpageDownloader.cs
index e6612195..664d8c79 100644
--- a/src/PG.StarWarsGame.Infrastructure/Services/Steam/ISteamWorkshopWebpageDownloader.cs
+++ b/src/PG.StarWarsGame.Infrastructure/Services/Steam/ISteamWorkshopWebpageDownloader.cs
@@ -6,5 +6,5 @@ namespace PG.StarWarsGame.Infrastructure.Services.Steam;
internal interface ISteamWorkshopWebpageDownloader
{
- Task GetSteamWorkshopsPageHtmlAsync(ulong workshopId, CultureInfo? culture);
+ Task GetSteamWorkshopsPageHtmlAsync(ulong workshopId, CultureInfo? culture);
}
\ No newline at end of file
diff --git a/src/PG.StarWarsGame.Infrastructure/Services/Steam/SteamWorkshopWebpageDownloader.cs b/src/PG.StarWarsGame.Infrastructure/Services/Steam/SteamWorkshopWebpageDownloader.cs
index eedeb552..2686742a 100644
--- a/src/PG.StarWarsGame.Infrastructure/Services/Steam/SteamWorkshopWebpageDownloader.cs
+++ b/src/PG.StarWarsGame.Infrastructure/Services/Steam/SteamWorkshopWebpageDownloader.cs
@@ -10,7 +10,7 @@ internal class SteamWorkshopWebpageDownloader : ISteamWorkshopWebpageDownloader
{
private const string SteamWorkshopsBaseUrl = "https://steamcommunity.com/sharedfiles/filedetails/?";
- public async Task GetSteamWorkshopsPageHtmlAsync(ulong workshopId, CultureInfo? culture)
+ public async Task GetSteamWorkshopsPageHtmlAsync(ulong workshopId, CultureInfo? culture)
{
var queryString = HttpUtility.ParseQueryString(string.Empty);
queryString.Add("id", workshopId.ToString());
@@ -18,18 +18,11 @@ internal class SteamWorkshopWebpageDownloader : ISteamWorkshopWebpageDownloader
if (culture != null && !Equals(culture, CultureInfo.InvariantCulture))
queryString.Add("l", culture.EnglishName.ToLower());
- try
- {
- var address = $"{SteamWorkshopsBaseUrl}{queryString}";
- using var client = new HttpClient();
- var reply = await client.GetStringAsync(address);
- var htmlDocument = new HtmlDocument();
- htmlDocument.LoadHtml(reply);
- return htmlDocument;
- }
- catch
- {
- return null;
- }
+ var address = $"{SteamWorkshopsBaseUrl}{queryString}";
+ using var client = new HttpClient();
+ var reply = await client.GetStringAsync(address);
+ var htmlDocument = new HtmlDocument();
+ htmlDocument.LoadHtml(reply);
+ return htmlDocument;
}
}
\ No newline at end of file
diff --git a/src/PG.StarWarsGame.Infrastructure/ThrowHelper.cs b/src/PG.StarWarsGame.Infrastructure/ThrowHelper.cs
index 401eb717..348c3a75 100644
--- a/src/PG.StarWarsGame.Infrastructure/ThrowHelper.cs
+++ b/src/PG.StarWarsGame.Infrastructure/ThrowHelper.cs
@@ -2,7 +2,7 @@
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
-using System.Runtime.CompilerServices;
+using PG.StarWarsGame.Infrastructure.Utilities.CompilerServices;
namespace PG.StarWarsGame.Infrastructure;
diff --git a/src/PG.StarWarsGame.Infrastructure/Utilities/CompilerServices/CallerArgumentExpressionAttribute.cs b/src/PG.StarWarsGame.Infrastructure/Utilities/CompilerServices/CallerArgumentExpressionAttribute.cs
index 093da83f..91d5d562 100644
--- a/src/PG.StarWarsGame.Infrastructure/Utilities/CompilerServices/CallerArgumentExpressionAttribute.cs
+++ b/src/PG.StarWarsGame.Infrastructure/Utilities/CompilerServices/CallerArgumentExpressionAttribute.cs
@@ -1,6 +1,8 @@
-#if !NET
+using System;
+
+#if !NET
#pragma warning disable IDE0130
-namespace System.Runtime.CompilerServices;
+namespace PG.StarWarsGame.Infrastructure.Utilities.CompilerServices;
#pragma warning restore IDE0130
[AttributeUsage(AttributeTargets.Parameter)]
diff --git a/src/PG.StarWarsGame.Infrastructure/Utilities/PlayableObjectExtensions.cs b/src/PG.StarWarsGame.Infrastructure/Utilities/PlayableObjectExtensions.cs
index 1518573c..5d746392 100644
--- a/src/PG.StarWarsGame.Infrastructure/Utilities/PlayableObjectExtensions.cs
+++ b/src/PG.StarWarsGame.Infrastructure/Utilities/PlayableObjectExtensions.cs
@@ -87,7 +87,7 @@ public static IEnumerable DataFiles(
subPath ??= string.Empty;
var fs = playableObject.Directory.FileSystem;
var searchLocation = fs.Path.Combine("Data", subPath);
- return EnumerateFiles(playableObject, fileSearchPattern, searchLocation, searchRecursive);
+ return playableObject.EnumerateFiles(fileSearchPattern, searchLocation, searchRecursive);
}
///
diff --git a/test/AET.SteamAbstraction.Test/AET.SteamAbstraction.Test.csproj b/test/AET.SteamAbstraction.Test/AET.SteamAbstraction.Test.csproj
index d3d787e4..57b5bd66 100644
--- a/test/AET.SteamAbstraction.Test/AET.SteamAbstraction.Test.csproj
+++ b/test/AET.SteamAbstraction.Test/AET.SteamAbstraction.Test.csproj
@@ -1,4 +1,4 @@
-
+
AET.SteamAbstraction.Test
@@ -9,17 +9,15 @@
$(TargetFrameworks);net481
false
true
+ Exe
-
- all
- runtime; build; native; contentfiles; analyzers; buildtransitive
-
-
+
+
-
-
+
+
runtime; build; native; contentfiles; analyzers; buildtransitive
all
diff --git a/test/AET.SteamAbstraction.Test/CompilerHelpers/Attributes.cs b/test/AET.SteamAbstraction.Test/CompilerHelpers/Attributes.cs
new file mode 100644
index 00000000..e1dc9a46
--- /dev/null
+++ b/test/AET.SteamAbstraction.Test/CompilerHelpers/Attributes.cs
@@ -0,0 +1,45 @@
+#if !NET5_0_OR_GREATER
+// ReSharper disable CheckNamespace
+// ReSharper disable InconsistentNaming
+namespace System.Runtime.Versioning;
+
+///
+/// Base type for all platform-specific API attributes.
+///
+
+internal abstract class OSPlatformAttribute(string platformName) : Attribute
+{
+ public string PlatformName { get; } = platformName;
+}
+
+///
+/// Records the platform that the project targeted.
+///
+[AttributeUsage(AttributeTargets.Assembly)]
+internal sealed class TargetPlatformAttribute(string platformName) : OSPlatformAttribute(platformName);
+
+///
+/// Records the operating system (and minimum version) that supports an API. Multiple attributes can be
+/// applied to indicate support on multiple operating systems.
+///
+///
+/// Callers can apply a
+/// or use guards to prevent calls to APIs on unsupported operating systems.
+///
+/// A given platform should only be specified once.
+///
+[AttributeUsage(AttributeTargets.Assembly |
+ AttributeTargets.Class |
+ AttributeTargets.Constructor |
+ AttributeTargets.Enum |
+ AttributeTargets.Event |
+ AttributeTargets.Field |
+ AttributeTargets.Interface |
+ AttributeTargets.Method |
+ AttributeTargets.Module |
+ AttributeTargets.Property |
+ AttributeTargets.Struct,
+ AllowMultiple = true, Inherited = false)]
+internal sealed class SupportedOSPlatformAttribute(string platformName) : OSPlatformAttribute(platformName);
+// ReSharper restore InconsistentNaming
+#endif
\ No newline at end of file
diff --git a/test/AET.SteamAbstraction.Test/ProcessHelperTest.cs b/test/AET.SteamAbstraction.Test/ProcessHelperTest.cs
index 9abf488e..82e6b7e4 100644
--- a/test/AET.SteamAbstraction.Test/ProcessHelperTest.cs
+++ b/test/AET.SteamAbstraction.Test/ProcessHelperTest.cs
@@ -2,20 +2,25 @@
using System.Diagnostics;
using System.Runtime.InteropServices;
using AET.SteamAbstraction.Utilities;
+using AnakinRaW.CommonUtilities.Testing;
using Microsoft.Extensions.DependencyInjection;
using Xunit;
namespace AET.SteamAbstraction.Test;
-public class ProcessHelperTest
+public class ProcessHelperTest : TestBaseWithServiceProvider
{
private readonly IProcessHelper _processHelper;
public ProcessHelperTest()
{
- var sc = new ServiceCollection();
- SteamAbstractionLayer.InitializeServices(sc);
- _processHelper = sc.BuildServiceProvider().GetRequiredService();
+ _processHelper = ServiceProvider.GetRequiredService();
+ }
+
+ protected override void SetupServices(IServiceCollection serviceCollection)
+ {
+ base.SetupServices(serviceCollection);
+ SteamAbstractionLayer.InitializeServices(serviceCollection);
}
[Fact]
diff --git a/test/AET.SteamAbstraction.Test/SteamAppManifestTest.cs b/test/AET.SteamAbstraction.Test/SteamAppManifestTest.cs
index e191113d..d3b61675 100644
--- a/test/AET.SteamAbstraction.Test/SteamAppManifestTest.cs
+++ b/test/AET.SteamAbstraction.Test/SteamAppManifestTest.cs
@@ -2,25 +2,29 @@
using System.Collections.Generic;
using System.IO.Abstractions;
using AET.SteamAbstraction.Games;
-using AET.SteamAbstraction.Testing.Installation;
+using AET.SteamAbstraction.Testing.TestBases;
+using AnakinRaW.CommonUtilities.Registry;
+using AnakinRaW.CommonUtilities.Testing.Extensions;
using Microsoft.Extensions.DependencyInjection;
-using PG.TestingUtilities;
using Testably.Abstractions.Testing;
using Xunit;
namespace AET.SteamAbstraction.Test;
-public class SteamAppManifestTest
+public class SteamAppManifestTest : SteamTestBase
{
private readonly MockFileSystem _fileSystem = new();
- private readonly IServiceProvider _serviceProvider;
public SteamAppManifestTest()
{
- var sc = new ServiceCollection();
- sc.AddSingleton(_fileSystem);
- SteamAbstractionLayer.InitializeServices(sc);
- _serviceProvider = sc.BuildServiceProvider();
+ Steam.InstallSteamFilesOnly();
+ }
+
+ protected override void SetupServices(IServiceCollection serviceCollection)
+ {
+ base.SetupServices(serviceCollection);
+ serviceCollection.AddSingleton(_fileSystem);
+ serviceCollection.AddSingleton(new InMemoryRegistry());
}
[Fact]
@@ -29,7 +33,7 @@ public void Ctor_NullArgs_Throws()
Assert.Throws(() => new SteamAppManifest(null!, _fileSystem.FileInfo.New("file.acf"), 0, "name", _fileSystem.DirectoryInfo.New("path"),
SteamAppState.StateFullyInstalled, new HashSet()));
- var lib = _fileSystem.InstallSteamLibrary("path", _serviceProvider, false);
+ var lib = Steam.InstallLibrary("path", false);
Assert.Throws(() => new SteamAppManifest(lib, null!, 0, "name", _fileSystem.DirectoryInfo.New("path"),
SteamAppState.StateFullyInstalled, new HashSet()));
@@ -49,7 +53,7 @@ public void Ctor_NullArgs_Throws()
[Fact]
public void Ctor_SetsProperties()
{
- var lib = _fileSystem.InstallSteamLibrary("path", _serviceProvider, false);
+ var lib = Steam.InstallLibrary("path", false);
var appManifest = new SteamAppManifest(lib, _fileSystem.FileInfo.New("file.acf"), 123, "name",
_fileSystem.DirectoryInfo.New("path"),
SteamAppState.StateFullyInstalled, new HashSet {987, 654});
@@ -66,8 +70,8 @@ public void Ctor_SetsProperties()
[Fact]
public void Equality()
{
- var lib = _fileSystem.InstallSteamLibrary("path", _serviceProvider, false);
- var otherLib = _fileSystem.InstallSteamLibrary("other", _serviceProvider, false);
+ var lib = Steam.InstallLibrary("path", false);
+ var otherLib = Steam.InstallLibrary("other", false);
const uint aId = 123;
const uint bId = 456;
@@ -78,7 +82,7 @@ public void Equality()
var appB = new SteamAppManifest(lib, _fileSystem.FileInfo.New(_fileSystem.Path.GetRandomFileName()), aId, _fileSystem.Path.GetRandomFileName(),
_fileSystem.DirectoryInfo.New(_fileSystem.Path.GetRandomFileName()),
- TestHelpers.GetRandomEnum(), new HashSet());
+ Random.Enum(), new HashSet());
var appOtherLib = new SteamAppManifest(otherLib, _fileSystem.FileInfo.New("file.acf"), aId, "name",
_fileSystem.DirectoryInfo.New("path"),
diff --git a/test/AET.SteamAbstraction.Test/SteamLibraryFinderTest.cs b/test/AET.SteamAbstraction.Test/SteamLibraryFinderTest.cs
index 3dd8ba3c..b88662fa 100644
--- a/test/AET.SteamAbstraction.Test/SteamLibraryFinderTest.cs
+++ b/test/AET.SteamAbstraction.Test/SteamLibraryFinderTest.cs
@@ -1,49 +1,41 @@
-using System;
-using System.Collections.Generic;
-using System.IO.Abstractions;
+using System.Collections.Generic;
using System.Linq;
-using System.Runtime.InteropServices;
using AET.SteamAbstraction.Library;
-using AET.SteamAbstraction.Registry;
-using AET.SteamAbstraction.Testing.Installation;
-using AnakinRaW.CommonUtilities.Registry;
-using Microsoft.Extensions.DependencyInjection;
-using PG.TestingUtilities;
-using Testably.Abstractions.Testing;
+using AET.SteamAbstraction.Testing.TestBases;
+using AnakinRaW.CommonUtilities.Testing.Attributes;
using Xunit;
+#if NET5_0_OR_GREATER
+using System.Runtime.Versioning;
+#endif
+
namespace AET.SteamAbstraction.Test;
-public class SteamLibraryFinderTest
+#if NET5_0_OR_GREATER
+[SupportedOSPlatform("windows")]
+#endif
+public class SteamLibraryFinderTest : InMemorySteamTestBase
{
private readonly SteamLibraryFinder _libraryFinder;
- private readonly MockFileSystem _fileSystem = new();
- private readonly IServiceProvider _serviceProvider;
public SteamLibraryFinderTest()
{
- var sc = new ServiceCollection();
- if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
- sc.AddSingleton(new InMemoryRegistry(InMemoryRegistryCreationFlags.Default));
- sc.AddSingleton(_fileSystem);
- SteamAbstractionLayer.InitializeServices(sc);
- _serviceProvider = sc.BuildServiceProvider();
- _libraryFinder = new SteamLibraryFinder(_serviceProvider);
+ _libraryFinder = new SteamLibraryFinder(ServiceProvider);
+ Steam.Install();
}
- [Fact]
+ // TODO: Target all platforms
+ [PlatformSpecificFact(TestPlatformIdentifier.Windows)]
public void FindLibraries_SteamNotFound_ReturnsEmpty()
{
- Assert.Empty(_libraryFinder.FindLibraries(_fileSystem.DirectoryInfo.New("does not exist")));
+ Assert.Empty(_libraryFinder.FindLibraries(FileSystem.DirectoryInfo.New("not steam")));
}
// TODO: Target all platforms
[PlatformSpecificFact(TestPlatformIdentifier.Windows)]
public void FindLibraries_NoLibrariesInstalled()
{
- using var registry = _serviceProvider.GetRequiredService().CreateRegistry();
- _fileSystem.InstallSteam(registry);
- var libs = _libraryFinder.FindLibraries(registry.InstallationDirectory!);
+ var libs = _libraryFinder.FindLibraries(Steam.Registry.InstallationDirectory!);
Assert.Empty(libs);
}
@@ -51,11 +43,8 @@ public void FindLibraries_NoLibrariesInstalled()
[PlatformSpecificFact(TestPlatformIdentifier.Windows)]
public void FindLibraries_DefaultLibraryInstalled()
{
- using var registry = _serviceProvider.GetRequiredService().CreateRegistry();
- _fileSystem.InstallSteam(registry);
- var lib = _fileSystem.InstallDefaultLibrary(_serviceProvider, addToConfig: true);
-
- var libs = _libraryFinder.FindLibraries(registry.InstallationDirectory!);
+ var lib = Steam.InstallDefaultLibrary(addToConfig: true);
+ var libs = _libraryFinder.FindLibraries(Steam.Registry.InstallationDirectory!);
Assert.Equal([lib], libs);
}
@@ -64,12 +53,8 @@ public void FindLibraries_DefaultLibraryInstalled()
[PlatformSpecificFact(TestPlatformIdentifier.Windows)]
public void FindLibraries_DefaultLibraryInstalledButNotInConfig_NotFound()
{
- using var registry = _serviceProvider.GetRequiredService().CreateRegistry();
- _fileSystem.InstallSteam(registry);
- _fileSystem.InstallDefaultLibrary(_serviceProvider, addToConfig: false);
-
- var libs = _libraryFinder.FindLibraries(registry.InstallationDirectory!);
-
+ Steam.InstallDefaultLibrary(addToConfig: false);
+ var libs = _libraryFinder.FindLibraries(Steam.InstallationDirectory!);
Assert.Empty(libs);
}
@@ -77,29 +62,26 @@ public void FindLibraries_DefaultLibraryInstalledButNotInConfig_NotFound()
[PlatformSpecificFact(TestPlatformIdentifier.Windows)]
public void FindLibraries_DefaultLibraryAndExternalLibInstalled()
{
- using var registry = _serviceProvider.GetRequiredService().CreateRegistry();
- _fileSystem.InstallSteam(registry);
- var defaultLib = _fileSystem.InstallDefaultLibrary(_serviceProvider, addToConfig: true);
- var externalLib = _fileSystem.InstallSteamLibrary("externalLib", _serviceProvider);
+ var defaultLib = Steam.InstallDefaultLibrary(addToConfig: true);
+ var externalLib = Steam.InstallLibrary("externalLib");
- var libs = _libraryFinder.FindLibraries(registry.InstallationDirectory!);
+ var libs = _libraryFinder.FindLibraries(Steam.InstallationDirectory!);
Assert.Equal(
new List { defaultLib, externalLib }.OrderBy(x => x.LibraryLocation.FullName),
libs.OrderBy(x => x.LibraryLocation.FullName));
}
+ // TODO: Target all platforms
[PlatformSpecificFact(TestPlatformIdentifier.Windows)]
public void FindLibraries_Windows_DefaultLibraryAndExternalLibInstalled_ExternalDoesNotHaveSteamDll_Skip()
{
- using var registry = _serviceProvider.GetRequiredService().CreateRegistry();
- _fileSystem.InstallSteam(registry);
- var defaultLib = _fileSystem.InstallDefaultLibrary(_serviceProvider, addToConfig: true);
- var externalLib = _fileSystem.InstallSteamLibrary("externalLib", _serviceProvider);
-
- _fileSystem.File.Delete(_fileSystem.Path.Combine(externalLib.LibraryLocation.FullName, "steam.dll"));
+ var defaultLib = Steam.InstallDefaultLibrary(addToConfig: true);
+ var externalLib = Steam.InstallLibrary("externalLib");
+
+ FileSystem.File.Delete(FileSystem.Path.Combine(externalLib.LibraryLocation.FullName, "steam.dll"));
- var libs = _libraryFinder.FindLibraries(registry.InstallationDirectory!);
+ var libs = _libraryFinder.FindLibraries(Steam.InstallationDirectory!);
Assert.Equal([defaultLib], libs.OrderBy(x => x.LibraryLocation.FullName));
}
@@ -108,14 +90,12 @@ public void FindLibraries_Windows_DefaultLibraryAndExternalLibInstalled_External
[PlatformSpecificFact(TestPlatformIdentifier.Windows)]
public void FindLibraries_DefaultLibraryAndExternalLibInstalled_ExternalDoesNotHaveVdf_Skip()
{
- using var registry = _serviceProvider.GetRequiredService().CreateRegistry();
- _fileSystem.InstallSteam(registry);
- var defaultLib = _fileSystem.InstallDefaultLibrary(_serviceProvider, addToConfig: true);
- var externalLib = _fileSystem.InstallSteamLibrary("externalLib", _serviceProvider);
+ var defaultLib = Steam.InstallDefaultLibrary(addToConfig: true);
+ var externalLib = Steam.InstallLibrary("externalLib");
- _fileSystem.File.Delete(_fileSystem.Path.Combine(externalLib.LibraryLocation.FullName, "libraryfolder.vdf"));
+ FileSystem.File.Delete(FileSystem.Path.Combine(externalLib.LibraryLocation.FullName, "libraryfolder.vdf"));
- var libs = _libraryFinder.FindLibraries(registry.InstallationDirectory!);
+ var libs = _libraryFinder.FindLibraries(Steam.InstallationDirectory!);
Assert.Equal([defaultLib], libs.OrderBy(x => x.LibraryLocation.FullName));
}
@@ -124,14 +104,12 @@ public void FindLibraries_DefaultLibraryAndExternalLibInstalled_ExternalDoesNotH
[PlatformSpecificFact(TestPlatformIdentifier.Windows)]
public void FindLibraries_DefaultLibraryAndExternalLibInstalled_ExternalFolderDoesNotExist()
{
- using var registry = _serviceProvider.GetRequiredService().CreateRegistry();
- _fileSystem.InstallSteam(registry);
- var defaultLib = _fileSystem.InstallDefaultLibrary(_serviceProvider, addToConfig: true);
- var externalLib = _fileSystem.InstallSteamLibrary("externalLib", _serviceProvider);
+ var defaultLib = Steam.InstallDefaultLibrary(addToConfig: true);
+ var externalLib = Steam.InstallLibrary("externalLib");
- _fileSystem.Directory.Delete(externalLib.LibraryLocation.FullName, true);
+ FileSystem.Directory.Delete(externalLib.LibraryLocation.FullName, true);
- var libs = _libraryFinder.FindLibraries(registry.InstallationDirectory!);
+ var libs = _libraryFinder.FindLibraries(Steam.InstallationDirectory!);
Assert.Equal([defaultLib], libs.OrderBy(x => x.LibraryLocation.FullName));
}
diff --git a/test/AET.SteamAbstraction.Test/SteamLibraryTest.cs b/test/AET.SteamAbstraction.Test/SteamLibraryTest.cs
index cf5e885a..3e39d97d 100644
--- a/test/AET.SteamAbstraction.Test/SteamLibraryTest.cs
+++ b/test/AET.SteamAbstraction.Test/SteamLibraryTest.cs
@@ -1,35 +1,25 @@
using System;
-using System.IO.Abstractions;
using System.Linq;
using System.Runtime.InteropServices;
using AET.SteamAbstraction.Library;
-using AET.SteamAbstraction.Testing.Installation;
-using Microsoft.Extensions.DependencyInjection;
-using Testably.Abstractions.Testing;
+using AET.SteamAbstraction.Testing.TestBases;
using Xunit;
namespace AET.SteamAbstraction.Test;
-public class SteamLibraryTest
+public class SteamLibraryTest : InMemorySteamTestBase
{
- private readonly IServiceProvider _serviceProvider;
- private readonly MockFileSystem _fileSystem = new();
-
public SteamLibraryTest()
{
- var sc = new ServiceCollection();
- sc.AddSingleton(_ => _fileSystem);
- SteamAbstractionLayer.InitializeServices(sc);
- _serviceProvider = sc.BuildServiceProvider();
-
- _fileSystem.InstallSteamFiles();
+ Steam.InstallSteamFilesOnly();
}
+
[Fact]
public void Ctor_NullArgs_Throws()
{
- Assert.Throws(() => new SteamLibrary(null!, _serviceProvider));
- Assert.Throws(() => new SteamLibrary(_fileSystem.DirectoryInfo.New("Library"), null!));
+ Assert.Throws(() => new SteamLibrary(null!, ServiceProvider));
+ Assert.Throws(() => new SteamLibrary(FileSystem.DirectoryInfo.New("Library"), null!));
}
[Theory]
@@ -39,8 +29,8 @@ public void Ctor_NullArgs_Throws()
[InlineData("other", false, false)]
public void TestEquality(string path, bool equalWindows, bool equalLinux)
{
- var lib = new SteamLibrary(_fileSystem.DirectoryInfo.New("Library"), _serviceProvider);
- var other = new SteamLibrary(_fileSystem.DirectoryInfo.New(path), _serviceProvider);
+ var lib = new SteamLibrary(FileSystem.DirectoryInfo.New("Library"), ServiceProvider);
+ var other = new SteamLibrary(FileSystem.DirectoryInfo.New(path), ServiceProvider);
var equal = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? equalWindows : equalLinux;
@@ -51,7 +41,7 @@ public void TestEquality(string path, bool equalWindows, bool equalLinux)
[Fact]
public void TestEquality_NullAndSame()
{
- var lib = new SteamLibrary(_fileSystem.DirectoryInfo.New("Library"), _serviceProvider);
+ var lib = new SteamLibrary(FileSystem.DirectoryInfo.New("Library"), ServiceProvider);
Assert.False(lib.Equals((object)null!));
Assert.False(lib.Equals(null));
@@ -63,12 +53,12 @@ public void TestEquality_NullAndSame()
[Fact]
public void Locations()
{
- var libDirBasePath = _fileSystem.DirectoryInfo.New("Library");
- var expectedSteamApps = _fileSystem.Path.Combine(libDirBasePath.FullName, "steamapps");
- var expectedCommon = _fileSystem.Path.Combine(expectedSteamApps, "common");
- var expectedWorkshop = _fileSystem.Path.Combine(expectedSteamApps, "workshop");
+ var libDirBasePath = FileSystem.DirectoryInfo.New("Library");
+ var expectedSteamApps = FileSystem.Path.Combine(libDirBasePath.FullName, "steamapps");
+ var expectedCommon = FileSystem.Path.Combine(expectedSteamApps, "common");
+ var expectedWorkshop = FileSystem.Path.Combine(expectedSteamApps, "workshop");
- var lib = new SteamLibrary(_fileSystem.DirectoryInfo.New("Library"), _serviceProvider);
+ var lib = new SteamLibrary(FileSystem.DirectoryInfo.New("Library"), ServiceProvider);
Assert.Equal(expectedSteamApps, lib.SteamAppsLocation.FullName);
Assert.Equal(expectedCommon, lib.CommonLocation.FullName);
Assert.Equal(expectedWorkshop, lib.WorkshopsLocation.FullName);
@@ -77,7 +67,7 @@ public void Locations()
[Fact]
public void GetApps_NoAppsInstalled_Empty()
{
- var library = _fileSystem.InstallSteamLibrary("Library", _serviceProvider);
+ var library = Steam.InstallLibrary("Library");
var apps = library.GetApps();
@@ -87,7 +77,7 @@ public void GetApps_NoAppsInstalled_Empty()
[Fact]
public void GetApps_NoSteamAppsDirectoryDoesNotExists_Empty()
{
- var library = _fileSystem.InstallSteamLibrary("Library", _serviceProvider);
+ var library = Steam.InstallLibrary("Library");
library.SteamAppsLocation.Delete(true);
var apps = library.GetApps();
@@ -98,8 +88,8 @@ public void GetApps_NoSteamAppsDirectoryDoesNotExists_Empty()
[Fact]
public void GetApps_InvalidAcfFile_Skipped()
{
- var library = _fileSystem.InstallSteamLibrary("Library", _serviceProvider);
- library.InstallCorruptApp(_fileSystem);
+ var library = Steam.InstallLibrary("Library");
+ library.InstallCorruptApp();
var apps = library.GetApps();
@@ -109,9 +99,9 @@ public void GetApps_InvalidAcfFile_Skipped()
[Fact]
public void TestApps()
{
- var library = _fileSystem.InstallSteamLibrary("Library", _serviceProvider);
+ var library = Steam.InstallLibrary("Library");
- library.InstallCorruptApp(_fileSystem);
+ library.InstallCorruptApp();
library.InstallGame(123, "Game1", "manifest1.acf");
var expectedGame2 = library.InstallGame(456, "Game2");
library.InstallGame(123, "NotGame1", "manifest2.acf");
diff --git a/test/AET.SteamAbstraction.Test/SteamRegistryFactoryTest.cs b/test/AET.SteamAbstraction.Test/SteamRegistryFactoryTest.cs
index 6a1738b6..6803f25f 100644
--- a/test/AET.SteamAbstraction.Test/SteamRegistryFactoryTest.cs
+++ b/test/AET.SteamAbstraction.Test/SteamRegistryFactoryTest.cs
@@ -1,32 +1,28 @@
-using System;
-using System.IO.Abstractions;
-using System.Runtime.InteropServices;
-using AET.SteamAbstraction.Registry;
+using AET.SteamAbstraction.Registry;
using AnakinRaW.CommonUtilities.Registry;
using Microsoft.Extensions.DependencyInjection;
+using System;
+using System.IO.Abstractions;
+using System.Runtime.InteropServices;
+using AnakinRaW.CommonUtilities.Testing;
using Testably.Abstractions.Testing;
using Xunit;
namespace AET.SteamAbstraction.Test;
-public class SteamRegistryFactoryTest
+public class SteamRegistryFactoryTest : TestBaseWithServiceProvider
{
- private readonly IRegistry _registry = new InMemoryRegistry();
- private readonly MockFileSystem _fileSystem = new();
- private readonly IServiceProvider _serviceProvider;
-
- public SteamRegistryFactoryTest()
+ protected override void SetupServices(IServiceCollection serviceCollection)
{
- var sc = new ServiceCollection();
- sc.AddSingleton(_fileSystem);
- sc.AddSingleton(_registry);
- _serviceProvider = sc.BuildServiceProvider();
+ base.SetupServices(serviceCollection);
+ serviceCollection.AddSingleton(new MockFileSystem());
+ serviceCollection.AddSingleton(new InMemoryRegistry());
}
[Fact]
public void Test_CreateWrapper()
{
- var factory = new SteamRegistryFactory(_serviceProvider);
+ var factory = new SteamRegistryFactory(ServiceProvider);
var registry = factory.CreateRegistry();
diff --git a/test/AET.SteamAbstraction.Test/SteamRegistryTestBase.cs b/test/AET.SteamAbstraction.Test/SteamRegistryTestBase.cs
index 9777a1f7..ede7d671 100644
--- a/test/AET.SteamAbstraction.Test/SteamRegistryTestBase.cs
+++ b/test/AET.SteamAbstraction.Test/SteamRegistryTestBase.cs
@@ -1,40 +1,36 @@
-using System;
+using AET.SteamAbstraction.Registry;
+using AET.SteamAbstraction.Testing;
+using AnakinRaW.CommonUtilities.Registry;
+using Microsoft.Extensions.DependencyInjection;
+using System;
using System.IO.Abstractions;
using System.Reflection;
-using AET.SteamAbstraction.Registry;
-using Microsoft.Extensions.DependencyInjection;
+using System.Runtime.InteropServices;
+using AnakinRaW.CommonUtilities.Testing;
using Testably.Abstractions.Testing;
using Xunit;
namespace AET.SteamAbstraction.Test;
-public abstract class SteamRegistryTestBase
+public abstract class SteamRegistryTestBase : TestBaseWithServiceProvider
{
protected readonly MockFileSystem FileSystem = new();
+ protected readonly IRegistry InternalRegistry = RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
+ ? new InMemoryRegistry(InMemoryRegistryCreationFlags.WindowsLike)
+ : new InMemoryRegistry();
- protected readonly string SteamInstallPath = "steamDir";
- protected readonly string SteamExePath = "steamDir/steam";
-
- protected readonly IServiceProvider ServiceProvider;
-
- protected SteamRegistryTestBase()
+ protected override void SetupServices(IServiceCollection serviceCollection)
{
- var sc = new ServiceCollection();
- sc.AddSingleton(FileSystem);
- SteamAbstractionLayer.InitializeServices(sc);
- // ReSharper disable once VirtualMemberCallInConstructor
- BuildServiceCollection(sc);
- ServiceProvider = sc.BuildServiceProvider();
+ base.SetupServices(serviceCollection);
+ serviceCollection.AddSingleton(FileSystem);
+ serviceCollection.AddSingleton(InternalRegistry);
+ SteamAbstractionLayer.InitializeServices(serviceCollection);
}
private protected abstract ISteamRegistry CreateRegistry(bool steamExists = true);
protected abstract void SetSteamPid(int pid);
- protected virtual void BuildServiceCollection(IServiceCollection serviceCollection)
- {
- }
-
[Fact]
public void TestInstallationProperties_SteamNotInstalled()
{
@@ -50,8 +46,8 @@ public void TestInstallationProperties_SteamInstalled()
{
var registry = CreateRegistry();
- Assert.Equal(FileSystem.FileInfo.New(SteamExePath).FullName, registry.ExecutableFile!.FullName);
- Assert.Equal(FileSystem.DirectoryInfo.New(SteamInstallPath).FullName, registry.InstallationDirectory!.FullName);
+ Assert.Equal(FileSystem.FileInfo.New(TestingSteamConstants.SteamExePath).FullName, registry.ExecutableFile!.FullName);
+ Assert.Equal(FileSystem.DirectoryInfo.New(TestingSteamConstants.SteamInstallPath).FullName, registry.InstallationDirectory!.FullName);
Assert.True(registry.ProcessId is null or 0);
}
@@ -60,8 +56,8 @@ public void TestInstallationProperties_SteamInstalledAndRunning()
{
var registry = CreateRegistry();
- Assert.Equal(FileSystem.FileInfo.New(SteamExePath).FullName, registry.ExecutableFile!.FullName);
- Assert.Equal(FileSystem.DirectoryInfo.New(SteamInstallPath).FullName, registry.InstallationDirectory!.FullName);
+ Assert.Equal(FileSystem.FileInfo.New(TestingSteamConstants.SteamExePath).FullName, registry.ExecutableFile!.FullName);
+ Assert.Equal(FileSystem.DirectoryInfo.New(TestingSteamConstants.SteamInstallPath).FullName, registry.InstallationDirectory!.FullName);
SetSteamPid(1234);
diff --git a/test/AET.SteamAbstraction.Test/SteamVdfReaderTest.cs b/test/AET.SteamAbstraction.Test/SteamVdfReaderTest.cs
index 6e3eb335..e741d6ab 100644
--- a/test/AET.SteamAbstraction.Test/SteamVdfReaderTest.cs
+++ b/test/AET.SteamAbstraction.Test/SteamVdfReaderTest.cs
@@ -1,27 +1,21 @@
-using System;
+using AET.SteamAbstraction.Games;
+using AET.SteamAbstraction.Testing;
+using AET.SteamAbstraction.Testing.TestBases;
+using System;
using System.Collections.Generic;
using System.IO;
-using System.IO.Abstractions;
using System.Linq;
-using AET.SteamAbstraction.Games;
-using AET.SteamAbstraction.Testing.Installation;
-using Microsoft.Extensions.DependencyInjection;
using Testably.Abstractions.Testing;
using Xunit;
using VdfException = AET.SteamAbstraction.Vdf.VdfException;
namespace AET.SteamAbstraction.Test;
-public class SteamVdfReaderTest
+public class SteamVdfReaderTest : InMemorySteamTestBase
{
- private readonly IServiceProvider _serviceProvider;
- private readonly MockFileSystem _fileSystem = new();
-
public SteamVdfReaderTest()
{
- var sc = new ServiceCollection();
- sc.AddSingleton(_ => _fileSystem);
- _serviceProvider = sc.BuildServiceProvider();
+ Steam.InstallSteamFilesOnly();
}
#region ReadLibraryLocationsFromConfig
@@ -29,8 +23,8 @@ public SteamVdfReaderTest()
[Fact]
public void ReadLibraryLocationsFromConfig_EmptyFile_Throws()
{
- _fileSystem.Initialize().WithFile("input.vdf");
- var input = _fileSystem.FileInfo.New("input.vdf");
+ FileSystem.Initialize().WithFile("input.vdf");
+ var input = FileSystem.FileInfo.New("input.vdf");
Assert.Throws(() => SteamVdfReader.ReadLibraryLocationsFromConfig(input).ToList());
}
@@ -42,9 +36,9 @@ public void ReadLibraryLocationsFromConfig_InvalidRootNodeName_Throws()
""0"" ""/Lib""
}
";
- _fileSystem.Initialize().WithFile("input.vdf").Which(d => d.HasStringContent(data));
+ FileSystem.Initialize().WithFile("input.vdf").Which(d => d.HasStringContent(data));
- var input = _fileSystem.FileInfo.New("input.vdf");
+ var input = FileSystem.FileInfo.New("input.vdf");
Assert.Throws(() => SteamVdfReader.ReadLibraryLocationsFromConfig(input).ToList());
}
@@ -52,9 +46,9 @@ public void ReadLibraryLocationsFromConfig_InvalidRootNodeName_Throws()
public void ReadLibraryLocationsFromConfig_InvalidRootNodeKind_Throws()
{
var data = @"""libraryfolders"" ""someData""";
- _fileSystem.Initialize().WithFile("input.vdf").Which(d => d.HasStringContent(data));
+ FileSystem.Initialize().WithFile("input.vdf").Which(d => d.HasStringContent(data));
- var input = _fileSystem.FileInfo.New("input.vdf");
+ var input = FileSystem.FileInfo.New("input.vdf");
Assert.Throws(() => SteamVdfReader.ReadLibraryLocationsFromConfig(input).ToList());
}
@@ -82,16 +76,16 @@ public void ReadLibraryLocationsFromConfig()
}
";
- var expected1 = _fileSystem.DirectoryInfo.New("/Lib1").FullName;
- var expected2 = _fileSystem.DirectoryInfo.New("/Lib2").FullName;
- var expected3 = _fileSystem.DirectoryInfo.New("/Lib3").FullName;
+ var expected1 = FileSystem.DirectoryInfo.New("/Lib1").FullName;
+ var expected2 = FileSystem.DirectoryInfo.New("/Lib2").FullName;
+ var expected3 = FileSystem.DirectoryInfo.New("/Lib3").FullName;
- var notExpected1 = _fileSystem.DirectoryInfo.New("/LibA").FullName;
- var notExpected2 = _fileSystem.DirectoryInfo.New("/LabelA").FullName;
+ var notExpected1 = FileSystem.DirectoryInfo.New("/LibA").FullName;
+ var notExpected2 = FileSystem.DirectoryInfo.New("/LabelA").FullName;
- _fileSystem.Initialize().WithFile("input.vdf").Which(d => d.HasStringContent(data));
+ FileSystem.Initialize().WithFile("input.vdf").Which(d => d.HasStringContent(data));
- var input = _fileSystem.FileInfo.New("input.vdf");
+ var input = FileSystem.FileInfo.New("input.vdf");
var locations = SteamVdfReader.ReadLibraryLocationsFromConfig(input).Select(l => l.FullName).ToList();
Assert.Contains(expected1, locations);
@@ -109,9 +103,9 @@ public void ReadLibraryLocationsFromConfig_NoLibrariesFound_EmptyEnumerable()
""NaN"" ""/Lib""
}
";
- _fileSystem.Initialize().WithFile("input.vdf").Which(d => d.HasStringContent(data));
+ FileSystem.Initialize().WithFile("input.vdf").Which(d => d.HasStringContent(data));
- var input = _fileSystem.FileInfo.New("input.vdf");
+ var input = FileSystem.FileInfo.New("input.vdf");
var libs = SteamVdfReader.ReadLibraryLocationsFromConfig(input);
Assert.Empty(libs);
}
@@ -123,9 +117,9 @@ public void ReadLibraryLocationsFromConfig_EmptyContent_EmptyEnumerable()
{
}
";
- _fileSystem.Initialize().WithFile("input.vdf").Which(d => d.HasStringContent(data));
+ FileSystem.Initialize().WithFile("input.vdf").Which(d => d.HasStringContent(data));
- var input = _fileSystem.FileInfo.New("input.vdf");
+ var input = FileSystem.FileInfo.New("input.vdf");
var libs = SteamVdfReader.ReadLibraryLocationsFromConfig(input);
Assert.Empty(libs);
}
@@ -137,15 +131,15 @@ public void ReadLibraryLocationsFromConfig_EmptyContent_EmptyEnumerable()
[Fact]
public void ReadManifest_NullArgs_Throws()
{
- var lib = _fileSystem.InstallSteamLibrary("steamLib", _serviceProvider, false);
+ var lib = Steam.InstallLibrary("steamLib", false);
Assert.Throws(() => SteamVdfReader.ReadManifest(null!, lib));
- Assert.Throws(() => SteamVdfReader.ReadManifest(_fileSystem.FileInfo.New("path"), null!));
+ Assert.Throws(() => SteamVdfReader.ReadManifest(FileSystem.FileInfo.New("path"), null!));
}
[Fact]
public void ReadManifest_CorrectManifest()
{
- var lib = _fileSystem.InstallSteamLibrary("steamLib", _serviceProvider, false);
+ var lib = Steam.InstallLibrary("steamLib", false);
var expectedManifest = lib.InstallGame(
1230,
@@ -295,19 +289,19 @@ public static IEnumerable