From 1e2fb879088d24dcad26dbd6a9d5d09f3bbfa3ef Mon Sep 17 00:00:00 2001 From: Chris Adamson Date: Tue, 19 Aug 2025 14:05:05 -0500 Subject: [PATCH] added isside check and tests (#562) * added isside check and tests * csharpier --- .../Services/LocationLifecycleService.cs | 27 ++++++-- .../Services/LocationLifecycleServiceTests.cs | 63 +++++++++++++++++++ 2 files changed, 84 insertions(+), 6 deletions(-) create mode 100644 Testing/UnitTests/Tests/Services/LocationLifecycleServiceTests.cs diff --git a/Libraries/SPTarkov.Server.Core/Services/LocationLifecycleService.cs b/Libraries/SPTarkov.Server.Core/Services/LocationLifecycleService.cs index 49952424..c3b1e3c4 100644 --- a/Libraries/SPTarkov.Server.Core/Services/LocationLifecycleService.cs +++ b/Libraries/SPTarkov.Server.Core/Services/LocationLifecycleService.cs @@ -57,6 +57,20 @@ public class LocationLifecycleService( protected readonly PmcConfig _pmcConfig = configServer.GetConfig(); protected readonly LostOnDeathConfig _lostOnDeathConfig = configServer.GetConfig(); + protected const string Pmc = "pmc"; + protected const string Savage = "savage"; + protected const string Scav = "scav"; + + /// + /// Check player type for pmc or scav + /// + /// string + /// bool + protected bool IsSide(string playerSide, string sideCheck = Pmc) + { + return string.Equals(playerSide, sideCheck, StringComparison.OrdinalIgnoreCase); + } + /// /// Handle client/match/local/start /// @@ -68,7 +82,7 @@ public class LocationLifecycleService( // Remove skill fatigue values ResetSkillPointsEarnedDuringRaid( - string.Equals(request.PlayerSide, "pmc", StringComparison.OrdinalIgnoreCase) + IsSide(request.PlayerSide) ? playerProfile.CharacterData.PmcData.Skills.Common : playerProfile.CharacterData.ScavData.Skills.Common ); @@ -141,11 +155,12 @@ public class LocationLifecycleService( protected void HandlePreRaidInventoryChecks(string playerSide, PmcData pmcData, string sessionId) { // If config enabled, remove players equipped items to prevent alt-F4 from persisting items - if (string.Equals(playerSide, "pmc", StringComparison.OrdinalIgnoreCase) && _lostOnDeathConfig.WipeOnRaidStart) + if (!IsSide(playerSide) || !_lostOnDeathConfig.WipeOnRaidStart) { - logger.Debug("Wiping player inventory on raid start to prevent alt-f4"); - inRaidHelper.DeleteInventory(pmcData, sessionId); + return; } + logger.Debug("Wiping player inventory on raid start to prevent alt-f4"); + inRaidHelper.DeleteInventory(pmcData, sessionId); } /// @@ -156,7 +171,7 @@ public class LocationLifecycleService( /// Maps location base data protected void AdjustExtracts(string playerSide, string location, LocationBase locationData) { - var playerIsScav = string.Equals(playerSide, "savage", StringComparison.OrdinalIgnoreCase); + var playerIsScav = IsSide(playerSide, Savage); if (!playerIsScav) { return; @@ -172,7 +187,7 @@ public class LocationLifecycleService( } // Find only scav extracts and overwrite existing exits with them - var scavExtracts = mapExtracts.Where(extract => string.Equals(extract.Side, "scav", StringComparison.OrdinalIgnoreCase)); + var scavExtracts = mapExtracts.Where(extract => IsSide(extract.Side, Scav)); if (scavExtracts.Any()) // Scav extracts found, use them { diff --git a/Testing/UnitTests/Tests/Services/LocationLifecycleServiceTests.cs b/Testing/UnitTests/Tests/Services/LocationLifecycleServiceTests.cs new file mode 100644 index 00000000..3f4f990e --- /dev/null +++ b/Testing/UnitTests/Tests/Services/LocationLifecycleServiceTests.cs @@ -0,0 +1,63 @@ +using System.Reflection; +using System.Runtime.Serialization; +using NUnit.Framework; +using SPTarkov.Server.Core.Generators; +using SPTarkov.Server.Core.Helpers; +using SPTarkov.Server.Core.Models.Utils; +using SPTarkov.Server.Core.Servers; +using SPTarkov.Server.Core.Services; +using SPTarkov.Server.Core.Utils; +using SPTarkov.Server.Core.Utils.Cloners; + +namespace UnitTests.Tests.Services; + +[TestFixture] +public class LocationLifecycleServiceTests +{ + // Note: The service has a heavy constructor with many DI deps. For testing the protected IsSide method, + // we bypass construction entirely and invoke the method via reflection. + + private static bool InvokeIsSide(object instance, string playerSide, string sideCheck) + { + var mi = typeof(LocationLifecycleService).GetMethod("IsSide", BindingFlags.Instance | BindingFlags.NonPublic); + Assert.IsNotNull(mi, "Could not find protected method IsSide via reflection"); + + var result = mi!.Invoke(instance, new object[] { playerSide, sideCheck }); + return result is bool b && b; + } + + private static LocationLifecycleService CreateUninitializedService() + { + // Skips running the heavy ctor and DI; safe for IsSide which only compares strings + return (LocationLifecycleService)FormatterServices.GetUninitializedObject(typeof(LocationLifecycleService)); + } + + [Test] + public void IsSide_ReturnsTrue_ForPmc_DefaultCheck_IsCaseInsensitive() + { + var svc = CreateUninitializedService(); + + // Default side is "pmc"; ensure case-insensitive match works + Assert.IsTrue(InvokeIsSide(svc, "PMC", "pmc")); + Assert.IsTrue(InvokeIsSide(svc, "pmc", "pmc")); + } + + [Test] + public void IsSide_ReturnsFalse_ForNonMatchingSide() + { + var svc = CreateUninitializedService(); + + Assert.IsFalse(InvokeIsSide(svc, "savage", "pmc")); + Assert.IsFalse(InvokeIsSide(svc, "beAr", "pmc")); + } + + [Test] + public void IsSide_ReturnsTrue_WhenCheckingScavAgainstSavage_IsCaseInsensitive() + { + var svc = CreateUninitializedService(); + + // In code, scav side string used for extracts is "savage" + Assert.IsTrue(InvokeIsSide(svc, "SAVAGE", "savage")); + Assert.IsTrue(InvokeIsSide(svc, "savage", "savage")); + } +}