From bfb34409900d9269e89b93e008f3ff06db236cd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E5=BF=97=E5=90=8C?= Date: Thu, 11 Jul 2024 12:55:46 +0800 Subject: [PATCH] Improve code coverage (#3354) * update * remove binary file * Add UT and fixed bug * Add UT and fixed bug * Add UT * Add UT * Add UT * Update src/Neo/SmartContract/Manifest/ContractManifest.cs Co-authored-by: Christopher Schuchardt * Update src/Neo/SmartContract/Manifest/ContractManifest.cs Co-authored-by: Christopher Schuchardt * Update src/Neo/SmartContract/Manifest/ContractManifest.cs Co-authored-by: Christopher Schuchardt * Update Base58.cs * Update UT_Cryptography_Helper.cs * Update Base58.cs * update * Update ContractManifest.cs * Revert change that affect a syscall * Revert try * Remove using * Update src/Neo/SmartContract/Manifest/ContractManifest.cs Co-authored-by: Christopher Schuchardt * Update src/Neo/SmartContract/Manifest/ContractAbi.cs Co-authored-by: Christopher Schuchardt * Update src/Neo/SmartContract/Manifest/ContractManifest.cs Co-authored-by: Christopher Schuchardt --------- Co-authored-by: Christopher Schuchardt Co-authored-by: Jimmy Co-authored-by: Fernando Diaz Toledano Co-authored-by: NGD Admin <154295625+NGDAdmin@users.noreply.github.com> --- src/Neo/SmartContract/Manifest/ContractAbi.cs | 4 +- .../Manifest/ContractManifest.cs | 11 +- tests/Neo.Json.UnitTests/UT_JArray.cs | 13 ++ tests/Neo.Json.UnitTests/UT_JBoolean.cs | 2 + tests/Neo.Json.UnitTests/UT_JNumber.cs | 23 ++++ tests/Neo.Json.UnitTests/UT_JString.cs | 16 ++- .../Cryptography/UT_BloomFilter.cs | 2 + .../Cryptography/UT_Cryptography_Helper.cs | 24 ++++ tests/Neo.UnitTests/Neo.UnitTests.csproj | 3 + .../Network/P2P/Payloads/UT_Block.cs | 21 +++ .../TestFile/SampleContractCall.manifest.json | 1 + .../TestFile/SampleEvent.manifest.json | 1 + .../TestFile/SampleException.manifest.json | 1 + .../TestFile/SampleHelloWorld.manifest.json | 1 + .../TestFile/SampleNep17Token.manifest.json | 1 + .../TestFile/SampleOracle.manifest.json | 1 + .../UT_ContractPermissionDescriptor.cs | 19 ++- .../SmartContract/Native/UT_StdLib.cs | 4 + .../SmartContract/UT_InteropService.cs | 123 ++++++++++++++++++ 19 files changed, 261 insertions(+), 10 deletions(-) create mode 100644 tests/Neo.UnitTests/SmartContract/Manifest/TestFile/SampleContractCall.manifest.json create mode 100644 tests/Neo.UnitTests/SmartContract/Manifest/TestFile/SampleEvent.manifest.json create mode 100644 tests/Neo.UnitTests/SmartContract/Manifest/TestFile/SampleException.manifest.json create mode 100644 tests/Neo.UnitTests/SmartContract/Manifest/TestFile/SampleHelloWorld.manifest.json create mode 100644 tests/Neo.UnitTests/SmartContract/Manifest/TestFile/SampleNep17Token.manifest.json create mode 100644 tests/Neo.UnitTests/SmartContract/Manifest/TestFile/SampleOracle.manifest.json diff --git a/src/Neo/SmartContract/Manifest/ContractAbi.cs b/src/Neo/SmartContract/Manifest/ContractAbi.cs index 3660d1a99e..cedd431d62 100644 --- a/src/Neo/SmartContract/Manifest/ContractAbi.cs +++ b/src/Neo/SmartContract/Manifest/ContractAbi.cs @@ -62,8 +62,8 @@ public static ContractAbi FromJson(JObject json) { ContractAbi abi = new() { - Methods = ((JArray)json["methods"]).Select(u => ContractMethodDescriptor.FromJson((JObject)u)).ToArray(), - Events = ((JArray)json["events"]).Select(u => ContractEventDescriptor.FromJson((JObject)u)).ToArray() + Methods = ((JArray)json!["methods"])?.Select(u => ContractMethodDescriptor.FromJson((JObject)u)).ToArray() ?? [], + Events = ((JArray)json!["events"])?.Select(u => ContractEventDescriptor.FromJson((JObject)u)).ToArray() ?? [] }; if (abi.Methods.Length == 0) throw new FormatException(); return abi; diff --git a/src/Neo/SmartContract/Manifest/ContractManifest.cs b/src/Neo/SmartContract/Manifest/ContractManifest.cs index 078e8fd35e..b1bd317e41 100644 --- a/src/Neo/SmartContract/Manifest/ContractManifest.cs +++ b/src/Neo/SmartContract/Manifest/ContractManifest.cs @@ -112,20 +112,21 @@ public static ContractManifest FromJson(JObject json) { ContractManifest manifest = new() { - Name = json["name"].GetString(), - Groups = ((JArray)json["groups"]).Select(u => ContractGroup.FromJson((JObject)u)).ToArray(), - SupportedStandards = ((JArray)json["supportedstandards"]).Select(u => u.GetString()).ToArray(), + Name = json["name"]!.GetString(), + Groups = ((JArray)json["groups"])?.Select(u => ContractGroup.FromJson((JObject)u)).ToArray() ?? [], + SupportedStandards = ((JArray)json["supportedstandards"])?.Select(u => u.GetString()).ToArray() ?? [], Abi = ContractAbi.FromJson((JObject)json["abi"]), - Permissions = ((JArray)json["permissions"]).Select(u => ContractPermission.FromJson((JObject)u)).ToArray(), + Permissions = ((JArray)json["permissions"])?.Select(u => ContractPermission.FromJson((JObject)u)).ToArray() ?? [], Trusts = WildcardContainer.FromJson(json["trusts"], u => ContractPermissionDescriptor.FromJson((JString)u)), Extra = (JObject)json["extra"] }; + if (string.IsNullOrEmpty(manifest.Name)) throw new FormatException(); _ = manifest.Groups.ToDictionary(p => p.PubKey); if (json["features"] is not JObject features || features.Count != 0) throw new FormatException(); - if (manifest.SupportedStandards.Any(p => string.IsNullOrEmpty(p))) + if (manifest.SupportedStandards.Any(string.IsNullOrEmpty)) throw new FormatException(); _ = manifest.SupportedStandards.ToDictionary(p => p); _ = manifest.Permissions.ToDictionary(p => p.Contract); diff --git a/tests/Neo.Json.UnitTests/UT_JArray.cs b/tests/Neo.Json.UnitTests/UT_JArray.cs index 40388d11fc..b6c603ca2a 100644 --- a/tests/Neo.Json.UnitTests/UT_JArray.cs +++ b/tests/Neo.Json.UnitTests/UT_JArray.cs @@ -254,5 +254,18 @@ public void TestAsString() var s = jArray.AsString(); Assert.AreEqual(s, "{\"name\":\"alice\",\"age\":30,\"score\":100.001,\"gender\":\"female\",\"isMarried\":true,\"pet\":{\"name\":\"Tom\",\"type\":\"cat\"}},{\"name\":\"bob\",\"age\":100000,\"score\":0.001,\"gender\":\"male\",\"isMarried\":false,\"pet\":{\"name\":\"Paul\",\"type\":\"dog\"}}"); } + + [TestMethod] + public void TestClone() + { + var jArray = new JArray + { + alice, + bob, + }; + var a = jArray.AsString(); + var b = jArray.Clone().AsString(); + a.Should().Be(b); + } } } diff --git a/tests/Neo.Json.UnitTests/UT_JBoolean.cs b/tests/Neo.Json.UnitTests/UT_JBoolean.cs index 3ab19bd1b3..0e81e99c35 100644 --- a/tests/Neo.Json.UnitTests/UT_JBoolean.cs +++ b/tests/Neo.Json.UnitTests/UT_JBoolean.cs @@ -36,8 +36,10 @@ public void TestEqual() { Assert.IsTrue(jTrue.Equals(new JBoolean(true))); Assert.IsTrue(jTrue == new JBoolean(true)); + Assert.IsTrue(jTrue != new JBoolean(false)); Assert.IsTrue(jFalse.Equals(new JBoolean())); Assert.IsTrue(jFalse == new JBoolean()); + Assert.IsTrue(jFalse.GetBoolean().ToString().ToLowerInvariant() == jFalse.ToString()); } } } diff --git a/tests/Neo.Json.UnitTests/UT_JNumber.cs b/tests/Neo.Json.UnitTests/UT_JNumber.cs index 6eb0598fd3..df8bdca619 100644 --- a/tests/Neo.Json.UnitTests/UT_JNumber.cs +++ b/tests/Neo.Json.UnitTests/UT_JNumber.cs @@ -9,6 +9,8 @@ // Redistribution and use in source and binary forms with or without // modifications are permitted. +using System.Numerics; + namespace Neo.Json.UnitTests { enum Woo @@ -72,6 +74,27 @@ public void TestEqual() Assert.IsTrue(minInt.Equals(JNumber.MIN_SAFE_INTEGER)); Assert.IsTrue(minInt == JNumber.MIN_SAFE_INTEGER); Assert.IsTrue(zero == new JNumber()); + Assert.IsFalse(zero != new JNumber()); + Assert.IsTrue(zero.AsNumber() == zero.GetNumber()); + Assert.IsFalse(zero == null); + + var jnum = new JNumber(1); + jnum.Equals(new JNumber(1)).Should().BeTrue(); + jnum.Equals((uint)1).Should().BeTrue(); + jnum.Equals((int)1).Should().BeTrue(); + jnum.Equals((ulong)1).Should().BeTrue(); + jnum.Equals((long)1).Should().BeTrue(); + jnum.Equals((byte)1).Should().BeTrue(); + jnum.Equals((sbyte)1).Should().BeTrue(); + jnum.Equals((short)1).Should().BeTrue(); + jnum.Equals((ushort)1).Should().BeTrue(); + jnum.Equals((decimal)1).Should().BeTrue(); + jnum.Equals((float)1).Should().BeTrue(); + jnum.Equals((double)1).Should().BeTrue(); + jnum.Equals(null).Should().BeFalse(); + var x = jnum; + jnum.Equals(x).Should().BeTrue(); + Assert.ThrowsException(() => jnum.Equals(new BigInteger(1))); } } } diff --git a/tests/Neo.Json.UnitTests/UT_JString.cs b/tests/Neo.Json.UnitTests/UT_JString.cs index 7e2bec9834..3f0ca159ab 100644 --- a/tests/Neo.Json.UnitTests/UT_JString.cs +++ b/tests/Neo.Json.UnitTests/UT_JString.cs @@ -63,10 +63,22 @@ public void TestGetEnum() public void TestEqual() { var str = "hello world"; + var str2 = "hello world2"; var jString = new JString(str); - Assert.IsTrue(jString.Equals(str)); + var jString2 = new JString(str2); + Assert.IsTrue(jString == str); - Assert.IsTrue(jString != "hello world2"); + Assert.IsFalse(jString == null); + Assert.IsTrue(jString != str2); + Assert.IsFalse(jString == str2); + + Assert.AreEqual(str, jString.GetString()); + Assert.IsTrue(jString.Equals(str)); + Assert.IsFalse(jString.Equals(jString2)); + Assert.IsFalse(jString.Equals(null)); + Assert.IsFalse(jString.Equals(123)); + var reference = jString; + Assert.IsTrue(jString.Equals(reference)); } } } diff --git a/tests/Neo.UnitTests/Cryptography/UT_BloomFilter.cs b/tests/Neo.UnitTests/Cryptography/UT_BloomFilter.cs index 907a5df2b9..f7bc1789dd 100644 --- a/tests/Neo.UnitTests/Cryptography/UT_BloomFilter.cs +++ b/tests/Neo.UnitTests/Cryptography/UT_BloomFilter.cs @@ -39,6 +39,8 @@ public void TestBloomFIlterConstructorGetKMTweak() uint nTweak = 123456; Action action = () => new BloomFilter(m, n, nTweak); action.Should().Throw(); + action = () => new BloomFilter(m, n, nTweak, new byte[] { 0, 1, 2, 3, 4 }); + action.Should().Throw(); m = 7; n = -10; diff --git a/tests/Neo.UnitTests/Cryptography/UT_Cryptography_Helper.cs b/tests/Neo.UnitTests/Cryptography/UT_Cryptography_Helper.cs index 01022baab9..4bfde89ba2 100644 --- a/tests/Neo.UnitTests/Cryptography/UT_Cryptography_Helper.cs +++ b/tests/Neo.UnitTests/Cryptography/UT_Cryptography_Helper.cs @@ -41,6 +41,17 @@ public void TestBase58CheckDecode() input = "3vQB7B6MrGQZaxCuFg4og"; action = () => input.Base58CheckDecode(); action.Should().Throw(); + + Assert.ThrowsException(() => string.Empty.Base58CheckDecode()); + } + + [TestMethod] + public void TestMurmurReadOnlySpan() + { + ReadOnlySpan input = "Hello, world!"u8; + byte[] input2 = input.ToArray(); + input.Murmur32(0).Should().Be(input2.Murmur32(0)); + input.Murmur128(0).Should().Equal(input2.Murmur128(0)); } [TestMethod] @@ -50,6 +61,19 @@ public void TestSha256() byte[] result = value.Sha256(0, value.Length); string resultStr = result.ToHexString(); resultStr.Should().Be("b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9"); + value.Sha256().Should().Equal(result); + ((Span)value).Sha256().Should().Equal(result); + ((ReadOnlySpan)value).Sha256().Should().Equal(result); + } + + [TestMethod] + public void TestKeccak256() + { + var input = "Hello, world!"u8.ToArray(); + var result = input.Keccak256(); + result.ToHexString().Should().Be("b6e16d27ac5ab427a7f68900ac5559ce272dc6c37c82b3e052246c82244c50e4"); + ((Span)input).Keccak256().Should().Equal(result); + ((ReadOnlySpan)input).Keccak256().Should().Equal(result); } [TestMethod] diff --git a/tests/Neo.UnitTests/Neo.UnitTests.csproj b/tests/Neo.UnitTests/Neo.UnitTests.csproj index fb246cbdc3..ce6d3b41a4 100644 --- a/tests/Neo.UnitTests/Neo.UnitTests.csproj +++ b/tests/Neo.UnitTests/Neo.UnitTests.csproj @@ -12,6 +12,9 @@ + + PreserveNewest + PreserveNewest PreserveNewest diff --git a/tests/Neo.UnitTests/Network/P2P/Payloads/UT_Block.cs b/tests/Neo.UnitTests/Network/P2P/Payloads/UT_Block.cs index 2021e5a187..075c083df2 100644 --- a/tests/Neo.UnitTests/Network/P2P/Payloads/UT_Block.cs +++ b/tests/Neo.UnitTests/Network/P2P/Payloads/UT_Block.cs @@ -13,7 +13,10 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.IO; using Neo.Json; +using Neo.Ledger; using Neo.Network.P2P.Payloads; +using Neo.SmartContract; +using Neo.SmartContract.Native; namespace Neo.UnitTests.Network.P2P.Payloads { @@ -21,6 +24,15 @@ namespace Neo.UnitTests.Network.P2P.Payloads public class UT_Block { Block uut; + private static ApplicationEngine GetEngine(bool hasContainer = false, bool hasSnapshot = false, bool hasBlock = false, bool addScript = true, long gas = 20_00000000) + { + var tx = hasContainer ? TestUtils.GetTransaction(UInt160.Zero) : null; + var snapshot = hasSnapshot ? TestBlockchain.GetTestSnapshot() : null; + var block = hasBlock ? new Block { Header = new Header() } : null; + var engine = ApplicationEngine.Create(TriggerType.Application, tx, snapshot, block, TestBlockchain.TheNeoSystem.Settings, gas: gas); + if (addScript) engine.LoadScript(new byte[] { 0x01 }); + return engine; + } [TestInitialize] public void TestSetup() @@ -136,6 +148,15 @@ private void AssertStandardBlockTestVals(UInt256 val256, UInt256 merkRoot, UInt1 public void Equals_SameObj() { uut.Equals(uut).Should().BeTrue(); + var obj = uut as object; + uut.Equals(obj).Should().BeTrue(); + } + + [TestMethod] + public void TestGetHashCode() + { + var snapshot = GetEngine(true, true).Snapshot; + NativeContract.Ledger.GetBlock(snapshot, 0).GetHashCode().Should().Be(-626492395); } [TestMethod] diff --git a/tests/Neo.UnitTests/SmartContract/Manifest/TestFile/SampleContractCall.manifest.json b/tests/Neo.UnitTests/SmartContract/Manifest/TestFile/SampleContractCall.manifest.json new file mode 100644 index 0000000000..bfbee88473 --- /dev/null +++ b/tests/Neo.UnitTests/SmartContract/Manifest/TestFile/SampleContractCall.manifest.json @@ -0,0 +1 @@ +{"name":"SampleContractCall","groups":[],"features":{},"supportedstandards":[],"abi":{"methods":[{"name":"onNEP17Payment","parameters":[{"name":"from","type":"Hash160"},{"name":"amount","type":"Integer"},{"name":"data","type":"Integer"}],"returntype":"Void","offset":0,"safe":false},{"name":"_initialize","parameters":[],"returntype":"Void","offset":91,"safe":false}],"events":[]},"permissions":[],"trusts":[],"extra":{"Author":"core-dev","Version":"0.0.1","Description":"A sample contract to demonstrate how to call a contract","Sourcecode":"https://github.com/neo-project/neo-devpack-dotnet/tree/master/examples/"}} \ No newline at end of file diff --git a/tests/Neo.UnitTests/SmartContract/Manifest/TestFile/SampleEvent.manifest.json b/tests/Neo.UnitTests/SmartContract/Manifest/TestFile/SampleEvent.manifest.json new file mode 100644 index 0000000000..7e71a2f2a5 --- /dev/null +++ b/tests/Neo.UnitTests/SmartContract/Manifest/TestFile/SampleEvent.manifest.json @@ -0,0 +1 @@ +{"name":"SampleEvent","groups":[],"features":{},"supportedstandards":[],"abi":{"methods":[{"name":"main","parameters":[],"returntype":"Boolean","offset":0,"safe":false}],"events":[{"name":"new_event_name","parameters":[{"name":"arg1","type":"ByteArray"},{"name":"arg2","type":"String"},{"name":"arg3","type":"Integer"}]},{"name":"event2","parameters":[{"name":"arg1","type":"ByteArray"},{"name":"arg2","type":"Integer"}]}]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":{"Author":"code-dev","Description":"A sample contract that demonstrates how to use Events","Version":"0.0.1","Sourcecode":"https://github.com/neo-project/neo-devpack-dotnet/tree/master/examples/"}} \ No newline at end of file diff --git a/tests/Neo.UnitTests/SmartContract/Manifest/TestFile/SampleException.manifest.json b/tests/Neo.UnitTests/SmartContract/Manifest/TestFile/SampleException.manifest.json new file mode 100644 index 0000000000..5d916af0f3 --- /dev/null +++ b/tests/Neo.UnitTests/SmartContract/Manifest/TestFile/SampleException.manifest.json @@ -0,0 +1 @@ +{"name":"SampleException","groups":[],"features":{},"supportedstandards":[],"abi":{"methods":[{"name":"try01","parameters":[],"returntype":"Any","offset":0,"safe":false},{"name":"try02","parameters":[],"returntype":"Any","offset":77,"safe":false},{"name":"try03","parameters":[],"returntype":"Any","offset":166,"safe":false},{"name":"tryNest","parameters":[],"returntype":"Any","offset":259,"safe":false},{"name":"tryFinally","parameters":[],"returntype":"Any","offset":404,"safe":false},{"name":"tryFinallyAndRethrow","parameters":[],"returntype":"Any","offset":474,"safe":false},{"name":"tryCatch","parameters":[],"returntype":"Any","offset":550,"safe":false},{"name":"tryWithTwoFinally","parameters":[],"returntype":"Any","offset":628,"safe":false},{"name":"tryecpointCast","parameters":[],"returntype":"Any","offset":920,"safe":false},{"name":"tryvalidByteString2Ecpoint","parameters":[],"returntype":"Any","offset":1010,"safe":false},{"name":"tryinvalidByteArray2UInt160","parameters":[],"returntype":"Any","offset":1100,"safe":false},{"name":"tryvalidByteArray2UInt160","parameters":[],"returntype":"Any","offset":1190,"safe":false},{"name":"tryinvalidByteArray2UInt256","parameters":[],"returntype":"Any","offset":1280,"safe":false},{"name":"tryvalidByteArray2UInt256","parameters":[],"returntype":"Any","offset":1370,"safe":false},{"name":"tryNULL2Ecpoint_1","parameters":[],"returntype":"Array","offset":1476,"safe":false},{"name":"tryNULL2Uint160_1","parameters":[],"returntype":"Array","offset":1652,"safe":false},{"name":"tryNULL2Uint256_1","parameters":[],"returntype":"Array","offset":1828,"safe":false},{"name":"tryNULL2Bytestring_1","parameters":[],"returntype":"Array","offset":1990,"safe":false},{"name":"tryUncatchableException","parameters":[],"returntype":"Any","offset":2141,"safe":false},{"name":"_initialize","parameters":[],"returntype":"Void","offset":2219,"safe":false}],"events":[]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":{"Author":"core-dev","Description":"A sample contract to demonstrate how to handle exception","Version":"0.0.1","Sourcecode":"https://github.com/neo-project/neo-devpack-dotnet/tree/master/examples/"}} \ No newline at end of file diff --git a/tests/Neo.UnitTests/SmartContract/Manifest/TestFile/SampleHelloWorld.manifest.json b/tests/Neo.UnitTests/SmartContract/Manifest/TestFile/SampleHelloWorld.manifest.json new file mode 100644 index 0000000000..4c7c4b9605 --- /dev/null +++ b/tests/Neo.UnitTests/SmartContract/Manifest/TestFile/SampleHelloWorld.manifest.json @@ -0,0 +1 @@ +{"name":"SampleHelloWorld","groups":[],"features":{},"supportedstandards":[],"abi":{"methods":[{"name":"sayHello","parameters":[],"returntype":"String","offset":0,"safe":true}],"events":[]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":{"Description":"A simple \u0060hello world\u0060 contract","E-mail":"dev@neo.org","Version":"0.0.1","Sourcecode":"https://github.com/neo-project/neo-devpack-dotnet/tree/master/examples/"}} \ No newline at end of file diff --git a/tests/Neo.UnitTests/SmartContract/Manifest/TestFile/SampleNep17Token.manifest.json b/tests/Neo.UnitTests/SmartContract/Manifest/TestFile/SampleNep17Token.manifest.json new file mode 100644 index 0000000000..bb9cf1682f --- /dev/null +++ b/tests/Neo.UnitTests/SmartContract/Manifest/TestFile/SampleNep17Token.manifest.json @@ -0,0 +1 @@ +{"name":"SampleNep17Token","groups":[],"features":{},"supportedstandards":["NEP-17"],"abi":{"methods":[{"name":"symbol","parameters":[],"returntype":"String","offset":1333,"safe":true},{"name":"decimals","parameters":[],"returntype":"Integer","offset":1348,"safe":true},{"name":"totalSupply","parameters":[],"returntype":"Integer","offset":52,"safe":true},{"name":"balanceOf","parameters":[{"name":"owner","type":"Hash160"}],"returntype":"Integer","offset":98,"safe":true},{"name":"transfer","parameters":[{"name":"from","type":"Hash160"},{"name":"to","type":"Hash160"},{"name":"amount","type":"Integer"},{"name":"data","type":"Any"}],"returntype":"Boolean","offset":362,"safe":false},{"name":"getOwner","parameters":[],"returntype":"Hash160","offset":808,"safe":true},{"name":"setOwner","parameters":[{"name":"newOwner","type":"Any"}],"returntype":"Void","offset":877,"safe":false},{"name":"getMinter","parameters":[],"returntype":"Hash160","offset":980,"safe":true},{"name":"setMinter","parameters":[{"name":"newMinter","type":"Hash160"}],"returntype":"Void","offset":1025,"safe":false},{"name":"mint","parameters":[{"name":"to","type":"Hash160"},{"name":"amount","type":"Integer"}],"returntype":"Void","offset":1103,"safe":false},{"name":"burn","parameters":[{"name":"account","type":"Hash160"},{"name":"amount","type":"Integer"}],"returntype":"Void","offset":1158,"safe":false},{"name":"verify","parameters":[],"returntype":"Boolean","offset":1216,"safe":true},{"name":"update","parameters":[{"name":"nefFile","type":"ByteArray"},{"name":"manifest","type":"String"}],"returntype":"Boolean","offset":1222,"safe":false},{"name":"_initialize","parameters":[],"returntype":"Void","offset":1271,"safe":false}],"events":[{"name":"Transfer","parameters":[{"name":"from","type":"Hash160"},{"name":"to","type":"Hash160"},{"name":"amount","type":"Integer"}]},{"name":"SetOwner","parameters":[{"name":"newOwner","type":"Hash160"}]},{"name":"SetMinter","parameters":[{"name":"newMinter","type":"Hash160"}]}]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":{"Author":"core-dev","Version":"0.0.1","Description":"A sample NEP-17 token","Sourcecode":"https://github.com/neo-project/neo-devpack-dotnet/tree/master/examples/"}} \ No newline at end of file diff --git a/tests/Neo.UnitTests/SmartContract/Manifest/TestFile/SampleOracle.manifest.json b/tests/Neo.UnitTests/SmartContract/Manifest/TestFile/SampleOracle.manifest.json new file mode 100644 index 0000000000..8570ccb3fb --- /dev/null +++ b/tests/Neo.UnitTests/SmartContract/Manifest/TestFile/SampleOracle.manifest.json @@ -0,0 +1 @@ +{"name":"SampleOracle","groups":[],"features":{},"supportedstandards":[],"abi":{"methods":[{"name":"getResponse","parameters":[],"returntype":"String","offset":0,"safe":true},{"name":"doRequest","parameters":[],"returntype":"Void","offset":35,"safe":false},{"name":"onOracleResponse","parameters":[{"name":"requestedUrl","type":"String"},{"name":"userData","type":"Any"},{"name":"oracleResponse","type":"Integer"},{"name":"jsonString","type":"String"}],"returntype":"Void","offset":333,"safe":false}],"events":[]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":{"Author":"code-dev","Description":"A sample contract to demonstrate how to use Example.SmartContract.Oracle Service","Version":"0.0.1","Sourcecode":"https://github.com/neo-project/neo-devpack-dotnet/tree/master/examples/"}} \ No newline at end of file diff --git a/tests/Neo.UnitTests/SmartContract/Manifest/UT_ContractPermissionDescriptor.cs b/tests/Neo.UnitTests/SmartContract/Manifest/UT_ContractPermissionDescriptor.cs index 1ef2397d69..cfcd9baf1e 100644 --- a/tests/Neo.UnitTests/SmartContract/Manifest/UT_ContractPermissionDescriptor.cs +++ b/tests/Neo.UnitTests/SmartContract/Manifest/UT_ContractPermissionDescriptor.cs @@ -9,10 +9,13 @@ // Redistribution and use in source and binary forms with or without // modifications are permitted. +using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.Json; using Neo.SmartContract.Manifest; using Neo.SmartContract.Native; using Neo.Wallets; +using System; using System.Security.Cryptography; namespace Neo.UnitTests.SmartContract.Manifest @@ -34,7 +37,7 @@ public void TestCreateByECPointAndIsWildcard() } [TestMethod] - public void TestFromAndToJson() + public void TestContractPermissionDescriptorFromAndToJson() { byte[] privateKey = new byte[32]; RandomNumberGenerator rng = RandomNumberGenerator.Create(); @@ -44,6 +47,20 @@ public void TestFromAndToJson() ContractPermissionDescriptor result = ContractPermissionDescriptor.FromJson(temp.ToJson()); Assert.AreEqual(null, result.Hash); Assert.AreEqual(result.Group, result.Group); + Assert.ThrowsException(() => ContractPermissionDescriptor.FromJson(string.Empty)); + } + + [TestMethod] + public void TestContractManifestFromJson() + { + Assert.ThrowsException(() => ContractManifest.FromJson(new Json.JObject())); + var jsonFiles = System.IO.Directory.GetFiles(System.IO.Path.Combine("SmartContract", "Manifest", "TestFile")); + foreach (var item in jsonFiles) + { + var json = JObject.Parse(System.IO.File.ReadAllText(item)) as JObject; + var manifest = ContractManifest.FromJson(json); + manifest.ToJson().ToString().Should().Be(json.ToString()); + } } [TestMethod] diff --git a/tests/Neo.UnitTests/SmartContract/Native/UT_StdLib.cs b/tests/Neo.UnitTests/SmartContract/Native/UT_StdLib.cs index f36fa2cfa4..b5c9c198ec 100644 --- a/tests/Neo.UnitTests/SmartContract/Native/UT_StdLib.cs +++ b/tests/Neo.UnitTests/SmartContract/Native/UT_StdLib.cs @@ -9,6 +9,7 @@ // Redistribution and use in source and binary forms with or without // modifications are permitted. +using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.SmartContract; using Neo.SmartContract.Native; @@ -53,6 +54,9 @@ public void TestItoaAtoi() Assert.ThrowsException(() => StdLib.Atoi("a", 10)); Assert.ThrowsException(() => StdLib.Atoi("g", 16)); Assert.ThrowsException(() => StdLib.Atoi("a", 11)); + + StdLib.Atoi(StdLib.Itoa(BigInteger.One, 10)).Should().Be(BigInteger.One); + StdLib.Atoi(StdLib.Itoa(BigInteger.MinusOne, 10)).Should().Be(BigInteger.MinusOne); } [TestMethod] diff --git a/tests/Neo.UnitTests/SmartContract/UT_InteropService.cs b/tests/Neo.UnitTests/SmartContract/UT_InteropService.cs index 06290922da..1edcfbd9ca 100644 --- a/tests/Neo.UnitTests/SmartContract/UT_InteropService.cs +++ b/tests/Neo.UnitTests/SmartContract/UT_InteropService.cs @@ -10,6 +10,7 @@ // modifications are permitted. using Akka.TestKit.Xunit2; +using Akka.Util.Internal; using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.Cryptography; @@ -507,6 +508,41 @@ public void TestBlockchain_GetContract() NativeContract.ContractManagement.GetContract(engine.Snapshot, state.Hash).Hash.Should().Be(state.Hash); } + [TestMethod] + public void TestBlockchain_GetContractById() + { + var engine = GetEngine(true, true); + var contract = NativeContract.ContractManagement.GetContractById(engine.Snapshot, -1); + contract.Id.Should().Be(-1); + contract.Manifest.Name.Should().Be(nameof(ContractManagement)); + } + + [TestMethod] + public void TestBlockchain_HasMethod() + { + var engine = GetEngine(true, true); + NativeContract.ContractManagement.HasMethod(engine.Snapshot, NativeContract.NEO.Hash, "symbol", 0).Should().Be(true); + NativeContract.ContractManagement.HasMethod(engine.Snapshot, NativeContract.NEO.Hash, "transfer", 4).Should().Be(true); + } + + [TestMethod] + public void TestBlockchain_ListContracts() + { + var engine = GetEngine(true, true); + var list = NativeContract.ContractManagement.ListContracts(engine.Snapshot); + list.ForEach(p => p.Id.Should().BeLessThan(0)); + + var snapshot = TestBlockchain.GetTestSnapshot(); + var state = TestUtils.GetContract(); + snapshot.AddContract(state.Hash, state); + engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot); + engine.LoadScript(new byte[] { 0x01 }); + NativeContract.ContractManagement.GetContract(engine.Snapshot, state.Hash).Hash.Should().Be(state.Hash); + + var list2 = NativeContract.ContractManagement.ListContracts(engine.Snapshot); + list2.Count().Should().Be(list.Count() + 1); + } + [TestMethod] public void TestStorage_GetContext() { @@ -739,5 +775,92 @@ private static ApplicationEngine GetEngine(bool hasContainer = false, bool hasSn if (addScript) engine.LoadScript(new byte[] { 0x01 }); return engine; } + + [TestMethod] + public void TestVerifyWithECDsaV0() + { + var privateKey = new byte[32]; + using var rng = System.Security.Cryptography.RandomNumberGenerator.Create(); + rng.GetBytes(privateKey); + var publicKeyR1 = new KeyPair(privateKey).PublicKey.ToArray(); + var publicKeyK1 = (Neo.Cryptography.ECC.ECCurve.Secp256k1.G * privateKey).ToArray(); + var hexMessage = "Hello, world!"u8.ToArray(); + var signatureR1 = Crypto.Sign(hexMessage, privateKey, Neo.Cryptography.ECC.ECCurve.Secp256r1); + var signatureK1 = Crypto.Sign(hexMessage, privateKey, Neo.Cryptography.ECC.ECCurve.Secp256k1); + + var result = CryptoLib.VerifyWithECDsaV0(hexMessage, publicKeyR1, signatureR1, NamedCurveHash.secp256r1SHA256); + result.Should().BeTrue(); + result = CryptoLib.VerifyWithECDsaV0(hexMessage, publicKeyK1, signatureK1, NamedCurveHash.secp256k1SHA256); + result.Should().BeTrue(); + result = CryptoLib.VerifyWithECDsaV0(hexMessage, publicKeyK1, new byte[0], NamedCurveHash.secp256k1SHA256); + result.Should().BeFalse(); + Assert.ThrowsException(() => CryptoLib.VerifyWithECDsaV0(hexMessage, publicKeyK1, new byte[64], NamedCurveHash.secp256r1Keccak256)); + } + + [TestMethod] + public void TestSha256() + { + var input = "Hello, world!"u8.ToArray(); + var actualHash = CryptoLib.Sha256(input); + var expectedHash = "315f5bdb76d078c43b8ac0064e4a0164612b1fce77c869345bfc94c75894edd3"; + actualHash.ToHexString().Should().Be(expectedHash); + } + + [TestMethod] + public void TestRIPEMD160() + { + var input = "Hello, world!"u8.ToArray(); + var actualHash = CryptoLib.RIPEMD160(input); + var expectedHash = "58262d1fbdbe4530d8865d3518c6d6e41002610f"; + actualHash.ToHexString().Should().Be(expectedHash); + } + + [TestMethod] + public void TestMurmur32() + { + var input = "Hello, world!"u8.ToArray(); + var actualHash = CryptoLib.Murmur32(input, 0); + var expectedHash = "433e36c0"; + actualHash.ToHexString().Should().Be(expectedHash); + } + + [TestMethod] + public void TestGetBlockHash() + { + var snapshot = GetEngine(true, true).Snapshot; + var hash = LedgerContract.Ledger.GetBlockHash(snapshot, 0); + var hash2 = LedgerContract.Ledger.GetBlock(snapshot, 0).Hash; + var hash3 = LedgerContract.Ledger.GetHeader(snapshot, 0).Hash; + hash.ToString().Should().Be(hash2.ToString()); + hash.ToString().Should().Be(hash3.ToString()); + hash.ToString().Should().Be("0x1f4d1defa46faa5e7b9b8d3f79a06bec777d7c26c4aa5f6f5899a291daa87c15"); + LedgerContract.Ledger.ContainsBlock(snapshot, hash).Should().BeTrue(); + } + + [TestMethod] + public void TestGetCandidateVote() + { + var snapshot = GetEngine(true, true).Snapshot; + var vote = LedgerContract.NEO.GetCandidateVote(snapshot, new ECPoint()); + vote.Should().Be(-1); + } + + [TestMethod] + public void TestContractPermissionDescriptorEquals() + { + var descriptor1 = ContractPermissionDescriptor.CreateWildcard(); + descriptor1.Equals(null).Should().BeFalse(); + descriptor1.Equals(null as object).Should().BeFalse(); + var descriptor2 = ContractPermissionDescriptor.Create(LedgerContract.NEO.Hash); + var descriptor3 = ContractPermissionDescriptor.Create(hash: null); + descriptor1.Equals(descriptor3).Should().BeTrue(); + descriptor1.Equals(descriptor3 as object).Should().BeTrue(); + var descriptor4 = ContractPermissionDescriptor.Create(group: null); + var descriptor5 = ContractPermissionDescriptor.Create(group: new ECPoint()); + descriptor1.Equals(descriptor4).Should().BeTrue(); + descriptor2.Equals(descriptor3).Should().BeFalse(); + descriptor5.Equals(descriptor3).Should().BeFalse(); + descriptor5.Equals(descriptor5).Should().BeTrue(); + } } }