From 2b7040a3e8cd8e6529751c86b850bfda10e37c4e Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Tue, 11 Feb 2025 13:15:42 +0100 Subject: [PATCH 01/12] Speed up Read only storage --- src/Neo/NeoSystem.cs | 2 +- src/Neo/Persistence/ClonedCache.cs | 2 +- src/Neo/Persistence/DataCache.cs | 71 ++++++++++++++++++++---------- src/Neo/Persistence/StoreCache.cs | 4 +- 4 files changed, 52 insertions(+), 27 deletions(-) diff --git a/src/Neo/NeoSystem.cs b/src/Neo/NeoSystem.cs index e57f41dd9b..b509509e6d 100644 --- a/src/Neo/NeoSystem.cs +++ b/src/Neo/NeoSystem.cs @@ -83,7 +83,7 @@ public class NeoSystem : IDisposable /// /// It doesn't need to be disposed because the inside it is null. /// - public DataCache StoreView => new StoreCache(store); + public StoreCache StoreView => new(store); /// /// The memory pool of the . diff --git a/src/Neo/Persistence/ClonedCache.cs b/src/Neo/Persistence/ClonedCache.cs index 768d850165..0d642e12ef 100644 --- a/src/Neo/Persistence/ClonedCache.cs +++ b/src/Neo/Persistence/ClonedCache.cs @@ -20,7 +20,7 @@ class ClonedCache : DataCache { private readonly DataCache _innerCache; - public ClonedCache(DataCache innerCache) + public ClonedCache(DataCache innerCache) : base(innerCache.HasChangeSet) { _innerCache = innerCache; } diff --git a/src/Neo/Persistence/DataCache.cs b/src/Neo/Persistence/DataCache.cs index ef749de46d..1da5196e6a 100644 --- a/src/Neo/Persistence/DataCache.cs +++ b/src/Neo/Persistence/DataCache.cs @@ -48,7 +48,12 @@ public class Trackable(StorageKey key, StorageItem item, TrackState state) } private readonly Dictionary _dictionary = new(); - private readonly HashSet _changeSet = new(); + private readonly HashSet? _changeSet; + + /// + /// True if ChangeSet is enabled + /// + public bool HasChangeSet => _changeSet != null; /// /// Reads a specified entry from the cache. If the entry is not in the cache, it will be automatically loaded from the underlying storage. @@ -77,6 +82,16 @@ public StorageItem this[StorageKey key] } } + /// + /// Data cache constructor + /// + /// True if you want to follow the change set + protected DataCache(bool followChangeSet) + { + if (followChangeSet) + _changeSet = []; + } + /// /// Adds a new entry to the cache. /// @@ -102,7 +117,7 @@ public void Add(StorageKey key, StorageItem value) { _dictionary[key] = new Trackable(key, value, TrackState.Added); } - _changeSet.Add(key); + _changeSet?.Add(key); } } @@ -118,6 +133,11 @@ public void Add(StorageKey key, StorageItem value) /// public virtual void Commit() { + if (_changeSet is null) + { + throw new InvalidOperationException("DataCache was created without 'followChangeSet'"); + } + lock (_dictionary) { foreach (var key in _changeSet) @@ -143,6 +163,24 @@ public virtual void Commit() } } + /// + /// Gets the change set in the cache. + /// + /// The change set. + public IEnumerable GetChangeSet() + { + if (_changeSet is null) + { + throw new InvalidOperationException("DataCache was created without 'followChangeSet'"); + } + + lock (_dictionary) + { + foreach (var key in _changeSet) + yield return _dictionary[key]; + } + } + /// /// Creates a snapshot, which uses this instance as the underlying storage. /// @@ -175,12 +213,12 @@ public void Delete(StorageKey key) if (trackable.State == TrackState.Added) { trackable.State = TrackState.NotFound; - _changeSet.Remove(key); + _changeSet?.Remove(key); } else if (trackable.State != TrackState.NotFound) { trackable.State = TrackState.Deleted; - _changeSet.Add(key); + _changeSet?.Add(key); } } else @@ -188,7 +226,7 @@ public void Delete(StorageKey key) var item = TryGetInternal(key); if (item == null) return; _dictionary.Add(key, new Trackable(key, item, TrackState.Deleted)); - _changeSet.Add(key); + _changeSet?.Add(key); } } } @@ -267,19 +305,6 @@ public void Delete(StorageKey key) yield break; } - /// - /// Gets the change set in the cache. - /// - /// The change set. - public IEnumerable GetChangeSet() - { - lock (_dictionary) - { - foreach (StorageKey key in _changeSet) - yield return _dictionary[key]; - } - } - /// /// Determines whether the cache contains the specified entry. /// @@ -342,13 +367,13 @@ public bool Contains(StorageKey key) else { trackable.State = TrackState.Added; - _changeSet.Add(key); + _changeSet?.Add(key); } } else if (trackable.State == TrackState.None) { trackable.State = TrackState.Changed; - _changeSet.Add(key); + _changeSet?.Add(key); } } else @@ -364,7 +389,7 @@ public bool Contains(StorageKey key) trackable = new Trackable(key, item, TrackState.Changed); } _dictionary.Add(key, trackable); - _changeSet.Add(key); + _changeSet?.Add(key); } return trackable.Item; } @@ -397,7 +422,7 @@ public StorageItem GetOrAdd(StorageKey key, Func factory) else { trackable.State = TrackState.Added; - _changeSet.Add(key); + _changeSet?.Add(key); } } } @@ -407,7 +432,7 @@ public StorageItem GetOrAdd(StorageKey key, Func factory) if (item == null) { trackable = new Trackable(key, factory(), TrackState.Added); - _changeSet.Add(key); + _changeSet?.Add(key); } else { diff --git a/src/Neo/Persistence/StoreCache.cs b/src/Neo/Persistence/StoreCache.cs index f90c5afc48..fb2e7f343b 100644 --- a/src/Neo/Persistence/StoreCache.cs +++ b/src/Neo/Persistence/StoreCache.cs @@ -31,7 +31,7 @@ public class StoreCache : DataCache, IDisposable /// Initializes a new instance of the class. /// /// An to create a readonly cache. - public StoreCache(IStore store) + public StoreCache(IStore store) : base(false) { _store = store; } @@ -40,7 +40,7 @@ public StoreCache(IStore store) /// Initializes a new instance of the class. /// /// An to create a snapshot cache. - public StoreCache(IStoreSnapshot snapshot) + public StoreCache(IStoreSnapshot snapshot) : base(true) { _store = snapshot; _snapshot = snapshot; From ff6941340fe8bc52f00e51ecad551d7a2817a989 Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Tue, 11 Feb 2025 13:21:52 +0100 Subject: [PATCH 02/12] Add ut --- ...adOnlyStoreView.cs => UT_ReadOnlyStore.cs} | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) rename tests/Neo.UnitTests/Persistence/{UT_ReadOnlyStoreView.cs => UT_ReadOnlyStore.cs} (72%) diff --git a/tests/Neo.UnitTests/Persistence/UT_ReadOnlyStoreView.cs b/tests/Neo.UnitTests/Persistence/UT_ReadOnlyStore.cs similarity index 72% rename from tests/Neo.UnitTests/Persistence/UT_ReadOnlyStoreView.cs rename to tests/Neo.UnitTests/Persistence/UT_ReadOnlyStore.cs index 783368d7ef..f9a238b494 100644 --- a/tests/Neo.UnitTests/Persistence/UT_ReadOnlyStoreView.cs +++ b/tests/Neo.UnitTests/Persistence/UT_ReadOnlyStore.cs @@ -12,13 +12,31 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.Persistence; using Neo.SmartContract; +using System; using System.Collections.Generic; +using System.Linq; namespace Neo.UnitTests.Persistence { [TestClass] - public class UT_ReadOnlyStoreView + public class UT_ReadOnlyStore { + [TestMethod] + public void TestError() + { + var store = new MemoryStore(); + var snapshot = new StoreCache(store); + + Assert.ThrowsException(() => snapshot.GetChangeSet().ToArray()); + Assert.ThrowsException(snapshot.Commit); + + // No errors + + snapshot = new StoreCache(store.GetSnapshot()); + _ = snapshot.GetChangeSet().ToArray(); + snapshot.Commit(); + } + [TestMethod] public void TestReadOnlyStoreView() { From aaedc8bb0781f7f84e99facf6bc63c223895689d Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Tue, 11 Feb 2025 13:28:31 +0100 Subject: [PATCH 03/12] Fix ut --- src/Neo/Persistence/StoreCache.cs | 3 ++- tests/Neo.UnitTests/Persistence/UT_CloneCache.cs | 2 +- tests/Neo.UnitTests/Persistence/UT_DataCache.cs | 2 +- tests/Neo.UnitTests/Persistence/UT_MemoryStore.cs | 3 ++- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Neo/Persistence/StoreCache.cs b/src/Neo/Persistence/StoreCache.cs index fb2e7f343b..313cc8a460 100644 --- a/src/Neo/Persistence/StoreCache.cs +++ b/src/Neo/Persistence/StoreCache.cs @@ -31,7 +31,8 @@ public class StoreCache : DataCache, IDisposable /// Initializes a new instance of the class. /// /// An to create a readonly cache. - public StoreCache(IStore store) : base(false) + /// True if you want to follow the change set + public StoreCache(IStore store, bool followChangeSet = false) : base(followChangeSet) { _store = store; } diff --git a/tests/Neo.UnitTests/Persistence/UT_CloneCache.cs b/tests/Neo.UnitTests/Persistence/UT_CloneCache.cs index 8c75457b9b..2a48c3a8b7 100644 --- a/tests/Neo.UnitTests/Persistence/UT_CloneCache.cs +++ b/tests/Neo.UnitTests/Persistence/UT_CloneCache.cs @@ -40,7 +40,7 @@ public class UT_CloneCache [TestInitialize] public void Init() { - myDataCache = new(store); + myDataCache = new(store, true); clonedCache = new ClonedCache(myDataCache); } diff --git a/tests/Neo.UnitTests/Persistence/UT_DataCache.cs b/tests/Neo.UnitTests/Persistence/UT_DataCache.cs index abc888de44..307e6e90d5 100644 --- a/tests/Neo.UnitTests/Persistence/UT_DataCache.cs +++ b/tests/Neo.UnitTests/Persistence/UT_DataCache.cs @@ -41,7 +41,7 @@ public class UT_DataCache [TestInitialize] public void Initialize() { - myDataCache = new(store); + myDataCache = new(store, true); } [TestMethod] diff --git a/tests/Neo.UnitTests/Persistence/UT_MemoryStore.cs b/tests/Neo.UnitTests/Persistence/UT_MemoryStore.cs index 1f25fa6f3e..85f2fb08e8 100644 --- a/tests/Neo.UnitTests/Persistence/UT_MemoryStore.cs +++ b/tests/Neo.UnitTests/Persistence/UT_MemoryStore.cs @@ -13,6 +13,7 @@ using Neo.Extensions; using Neo.Persistence; using Neo.SmartContract; +using System; using System.Linq; using System.Text; @@ -83,7 +84,7 @@ public void NeoSystemStoreViewTest() var value = new StorageItem(Encoding.UTF8.GetBytes("testValue")); store.Add(key, value); - store.Commit(); + Assert.ThrowsException(store.Commit); var result = store.TryGet(key); // The StoreView is a readonly view of the store, here it will have value in the cache From f06cf0b1a7b8d064db73965f9c06521abe2da6e3 Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Tue, 11 Feb 2025 13:32:12 +0100 Subject: [PATCH 04/12] Format --- tests/Neo.UnitTests/Persistence/UT_ReadOnlyStore.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Neo.UnitTests/Persistence/UT_ReadOnlyStore.cs b/tests/Neo.UnitTests/Persistence/UT_ReadOnlyStore.cs index f9a238b494..ccbddd7974 100644 --- a/tests/Neo.UnitTests/Persistence/UT_ReadOnlyStore.cs +++ b/tests/Neo.UnitTests/Persistence/UT_ReadOnlyStore.cs @@ -1,6 +1,6 @@ // Copyright (C) 2015-2025 The Neo Project. // -// UT_ReadOnlyStoreView.cs file belongs to the neo project and is free +// UT_ReadOnlyStore.cs file belongs to the neo project and is free // software distributed under the MIT software license, see the // accompanying file LICENSE in the main directory of the // repository or http://www.opensource.org/licenses/mit-license.php From 10790c1e512043d4181fe6fe906c161a1c710fec Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Tue, 11 Feb 2025 13:45:18 +0100 Subject: [PATCH 05/12] Fix CloneCache --- src/Neo/Persistence/ClonedCache.cs | 2 +- tests/Neo.Plugins.RpcServer.Tests/UT_RpcServer.Wallet.cs | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Neo/Persistence/ClonedCache.cs b/src/Neo/Persistence/ClonedCache.cs index 0d642e12ef..beab36ec12 100644 --- a/src/Neo/Persistence/ClonedCache.cs +++ b/src/Neo/Persistence/ClonedCache.cs @@ -20,7 +20,7 @@ class ClonedCache : DataCache { private readonly DataCache _innerCache; - public ClonedCache(DataCache innerCache) : base(innerCache.HasChangeSet) + public ClonedCache(DataCache innerCache) : base(true) { _innerCache = innerCache; } diff --git a/tests/Neo.Plugins.RpcServer.Tests/UT_RpcServer.Wallet.cs b/tests/Neo.Plugins.RpcServer.Tests/UT_RpcServer.Wallet.cs index 4423c9a66e..a1a77916d6 100644 --- a/tests/Neo.Plugins.RpcServer.Tests/UT_RpcServer.Wallet.cs +++ b/tests/Neo.Plugins.RpcServer.Tests/UT_RpcServer.Wallet.cs @@ -13,7 +13,6 @@ using Neo.Extensions; using Neo.Json; using Neo.Network.P2P.Payloads; -using Neo.Persistence; using Neo.SmartContract; using Neo.SmartContract.Native; using Neo.UnitTests; @@ -342,7 +341,7 @@ public void TestListAddress_WhenWalletNotOpen() public void TestCancelTransaction() { TestUtilOpenWallet(); - var snapshot = _neoSystem.GetSnapshot(); + var snapshot = _neoSystem.GetSnapshotCache(); var tx = TestUtils.CreateValidTx(snapshot, _wallet, _walletAccount); snapshot.Commit(); var paramsArray = new JArray(tx.Hash.ToString(), new JArray(_walletAccount.Address)); From 911a79e26324a04b65f9bf8447719f9505c70f81 Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Thu, 13 Feb 2025 09:28:13 +0100 Subject: [PATCH 06/12] Rename --- src/Neo/Persistence/ClonedCache.cs | 2 +- src/Neo/Persistence/DataCache.cs | 10 +++++----- src/Neo/Persistence/StoreCache.cs | 6 +++--- tests/Neo.UnitTests/Persistence/UT_CloneCache.cs | 2 +- tests/Neo.UnitTests/Persistence/UT_DataCache.cs | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/Neo/Persistence/ClonedCache.cs b/src/Neo/Persistence/ClonedCache.cs index db61dbcf02..726c55bb98 100644 --- a/src/Neo/Persistence/ClonedCache.cs +++ b/src/Neo/Persistence/ClonedCache.cs @@ -20,7 +20,7 @@ class ClonedCache : DataCache { private readonly DataCache _innerCache; - public ClonedCache(DataCache innerCache) : base(true) + public ClonedCache(DataCache innerCache) : base(false) { _innerCache = innerCache; } diff --git a/src/Neo/Persistence/DataCache.cs b/src/Neo/Persistence/DataCache.cs index cf321b8a1f..57f8b5e42c 100644 --- a/src/Neo/Persistence/DataCache.cs +++ b/src/Neo/Persistence/DataCache.cs @@ -46,9 +46,9 @@ public class Trackable(StorageItem item, TrackState state) private readonly HashSet? _changeSet; /// - /// True if ChangeSet is enabled + /// True if DataCache is readOnly /// - public bool HasChangeSet => _changeSet != null; + public bool IsReadOnly => _changeSet == null; /// /// Reads a specified entry from the cache. If the entry is not in the cache, it will be automatically loaded from the underlying storage. @@ -80,10 +80,10 @@ public StorageItem this[StorageKey key] /// /// Data cache constructor /// - /// True if you want to follow the change set - protected DataCache(bool followChangeSet) + /// True if you don't want to allow writes + protected DataCache(bool readOnly) { - if (followChangeSet) + if (!readOnly) _changeSet = []; } diff --git a/src/Neo/Persistence/StoreCache.cs b/src/Neo/Persistence/StoreCache.cs index 1c1197a50f..6f1dc1628d 100644 --- a/src/Neo/Persistence/StoreCache.cs +++ b/src/Neo/Persistence/StoreCache.cs @@ -31,8 +31,8 @@ public class StoreCache : DataCache, IDisposable /// Initializes a new instance of the class. /// /// An to create a readonly cache. - /// True if you want to follow the change set - public StoreCache(IStore store, bool followChangeSet = false) : base(followChangeSet) + /// True if you don't want to allow writes + public StoreCache(IStore store, bool readOnly = true) : base(readOnly) { _store = store; } @@ -41,7 +41,7 @@ public StoreCache(IStore store, bool followChangeSet = false) : base(followChang /// Initializes a new instance of the class. /// /// An to create a snapshot cache. - public StoreCache(IStoreSnapshot snapshot) : base(true) + public StoreCache(IStoreSnapshot snapshot) : base(false) { _store = snapshot; _snapshot = snapshot; diff --git a/tests/Neo.UnitTests/Persistence/UT_CloneCache.cs b/tests/Neo.UnitTests/Persistence/UT_CloneCache.cs index 77f81b44f7..311557db5f 100644 --- a/tests/Neo.UnitTests/Persistence/UT_CloneCache.cs +++ b/tests/Neo.UnitTests/Persistence/UT_CloneCache.cs @@ -41,7 +41,7 @@ public class UT_CloneCache [TestInitialize] public void Init() { - myDataCache = new(store, true); + myDataCache = new(store, false); clonedCache = new ClonedCache(myDataCache); } diff --git a/tests/Neo.UnitTests/Persistence/UT_DataCache.cs b/tests/Neo.UnitTests/Persistence/UT_DataCache.cs index 57f096e871..058c3fbe74 100644 --- a/tests/Neo.UnitTests/Persistence/UT_DataCache.cs +++ b/tests/Neo.UnitTests/Persistence/UT_DataCache.cs @@ -42,7 +42,7 @@ public class UT_DataCache [TestInitialize] public void Initialize() { - myDataCache = new(store, true); + myDataCache = new(store, false); } [TestMethod] From 5eff62b2a5e68499a1c982210b24d48aff0f30ff Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Thu, 13 Feb 2025 09:29:14 +0100 Subject: [PATCH 07/12] change error message --- src/Neo/Persistence/DataCache.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Neo/Persistence/DataCache.cs b/src/Neo/Persistence/DataCache.cs index 57f8b5e42c..e3314810f3 100644 --- a/src/Neo/Persistence/DataCache.cs +++ b/src/Neo/Persistence/DataCache.cs @@ -130,7 +130,7 @@ public virtual void Commit() { if (_changeSet is null) { - throw new InvalidOperationException("DataCache was created without 'followChangeSet'"); + throw new InvalidOperationException("DataCache is read only"); } lock (_dictionary) @@ -166,7 +166,7 @@ public IEnumerable> GetChangeSet() { if (_changeSet is null) { - throw new InvalidOperationException("DataCache was created without 'followChangeSet'"); + throw new InvalidOperationException("DataCache is read only"); } lock (_dictionary) From 46f92c40763264b9745484046e8007a8613e57d7 Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Thu, 13 Feb 2025 16:06:04 +0100 Subject: [PATCH 08/12] Fix clone cache tests --- .../Persistence/UT_CloneCache.cs | 146 ++++++++++-------- 1 file changed, 78 insertions(+), 68 deletions(-) diff --git a/tests/Neo.UnitTests/Persistence/UT_CloneCache.cs b/tests/Neo.UnitTests/Persistence/UT_CloneCache.cs index 311557db5f..c317a040f2 100644 --- a/tests/Neo.UnitTests/Persistence/UT_CloneCache.cs +++ b/tests/Neo.UnitTests/Persistence/UT_CloneCache.cs @@ -24,121 +24,131 @@ namespace Neo.UnitTests.IO.Caching [TestClass] public class UT_CloneCache { - private readonly MemoryStore store = new(); - private StoreCache myDataCache; - private ClonedCache clonedCache; - - private static readonly StorageKey key1 = new() { Id = 0, Key = Encoding.UTF8.GetBytes("key1") }; - private static readonly StorageKey key2 = new() { Id = 0, Key = Encoding.UTF8.GetBytes("key2") }; - private static readonly StorageKey key3 = new() { Id = 0, Key = Encoding.UTF8.GetBytes("key3") }; - private static readonly StorageKey key4 = new() { Id = 0, Key = Encoding.UTF8.GetBytes("key4") }; - - private static readonly StorageItem value1 = new(Encoding.UTF8.GetBytes("value1")); - private static readonly StorageItem value2 = new(Encoding.UTF8.GetBytes("value2")); - private static readonly StorageItem value3 = new(Encoding.UTF8.GetBytes("value3")); - private static readonly StorageItem value4 = new(Encoding.UTF8.GetBytes("value4")); - - [TestInitialize] - public void Init() - { - myDataCache = new(store, false); - clonedCache = new ClonedCache(myDataCache); - } + private readonly MemoryStore _store = new(); + + private static readonly StorageKey s_key1 = new() { Id = 0, Key = Encoding.UTF8.GetBytes("key1") }; + private static readonly StorageKey s_key2 = new() { Id = 0, Key = Encoding.UTF8.GetBytes("key2") }; + private static readonly StorageKey s_key3 = new() { Id = 0, Key = Encoding.UTF8.GetBytes("key3") }; + private static readonly StorageKey s_key4 = new() { Id = 0, Key = Encoding.UTF8.GetBytes("key4") }; + + private static readonly StorageItem s_value1 = new(Encoding.UTF8.GetBytes("value1")); + private static readonly StorageItem s_value2 = new(Encoding.UTF8.GetBytes("value2")); + private static readonly StorageItem s_value3 = new(Encoding.UTF8.GetBytes("value3")); [TestMethod] public void TestCloneCache() { + var myDataCache = new StoreCache(_store); + var clonedCache = myDataCache.CloneCache(); Assert.IsNotNull(clonedCache); } [TestMethod] public void TestAddInternal() { - clonedCache.Add(key1, value1); - Assert.AreEqual(value1, clonedCache[key1]); + var myDataCache = new StoreCache(_store); + var clonedCache = myDataCache.CloneCache(); + + clonedCache.Add(s_key1, s_value1); + Assert.AreEqual(s_value1, clonedCache[s_key1]); clonedCache.Commit(); - Assert.IsTrue(myDataCache[key1].Value.Span.SequenceEqual(value1.Value.Span)); + Assert.IsTrue(myDataCache[s_key1].Value.Span.SequenceEqual(s_value1.Value.Span)); } [TestMethod] public void TestDeleteInternal() { - myDataCache.Add(key1, value1); - clonedCache.Delete(key1); // trackable.State = TrackState.Deleted + var myDataCache = new StoreCache(_store); + var clonedCache = myDataCache.CloneCache(); + + myDataCache.Add(s_key1, s_value1); + clonedCache.Delete(s_key1); // trackable.State = TrackState.Deleted clonedCache.Commit(); - Assert.IsNull(clonedCache.TryGet(key1)); - Assert.IsNull(myDataCache.TryGet(key1)); + Assert.IsNull(clonedCache.TryGet(s_key1)); + Assert.IsNull(myDataCache.TryGet(s_key1)); } [TestMethod] public void TestFindInternal() { - clonedCache.Add(key1, value1); - myDataCache.Add(key2, value2); - store.Put(key3.ToArray(), value3.ToArray()); + var myDataCache = new StoreCache(_store); + var clonedCache = myDataCache.CloneCache(); - var items = clonedCache.Find(key1.ToArray()); - Assert.AreEqual(key1, items.ElementAt(0).Key); - Assert.AreEqual(value1, items.ElementAt(0).Value); + clonedCache.Add(s_key1, s_value1); + myDataCache.Add(s_key2, s_value2); + _store.Put(s_key3.ToArray(), s_value3.ToArray()); + + var items = clonedCache.Find(s_key1.ToArray()); + Assert.AreEqual(s_key1, items.ElementAt(0).Key); + Assert.AreEqual(s_value1, items.ElementAt(0).Value); Assert.AreEqual(1, items.Count()); - items = clonedCache.Find(key2.ToArray()); - Assert.AreEqual(key2, items.ElementAt(0).Key); - Assert.IsTrue(value2.EqualsTo(items.ElementAt(0).Value)); + items = clonedCache.Find(s_key2.ToArray()); + Assert.AreEqual(s_key2, items.ElementAt(0).Key); + Assert.IsTrue(s_value2.EqualsTo(items.ElementAt(0).Value)); Assert.AreEqual(1, items.Count()); - items = clonedCache.Find(key3.ToArray()); - Assert.AreEqual(key3, items.ElementAt(0).Key); - Assert.IsTrue(value3.EqualsTo(items.ElementAt(0).Value)); + items = clonedCache.Find(s_key3.ToArray()); + Assert.AreEqual(s_key3, items.ElementAt(0).Key); + Assert.IsTrue(s_value3.EqualsTo(items.ElementAt(0).Value)); Assert.AreEqual(1, items.Count()); - items = clonedCache.Find(key4.ToArray()); + items = clonedCache.Find(s_key4.ToArray()); Assert.AreEqual(0, items.Count()); } [TestMethod] public void TestGetInternal() { - clonedCache.Add(key1, value1); - myDataCache.Add(key2, value2); - store.Put(key3.ToArray(), value3.ToArray()); + var myDataCache = new StoreCache(_store); + var clonedCache = myDataCache.CloneCache(); + + clonedCache.Add(s_key1, s_value1); + myDataCache.Add(s_key2, s_value2); + _store.Put(s_key3.ToArray(), s_value3.ToArray()); - Assert.IsTrue(value1.EqualsTo(clonedCache[key1])); - Assert.IsTrue(value2.EqualsTo(clonedCache[key2])); - Assert.IsTrue(value3.EqualsTo(clonedCache[key3])); + Assert.IsTrue(s_value1.EqualsTo(clonedCache[s_key1])); + Assert.IsTrue(s_value2.EqualsTo(clonedCache[s_key2])); + Assert.IsTrue(s_value3.EqualsTo(clonedCache[s_key3])); - Action action = () => + void Action() { - var item = clonedCache[key4]; - }; - Assert.ThrowsException(action); + var item = clonedCache[s_key4]; + } + Assert.ThrowsException(Action); } [TestMethod] public void TestTryGetInternal() { - clonedCache.Add(key1, value1); - myDataCache.Add(key2, value2); - store.Put(key3.ToArray(), value3.ToArray()); - - Assert.IsTrue(value1.EqualsTo(clonedCache.TryGet(key1))); - Assert.IsTrue(value2.EqualsTo(clonedCache.TryGet(key2))); - Assert.IsTrue(value3.EqualsTo(clonedCache.TryGet(key3))); - Assert.IsNull(clonedCache.TryGet(key4)); + var myDataCache = new StoreCache(_store); + var clonedCache = myDataCache.CloneCache(); + + clonedCache.Add(s_key1, s_value1); + myDataCache.Add(s_key2, s_value2); + _store.Put(s_key3.ToArray(), s_value3.ToArray()); + + Assert.IsTrue(s_value1.EqualsTo(clonedCache.TryGet(s_key1))); + Assert.IsTrue(s_value2.EqualsTo(clonedCache.TryGet(s_key2))); + Assert.IsTrue(s_value3.EqualsTo(clonedCache.TryGet(s_key3))); + Assert.IsNull(clonedCache.TryGet(s_key4)); } [TestMethod] public void TestUpdateInternal() { - clonedCache.Add(key1, value1); - myDataCache.Add(key2, value2); - store.Put(key3.ToArray(), value3.ToArray()); + var myDataCache = new StoreCache(_store); + var clonedCache = myDataCache.CloneCache(); + + clonedCache.Add(s_key1, s_value1); + myDataCache.Add(s_key2, s_value2); + _store.Put(s_key3.ToArray(), s_value3.ToArray()); - clonedCache.GetAndChange(key1).Value = Encoding.Default.GetBytes("value_new_1"); - clonedCache.GetAndChange(key2).Value = Encoding.Default.GetBytes("value_new_2"); - clonedCache.GetAndChange(key3).Value = Encoding.Default.GetBytes("value_new_3"); + clonedCache.GetAndChange(s_key1).Value = Encoding.Default.GetBytes("value_new_1"); + clonedCache.GetAndChange(s_key2).Value = Encoding.Default.GetBytes("value_new_2"); + clonedCache.GetAndChange(s_key3).Value = Encoding.Default.GetBytes("value_new_3"); clonedCache.Commit(); @@ -146,10 +156,10 @@ public void TestUpdateInternal() StorageItem value_new_2 = new(Encoding.UTF8.GetBytes("value_new_2")); StorageItem value_new_3 = new(Encoding.UTF8.GetBytes("value_new_3")); - Assert.IsTrue(value_new_1.EqualsTo(clonedCache[key1])); - Assert.IsTrue(value_new_2.EqualsTo(clonedCache[key2])); - Assert.IsTrue(value_new_3.EqualsTo(clonedCache[key3])); - Assert.IsTrue(value_new_2.EqualsTo(clonedCache[key2])); + Assert.IsTrue(value_new_1.EqualsTo(clonedCache[s_key1])); + Assert.IsTrue(value_new_2.EqualsTo(clonedCache[s_key2])); + Assert.IsTrue(value_new_3.EqualsTo(clonedCache[s_key3])); + Assert.IsTrue(value_new_2.EqualsTo(clonedCache[s_key2])); } [TestMethod] From df37bb6b8ce67e55c3174016a4c7d7fed14207d9 Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Sat, 22 Feb 2025 15:26:21 +0100 Subject: [PATCH 09/12] Fix merge --- tests/Neo.UnitTests/Persistence/UT_CloneCache.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Neo.UnitTests/Persistence/UT_CloneCache.cs b/tests/Neo.UnitTests/Persistence/UT_CloneCache.cs index 3abd742a06..2b5b7faaaa 100644 --- a/tests/Neo.UnitTests/Persistence/UT_CloneCache.cs +++ b/tests/Neo.UnitTests/Persistence/UT_CloneCache.cs @@ -116,8 +116,8 @@ public void TestGetInternal() void Action() { var item = clonedCache[s_key4]; - }; - Assert.ThrowsExactly(action); + } + Assert.ThrowsExactly(Action); } [TestMethod] From 1ce2865f343649f5c7128e867468fbf5f9b3e086 Mon Sep 17 00:00:00 2001 From: Shargon Date: Sat, 22 Feb 2025 19:59:35 +0500 Subject: [PATCH 10/12] Update UT_MemoryStore.cs --- tests/Neo.UnitTests/Persistence/UT_MemoryStore.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Neo.UnitTests/Persistence/UT_MemoryStore.cs b/tests/Neo.UnitTests/Persistence/UT_MemoryStore.cs index 61500538bd..d54e40814b 100644 --- a/tests/Neo.UnitTests/Persistence/UT_MemoryStore.cs +++ b/tests/Neo.UnitTests/Persistence/UT_MemoryStore.cs @@ -85,7 +85,7 @@ public void NeoSystemStoreViewTest() var value = new StorageItem(Encoding.UTF8.GetBytes("testValue")); store.Add(key, value); - Assert.ThrowsException(store.Commit); + _ = Assert.ThrowsExactly(store.Commit); var result = store.TryGet(key); // The StoreView is a readonly view of the store, here it will have value in the cache From 6d5bb9096ee1a8a2cad394cfa4f6059387a8838c Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Sat, 22 Feb 2025 16:06:37 +0100 Subject: [PATCH 11/12] Fix build --- tests/Neo.UnitTests/Persistence/UT_ReadOnlyStore.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Neo.UnitTests/Persistence/UT_ReadOnlyStore.cs b/tests/Neo.UnitTests/Persistence/UT_ReadOnlyStore.cs index 5c1e89debe..b3007c740e 100644 --- a/tests/Neo.UnitTests/Persistence/UT_ReadOnlyStore.cs +++ b/tests/Neo.UnitTests/Persistence/UT_ReadOnlyStore.cs @@ -28,8 +28,8 @@ public void TestError() var store = new MemoryStore(); var snapshot = new StoreCache(store); - Assert.ThrowsException(() => snapshot.GetChangeSet().ToArray()); - Assert.ThrowsException(snapshot.Commit); + Assert.ThrowsExactly(() => snapshot.GetChangeSet().ToArray()); + Assert.ThrowsExactly(snapshot.Commit); // No errors From 5f4c2aec71888eb8666560403479928a0b594a35 Mon Sep 17 00:00:00 2001 From: Shargon Date: Fri, 28 Feb 2025 13:50:03 +0500 Subject: [PATCH 12/12] Update src/Neo/Persistence/StoreCache.cs --- src/Neo/Persistence/StoreCache.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Neo/Persistence/StoreCache.cs b/src/Neo/Persistence/StoreCache.cs index 6f1dc1628d..a3848e14bc 100644 --- a/src/Neo/Persistence/StoreCache.cs +++ b/src/Neo/Persistence/StoreCache.cs @@ -31,7 +31,7 @@ public class StoreCache : DataCache, IDisposable /// Initializes a new instance of the class. /// /// An to create a readonly cache. - /// True if you don't want to allow writes + /// True if you don't want to track write changes public StoreCache(IStore store, bool readOnly = true) : base(readOnly) { _store = store;