From 5b982f3be815a1deb1494101423bb5998929cad0 Mon Sep 17 00:00:00 2001 From: Emmanuel Date: Tue, 16 Dec 2025 15:07:35 -0500 Subject: [PATCH 1/7] added tests for helpers and init common lib --- test/unit/CommonLibHelperTests.cs | 82 ++++++++++++++++++++++++++++ test/unit/CommonLibTests.cs | 89 +++++++++++++++++++++++++++++++ 2 files changed, 171 insertions(+) create mode 100644 test/unit/CommonLibTests.cs diff --git a/test/unit/CommonLibHelperTests.cs b/test/unit/CommonLibHelperTests.cs index e2cfe24f3..5f809f202 100644 --- a/test/unit/CommonLibHelperTests.cs +++ b/test/unit/CommonLibHelperTests.cs @@ -1,4 +1,5 @@ using System; +using System.Security.Principal; using System.Text; using System.Threading.Tasks; using SharpHoundCommonLib; @@ -293,5 +294,86 @@ public async Task RetryOnException_SucceedsOnLastAttempt() { Assert.True(success); } + + /// new + [Fact] + public void DomainNameToDistinguishedName_DotsBecomeDcComponents() + { + var result = Helpers.DomainNameToDistinguishedName("test.local"); + Assert.Equal("DC=test,DC=local", result); + } + + [Fact] + public void ConvertSidToHexSid_ValidSid_MatchesSecurityIdentifierBinaryForm() + { + // Arrange + var sid = "S-1-5-32-544"; + var expected = BuildExpectedHexSid(sid); + + // Act + var actual = Helpers.ConvertSidToHexSid(sid); + + // Assert + Assert.Equal(expected, actual); + return; + + static string BuildExpectedHexSid(string sid) + { + var securityIdentifier = new SecurityIdentifier(sid); + var sidBytes = new byte[securityIdentifier.BinaryLength]; + securityIdentifier.GetBinaryForm(sidBytes, 0); + return $"\\{BitConverter.ToString(sidBytes).Replace('-', '\\')}"; + } + } + + [Fact] + public void ConvertSidToHexSid_InvalidSid_Throws() + { + Assert.ThrowsAny(() => Helpers.ConvertSidToHexSid("NOT-A-SID")); + } + + [Theory] + [InlineData("s-1-5-18")] + [InlineData("S-1-5-18")] + public void IsSidFiltered_FilteredWellKnownSidsCaseInsensitive_ReturnsTrue(string sid) + { + Assert.True(Helpers.IsSidFiltered(sid)); + } + + [Theory] + [InlineData("S-1-5-80-1234567890")] + [InlineData("S-1-5-82-1234567890")] + [InlineData("S-1-5-90-0")] + [InlineData("S-1-5-96-0")] + public void IsSidFiltered_FilteredPrefixes_ReturnsTrue(string sid) + { + Assert.True(Helpers.IsSidFiltered(sid)); + } + + [Theory] + [InlineData("S-1-5-21-1234567890")] + [InlineData("S-1-5-21")] + public void IsSidFiltered_ReturnsFalse(string sid) + { + Assert.False(Helpers.IsSidFiltered(sid)); + } + + [Fact] + public void ConvertLdapTimeToLong_Null_ReturnsMinusOne() + { + Assert.Equal(-1, Helpers.ConvertLdapTimeToLong(null)); + } + + [Fact] + public void ConvertLdapTimeToLong_InvalidNumber_ThrowsFormatException() + { + Assert.Throws(() => Helpers.ConvertLdapTimeToLong("not-a-number")); + } + + [Fact] + public void ConvertLdapTimeToLong_ValidNumber_Parses() + { + Assert.Equal(123456789L, Helpers.ConvertLdapTimeToLong("123456789")); + } } } \ No newline at end of file diff --git a/test/unit/CommonLibTests.cs b/test/unit/CommonLibTests.cs new file mode 100644 index 000000000..f4a7576e1 --- /dev/null +++ b/test/unit/CommonLibTests.cs @@ -0,0 +1,89 @@ +using System; +using System.Reflection; +using Microsoft.Extensions.Logging; +using Moq; +using SharpHoundCommonLib; +using Xunit; + +namespace CommonLibTest; + +public class CommonLibTests +{ + + public CommonLibTests() + { + ResetCommonLibState(); + } + + [Fact] + public void InitializeCommonLib_FirstCallWithoutCache_CreatesAndSetsCacheInstance() + { + // Arrange & Act + CommonLib.InitializeCommonLib(); + + // Assert + var cache = Cache.GetCacheInstance(); + Assert.NotNull(cache); + Assert.NotNull(cache.IdToTypeCache); + Assert.NotNull(cache.ValueToIdCache); + Assert.NotNull(cache.GlobalCatalogCache); + Assert.NotNull(cache.MachineSidCache); + Assert.NotNull(cache.SIDToDomainCache); + } + + [Fact] + public void InitializeCommonLib_UsesProvidedInstance() + { + // Arrange + var provided = Cache.CreateNewCache(); + + // Act + CommonLib.InitializeCommonLib(cache: provided); + + // Assert + Assert.Same(provided, Cache.GetCacheInstance()); + } + + [Fact] + public void InitializeCommonLib_2Calls_LogsWarningAndDoesNotReplaceCache() + { + // Arrange + var cache1 = Cache.CreateNewCache(); + CommonLib.InitializeCommonLib(cache: cache1); + + var cache2 = Cache.CreateNewCache(); + var logger = new Mock(); + + // Act + CommonLib.InitializeCommonLib(logger.Object, cache2); + + // Assert + Assert.Same(cache1, Cache.GetCacheInstance()); + + logger.Verify(x => x.Log( + LogLevel.Warning, + It.IsAny(), + It.Is((v, _) => + v.ToString() != null && + v.ToString().Contains("already initialized", StringComparison.InvariantCultureIgnoreCase)), + It.IsAny(), + It.IsAny>()), + Times.Once()); + } + + private static void ResetCommonLibState() + { + // Reset CommonLib._initialized (private static) + var commonLibType = typeof(CommonLib); + var initializedField = commonLibType.GetField("_initialized", + BindingFlags.Static | BindingFlags.NonPublic); + + if (initializedField == null) + throw new InvalidOperationException("CommonLib _initialized field not found"); + + initializedField.SetValue(null, false); + + // Reset cache singleton so tests don't leak state into each other + Cache.SetCacheInstance(null); + } +} \ No newline at end of file From 80da004e63caa1f066441d77c09f3d27c405551f Mon Sep 17 00:00:00 2001 From: Emmanuel Date: Tue, 16 Dec 2025 15:14:02 -0500 Subject: [PATCH 2/7] added a comment --- test/unit/CommonLibTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/CommonLibTests.cs b/test/unit/CommonLibTests.cs index f4a7576e1..149cb343e 100644 --- a/test/unit/CommonLibTests.cs +++ b/test/unit/CommonLibTests.cs @@ -58,7 +58,7 @@ public void InitializeCommonLib_2Calls_LogsWarningAndDoesNotReplaceCache() CommonLib.InitializeCommonLib(logger.Object, cache2); // Assert - Assert.Same(cache1, Cache.GetCacheInstance()); + Assert.Same(cache1, Cache.GetCacheInstance()); // cache1 should be then one used since lib was already initialized logger.Verify(x => x.Log( LogLevel.Warning, From 6facb5c288d35a475f30768c8ffe6ed90d0084ac Mon Sep 17 00:00:00 2001 From: Emmanuel Date: Tue, 16 Dec 2025 15:17:02 -0500 Subject: [PATCH 3/7] coderabbit suggestion --- test/unit/CommonLibHelperTests.cs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/test/unit/CommonLibHelperTests.cs b/test/unit/CommonLibHelperTests.cs index 5f809f202..34d31cbc1 100644 --- a/test/unit/CommonLibHelperTests.cs +++ b/test/unit/CommonLibHelperTests.cs @@ -303,18 +303,15 @@ public void DomainNameToDistinguishedName_DotsBecomeDcComponents() Assert.Equal("DC=test,DC=local", result); } - [Fact] - public void ConvertSidToHexSid_ValidSid_MatchesSecurityIdentifierBinaryForm() + [Theory] + [InlineData("S-1-5-32-544", "\\01\\02\\00\\00\\00\\00\\00\\05\\20\\00\\00\\00\\20\\02\\00\\00")] + public void ConvertSidToHexSid_ValidSid_MatchesSecurityIdentifierBinaryForm(string sid, string expectedHexSid) { - // Arrange - var sid = "S-1-5-32-544"; - var expected = BuildExpectedHexSid(sid); - - // Act + // Arrange & Act var actual = Helpers.ConvertSidToHexSid(sid); // Assert - Assert.Equal(expected, actual); + Assert.Equal(expectedHexSid, actual); return; static string BuildExpectedHexSid(string sid) From 74064cf0eb826883ad81dcd92919a0bafa930f89 Mon Sep 17 00:00:00 2001 From: Emmanuel Date: Tue, 16 Dec 2025 15:17:38 -0500 Subject: [PATCH 4/7] removed comment --- test/unit/CommonLibHelperTests.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/test/unit/CommonLibHelperTests.cs b/test/unit/CommonLibHelperTests.cs index 34d31cbc1..0cad80e12 100644 --- a/test/unit/CommonLibHelperTests.cs +++ b/test/unit/CommonLibHelperTests.cs @@ -295,7 +295,6 @@ public async Task RetryOnException_SucceedsOnLastAttempt() { Assert.True(success); } - /// new [Fact] public void DomainNameToDistinguishedName_DotsBecomeDcComponents() { From 06ae9d84c74af34e55d5aeb28ac36b783a8f48ee Mon Sep 17 00:00:00 2001 From: Emmanuel Date: Tue, 16 Dec 2025 16:42:37 -0500 Subject: [PATCH 5/7] made some test the were using cache run in sequence so they dont step on eachother --- .../CacheTestsCollectionDefinition.cs | 9 + test/unit/CommonLibTests.cs | 4 +- .../unit/UserRightsAssignmentProcessorTest.cs | 294 +++++++++--------- 3 files changed, 161 insertions(+), 146 deletions(-) create mode 100644 test/unit/CollectionDefinitons/CacheTestsCollectionDefinition.cs diff --git a/test/unit/CollectionDefinitons/CacheTestsCollectionDefinition.cs b/test/unit/CollectionDefinitons/CacheTestsCollectionDefinition.cs new file mode 100644 index 000000000..b2397c100 --- /dev/null +++ b/test/unit/CollectionDefinitons/CacheTestsCollectionDefinition.cs @@ -0,0 +1,9 @@ +using Xunit; + +namespace CommonLibTest.CollectionDefinitons; + +/// +/// Test that use cache cannot run in parallel, they can have flaky behavior +/// +[CollectionDefinition(nameof(CacheTestCollectionDefinition), DisableParallelization = true)] +public class CacheTestCollectionDefinition{} diff --git a/test/unit/CommonLibTests.cs b/test/unit/CommonLibTests.cs index 149cb343e..788e08254 100644 --- a/test/unit/CommonLibTests.cs +++ b/test/unit/CommonLibTests.cs @@ -1,5 +1,6 @@ using System; using System.Reflection; +using CommonLibTest.CollectionDefinitons; using Microsoft.Extensions.Logging; using Moq; using SharpHoundCommonLib; @@ -7,6 +8,7 @@ namespace CommonLibTest; +[Collection(nameof(CacheTestCollectionDefinition))] public class CommonLibTests { @@ -70,7 +72,7 @@ public void InitializeCommonLib_2Calls_LogsWarningAndDoesNotReplaceCache() It.IsAny>()), Times.Once()); } - + private static void ResetCommonLibState() { // Reset CommonLib._initialized (private static) diff --git a/test/unit/UserRightsAssignmentProcessorTest.cs b/test/unit/UserRightsAssignmentProcessorTest.cs index 459c06bf4..70b7421b7 100644 --- a/test/unit/UserRightsAssignmentProcessorTest.cs +++ b/test/unit/UserRightsAssignmentProcessorTest.cs @@ -1,146 +1,150 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using CommonLibTest.Facades; -using CommonLibTest.Facades.LSAMocks.DCMocks; -using CommonLibTest.Facades.LSAMocks.WorkstationMocks; -using Moq; -using Newtonsoft.Json; -using SharpHoundCommonLib; -using SharpHoundCommonLib.Enums; -using SharpHoundCommonLib.Processors; -using SharpHoundRPC; -using Xunit; -using Xunit.Abstractions; - -namespace CommonLibTest -{ - public class UserRightsAssignmentProcessorTest - { - private readonly ITestOutputHelper _testOutputHelper; - - public UserRightsAssignmentProcessorTest(ITestOutputHelper testOutputHelper) - { - _testOutputHelper = testOutputHelper; - } - - [WindowsOnlyFact] - public async Task UserRightsAssignmentProcessor_TestWorkstation() - { - var mockProcessor = new Mock(new MockLdapUtils(), null); - var mockLSAPolicy = new MockWorkstationLSAPolicy(); - mockProcessor.Setup(x => x.OpenLSAPolicy(It.IsAny())).Returns(mockLSAPolicy); - var processor = mockProcessor.Object; - var machineDomainSid = $"{Consts.MockDomainSid}-1001"; - var results = await processor.GetUserRightsAssignments("win10.testlab.local", machineDomainSid, "testlab.local", false) - .ToArrayAsync(); - - var privilege = results[0]; - Assert.Equal(LSAPrivileges.RemoteInteractiveLogon, privilege.Privilege); - Assert.Equal(3, results[0].Results.Length); - var adminResult = privilege.Results.First(x => x.ObjectIdentifier.EndsWith("-544")); - Assert.Equal($"{machineDomainSid}-544", adminResult.ObjectIdentifier); - Assert.Equal(Label.LocalGroup, adminResult.ObjectType); - var rdpResult = privilege.Results.First(x => x.ObjectIdentifier.EndsWith("-555")); - Assert.Equal($"{machineDomainSid}-555", rdpResult.ObjectIdentifier); - Assert.Equal(Label.LocalGroup, rdpResult.ObjectType); - } - - [WindowsOnlyFact] - public async Task UserRightsAssignmentProcessor_TestDC() - { - var mockProcessor = new Mock(new MockLdapUtils(), null); - var mockLSAPolicy = new MockDCLSAPolicy(); - mockProcessor.Setup(x => x.OpenLSAPolicy(It.IsAny())).Returns(mockLSAPolicy); - var processor = mockProcessor.Object; - var machineDomainSid = $"{Consts.MockDomainSid}-1000"; - var results = await processor.GetUserRightsAssignments("primary.testlab.local", machineDomainSid, "testlab.local", true) - .ToArrayAsync(); - - var privilege = results[0]; - _testOutputHelper.WriteLine(JsonConvert.SerializeObject(privilege)); - Assert.Equal(LSAPrivileges.RemoteInteractiveLogon, privilege.Privilege); - Assert.Single(results[0].Results); - var adminResult = privilege.Results.First(x => x.ObjectIdentifier.EndsWith("-544")); - Assert.Equal("TESTLAB.LOCAL-S-1-5-32-544", adminResult.ObjectIdentifier); - Assert.Equal(Label.Group, adminResult.ObjectType); - } - - // Obsolete by AdaptiveTimeout - // [Fact] - // public async Task UserRightsAssignmentProcessor_TestTimeout() { - // var mockProcessor = new Mock(new MockLdapUtils(), null); - // mockProcessor.Setup(x => x.OpenLSAPolicy(It.IsAny())).Returns(()=> { - // Task.Delay(100).Wait(); - // return NtStatus.StatusAccessDenied; - // }); - // var processor = mockProcessor.Object; - // var machineDomainSid = $"{Consts.MockDomainSid}-1000"; - // var receivedStatus = new List(); - // processor.ComputerStatusEvent += status => { - // receivedStatus.Add(status); - // return Task.CompletedTask; - // }; - // var results = await processor.GetUserRightsAssignments("primary.testlab.local", machineDomainSid, "testlab.local", true, null) - // .ToArrayAsync(); - // Assert.Empty(results); - // Assert.Single(receivedStatus); - // var status = receivedStatus[0]; - // Assert.Equal("Timeout", status.Status); - // } - - [WindowsOnlyFact] - public async Task UserRightsAssignmentProcessor_TestGetLocalDomainInformationFail() - { - var mockProcessor = new Mock(new MockLdapUtils(), null); - var mockLSAPolicy = new MockFailLSAPolicy_GetLocalDomainInformation(); - mockProcessor.Setup(x => x.OpenLSAPolicy(It.IsAny())).Returns(()=> { - Task.Delay(100).Wait(); - return NtStatus.StatusAccessDenied; - }); - mockProcessor.Setup(x => x.OpenLSAPolicy(It.IsAny())).Returns(mockLSAPolicy); - var processor = mockProcessor.Object; - var machineDomainSid = $"{Consts.MockDomainSid}-1001"; - var receivedStatus = new List(); - processor.ComputerStatusEvent += async status => { - receivedStatus.Add(status); - }; - var results = await processor.GetUserRightsAssignments("win10.testlab.local", machineDomainSid, "testlab.local", false) - .ToArrayAsync(); - - Assert.Empty(results); - Assert.Single(receivedStatus); - var status = receivedStatus[0]; - Assert.Equal("StatusAccessDenied", status.Status); - Assert.Equal("LSAGetMachineSID", status.Task); - } - - [WindowsOnlyFact] - public async Task UserRightsAssignmentProcessor_TestGetResolvedPrincipalsWithPrivilegeFail() - { - var mockProcessor = new Mock(new MockLdapUtils(), null); - var mockLSAPolicy = new MockFailLSAPolicy_GetResolvedPrincipalsWithPrivilege(); - mockProcessor.Setup(x => x.OpenLSAPolicy(It.IsAny())).Returns(mockLSAPolicy); - var processor = mockProcessor.Object; - var machineDomainSid = $"{Consts.MockDomainSid}-1001"; - var receivedStatus = new List(); - processor.ComputerStatusEvent += async status => { - receivedStatus.Add(status); - }; - var results = await processor.GetUserRightsAssignments("win10.testlab.local", machineDomainSid, "testlab.local", false) - .ToArrayAsync(); - - Assert.Single(results); - - var result = results[0]; - Assert.False(result.Collected); - Assert.Equal("LSAEnumerateAccountsWithUserRights returned StatusAccessDenied", result.FailureReason); - Assert.Single(receivedStatus); - var status = receivedStatus[0]; - Assert.Equal("StatusAccessDenied", status.Status); - Assert.Equal("LSAEnumerateAccountsWithUserRight", status.Task); - } - } +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using CommonLibTest.CollectionDefinitons; +using CommonLibTest.Facades; +using CommonLibTest.Facades.LSAMocks.DCMocks; +using CommonLibTest.Facades.LSAMocks.WorkstationMocks; +using Moq; +using Newtonsoft.Json; +using SharpHoundCommonLib; +using SharpHoundCommonLib.Enums; +using SharpHoundCommonLib.Processors; +using SharpHoundRPC; +using Xunit; +using Xunit.Abstractions; + +namespace CommonLibTest +{ + [Collection(nameof(CacheTestCollectionDefinition))] + public class UserRightsAssignmentProcessorTest + { + private readonly ITestOutputHelper _testOutputHelper; + + public UserRightsAssignmentProcessorTest(ITestOutputHelper testOutputHelper) + { + _testOutputHelper = testOutputHelper; + + // reseting cache for tests + Cache.SetCacheInstance(null); + } + + [WindowsOnlyFact] + public async Task UserRightsAssignmentProcessor_TestWorkstation() + { + var mockProcessor = new Mock(new MockLdapUtils(), null); + var mockLSAPolicy = new MockWorkstationLSAPolicy(); + mockProcessor.Setup(x => x.OpenLSAPolicy(It.IsAny())).Returns(mockLSAPolicy); + var processor = mockProcessor.Object; + var machineDomainSid = $"{Consts.MockDomainSid}-1001"; + var results = await processor.GetUserRightsAssignments("win10.testlab.local", machineDomainSid, "testlab.local", false) + .ToArrayAsync(); + + var privilege = results[0]; + Assert.Equal(LSAPrivileges.RemoteInteractiveLogon, privilege.Privilege); + Assert.Equal(3, results[0].Results.Length); + var adminResult = privilege.Results.First(x => x.ObjectIdentifier.EndsWith("-544")); + Assert.Equal($"{machineDomainSid}-544", adminResult.ObjectIdentifier); + Assert.Equal(Label.LocalGroup, adminResult.ObjectType); + var rdpResult = privilege.Results.First(x => x.ObjectIdentifier.EndsWith("-555")); + Assert.Equal($"{machineDomainSid}-555", rdpResult.ObjectIdentifier); + Assert.Equal(Label.LocalGroup, rdpResult.ObjectType); + } + + [WindowsOnlyFact] + public async Task UserRightsAssignmentProcessor_TestDC() + { + var mockProcessor = new Mock(new MockLdapUtils(), null); + var mockLSAPolicy = new MockDCLSAPolicy(); + mockProcessor.Setup(x => x.OpenLSAPolicy(It.IsAny())).Returns(mockLSAPolicy); + var processor = mockProcessor.Object; + var machineDomainSid = $"{Consts.MockDomainSid}-1000"; + var results = await processor.GetUserRightsAssignments("primary.testlab.local", machineDomainSid, "testlab.local", true) + .ToArrayAsync(); + + var privilege = results[0]; + _testOutputHelper.WriteLine(JsonConvert.SerializeObject(privilege)); + Assert.Equal(LSAPrivileges.RemoteInteractiveLogon, privilege.Privilege); + Assert.Single(results[0].Results); + var adminResult = privilege.Results.First(x => x.ObjectIdentifier.EndsWith("-544")); + Assert.Equal("TESTLAB.LOCAL-S-1-5-32-544", adminResult.ObjectIdentifier); + Assert.Equal(Label.Group, adminResult.ObjectType); + } + + // Obsolete by AdaptiveTimeout + // [Fact] + // public async Task UserRightsAssignmentProcessor_TestTimeout() { + // var mockProcessor = new Mock(new MockLdapUtils(), null); + // mockProcessor.Setup(x => x.OpenLSAPolicy(It.IsAny())).Returns(()=> { + // Task.Delay(100).Wait(); + // return NtStatus.StatusAccessDenied; + // }); + // var processor = mockProcessor.Object; + // var machineDomainSid = $"{Consts.MockDomainSid}-1000"; + // var receivedStatus = new List(); + // processor.ComputerStatusEvent += status => { + // receivedStatus.Add(status); + // return Task.CompletedTask; + // }; + // var results = await processor.GetUserRightsAssignments("primary.testlab.local", machineDomainSid, "testlab.local", true, null) + // .ToArrayAsync(); + // Assert.Empty(results); + // Assert.Single(receivedStatus); + // var status = receivedStatus[0]; + // Assert.Equal("Timeout", status.Status); + // } + + [WindowsOnlyFact] + public async Task UserRightsAssignmentProcessor_TestGetLocalDomainInformationFail() + { + var mockProcessor = new Mock(new MockLdapUtils(), null); + var mockLSAPolicy = new MockFailLSAPolicy_GetLocalDomainInformation(); + mockProcessor.Setup(x => x.OpenLSAPolicy(It.IsAny())).Returns(()=> { + Task.Delay(100).Wait(); + return NtStatus.StatusAccessDenied; + }); + mockProcessor.Setup(x => x.OpenLSAPolicy(It.IsAny())).Returns(mockLSAPolicy); + var processor = mockProcessor.Object; + var machineDomainSid = $"{Consts.MockDomainSid}-1001"; + var receivedStatus = new List(); + processor.ComputerStatusEvent += async status => { + receivedStatus.Add(status); + }; + var results = await processor.GetUserRightsAssignments("win10.testlab.local", machineDomainSid, "testlab.local", false) + .ToArrayAsync(); + + Assert.Empty(results); + Assert.Single(receivedStatus); + var status = receivedStatus[0]; + Assert.Equal("StatusAccessDenied", status.Status); + Assert.Equal("LSAGetMachineSID", status.Task); + } + + [WindowsOnlyFact] + public async Task UserRightsAssignmentProcessor_TestGetResolvedPrincipalsWithPrivilegeFail() + { + var mockProcessor = new Mock(new MockLdapUtils(), null); + var mockLSAPolicy = new MockFailLSAPolicy_GetResolvedPrincipalsWithPrivilege(); + mockProcessor.Setup(x => x.OpenLSAPolicy(It.IsAny())).Returns(mockLSAPolicy); + var processor = mockProcessor.Object; + var machineDomainSid = $"{Consts.MockDomainSid}-1001"; + var receivedStatus = new List(); + processor.ComputerStatusEvent += async status => { + receivedStatus.Add(status); + }; + var results = await processor.GetUserRightsAssignments("win10.testlab.local", machineDomainSid, "testlab.local", false) + .ToArrayAsync(); + + Assert.Single(results); + + var result = results[0]; + Assert.False(result.Collected); + Assert.Equal("LSAEnumerateAccountsWithUserRights returned StatusAccessDenied", result.FailureReason); + Assert.Single(receivedStatus); + var status = receivedStatus[0]; + Assert.Equal("StatusAccessDenied", status.Status); + Assert.Equal("LSAEnumerateAccountsWithUserRight", status.Task); + } + } } \ No newline at end of file From 0609651eda62f35608c83a537a1bf7221800f535 Mon Sep 17 00:00:00 2001 From: Emmanuel Date: Tue, 16 Dec 2025 16:43:44 -0500 Subject: [PATCH 6/7] made some test the were using cache run in sequence so they dont step on eachother --- .../CacheTestsCollectionDefinition.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) rename test/unit/{CollectionDefinitons => CollectionDefinitions}/CacheTestsCollectionDefinition.cs (97%) diff --git a/test/unit/CollectionDefinitons/CacheTestsCollectionDefinition.cs b/test/unit/CollectionDefinitions/CacheTestsCollectionDefinition.cs similarity index 97% rename from test/unit/CollectionDefinitons/CacheTestsCollectionDefinition.cs rename to test/unit/CollectionDefinitions/CacheTestsCollectionDefinition.cs index b2397c100..0559bba47 100644 --- a/test/unit/CollectionDefinitons/CacheTestsCollectionDefinition.cs +++ b/test/unit/CollectionDefinitions/CacheTestsCollectionDefinition.cs @@ -1,9 +1,9 @@ -using Xunit; - -namespace CommonLibTest.CollectionDefinitons; - -/// -/// Test that use cache cannot run in parallel, they can have flaky behavior -/// -[CollectionDefinition(nameof(CacheTestCollectionDefinition), DisableParallelization = true)] -public class CacheTestCollectionDefinition{} +using Xunit; + +namespace CommonLibTest.CollectionDefinitons; + +/// +/// Test that use cache cannot run in parallel, they can have flaky behavior +/// +[CollectionDefinition(nameof(CacheTestCollectionDefinition), DisableParallelization = true)] +public class CacheTestCollectionDefinition{} From ca20c6ca82da3701776099abb61b08f507e497c9 Mon Sep 17 00:00:00 2001 From: Emmanuel Date: Wed, 17 Dec 2025 13:24:01 -0500 Subject: [PATCH 7/7] cleanup the UT a bit --- .../CacheTestsCollectionDefinition.cs | 18 +++++++++--------- test/unit/CommonLibTests.cs | 2 +- test/unit/UserRightsAssignmentProcessorTest.cs | 5 +++-- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/test/unit/CollectionDefinitions/CacheTestsCollectionDefinition.cs b/test/unit/CollectionDefinitions/CacheTestsCollectionDefinition.cs index 0559bba47..c03cbc593 100644 --- a/test/unit/CollectionDefinitions/CacheTestsCollectionDefinition.cs +++ b/test/unit/CollectionDefinitions/CacheTestsCollectionDefinition.cs @@ -1,9 +1,9 @@ -using Xunit; - -namespace CommonLibTest.CollectionDefinitons; - -/// -/// Test that use cache cannot run in parallel, they can have flaky behavior -/// -[CollectionDefinition(nameof(CacheTestCollectionDefinition), DisableParallelization = true)] -public class CacheTestCollectionDefinition{} +using Xunit; + +namespace CommonLibTest.CollectionDefinitions; + +/// +/// Test that use cache cannot run in parallel, they can have flaky behavior +/// +[CollectionDefinition(nameof(CacheTestCollectionDefinition), DisableParallelization = true)] +public class CacheTestCollectionDefinition{} diff --git a/test/unit/CommonLibTests.cs b/test/unit/CommonLibTests.cs index 788e08254..8f1f595e0 100644 --- a/test/unit/CommonLibTests.cs +++ b/test/unit/CommonLibTests.cs @@ -1,6 +1,6 @@ using System; using System.Reflection; -using CommonLibTest.CollectionDefinitons; +using CommonLibTest.CollectionDefinitions; using Microsoft.Extensions.Logging; using Moq; using SharpHoundCommonLib; diff --git a/test/unit/UserRightsAssignmentProcessorTest.cs b/test/unit/UserRightsAssignmentProcessorTest.cs index 70b7421b7..14fbc9f8c 100644 --- a/test/unit/UserRightsAssignmentProcessorTest.cs +++ b/test/unit/UserRightsAssignmentProcessorTest.cs @@ -1,8 +1,9 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Threading; using System.Threading.Tasks; -using CommonLibTest.CollectionDefinitons; +using CommonLibTest.CollectionDefinitions; using CommonLibTest.Facades; using CommonLibTest.Facades.LSAMocks.DCMocks; using CommonLibTest.Facades.LSAMocks.WorkstationMocks; @@ -26,7 +27,7 @@ public UserRightsAssignmentProcessorTest(ITestOutputHelper testOutputHelper) { _testOutputHelper = testOutputHelper; - // reseting cache for tests + //reseting cache Cache.SetCacheInstance(null); }