using qdr.fnd.core.pqueue.Enums; using qdr.fnd.core.pqueue.Exceptions; using qdr.fnd.core.pqueue.Storages; using qdr.fnd.core.pqueue.test.Mocks; using Quadarax.Foundation.Core.Data; using Quadarax.Foundation.Core.Thread; using Quadarax.Foundation.Core.Value.Extensions; using Quadarax.Foundation.Core.Value.Generators; namespace qdr.fnd.core.pqueue.test.Storages { public class MemoryStorageProviderTest { private LoggerMock _logger; private string _owner = "owner"; private string _ownerRef = "ownerRef"; private string _providerClass = "providerClass"; private int _initialAttempts = 10; private DateTime _created = DateTime.Now; [SetUp] public void Setup() { _logger = new LoggerMock(); } [Test(TestOf=typeof(MemoryStorageProvider))] public void ConstructorOk() { var provider = new MemoryStorageProvider(_logger); } [Test(TestOf=typeof(MemoryStorageProvider))] public void CreateItemOk() { var provider = new MemoryStorageProvider(_logger); var itemId = provider.CreateItem(_owner, _ownerRef, _providerClass, _initialAttempts, _created); Assert.That(string.IsNullOrEmpty(itemId), Is.False); } [Test(TestOf=typeof(MemoryStorageProvider))] public void ContainsItemOk() { var provider = new MemoryStorageProvider(_logger); var itemId = provider.CreateItem(_owner, _ownerRef, _providerClass, _initialAttempts, _created); Assert.That(provider.ContainsItem(itemId), Is.True); Assert.That(provider.ContainsItem("not-exist"), Is.False); } [Test(TestOf=typeof(MemoryStorageProvider))] public void DeleteItemOk() { var provider = new MemoryStorageProvider(_logger); var itemId = provider.CreateItem(_owner, _ownerRef, _providerClass, _initialAttempts, _created); provider.DeleteItem(itemId); Assert.That(provider.ContainsItem(itemId), Is.False); } [Test(TestOf = typeof(MemoryStorageProvider))] public void DeleteItemFail() { var provider = new MemoryStorageProvider(_logger); var itemId = provider.CreateItem(_owner, _ownerRef, _providerClass, _initialAttempts, _created); provider.DeleteItem(itemId); Assert.Throws(() => provider.DeleteItem(string.Empty)); var psEx = Assert.Throws(() => provider.DeleteItem(itemId)); Assert.That(psEx, Is.Not.Null); Assert.That(psEx.Code, Is.EqualTo(PSStorageException.ErrorCodes.PsStorageItemNotFound)); } [Test(TestOf=typeof(MemoryStorageProvider))] public void UpdateItemPriorityOk() { var provider = new MemoryStorageProvider(_logger); var itemId = provider.CreateItem(_owner, _ownerRef, _providerClass, _initialAttempts, _created); var priority = 99; var item = provider.GetItem(itemId); Assert.That(item.Priority, Is.Not.EqualTo(priority)); provider.UpdateItemPriority(itemId, priority); item = provider.GetItem(itemId); Assert.That(item.Priority, Is.EqualTo(priority)); } [Test(TestOf = typeof(MemoryStorageProvider))] public void UpdateItemPriorityFail() { var provider = new MemoryStorageProvider(_logger); Assert.Throws(() => provider.UpdateItemPriority(string.Empty,0)); var psEx = Assert.Throws(() => provider.DeleteItem("not-exists")); Assert.That(psEx, Is.Not.Null); Assert.That(psEx.Code, Is.EqualTo(PSStorageException.ErrorCodes.PsStorageItemNotFound)); } [Test(TestOf=typeof(MemoryStorageProvider))] public void UpdateItemValidityOk() { var provider = new MemoryStorageProvider(_logger); var itemId = provider.CreateItem(_owner, _ownerRef, _providerClass, _initialAttempts, _created); var validFrom = DateTime.Now; var validTo = validFrom.AddHours(1); var item = provider.GetItem(itemId); Assert.That(item.ValidFrom, Is.Not.EqualTo(validFrom)); Assert.That(item.ValidTo, Is.Not.EqualTo(validTo)); provider.UpdateItemValidity(itemId, validFrom, validTo); item = provider.GetItem(itemId); Assert.That(item.ValidFrom, Is.EqualTo(validFrom)); Assert.That(item.ValidTo, Is.EqualTo(validTo)); provider.UpdateItemValidity(itemId, validFrom, null); Assert.That(item.ValidTo, Is.Null); } [Test(TestOf = typeof(MemoryStorageProvider))] public void UpdateItemValidityFail() { var provider = new MemoryStorageProvider(_logger); Assert.Throws(() => provider.UpdateItemValidity(string.Empty,DateTime.Now, DateTime.Now)); var psEx = Assert.Throws(() => provider.UpdateItemValidity("not-exists",DateTime.Now, DateTime.Now)); Assert.That(psEx, Is.Not.Null); Assert.That(psEx.Code, Is.EqualTo(PSStorageException.ErrorCodes.PsStorageItemNotFound)); } [Test(TestOf = typeof(MemoryStorageProvider))] public void GetItemFail() { var provider = new MemoryStorageProvider(_logger); Assert.Throws(() => provider.GetItem(string.Empty)); var psEx = Assert.Throws(() => provider.GetItem("not-exists")); Assert.That(psEx, Is.Not.Null); Assert.That(psEx.Code, Is.EqualTo(PSStorageException.ErrorCodes.PsStorageItemNotFound)); } [Test(TestOf=typeof(MemoryStorageProvider))] public void UpdateItemStatusOk() { var provider = new MemoryStorageProvider(_logger); var itemId = provider.CreateItem(_owner, _ownerRef, _providerClass, _initialAttempts, _created); var status = PsStatusEnum.DoneOk; var transient = true; var item = provider.GetItem(itemId); Assert.That(item.Status, Is.Not.EqualTo(status)); Assert.That(item.IsStatusTransient, Is.Not.EqualTo(transient)); provider.UpdateItemStatus(itemId, status, transient); item = provider.GetItem(itemId); Assert.That(item.Status, Is.EqualTo(status)); Assert.That(item.IsStatusTransient, Is.EqualTo(transient)); provider.UpdateItemStatus(itemId, null, !transient); item = provider.GetItem(itemId); Assert.That(item.Status, Is.EqualTo(status)); Assert.That(item.IsStatusTransient, Is.EqualTo(!transient)); } [Test(TestOf = typeof(MemoryStorageProvider))] public void UpdateItemStatusFail() { var provider = new MemoryStorageProvider(_logger); Assert.Throws(() => provider.UpdateItemStatus(string.Empty,null, true)); var psEx = Assert.Throws(() => provider.UpdateItemStatus("not-exists",null, true)); Assert.That(psEx, Is.Not.Null); Assert.That(psEx.Code, Is.EqualTo(PSStorageException.ErrorCodes.PsStorageItemNotFound)); } [Test(TestOf=typeof(MemoryStorageProvider))] public void UpdateItemStartedOk() { var provider = new MemoryStorageProvider(_logger); var itemId = provider.CreateItem(_owner, _ownerRef, _providerClass, _initialAttempts, _created); var started = DateTime.Now; var item = provider.GetItem(itemId); Assert.That(item.Started, Is.Not.EqualTo(started)); provider.UpdateItemStarted(itemId, started); item = provider.GetItem(itemId); Assert.That(item.Started, Is.EqualTo(started)); provider.UpdateItemStarted(itemId, null); item = provider.GetItem(itemId); Assert.That(item.Started, Is.Null); } [Test(TestOf = typeof(MemoryStorageProvider))] public void UpdateItemStartedFail() { var provider = new MemoryStorageProvider(_logger); Assert.Throws(() => provider.UpdateItemStarted(string.Empty,null)); var psEx = Assert.Throws(() => provider.UpdateItemStarted("not-exists",null)); Assert.That(psEx, Is.Not.Null); Assert.That(psEx.Code, Is.EqualTo(PSStorageException.ErrorCodes.PsStorageItemNotFound)); } [Test(TestOf=typeof(MemoryStorageProvider))] public void UpdateItemFinishedOk() { var provider = new MemoryStorageProvider(_logger); var itemId = provider.CreateItem(_owner, _ownerRef, _providerClass, _initialAttempts, _created); var finished = DateTime.Now; var item = provider.GetItem(itemId); Assert.That(item.Finished, Is.Not.EqualTo(finished)); provider.UpdateItemFinished(itemId, finished); item = provider.GetItem(itemId); Assert.That(item.Finished, Is.EqualTo(finished)); provider.UpdateItemFinished(itemId, null); item = provider.GetItem(itemId); Assert.That(item.Finished, Is.Null); } [Test(TestOf = typeof(MemoryStorageProvider))] public void UpdateItemFinishedFail() { var provider = new MemoryStorageProvider(_logger); Assert.Throws(() => provider.UpdateItemFinished(string.Empty,null)); var psEx = Assert.Throws(() => provider.UpdateItemFinished("not-exists",null)); Assert.That(psEx, Is.Not.Null); Assert.That(psEx.Code, Is.EqualTo(PSStorageException.ErrorCodes.PsStorageItemNotFound)); } [Test(TestOf=typeof(MemoryStorageProvider))] public void CreateItemAttributeOk() { var provider = new MemoryStorageProvider(_logger); var typeClass = "System.String"; var value = "valueXXX"; var itemId = provider.CreateItem(_owner, _ownerRef, _providerClass, _initialAttempts, _created); var item = provider.GetItem(itemId); Assert.That(item.Arguments.Count(), Is.EqualTo(0)); provider.CreateItemAttribute(itemId, _owner, value,typeClass,true); item = provider.GetItem(itemId); Assert.That(item.Arguments.FirstOrDefault(x=>x.Name == _owner), Is.Not.Null); var attr = item.Arguments.First(x=>x.Name == _owner); Assert.That(attr.ValueType.FullName, Is.EqualTo(Type.GetType(typeClass)?.FullName)); Assert.That(attr.IsOutput, Is.EqualTo(true)); } [Test(TestOf = typeof(MemoryStorageProvider))] public void CreateItemAttributeFail() { var provider = new MemoryStorageProvider(_logger); var typeClass = "System.String"; var value = "valueXXX"; Assert.Throws(() => provider.CreateItemAttribute(string.Empty,_owner,typeClass, value, true)); var psEx = Assert.Throws(() => provider.CreateItemAttribute("non=exists",_owner,typeClass, value, true)); Assert.That(psEx, Is.Not.Null); Assert.That(psEx.Code, Is.EqualTo(PSStorageException.ErrorCodes.PsStorageItemNotFound)); var itemId = provider.CreateItem(_owner, _ownerRef, _providerClass, _initialAttempts, _created); provider.CreateItemAttribute(itemId, _owner, value,typeClass,true); psEx = Assert.Throws(() => provider.CreateItemAttribute(itemId,_owner,typeClass, value, true)); Assert.That(psEx, Is.Not.Null); Assert.That(psEx.Code, Is.EqualTo(PSStorageException.ErrorCodes.PsStorageItemArgumentAlreadyExists)); Assert.Throws(() => provider.CreateItemAttribute(itemId,string.Empty,typeClass, value, true)); Assert.Throws(() => provider.CreateItemAttribute(itemId, null!, typeClass, value, true)); Assert.Throws(() => provider.CreateItemAttribute(itemId,"non-exists",string.Empty, value, true)); Assert.Throws(() => provider.CreateItemAttribute(itemId, "non-exists", null!, value, true)); } [Test(TestOf=typeof(MemoryStorageProvider))] public void UpdateItemAttributeOk() { var provider = new MemoryStorageProvider(_logger); var typeClass = "System.String"; var value = "valueXXX"; var itemId = provider.CreateItem(_owner, _ownerRef, _providerClass, _initialAttempts, _created); var item = provider.GetItem(itemId); Assert.That(item.Arguments.Count(), Is.EqualTo(0)); provider.CreateItemAttribute(itemId, _owner, value,typeClass,true); item = provider.GetItem(itemId); var attr = item.Arguments.FirstOrDefault(x=>x.Name == _owner); Assert.That(attr, Is.Not.Null); provider.UpdateItemAttribute(itemId, _owner, value + "1"); item = provider.GetItem(itemId); attr = item.Arguments.FirstOrDefault(x=>x.Name == _owner); Assert.That(attr, Is.Not.Null); Assert.That(attr.Value, Is.EqualTo(value + "1")); } [Test(TestOf = typeof(MemoryStorageProvider))] public void UpdateItemAttributeFail() { var provider = new MemoryStorageProvider(_logger); var typeClass = "System.String"; var itemId = provider.CreateItem(_owner, _ownerRef, _providerClass, _initialAttempts, _created); var psEx = Assert.Throws(() => provider.UpdateItemAttribute(itemId,_owner,typeClass)); Assert.That(psEx, Is.Not.Null); Assert.That(psEx.Code, Is.EqualTo(PSStorageException.ErrorCodes.PsStorageItemArgumentNotFound)); Assert.Throws(() => provider.UpdateItemAttribute(itemId,string.Empty,typeClass)); Assert.Throws(() => provider.UpdateItemAttribute(itemId, null!, typeClass)); } [Test(TestOf=typeof(MemoryStorageProvider))] public void DeleteItemAttributeOk() { var provider = new MemoryStorageProvider(_logger); var typeClass = "System.String"; var value = "valueXXX"; var itemId = provider.CreateItem(_owner, _ownerRef, _providerClass, _initialAttempts, _created); var item = provider.GetItem(itemId); Assert.That(item.Arguments.Count(), Is.EqualTo(0)); provider.CreateItemAttribute(itemId, _owner, value,typeClass,true); item = provider.GetItem(itemId); var attr = item.Arguments.FirstOrDefault(x=>x.Name == _owner); Assert.That(attr, Is.Not.Null); provider.DeleteItemAttribute(itemId, _owner); item = provider.GetItem(itemId); Assert.That(item.Arguments.Count(), Is.EqualTo(0)); } [Test(TestOf = typeof(MemoryStorageProvider))] public void DeleteItemAttributeFail() { var provider = new MemoryStorageProvider(_logger); var itemId = provider.CreateItem(_owner, _ownerRef, _providerClass, _initialAttempts, _created); var psEx = Assert.Throws(() => provider.DeleteItemAttribute(itemId,_owner)); Assert.That(psEx, Is.Not.Null); Assert.That(psEx.Code, Is.EqualTo(PSStorageException.ErrorCodes.PsStorageItemArgumentNotFound)); Assert.Throws(() => provider.DeleteItemAttribute(itemId,string.Empty)); Assert.Throws(() => provider.DeleteItemAttribute(itemId, null!)); } [Test(TestOf=typeof(MemoryStorageProvider))] public void AppendLogOk() { var provider = new MemoryStorageProvider(_logger); var value = "valueXXX"; var code = -1; ErrorLevelEnum level = ErrorLevelEnum.Error; var itemId = provider.CreateItem(_owner, _ownerRef, _providerClass, _initialAttempts, _created); var item = provider.GetItem(itemId); Assert.That(item.Log.Count(), Is.EqualTo(0)); provider.AppendLog(itemId, value, code, level); item = provider.GetItem(itemId); var logItem = item.Log.FirstOrDefault(x=>x.Message == value); Assert.That(logItem, Is.Not.Null); Assert.That(logItem.Code, Is.EqualTo(code)); Assert.That(logItem.Level, Is.EqualTo(level)); } [Test(TestOf = typeof(MemoryStorageProvider))] public void AppendLogFail() { var provider = new MemoryStorageProvider(_logger); var itemId = provider.CreateItem(_owner, _ownerRef, _providerClass, _initialAttempts, _created); Assert.Throws(() => provider.AppendLog(itemId,string.Empty, 0,ErrorLevelEnum.Error)); Assert.Throws(() => provider.AppendLog(itemId,null!, 0,ErrorLevelEnum.Error)); } [Test(TestOf=typeof(MemoryStorageProvider))] public void AppendStatusJournalOk() { var provider = new MemoryStorageProvider(_logger); var value = "valueXXX"; PsStatusEnum status = PsStatusEnum.DoneOk; var isTransient = true; var itemId = provider.CreateItem(_owner, _ownerRef, _providerClass, _initialAttempts, _created); var item = provider.GetItem(itemId); Assert.That(item.StatusJournal.Count(), Is.EqualTo(0)); provider.AppendStatusJournal(itemId, status, isTransient, value); item = provider.GetItem(itemId); var journal = item.StatusJournal.FirstOrDefault(x=>x.Description == value); Assert.That(journal, Is.Not.Null); Assert.That(journal.PreviousStatus, Is.EqualTo(status)); Assert.That(journal.PreviousIsStatusTransient, Is.EqualTo(isTransient)); } [Test(TestOf = typeof(MemoryStorageProvider))] public void AppendStatusJournalFail() { var provider = new MemoryStorageProvider(_logger); var itemId = provider.CreateItem(_owner, _ownerRef, _providerClass, _initialAttempts, _created); // no further tests needed } [Test(TestOf=typeof(MemoryStorageProvider))] public void QueryOk() { var provider = new MemoryStorageProvider(_logger); var status1 = PsStatusEnum.DoneOk; var status2 = PsStatusEnum.DoneFailed; var itemId1 = provider.CreateItem(_owner+"1", _ownerRef+"1", _providerClass, _initialAttempts, _created); var itemId2 = provider.CreateItem(_owner+"2", _ownerRef+"2", _providerClass, _initialAttempts, _created); var itemId3 = provider.CreateItem(_owner+"2", _ownerRef+"3", _providerClass, _initialAttempts, _created); provider.UpdateItemStatus(itemId1, status1, true); provider.UpdateItemStatus(itemId2, status2, true); provider.UpdateItemStatus(itemId3, status2, false); var result = provider.Query(_owner+"1", null).ToList(); Assert.That(result.Count, Is.EqualTo(1)); result = provider.Query(_owner+"2", null).ToList(); Assert.That(result.Count, Is.EqualTo(2)); result = provider.Query(null, _ownerRef+"3").ToList(); Assert.That(result.Count, Is.EqualTo(1)); result = provider.Query(null, null, new Tuple(true,status1), new Tuple(true, status2)).ToList(); Assert.That(result.Count, Is.EqualTo(2)); } [Test(TestOf=typeof(MemoryStorageProvider))] public void DurabilityTest() { var provider = new MemoryStorageProvider(_logger); var moshpit = new MoshPit(new MoshPitContext(provider)); moshpit.AddAction((ctx) => { var itemId = ctx.Provider.CreateItem(ctx.HashGenerator.NewId(), ctx.HashGenerator.NewId(), ctx.HashGenerator.NewId(), 10, DateTime.Now); ctx.Provider.AppendLog(itemId, "log", 0, ErrorLevelEnum.Error); ctx.Provider.AppendStatusJournal(itemId, PsStatusEnum.DoneOk, true, "journal"); ctx.Identities.Add(itemId); }); moshpit.AddAction((ctx) => { if (ctx.Identities.Count==0) return; var itemId = ctx.Identities.GetRandom(); ctx.Identities.Remove(itemId); ctx.Provider.DeleteItem(itemId); }); moshpit.AddAction((ctx) => { if (ctx.Identities.Count==0) return; var itemId = ctx.Identities.GetRandom(); ctx.Identities.Remove(itemId); ctx.Provider.DeleteItem(itemId); }); moshpit.AddAction((ctx) => { if (ctx.Identities.Count==0) return; var itemId = ctx.Identities.GetRandom(); ctx.Provider.UpdateItemStatus(itemId, PsStatusEnum.DoneOk,false); }); moshpit.Start(100, 10000); TestContext.WriteLine($"Total duration: {moshpit.TotalDuration}"); TestContext.WriteLine($"Total iterations: {moshpit.Iterations}"); TestContext.WriteLine($"AVG iteration duration: {moshpit.AvgIterationDuration}"); TestContext.WriteLine($"AVG iterations per second: {moshpit.AvgIterationPerSecond}"); } private class MoshPitContext { public MemoryStorageProvider Provider { get;} public List Identities { get; } public TinyHash HashGenerator { get; } public MoshPitContext(MemoryStorageProvider provider) { Provider = provider; Identities = new List(); HashGenerator = new TinyHash(5); } } } }