From c891a94ead375dcceb5272b8c8c350dea5d86ad7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E5=BF=97=E5=90=8C?= Date: Thu, 22 Aug 2024 11:43:21 +0800 Subject: [PATCH 1/5] Add UT Neo.Extensions --- src/Neo.Extensions/BigIntegerExtensions.cs | 5 ++ .../UT_BigIntegerExtensions.cs | 69 ++++++++++++++++++- .../Neo.Extensions.Tests/UT_ByteExtensions.cs | 24 +++++++ 3 files changed, 96 insertions(+), 2 deletions(-) diff --git a/src/Neo.Extensions/BigIntegerExtensions.cs b/src/Neo.Extensions/BigIntegerExtensions.cs index 38a0e60bb5..18667262e6 100644 --- a/src/Neo.Extensions/BigIntegerExtensions.cs +++ b/src/Neo.Extensions/BigIntegerExtensions.cs @@ -43,6 +43,11 @@ public static BigInteger Mod(this BigInteger x, BigInteger y) public static BigInteger ModInverse(this BigInteger a, BigInteger n) { + if (BigInteger.GreatestCommonDivisor(a, n) != 1) + { + throw new ArithmeticException("No modular inverse exists for the given inputs."); + } + BigInteger i = n, v = 0, d = 1; while (a > 0) { diff --git a/tests/Neo.Extensions.Tests/UT_BigIntegerExtensions.cs b/tests/Neo.Extensions.Tests/UT_BigIntegerExtensions.cs index b887d1c973..8f570c8ff2 100644 --- a/tests/Neo.Extensions.Tests/UT_BigIntegerExtensions.cs +++ b/tests/Neo.Extensions.Tests/UT_BigIntegerExtensions.cs @@ -11,6 +11,8 @@ using FluentAssertions; using Neo.Extensions; +using System; +using System.Collections.Generic; using System.Numerics; namespace Neo.Extensions.Tests @@ -32,16 +34,79 @@ public void TestGetLowestSetBit() var big4 = new BigInteger(long.MinValue); big4.GetLowestSetBit().Should().Be(63); + + var big5 = new BigInteger(-18); + big5.GetLowestSetBit().Should().Be(1); + + var big6 = BigInteger.Pow(2, 1000); + big6.GetLowestSetBit().Should().Be(1000); } [TestMethod] public void TestToByteArrayStandard() { BigInteger number = BigInteger.Zero; - Assert.AreEqual("", number.ToByteArrayStandard().ToHexString()); + number.ToByteArrayStandard().Should().BeEmpty(); number = BigInteger.One; - Assert.AreEqual("01", number.ToByteArrayStandard().ToHexString()); + number.ToByteArrayStandard().Should().Equal(new byte[] { 0x01 }); + + number = new BigInteger(256); // Binary: 100000000 + number.ToByteArrayStandard().Should().Equal(new byte[] { 0x00, 0x01 }); + } + + [TestMethod] + public void TestMod() + { + var x = new BigInteger(-13); + var y = new BigInteger(5); + var result = x.Mod(y); + result.Should().Be(2); // -13 % 5 is -3, but Mod method should return 2 + } + + [TestMethod] + public void TestModInverse() + { + var a = new BigInteger(3); + var n = new BigInteger(11); + var result = a.ModInverse(n); + result.Should().Be(4); // 3 * 4 % 11 == 1 + + a = new BigInteger(1); + n = new BigInteger(11); + result = a.ModInverse(n); + result.Should().Be(1); // 1 * 1 % 11 == 1 + + a = new BigInteger(13); + n = new BigInteger(11); + result = a.ModInverse(n); + result.Should().Be(6); // 13 % 11 = 2, and 2 * 6 % 11 == 1 + + a = new BigInteger(6); + n = new BigInteger(12); // 6 and 12 are not coprime + Action act = () => a.ModInverse(n); + act.Should().Throw() + .WithMessage("No modular inverse exists for the given inputs."); + } + + [TestMethod] + public void TestBit() + { + var bigInteger = new BigInteger(5); // Binary: 101 + var result = bigInteger.TestBit(2); + result.Should().BeTrue(); // Bit at index 2 is set (1) + + bigInteger = new BigInteger(5); // Binary: 101 + result = bigInteger.TestBit(1); + result.Should().BeFalse(); // Bit at index 1 is not set (0) + } + + [TestMethod] + public void TestSum() + { + var bigIntegers = new List { 1, 2, 3, 4 }; + var result = bigIntegers.Sum(); + result.Should().Be(10); } } } diff --git a/tests/Neo.Extensions.Tests/UT_ByteExtensions.cs b/tests/Neo.Extensions.Tests/UT_ByteExtensions.cs index a66d462694..3c0c21b8f0 100644 --- a/tests/Neo.Extensions.Tests/UT_ByteExtensions.cs +++ b/tests/Neo.Extensions.Tests/UT_ByteExtensions.cs @@ -33,5 +33,29 @@ public void TestToHexString() str1.ToHexString(false).Should().Be("6e656f"); str1.ToHexString(true).Should().Be("6f656e"); } + + [TestMethod] + public void TestReadOnlySpanToHexString() + { + byte[] input = { 0x0F, 0xA4, 0x3B }; + var span = new ReadOnlySpan(input); + string result = span.ToHexString(); + result.Should().Be("0fa43b"); + + input = Array.Empty(); + span = new ReadOnlySpan(input); + result = span.ToHexString(); + result.Should().BeEmpty(); + + input = new byte[] { 0x5A }; + span = new ReadOnlySpan(input); + result = span.ToHexString(); + result.Should().Be("5a"); + + input = new byte[] { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }; + span = new ReadOnlySpan(input); + result = span.ToHexString(); + result.Should().Be("0123456789abcdef"); + } } } From 6d0a61b2da9e25f2b3cc63b32b06052bfc524143 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E5=BF=97=E5=90=8C?= Date: Mon, 26 Aug 2024 10:49:32 +0800 Subject: [PATCH 2/5] resolve conflicts --- .../UT_RpcServer.Blockchain.cs | 61 +++++++++++++++++-- .../Extensions/NativeContractExtensions.cs | 20 +++++- 2 files changed, 75 insertions(+), 6 deletions(-) diff --git a/tests/Neo.Plugins.RpcServer.Tests/UT_RpcServer.Blockchain.cs b/tests/Neo.Plugins.RpcServer.Tests/UT_RpcServer.Blockchain.cs index 2fbb2f6f3f..b04b5e33d4 100644 --- a/tests/Neo.Plugins.RpcServer.Tests/UT_RpcServer.Blockchain.cs +++ b/tests/Neo.Plugins.RpcServer.Tests/UT_RpcServer.Blockchain.cs @@ -11,7 +11,9 @@ using Akka.Actor; using Akka.Util.Internal; +using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.Cryptography.ECC; using Neo.IO; using Neo.Json; using Neo.Ledger; @@ -23,6 +25,8 @@ using Neo.UnitTests.Extensions; using System; using System.Linq; +using System.Security.Policy; +using static Neo.SmartContract.Native.NeoToken; namespace Neo.Plugins.RpcServer.Tests { @@ -61,6 +65,11 @@ public void TestGetBlockByHash() { Assert.AreEqual(VerifyResult.Succeed, tx.VerifyStateIndependent(UnitTests.TestProtocolSettings.Default)); }); + + result = _rpcServer.GetBlock(new BlockHashOrIndex(block.Hash), true); + var block3 = block.ToJson(UnitTests.TestProtocolSettings.Default); + block3["confirmations"] = NativeContract.Ledger.CurrentIndex(snapshot) - block.Index + 1; + result.ToString().Should().Be(block3.ToString()); } [TestMethod] @@ -78,6 +87,11 @@ public void TestGetBlockByIndex() { Assert.AreEqual(VerifyResult.Succeed, tx.VerifyStateIndependent(UnitTests.TestProtocolSettings.Default)); }); + + result = _rpcServer.GetBlock(new BlockHashOrIndex(block.Index), true); + var block3 = block.ToJson(UnitTests.TestProtocolSettings.Default); + block3["confirmations"] = NativeContract.Ledger.CurrentIndex(snapshot) - block.Index + 1; + result.ToString().Should().Be(block3.ToString()); } [TestMethod] @@ -120,6 +134,11 @@ public void TestGetBlockHeader() var header = block.Header.ToJson(_neoSystem.Settings); header["confirmations"] = NativeContract.Ledger.CurrentIndex(snapshot) - block.Index + 1; Assert.AreEqual(header.ToString(), result.ToString()); + + result = _rpcServer.GetBlockHeader(new BlockHashOrIndex(block.Hash), false); + var headerArr = Convert.FromBase64String(result.AsString()); + var header2 = headerArr.AsSerializable
(); + header2.ToJson(_neoSystem.Settings).ToString().Should().Be(block.Header.ToJson(_neoSystem.Settings).ToString()); } [TestMethod] @@ -129,9 +148,23 @@ public void TestGetContractState() var contractState = TestUtils.GetContract(); snapshot.AddContract(contractState.Hash, contractState); snapshot.Commit(); + var result = _rpcServer.GetContractState(new ContractNameOrHashOrId(contractState.Hash)); + Assert.AreEqual(contractState.ToJson().ToString(), result.ToString()); + result = _rpcServer.GetContractState(new ContractNameOrHashOrId(contractState.Id)); Assert.AreEqual(contractState.ToJson().ToString(), result.ToString()); + + var byId = _rpcServer.GetContractState(new ContractNameOrHashOrId(-1)); + var byName = _rpcServer.GetContractState(new ContractNameOrHashOrId("ContractManagement")); + byId.ToString().Should().Be(byName.ToString()); + + snapshot.DeleteContract(contractState.Hash); + snapshot.Commit(); + Action act = () => _rpcServer.GetContractState(new ContractNameOrHashOrId(contractState.Hash)); + act.Should().Throw().WithMessage(RpcError.UnknownContract.Message); + act = () => _rpcServer.GetContractState(new ContractNameOrHashOrId(contractState.Id)); + act.Should().Throw().WithMessage(RpcError.UnknownContract.Message); } [TestMethod] @@ -143,8 +176,10 @@ public void TestGetRawMemPool() _neoSystem.MemPool.TryAdd(tx, snapshot); var result = _rpcServer.GetRawMemPool(); - Assert.IsTrue(((JArray)result).Any(p => p.AsString() == tx.Hash.ToString())); + + result = _rpcServer.GetRawMemPool(true); + Assert.IsTrue(((JArray)result["verified"]).Any(p => p.AsString() == tx.Hash.ToString())); } [TestMethod] @@ -154,10 +189,14 @@ public void TestGetRawTransaction() var tx = TestUtils.CreateValidTx(snapshot, _wallet, _walletAccount); _neoSystem.MemPool.TryAdd(tx, snapshot); snapshot.Commit(); - var result = _rpcServer.GetRawTransaction(tx.Hash, true); + var result = _rpcServer.GetRawTransaction(tx.Hash, true); var json = Utility.TransactionToJson(tx, _neoSystem.Settings); Assert.AreEqual(json.ToString(), result.ToString()); + + result = _rpcServer.GetRawTransaction(tx.Hash, false); + var tx2 = Convert.FromBase64String(result.AsString()).AsSerializable(); + tx2.ToJson(_neoSystem.Settings).ToString().Should().Be(tx.ToJson(_neoSystem.Settings).ToString()); } [TestMethod] @@ -197,6 +236,15 @@ public void TestFindStorage() json["next"] = 1; json["results"] = jarr; Assert.AreEqual(json.ToString(), result.ToString()); + + var result2 = _rpcServer.FindStorage(new ContractNameOrHashOrId(contractState.Hash), Convert.ToBase64String(key)); + result2.ToString().Should().Be(result.ToString()); + + Enumerable.Range(0, 51).ToList().ForEach(i => TestUtils.StorageItemAdd(snapshot, contractState.Id, new byte[] { 0x01, (byte)i }, new byte[] { 0x02 })); + snapshot.Commit(); + var result4 = _rpcServer.FindStorage(new ContractNameOrHashOrId(contractState.Hash), Convert.ToBase64String(new byte[] { 0x01 }), 0); + result4["next"].Should().Be(RpcServerSettings.Default.FindStoragePageSize); + (result4["truncated"]).AsBoolean().Should().Be(true); } [TestMethod] @@ -232,12 +280,16 @@ public void TestGetNextBlockValidators() public void TestGetCandidates() { var snapshot = _neoSystem.GetSnapshotCache(); + var result = _rpcServer.GetCandidates(); var json = new JArray(); var validators = NativeContract.NEO.GetNextBlockValidators(snapshot, _neoSystem.Settings.ValidatorsCount); + + var key = new KeyBuilder(NativeContract.NEO.Id, 33).Add(ECPoint.Parse("02237309a0633ff930d51856db01d17c829a5b2e5cc2638e9c03b4cfa8e9c9f971", ECCurve.Secp256r1)); + snapshot.Add(key, new StorageItem(new CandidateState() { Registered = true, Votes = 10000 })); snapshot.Commit(); var candidates = NativeContract.NEO.GetCandidates(_neoSystem.GetSnapshotCache()); - + result = _rpcServer.GetCandidates(); foreach (var candidate in candidates) { var item = new JObject(); @@ -350,7 +402,8 @@ public void TestGetBlockHashInvalidIndex() var block = TestUtils.CreateBlockWithValidTransactions(snapshot, _wallet, _walletAccount, 3); TestUtils.BlocksAdd(snapshot, block.Hash, block); snapshot.Commit(); - Assert.ThrowsException(() => _rpcServer.GetBlockHash(block.Index + 1)); + Action act = () => _rpcServer.GetBlockHash(block.Index + 1); + act.Should().Throw(); } [TestMethod] diff --git a/tests/Neo.UnitTests/Extensions/NativeContractExtensions.cs b/tests/Neo.UnitTests/Extensions/NativeContractExtensions.cs index 9a282759a9..68523e964e 100644 --- a/tests/Neo.UnitTests/Extensions/NativeContractExtensions.cs +++ b/tests/Neo.UnitTests/Extensions/NativeContractExtensions.cs @@ -9,6 +9,8 @@ // Redistribution and use in source and binary forms with or without // modifications are permitted. +using FluentAssertions; +using Neo.IO; using Neo.Network.P2P.Payloads; using Neo.Persistence; using Neo.SmartContract; @@ -100,14 +102,28 @@ public static void DestroyContract(this DataCache snapshot, UInt160 callingScrip public static void AddContract(this DataCache snapshot, UInt160 hash, ContractState state) { - var key = new KeyBuilder(NativeContract.ContractManagement.Id, 8).Add(hash); - snapshot.Add(key, new StorageItem(state)); + { + //key: hash, value: ContractState + var key = new KeyBuilder(NativeContract.ContractManagement.Id, 8).Add(hash); + snapshot.Add(key, new StorageItem(state)); + //key: id, value: hash + var key2 = new KeyBuilder(NativeContract.ContractManagement.Id, 12).AddBigEndian(state.Id); + if (!snapshot.Contains(key2)) snapshot.Add(key2, new StorageItem(hash.ToArray())); + } } public static void DeleteContract(this DataCache snapshot, UInt160 hash) { + //key: hash, value: ContractState var key = new KeyBuilder(NativeContract.ContractManagement.Id, 8).Add(hash); + var value = snapshot.TryGet(key)?.GetInteroperable(); snapshot.Delete(key); + if (value != null) + { + //key: id, value: hash + var key2 = new KeyBuilder(NativeContract.ContractManagement.Id, 12).AddBigEndian(value.Id); + snapshot.Delete(key2); + } } public static StackItem Call(this NativeContract contract, DataCache snapshot, string method, params ContractParameter[] args) From 4e4178b2d6de9f229e44c6d643ab5e9761212267 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E5=BF=97=E5=90=8C?= Date: Mon, 26 Aug 2024 10:51:02 +0800 Subject: [PATCH 3/5] Revert "resolve conflicts" This reverts commit 6d0a61b2da9e25f2b3cc63b32b06052bfc524143. --- .../UT_RpcServer.Blockchain.cs | 61 ++----------------- .../Extensions/NativeContractExtensions.cs | 20 +----- 2 files changed, 6 insertions(+), 75 deletions(-) diff --git a/tests/Neo.Plugins.RpcServer.Tests/UT_RpcServer.Blockchain.cs b/tests/Neo.Plugins.RpcServer.Tests/UT_RpcServer.Blockchain.cs index b04b5e33d4..2fbb2f6f3f 100644 --- a/tests/Neo.Plugins.RpcServer.Tests/UT_RpcServer.Blockchain.cs +++ b/tests/Neo.Plugins.RpcServer.Tests/UT_RpcServer.Blockchain.cs @@ -11,9 +11,7 @@ using Akka.Actor; using Akka.Util.Internal; -using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; -using Neo.Cryptography.ECC; using Neo.IO; using Neo.Json; using Neo.Ledger; @@ -25,8 +23,6 @@ using Neo.UnitTests.Extensions; using System; using System.Linq; -using System.Security.Policy; -using static Neo.SmartContract.Native.NeoToken; namespace Neo.Plugins.RpcServer.Tests { @@ -65,11 +61,6 @@ public void TestGetBlockByHash() { Assert.AreEqual(VerifyResult.Succeed, tx.VerifyStateIndependent(UnitTests.TestProtocolSettings.Default)); }); - - result = _rpcServer.GetBlock(new BlockHashOrIndex(block.Hash), true); - var block3 = block.ToJson(UnitTests.TestProtocolSettings.Default); - block3["confirmations"] = NativeContract.Ledger.CurrentIndex(snapshot) - block.Index + 1; - result.ToString().Should().Be(block3.ToString()); } [TestMethod] @@ -87,11 +78,6 @@ public void TestGetBlockByIndex() { Assert.AreEqual(VerifyResult.Succeed, tx.VerifyStateIndependent(UnitTests.TestProtocolSettings.Default)); }); - - result = _rpcServer.GetBlock(new BlockHashOrIndex(block.Index), true); - var block3 = block.ToJson(UnitTests.TestProtocolSettings.Default); - block3["confirmations"] = NativeContract.Ledger.CurrentIndex(snapshot) - block.Index + 1; - result.ToString().Should().Be(block3.ToString()); } [TestMethod] @@ -134,11 +120,6 @@ public void TestGetBlockHeader() var header = block.Header.ToJson(_neoSystem.Settings); header["confirmations"] = NativeContract.Ledger.CurrentIndex(snapshot) - block.Index + 1; Assert.AreEqual(header.ToString(), result.ToString()); - - result = _rpcServer.GetBlockHeader(new BlockHashOrIndex(block.Hash), false); - var headerArr = Convert.FromBase64String(result.AsString()); - var header2 = headerArr.AsSerializable
(); - header2.ToJson(_neoSystem.Settings).ToString().Should().Be(block.Header.ToJson(_neoSystem.Settings).ToString()); } [TestMethod] @@ -148,23 +129,9 @@ public void TestGetContractState() var contractState = TestUtils.GetContract(); snapshot.AddContract(contractState.Hash, contractState); snapshot.Commit(); - var result = _rpcServer.GetContractState(new ContractNameOrHashOrId(contractState.Hash)); - Assert.AreEqual(contractState.ToJson().ToString(), result.ToString()); - result = _rpcServer.GetContractState(new ContractNameOrHashOrId(contractState.Id)); Assert.AreEqual(contractState.ToJson().ToString(), result.ToString()); - - var byId = _rpcServer.GetContractState(new ContractNameOrHashOrId(-1)); - var byName = _rpcServer.GetContractState(new ContractNameOrHashOrId("ContractManagement")); - byId.ToString().Should().Be(byName.ToString()); - - snapshot.DeleteContract(contractState.Hash); - snapshot.Commit(); - Action act = () => _rpcServer.GetContractState(new ContractNameOrHashOrId(contractState.Hash)); - act.Should().Throw().WithMessage(RpcError.UnknownContract.Message); - act = () => _rpcServer.GetContractState(new ContractNameOrHashOrId(contractState.Id)); - act.Should().Throw().WithMessage(RpcError.UnknownContract.Message); } [TestMethod] @@ -176,10 +143,8 @@ public void TestGetRawMemPool() _neoSystem.MemPool.TryAdd(tx, snapshot); var result = _rpcServer.GetRawMemPool(); - Assert.IsTrue(((JArray)result).Any(p => p.AsString() == tx.Hash.ToString())); - result = _rpcServer.GetRawMemPool(true); - Assert.IsTrue(((JArray)result["verified"]).Any(p => p.AsString() == tx.Hash.ToString())); + Assert.IsTrue(((JArray)result).Any(p => p.AsString() == tx.Hash.ToString())); } [TestMethod] @@ -189,14 +154,10 @@ public void TestGetRawTransaction() var tx = TestUtils.CreateValidTx(snapshot, _wallet, _walletAccount); _neoSystem.MemPool.TryAdd(tx, snapshot); snapshot.Commit(); - var result = _rpcServer.GetRawTransaction(tx.Hash, true); + var json = Utility.TransactionToJson(tx, _neoSystem.Settings); Assert.AreEqual(json.ToString(), result.ToString()); - - result = _rpcServer.GetRawTransaction(tx.Hash, false); - var tx2 = Convert.FromBase64String(result.AsString()).AsSerializable(); - tx2.ToJson(_neoSystem.Settings).ToString().Should().Be(tx.ToJson(_neoSystem.Settings).ToString()); } [TestMethod] @@ -236,15 +197,6 @@ public void TestFindStorage() json["next"] = 1; json["results"] = jarr; Assert.AreEqual(json.ToString(), result.ToString()); - - var result2 = _rpcServer.FindStorage(new ContractNameOrHashOrId(contractState.Hash), Convert.ToBase64String(key)); - result2.ToString().Should().Be(result.ToString()); - - Enumerable.Range(0, 51).ToList().ForEach(i => TestUtils.StorageItemAdd(snapshot, contractState.Id, new byte[] { 0x01, (byte)i }, new byte[] { 0x02 })); - snapshot.Commit(); - var result4 = _rpcServer.FindStorage(new ContractNameOrHashOrId(contractState.Hash), Convert.ToBase64String(new byte[] { 0x01 }), 0); - result4["next"].Should().Be(RpcServerSettings.Default.FindStoragePageSize); - (result4["truncated"]).AsBoolean().Should().Be(true); } [TestMethod] @@ -280,16 +232,12 @@ public void TestGetNextBlockValidators() public void TestGetCandidates() { var snapshot = _neoSystem.GetSnapshotCache(); - var result = _rpcServer.GetCandidates(); var json = new JArray(); var validators = NativeContract.NEO.GetNextBlockValidators(snapshot, _neoSystem.Settings.ValidatorsCount); - - var key = new KeyBuilder(NativeContract.NEO.Id, 33).Add(ECPoint.Parse("02237309a0633ff930d51856db01d17c829a5b2e5cc2638e9c03b4cfa8e9c9f971", ECCurve.Secp256r1)); - snapshot.Add(key, new StorageItem(new CandidateState() { Registered = true, Votes = 10000 })); snapshot.Commit(); var candidates = NativeContract.NEO.GetCandidates(_neoSystem.GetSnapshotCache()); - result = _rpcServer.GetCandidates(); + foreach (var candidate in candidates) { var item = new JObject(); @@ -402,8 +350,7 @@ public void TestGetBlockHashInvalidIndex() var block = TestUtils.CreateBlockWithValidTransactions(snapshot, _wallet, _walletAccount, 3); TestUtils.BlocksAdd(snapshot, block.Hash, block); snapshot.Commit(); - Action act = () => _rpcServer.GetBlockHash(block.Index + 1); - act.Should().Throw(); + Assert.ThrowsException(() => _rpcServer.GetBlockHash(block.Index + 1)); } [TestMethod] diff --git a/tests/Neo.UnitTests/Extensions/NativeContractExtensions.cs b/tests/Neo.UnitTests/Extensions/NativeContractExtensions.cs index 68523e964e..9a282759a9 100644 --- a/tests/Neo.UnitTests/Extensions/NativeContractExtensions.cs +++ b/tests/Neo.UnitTests/Extensions/NativeContractExtensions.cs @@ -9,8 +9,6 @@ // Redistribution and use in source and binary forms with or without // modifications are permitted. -using FluentAssertions; -using Neo.IO; using Neo.Network.P2P.Payloads; using Neo.Persistence; using Neo.SmartContract; @@ -102,28 +100,14 @@ public static void DestroyContract(this DataCache snapshot, UInt160 callingScrip public static void AddContract(this DataCache snapshot, UInt160 hash, ContractState state) { - { - //key: hash, value: ContractState - var key = new KeyBuilder(NativeContract.ContractManagement.Id, 8).Add(hash); - snapshot.Add(key, new StorageItem(state)); - //key: id, value: hash - var key2 = new KeyBuilder(NativeContract.ContractManagement.Id, 12).AddBigEndian(state.Id); - if (!snapshot.Contains(key2)) snapshot.Add(key2, new StorageItem(hash.ToArray())); - } + var key = new KeyBuilder(NativeContract.ContractManagement.Id, 8).Add(hash); + snapshot.Add(key, new StorageItem(state)); } public static void DeleteContract(this DataCache snapshot, UInt160 hash) { - //key: hash, value: ContractState var key = new KeyBuilder(NativeContract.ContractManagement.Id, 8).Add(hash); - var value = snapshot.TryGet(key)?.GetInteroperable(); snapshot.Delete(key); - if (value != null) - { - //key: id, value: hash - var key2 = new KeyBuilder(NativeContract.ContractManagement.Id, 12).AddBigEndian(value.Id); - snapshot.Delete(key2); - } } public static StackItem Call(this NativeContract contract, DataCache snapshot, string method, params ContractParameter[] args) From 7dc92f308ab6d54823e658986158786f0a4716be Mon Sep 17 00:00:00 2001 From: Jimmy Date: Wed, 28 Aug 2024 00:46:04 +0800 Subject: [PATCH 4/5] add edge case --- .../UT_BigIntegerExtensions.cs | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/tests/Neo.Extensions.Tests/UT_BigIntegerExtensions.cs b/tests/Neo.Extensions.Tests/UT_BigIntegerExtensions.cs index 8f570c8ff2..d01ad68bd3 100644 --- a/tests/Neo.Extensions.Tests/UT_BigIntegerExtensions.cs +++ b/tests/Neo.Extensions.Tests/UT_BigIntegerExtensions.cs @@ -11,6 +11,7 @@ using FluentAssertions; using Neo.Extensions; +using Neo.Json; using System; using System.Collections.Generic; using System.Numerics; @@ -42,6 +43,15 @@ public void TestGetLowestSetBit() big6.GetLowestSetBit().Should().Be(1000); } + [TestMethod] + public void TestGetLowestSetBit_EdgeCases() + { + BigInteger.MinusOne.GetLowestSetBit().Should().Be(0); + BigInteger.One.GetLowestSetBit().Should().Be(0); + new BigInteger(ulong.MaxValue).GetLowestSetBit().Should().Be(0); + (BigInteger.One << 1000).GetLowestSetBit().Should().Be(1000); + } + [TestMethod] public void TestToByteArrayStandard() { @@ -55,6 +65,15 @@ public void TestToByteArrayStandard() number.ToByteArrayStandard().Should().Equal(new byte[] { 0x00, 0x01 }); } + [TestMethod] + public void TestToByteArrayStandard_EdgeCases() + { + BigInteger.MinusOne.ToByteArrayStandard().Should().Equal(new byte[] { 0xFF }); + new BigInteger(byte.MaxValue).ToByteArrayStandard().Should().Equal(new byte[] { 0xFF, 0x00 }); + new BigInteger(ushort.MaxValue).ToByteArrayStandard().Should().Equal(new byte[] { 0xFF, 0xFF, 0x00 }); + new BigInteger(JNumber.MIN_SAFE_INTEGER).ToByteArrayStandard().Should().Equal(new byte[] { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0 }); + } + [TestMethod] public void TestMod() { @@ -64,6 +83,17 @@ public void TestMod() result.Should().Be(2); // -13 % 5 is -3, but Mod method should return 2 } + [TestMethod] + public void TestMod_EdgeCases() + { + BigInteger.Zero.Mod(5).Should().Be(0); + BigInteger.MinusOne.Mod(5).Should().Be(4); + new BigInteger(long.MinValue).Mod(long.MaxValue).Should().Be(9223372036854775806); + // Sign of the result: % can return negative values, while Mod always returns non-negative values. + var longMod = long.MinValue % long.MaxValue; + new BigInteger(long.MinValue).Mod(long.MaxValue).Should().NotBe(longMod); + } + [TestMethod] public void TestModInverse() { @@ -89,6 +119,20 @@ public void TestModInverse() .WithMessage("No modular inverse exists for the given inputs."); } + [TestMethod] + public void TestModInverse_EdgeCases() + { + Action act = () => BigInteger.Zero.ModInverse(11); + act.Should().Throw(); + + BigInteger.One.ModInverse(2).Should().Be(1); + + act = () => new BigInteger(2).ModInverse(4); + act.Should().Throw(); + + new BigInteger(long.MaxValue - 1).ModInverse(long.MaxValue).Should().Be(long.MaxValue - 1); + } + [TestMethod] public void TestBit() { @@ -101,6 +145,17 @@ public void TestBit() result.Should().BeFalse(); // Bit at index 1 is not set (0) } + [TestMethod] + public void TestBit_EdgeCases() + { + BigInteger.Zero.TestBit(0).Should().BeFalse(); + BigInteger.Zero.TestBit(100).Should().BeFalse(); + BigInteger.MinusOne.TestBit(0).Should().BeTrue(); + BigInteger.MinusOne.TestBit(1000).Should().BeTrue(); + (BigInteger.One << 1000).TestBit(1000).Should().BeTrue(); + (BigInteger.One << 1000).TestBit(999).Should().BeFalse(); + } + [TestMethod] public void TestSum() { @@ -108,5 +163,13 @@ public void TestSum() var result = bigIntegers.Sum(); result.Should().Be(10); } + + [TestMethod] + public void TestSum_EdgeCases() + { + new List().Sum().Should().Be(0); + new List { JNumber.MIN_SAFE_INTEGER, JNumber.MAX_SAFE_INTEGER }.Sum().Should().Be(0); + new List { JNumber.MAX_SAFE_INTEGER, JNumber.MAX_SAFE_INTEGER }.Sum().Should().Be(JNumber.MAX_SAFE_INTEGER * 2); + } } } From 3c475d328f93362fbef5dc8bfce152a2db1658ba Mon Sep 17 00:00:00 2001 From: Jimmy Date: Wed, 28 Aug 2024 01:06:20 +0800 Subject: [PATCH 5/5] update mod test --- .../UT_BigIntegerExtensions.cs | 29 +++++++++++++++---- 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/tests/Neo.Extensions.Tests/UT_BigIntegerExtensions.cs b/tests/Neo.Extensions.Tests/UT_BigIntegerExtensions.cs index d01ad68bd3..d1d8d0aab3 100644 --- a/tests/Neo.Extensions.Tests/UT_BigIntegerExtensions.cs +++ b/tests/Neo.Extensions.Tests/UT_BigIntegerExtensions.cs @@ -86,12 +86,29 @@ public void TestMod() [TestMethod] public void TestMod_EdgeCases() { - BigInteger.Zero.Mod(5).Should().Be(0); - BigInteger.MinusOne.Mod(5).Should().Be(4); - new BigInteger(long.MinValue).Mod(long.MaxValue).Should().Be(9223372036854775806); - // Sign of the result: % can return negative values, while Mod always returns non-negative values. - var longMod = long.MinValue % long.MaxValue; - new BigInteger(long.MinValue).Mod(long.MaxValue).Should().NotBe(longMod); + // Test case 1: Mod of zero + BigInteger.Zero.Mod(5).Should().Be(0, "Mod of zero should always be zero"); + + // Test case 2: Mod of -1 + BigInteger.MinusOne.Mod(5).Should().Be(4, "Mod of -1 should return the modulus minus 1"); + + // Test case 3: Mod with large numbers + BigInteger minValue = new BigInteger(long.MinValue); + BigInteger maxValue = new BigInteger(long.MaxValue); + minValue.Mod(maxValue).Should().Be(9223372036854775806, "Mod with large numbers should be calculated correctly"); + + // Test case 4: Comparing Mod with % operator + BigInteger result = minValue.Mod(maxValue); + result.Should().NotBe(long.MinValue % long.MaxValue, "Mod should always return non-negative values, unlike % operator"); + + // Test case 5: Verifying % operator behavior + (long.MinValue % long.MaxValue).Should().Be((long)(minValue % maxValue), "% operator should behave consistently for BigInteger and long"); + + // Test case 6: Mod with prime numbers + new BigInteger(17).Mod(19).Should().Be(17, "Mod with a larger prime should return the original number"); + + // Test case 7: Mod with powers of 2 + new BigInteger(1024).Mod(16).Should().Be(0, "Mod with powers of 2 should utilize bitwise operations efficiently"); } [TestMethod]