From e8ef0725f89678251070580254984c62e408047b Mon Sep 17 00:00:00 2001 From: Jordi Date: Wed, 7 Feb 2024 00:20:10 +0100 Subject: [PATCH 1/3] Should not attempt to read subscription usage while in a CI build --- CHANGELOG.md | 6 ++++++ .../CommercialLicense/EnvironmentReader.cs | 16 ++++++++++++++++ .../CommercialLicense/SubscriptionManager.cs | 7 +++++++ .../CommercialLicense/SubscriptionValidator.cs | 2 +- src/FakeXrmEasy.Core/FakeXrmEasy.Core.csproj | 2 +- .../CommercialLicense/FakeEnvironmentReader.cs | 6 ++++++ .../FakeXrmEasy.Core.Tests.csproj | 14 +++++++------- 7 files changed, 44 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 396ac433..3e09e217 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## [2.4.1] + +### Changed + +- Should not read subscription usage while in a CI build + ## [2.4.0] ## Added diff --git a/src/FakeXrmEasy.Core/CommercialLicense/EnvironmentReader.cs b/src/FakeXrmEasy.Core/CommercialLicense/EnvironmentReader.cs index a92c1d8b..e4adf5f6 100644 --- a/src/FakeXrmEasy.Core/CommercialLicense/EnvironmentReader.cs +++ b/src/FakeXrmEasy.Core/CommercialLicense/EnvironmentReader.cs @@ -5,13 +5,29 @@ namespace FakeXrmEasy.Core.CommercialLicense internal interface IEnvironmentReader { string GetEnvironmentVariable(string variableName); + bool IsRunningInContinuousIntegration(); } internal class EnvironmentReader: IEnvironmentReader { + /// + /// Gets the value of environment variable with name variableName + /// + /// + /// public string GetEnvironmentVariable(string variableName) { return Environment.GetEnvironmentVariable(variableName); } + + /// + /// Checks if the test run is running in a CI environment + /// + /// + public bool IsRunningInContinuousIntegration() + { + return "1".Equals(GetEnvironmentVariable("FAKE_XRM_EASY_CI")) + || "True".Equals(GetEnvironmentVariable("TF_BUILD")); + } } } \ No newline at end of file diff --git a/src/FakeXrmEasy.Core/CommercialLicense/SubscriptionManager.cs b/src/FakeXrmEasy.Core/CommercialLicense/SubscriptionManager.cs index 00a9a9a2..bdd30109 100644 --- a/src/FakeXrmEasy.Core/CommercialLicense/SubscriptionManager.cs +++ b/src/FakeXrmEasy.Core/CommercialLicense/SubscriptionManager.cs @@ -41,6 +41,13 @@ internal static void SetSubscriptionStorageProvider(ISubscriptionStorageProvider { if (_subscriptionUsage == null) { + var environmentReader = new EnvironmentReader(); + if (environmentReader.IsRunningInContinuousIntegration()) + { + _subscriptionUsage = new SubscriptionUsage(); + return; + } + _upgradeRequested = upgradeRequested; _renewalRequested = renewalRequested; diff --git a/src/FakeXrmEasy.Core/CommercialLicense/SubscriptionValidator.cs b/src/FakeXrmEasy.Core/CommercialLicense/SubscriptionValidator.cs index 220c97a4..5beb0cd9 100644 --- a/src/FakeXrmEasy.Core/CommercialLicense/SubscriptionValidator.cs +++ b/src/FakeXrmEasy.Core/CommercialLicense/SubscriptionValidator.cs @@ -88,7 +88,7 @@ internal bool IsSubscriptionPlanValid() internal bool IsUsageValid() { - if (IsRunningInContinuousIntegration()) + if (_environmentReader.IsRunningInContinuousIntegration()) { return true; } diff --git a/src/FakeXrmEasy.Core/FakeXrmEasy.Core.csproj b/src/FakeXrmEasy.Core/FakeXrmEasy.Core.csproj index bee0b7c2..0980fd0b 100644 --- a/src/FakeXrmEasy.Core/FakeXrmEasy.Core.csproj +++ b/src/FakeXrmEasy.Core/FakeXrmEasy.Core.csproj @@ -8,7 +8,7 @@ net452 net452 FakeXrmEasy.Core - 2.4.0 + 2.4.1 Jordi Montaña Dynamics Value FakeXrmEasy Core diff --git a/tests/FakeXrmEasy.Core.Tests/CommercialLicense/FakeEnvironmentReader.cs b/tests/FakeXrmEasy.Core.Tests/CommercialLicense/FakeEnvironmentReader.cs index 6daaa53e..a645d77d 100644 --- a/tests/FakeXrmEasy.Core.Tests/CommercialLicense/FakeEnvironmentReader.cs +++ b/tests/FakeXrmEasy.Core.Tests/CommercialLicense/FakeEnvironmentReader.cs @@ -24,6 +24,12 @@ public string GetEnvironmentVariable(string variableName) return variableValue; } + public bool IsRunningInContinuousIntegration() + { + return "1".Equals(GetEnvironmentVariable("FAKE_XRM_EASY_CI")) + || "True".Equals(GetEnvironmentVariable("TF_BUILD")); + } + public void SetEnvironmentVariable(string variableName, string variableValue) { _variables.AddOrUpdate(variableName, variableValue, (key, oldValue) => variableValue); diff --git a/tests/FakeXrmEasy.Core.Tests/FakeXrmEasy.Core.Tests.csproj b/tests/FakeXrmEasy.Core.Tests/FakeXrmEasy.Core.Tests.csproj index 53170db7..579ccb29 100644 --- a/tests/FakeXrmEasy.Core.Tests/FakeXrmEasy.Core.Tests.csproj +++ b/tests/FakeXrmEasy.Core.Tests/FakeXrmEasy.Core.Tests.csproj @@ -11,7 +11,7 @@ true FakeXrmEasy.CoreTests - 2.4.0 + 2.4.1 Jordi Montaña Dynamics Value S.L. Internal Unit test suite for FakeXrmEasy.Core package @@ -137,22 +137,22 @@ - + - + - + - + - + - + From 47172f12c42035cfe6b91da8e8c67ac94176c584 Mon Sep 17 00:00:00 2001 From: Jordi Date: Wed, 7 Feb 2024 19:37:51 +0100 Subject: [PATCH 2/3] Major refactor of the SubscriptionManager class. Do not read usage while in CI. --- .../CommercialLicense/SubscriptionManager.cs | 107 +++++++++++++----- .../Middleware/MiddlewareBuilder.cs | 15 +-- .../FakeSubscriptionStorageProvider.cs | 23 ++++ .../SubscriptionManagerTests.cs | 36 +++++- .../Middleware/MiddlewareBuilderTests.cs | 15 ++- 5 files changed, 156 insertions(+), 40 deletions(-) create mode 100644 tests/FakeXrmEasy.Core.Tests/CommercialLicense/FakeSubscriptionStorageProvider.cs diff --git a/src/FakeXrmEasy.Core/CommercialLicense/SubscriptionManager.cs b/src/FakeXrmEasy.Core/CommercialLicense/SubscriptionManager.cs index bdd30109..00f475e2 100644 --- a/src/FakeXrmEasy.Core/CommercialLicense/SubscriptionManager.cs +++ b/src/FakeXrmEasy.Core/CommercialLicense/SubscriptionManager.cs @@ -7,53 +7,102 @@ namespace FakeXrmEasy.Core.CommercialLicense { - internal static class SubscriptionManager + internal class SubscriptionManager { - internal static ISubscriptionInfo _subscriptionInfo; - internal static readonly object _subscriptionInfoLock = new object(); - - internal static ISubscriptionUsage _subscriptionUsage; - internal static readonly object _subscriptionUsageLock = new object(); + internal ISubscriptionInfo _subscriptionInfo; + internal ISubscriptionUsage _subscriptionUsage; + internal readonly SubscriptionUsageManager _subscriptionUsageManager; + + private bool _renewalRequested = false; + private bool _upgradeRequested = false; - internal static bool _renewalRequested = false; - internal static bool _upgradeRequested = false; + private static readonly object _subscriptionManagerLock = new object(); + private static SubscriptionManager _instance = null; + private readonly IEnvironmentReader _environmentReader; + internal SubscriptionManager(IEnvironmentReader environmentReader, + ISubscriptionInfo subscriptionInfo, + ISubscriptionUsage subscriptionUsage, + SubscriptionUsageManager subscriptionUsageManager) + { + _environmentReader = environmentReader; + _subscriptionInfo = subscriptionInfo; + _subscriptionUsage = subscriptionUsage; + _subscriptionUsageManager = subscriptionUsageManager; + } - private static void SetLicenseKey(string licenseKey) + internal static SubscriptionManager Instance { - lock (_subscriptionInfoLock) + get { - if (_subscriptionInfo == null) + lock (_subscriptionManagerLock) { - var subscriptionPlanManager = new SubscriptionPlanManager(); - _subscriptionInfo = subscriptionPlanManager.GetSubscriptionInfoFromKey(licenseKey); + if (_instance == null) + { + _instance = new SubscriptionManager( + new EnvironmentReader(), + null, + null, + new SubscriptionUsageManager()); + } } + + return _instance; } } + + /// + /// For testing + /// + /// + internal static void SetFakeInstance(SubscriptionManager instance) + { + _instance = instance; + } - internal static void SetSubscriptionStorageProvider(ISubscriptionStorageProvider subscriptionStorageProvider, + internal ISubscriptionInfo SubscriptionInfo => _subscriptionInfo; + internal ISubscriptionUsage SubscriptionUsage => _subscriptionUsage; + internal bool RenewalRequested => _renewalRequested; + + internal void SetLicenseKey(string licenseKey) + { + if (_subscriptionInfo == null) + { + var subscriptionPlanManager = new SubscriptionPlanManager(); + _subscriptionInfo = subscriptionPlanManager.GetSubscriptionInfoFromKey(licenseKey); + } + } + + internal void SetSubscriptionStorageProvider_Internal(ISubscriptionStorageProvider subscriptionStorageProvider, IUserReader userReader, bool upgradeRequested, bool renewalRequested) + { SetLicenseKey(subscriptionStorageProvider.GetLicenseKey()); - - lock (_subscriptionUsageLock) + if (_subscriptionUsage == null) { - if (_subscriptionUsage == null) + if (_environmentReader.IsRunningInContinuousIntegration()) { - var environmentReader = new EnvironmentReader(); - if (environmentReader.IsRunningInContinuousIntegration()) - { - _subscriptionUsage = new SubscriptionUsage(); - return; - } - - _upgradeRequested = upgradeRequested; - _renewalRequested = renewalRequested; - - var usageManager = new SubscriptionUsageManager(); - _subscriptionUsage = usageManager.ReadAndUpdateUsage(_subscriptionInfo, subscriptionStorageProvider, userReader, _upgradeRequested); + _subscriptionUsage = new SubscriptionUsage(); + return; } + + _upgradeRequested = upgradeRequested; + _renewalRequested = renewalRequested; + + _subscriptionUsage = _subscriptionUsageManager.ReadAndUpdateUsage(_subscriptionInfo, subscriptionStorageProvider, userReader, _upgradeRequested); + } + } + internal void SetSubscriptionStorageProvider(ISubscriptionStorageProvider subscriptionStorageProvider, + IUserReader userReader, + bool upgradeRequested, + bool renewalRequested) + { + lock (_subscriptionManagerLock) + { + SetLicenseKey(subscriptionStorageProvider.GetLicenseKey()); + SetSubscriptionStorageProvider_Internal(subscriptionStorageProvider, userReader, upgradeRequested, + renewalRequested); } } } diff --git a/src/FakeXrmEasy.Core/Middleware/MiddlewareBuilder.cs b/src/FakeXrmEasy.Core/Middleware/MiddlewareBuilder.cs index 73246553..2648dba8 100644 --- a/src/FakeXrmEasy.Core/Middleware/MiddlewareBuilder.cs +++ b/src/FakeXrmEasy.Core/Middleware/MiddlewareBuilder.cs @@ -91,14 +91,14 @@ public IXrmFakedContext Build() if (_context.LicenseContext == FakeXrmEasyLicense.Commercial) { - var subscriptionInfo = SubscriptionManager._subscriptionInfo; - if (subscriptionInfo != null) + var subscriptionManager = SubscriptionManager.Instance; + if (subscriptionManager.SubscriptionInfo != null) { var subscriptionValidator = new SubscriptionValidator( new EnvironmentReader(), - SubscriptionManager._subscriptionInfo, - SubscriptionManager._subscriptionUsage, - SubscriptionManager._renewalRequested); + subscriptionManager.SubscriptionInfo, + subscriptionManager.SubscriptionUsage, + subscriptionManager.RenewalRequested); subscriptionValidator.IsValid(); } @@ -146,8 +146,9 @@ public IMiddlewareBuilder SetSubscriptionStorageProvider(ISubscriptionStoragePro var userReader = new UserReader(); Console.WriteLine($"Setting Subscription Storage Provider..."); Console.WriteLine($" -> Running as '{userReader.GetCurrentUserName()}' ..."); - - SubscriptionManager.SetSubscriptionStorageProvider(storageProvider, userReader, upgradeRequested, renewalRequested); + + var subscriptionManagerInstance = SubscriptionManager.Instance; + subscriptionManagerInstance.SetSubscriptionStorageProvider(storageProvider, userReader, upgradeRequested, renewalRequested); Console.WriteLine($"Setting Subscription Storage Provider ok."); return this; diff --git a/tests/FakeXrmEasy.Core.Tests/CommercialLicense/FakeSubscriptionStorageProvider.cs b/tests/FakeXrmEasy.Core.Tests/CommercialLicense/FakeSubscriptionStorageProvider.cs new file mode 100644 index 00000000..422ec508 --- /dev/null +++ b/tests/FakeXrmEasy.Core.Tests/CommercialLicense/FakeSubscriptionStorageProvider.cs @@ -0,0 +1,23 @@ +using FakeXrmEasy.Abstractions.CommercialLicense; +using FakeXrmEasy.Core.CommercialLicense; + +namespace FakeXrmEasy.Core.Tests.CommercialLicense +{ + public class FakeSubscriptionStorageProvider: ISubscriptionStorageProvider + { + public string GetLicenseKey() + { + return "license-key"; + } + + public ISubscriptionUsage Read() + { + return new SubscriptionUsage(); + } + + public void Write(ISubscriptionUsage currentUsage) + { + //Do nothing + } + } +} \ No newline at end of file diff --git a/tests/FakeXrmEasy.Core.Tests/CommercialLicense/SubscriptionManagerTests.cs b/tests/FakeXrmEasy.Core.Tests/CommercialLicense/SubscriptionManagerTests.cs index 171e3eab..ffe73ca6 100644 --- a/tests/FakeXrmEasy.Core.Tests/CommercialLicense/SubscriptionManagerTests.cs +++ b/tests/FakeXrmEasy.Core.Tests/CommercialLicense/SubscriptionManagerTests.cs @@ -4,15 +4,49 @@ using FakeItEasy; using FakeXrmEasy.Abstractions.CommercialLicense; using FakeXrmEasy.Core.CommercialLicense; +using FakeXrmEasy.Core.CommercialLicense.Exceptions; using Xunit; namespace FakeXrmEasy.Core.Tests.CommercialLicense { public class SubscriptionManagerTests { + private SubscriptionManager _subscriptionManager; + private readonly FakeEnvironmentReader _environmentReader; + private readonly ISubscriptionInfo _subscriptionInfo; + private readonly ISubscriptionUsage _subscriptionUsage; + private readonly SubscriptionUsageManager _subscriptionUsageManager; + private readonly ISubscriptionStorageProvider _fakeSubscriptionStorageProvider; + public SubscriptionManagerTests() + { + _environmentReader = new FakeEnvironmentReader(); + _subscriptionUsageManager = new SubscriptionUsageManager(); + _fakeSubscriptionStorageProvider = A.Fake(); + } + [Fact] + public void Should_set_license_key_and_throw_exception_when_invalid() + { + _subscriptionManager = new SubscriptionManager(_environmentReader, null, null, _subscriptionUsageManager); + Assert.Throws(() => _subscriptionManager.SetLicenseKey("dummy")); + } - + [Fact] + public void Should_not_read_usage_when_running_in_CI() + { + var subscriptionInfo = new SubscriptionInfo() + { + NumberOfUsers = 1, + EndDate = DateTime.UtcNow.AddMonths(1) + }; + _environmentReader.SetEnvironmentVariable("FAKE_XRM_EASY_CI", "1"); + + _subscriptionManager = new SubscriptionManager(_environmentReader, subscriptionInfo, null, _subscriptionUsageManager); + _subscriptionManager.SetSubscriptionStorageProvider_Internal(_fakeSubscriptionStorageProvider, new UserReader(), false, false); + + Assert.NotNull(_subscriptionManager._subscriptionUsage); + A.CallTo(() => _fakeSubscriptionStorageProvider.Read()).MustNotHaveHappened(); + } diff --git a/tests/FakeXrmEasy.Core.Tests/Middleware/MiddlewareBuilderTests.cs b/tests/FakeXrmEasy.Core.Tests/Middleware/MiddlewareBuilderTests.cs index 2df5de5a..b9ed4ec0 100644 --- a/tests/FakeXrmEasy.Core.Tests/Middleware/MiddlewareBuilderTests.cs +++ b/tests/FakeXrmEasy.Core.Tests/Middleware/MiddlewareBuilderTests.cs @@ -11,6 +11,7 @@ using FakeXrmEasy.Abstractions.Exceptions; using FakeXrmEasy.Core.CommercialLicense; using FakeXrmEasy.Core.CommercialLicense.Exceptions; +using FakeXrmEasy.Core.Tests.CommercialLicense; namespace FakeXrmEasy.Core.Tests.Middleware { @@ -148,12 +149,20 @@ public void Should_throw_exception_when_building_without_a_license() [Fact] public void Should_not_throw_exception_when_using_commercial_license_with_custom_storage_and_valid_data() { - SubscriptionManager._subscriptionInfo = _subscriptionInfo; - SubscriptionManager._subscriptionUsage = _subscriptionUsage; - + var subscriptionManager = new SubscriptionManager(new FakeEnvironmentReader(), + new SubscriptionInfo() + { + NumberOfUsers = 1, + EndDate = DateTime.UtcNow.AddMonths(1) + }, null, + new SubscriptionUsageManager()); + + SubscriptionManager.SetFakeInstance(subscriptionManager); + var ctx = MiddlewareBuilder .New() .SetLicense(FakeXrmEasyLicense.Commercial) + .SetSubscriptionStorageProvider(new FakeSubscriptionStorageProvider()) .Build(); Assert.Equal(FakeXrmEasyLicense.Commercial, ctx.LicenseContext); From 2b1092eb57247e972f339a7bb8634474efbb096b Mon Sep 17 00:00:00 2001 From: Jordi Date: Wed, 7 Feb 2024 19:50:15 +0100 Subject: [PATCH 3/3] Fix code smells --- .../CommercialLicense/SubscriptionManager.cs | 4 +--- .../CommercialLicense/SubscriptionValidator.cs | 6 ------ .../CommercialLicense/SubscriptionManagerTests.cs | 2 -- 3 files changed, 1 insertion(+), 11 deletions(-) diff --git a/src/FakeXrmEasy.Core/CommercialLicense/SubscriptionManager.cs b/src/FakeXrmEasy.Core/CommercialLicense/SubscriptionManager.cs index 00f475e2..ddfcb4db 100644 --- a/src/FakeXrmEasy.Core/CommercialLicense/SubscriptionManager.cs +++ b/src/FakeXrmEasy.Core/CommercialLicense/SubscriptionManager.cs @@ -14,7 +14,6 @@ internal class SubscriptionManager internal readonly SubscriptionUsageManager _subscriptionUsageManager; private bool _renewalRequested = false; - private bool _upgradeRequested = false; private static readonly object _subscriptionManagerLock = new object(); private static SubscriptionManager _instance = null; @@ -87,10 +86,9 @@ internal void SetSubscriptionStorageProvider_Internal(ISubscriptionStorageProvid return; } - _upgradeRequested = upgradeRequested; _renewalRequested = renewalRequested; - _subscriptionUsage = _subscriptionUsageManager.ReadAndUpdateUsage(_subscriptionInfo, subscriptionStorageProvider, userReader, _upgradeRequested); + _subscriptionUsage = _subscriptionUsageManager.ReadAndUpdateUsage(_subscriptionInfo, subscriptionStorageProvider, userReader, upgradeRequested); } } internal void SetSubscriptionStorageProvider(ISubscriptionStorageProvider subscriptionStorageProvider, diff --git a/src/FakeXrmEasy.Core/CommercialLicense/SubscriptionValidator.cs b/src/FakeXrmEasy.Core/CommercialLicense/SubscriptionValidator.cs index 5beb0cd9..b4c13991 100644 --- a/src/FakeXrmEasy.Core/CommercialLicense/SubscriptionValidator.cs +++ b/src/FakeXrmEasy.Core/CommercialLicense/SubscriptionValidator.cs @@ -118,11 +118,5 @@ internal bool IsUsageValid() } return true; } - - private bool IsRunningInContinuousIntegration() - { - return "1".Equals(_environmentReader.GetEnvironmentVariable("FAKE_XRM_EASY_CI")) - || "True".Equals(_environmentReader.GetEnvironmentVariable("TF_BUILD")); - } } } \ No newline at end of file diff --git a/tests/FakeXrmEasy.Core.Tests/CommercialLicense/SubscriptionManagerTests.cs b/tests/FakeXrmEasy.Core.Tests/CommercialLicense/SubscriptionManagerTests.cs index ffe73ca6..4bed337d 100644 --- a/tests/FakeXrmEasy.Core.Tests/CommercialLicense/SubscriptionManagerTests.cs +++ b/tests/FakeXrmEasy.Core.Tests/CommercialLicense/SubscriptionManagerTests.cs @@ -13,8 +13,6 @@ public class SubscriptionManagerTests { private SubscriptionManager _subscriptionManager; private readonly FakeEnvironmentReader _environmentReader; - private readonly ISubscriptionInfo _subscriptionInfo; - private readonly ISubscriptionUsage _subscriptionUsage; private readonly SubscriptionUsageManager _subscriptionUsageManager; private readonly ISubscriptionStorageProvider _fakeSubscriptionStorageProvider; public SubscriptionManagerTests()