From 12a6209037c0dc1c700630e9b67f4da38e63fa74 Mon Sep 17 00:00:00 2001 From: Ash R Date: Wed, 26 Jul 2017 04:04:57 +0100 Subject: [PATCH] Core unit tests 2 (#36) * Recreate unit tests on new branch, after source repo rebranding and renaming, faster than fixing a load of merge conflicts * finish testing CalculateNetFee in block.cs. Add some dummy classes to help test. Normalise the namespaces and remove unnecessary usings. * improve the culture testing of AssetState.cs GetName * Add a general unit test that will run all other unit tests, in a variety of cultures * Deserialize and Serialize unit tests for block.cs * fix tests so that daylight savings dont affect expected result * Block.cs tests for Equals() and Trim() and FromTrimmedData() * Update README with NEO and correct folder * test for RebuildMerkleRoot() * tests for tojson() and verify() when completely is false * test for block verify fail when consensus doesn't match * fix failing test from merge conflicts --- neo.UnitTests/README.md | 6 +- neo.UnitTests/TestBlockchain.cs | 146 +++++++++ neo.UnitTests/TestTransaction.cs | 18 ++ neo.UnitTests/TestUtils.cs | 12 +- neo.UnitTests/UT_AccountState.cs | 1 - neo.UnitTests/UT_AssetState.cs | 9 +- neo.UnitTests/UT_Block.cs | 521 +++++++++++++++++++++++++++---- neo.UnitTests/UT_Culture.cs | 88 ++++++ 8 files changed, 723 insertions(+), 78 deletions(-) create mode 100644 neo.UnitTests/TestBlockchain.cs create mode 100644 neo.UnitTests/TestTransaction.cs create mode 100644 neo.UnitTests/UT_Culture.cs diff --git a/neo.UnitTests/README.md b/neo.UnitTests/README.md index 5a8fcee344..9d8657d24a 100644 --- a/neo.UnitTests/README.md +++ b/neo.UnitTests/README.md @@ -1,7 +1,7 @@ -AntShares Unit Tests +NEO Unit Tests ==================== -This project is a work in progress, aiming to provide unit test coverage for the core AntShares code. +This project is a work in progress, aiming to provide unit test coverage for the core NEO code. Please note that we are aware that we are not using proper isolation / dependency injection / mocking techniques in these tests. To do that would require larger reworks of the base code which is a change for a later date in discussion with the core team, at the moment we are just aiming to get some basic coverage going. @@ -12,7 +12,7 @@ We use built in Visual Studio functionality with MSTest and the Microsoft.Visual To run the tests, build the solution to discover tests, then view and run the tests from the 'Test Explorer' window within Visual Studio. OR -With .NET Core SDK installed, use the CLI to navigate to the src\AntShares.UnitTest and use the command 'dotnet restore' to get packages, followed by 'dotnet test' to run tests. +With .NET Core SDK installed, use the CLI to navigate to the neo.UnitTest folder and use the command 'dotnet restore' to get packages, followed by 'dotnet test' to run tests. Coverage ==================== diff --git a/neo.UnitTests/TestBlockchain.cs b/neo.UnitTests/TestBlockchain.cs new file mode 100644 index 0000000000..1755746f5d --- /dev/null +++ b/neo.UnitTests/TestBlockchain.cs @@ -0,0 +1,146 @@ +using Neo.Core; +using System; +using System.Collections.Generic; +using Neo.Cryptography.ECC; + +namespace Neo.UnitTests +{ + public class TestBlockchain : Blockchain + { + private UInt256 _assetId; + + public TestBlockchain(UInt256 assetId) + { + _assetId = assetId; + } + + public override UInt256 CurrentBlockHash => throw new NotImplementedException(); + + public override UInt256 CurrentHeaderHash => throw new NotImplementedException(); + + public override uint HeaderHeight => throw new NotImplementedException(); + + public override uint Height => throw new NotImplementedException(); + + public override bool AddBlock(Block block) + { + throw new NotImplementedException(); + } + + public override bool ContainsBlock(UInt256 hash) + { + return true; // for verify in UT_Block + } + + public override bool ContainsTransaction(UInt256 hash) + { + throw new NotImplementedException(); + } + + public override bool ContainsUnspent(UInt256 hash, ushort index) + { + throw new NotImplementedException(); + } + + public override void Dispose() + { + // do nothing + } + + public override AccountState GetAccountState(UInt160 script_hash) + { + throw new NotImplementedException(); + } + + public override AssetState GetAssetState(UInt256 asset_id) + { + throw new NotImplementedException(); + } + + public override Block GetBlock(UInt256 hash) + { + throw new NotImplementedException(); + } + + public override UInt256 GetBlockHash(uint height) + { + throw new NotImplementedException(); + } + + public override ContractState GetContract(UInt160 hash) + { + throw new NotImplementedException(); + } + + public override IEnumerable GetEnrollments() + { + ECPoint ecp = TestUtils.StandbyValidators[0]; + return new ValidatorState[] { new ValidatorState() { PublicKey = ecp } }; + } + + public override Header GetHeader(uint height) + { + throw new NotImplementedException(); + } + + public override Header GetHeader(UInt256 hash) + { + throw new NotImplementedException(); + } + + public override Block GetNextBlock(UInt256 hash) + { + throw new NotImplementedException(); + } + + public override UInt256 GetNextBlockHash(UInt256 hash) + { + throw new NotImplementedException(); + } + + public override StorageItem GetStorageItem(StorageKey key) + { + throw new NotImplementedException(); + } + + public override long GetSysFeeAmount(UInt256 hash) + { + throw new NotImplementedException(); + } + + public override Transaction GetTransaction(UInt256 hash, out int height) + { + height = 0; + return new TestTransaction(_assetId, TransactionType.ClaimTransaction); + } + + public override Dictionary GetUnclaimed(UInt256 hash) + { + throw new NotImplementedException(); + } + + public override TransactionOutput GetUnspent(UInt256 hash, ushort index) + { + throw new NotImplementedException(); + } + + public override IEnumerable GetVotes(IEnumerable others) + { + VoteState vs = new VoteState() { Count = Fixed8.FromDecimal(1), PublicKeys = TestUtils.StandbyValidators}; + return new VoteState[] + { + vs + }; + } + + public override bool IsDoubleSpend(Transaction tx) + { + throw new NotImplementedException(); + } + + protected override void AddHeaders(IEnumerable
headers) + { + throw new NotImplementedException(); + } + } +} diff --git a/neo.UnitTests/TestTransaction.cs b/neo.UnitTests/TestTransaction.cs new file mode 100644 index 0000000000..dbf89ff621 --- /dev/null +++ b/neo.UnitTests/TestTransaction.cs @@ -0,0 +1,18 @@ +using Neo.Core; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Neo.UnitTests +{ + public class TestTransaction : Transaction + { + public TestTransaction(UInt256 assetId, TransactionType type) : base(type) + { + TransactionOutput transVal = new TransactionOutput(); + transVal.Value = Fixed8.FromDecimal(50); + transVal.AssetId = assetId; + base.Outputs = new TransactionOutput[1] { transVal }; + } + } +} diff --git a/neo.UnitTests/TestUtils.cs b/neo.UnitTests/TestUtils.cs index b10e233d43..10663049bb 100644 --- a/neo.UnitTests/TestUtils.cs +++ b/neo.UnitTests/TestUtils.cs @@ -1,10 +1,6 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using Neo.Cryptography.ECC; -namespace Neo.UnitTest +namespace Neo.UnitTests { public static class TestUtils { @@ -18,5 +14,7 @@ public static byte[] GetByteArray(int length, byte firstByte) } return array; } - } + + public static readonly ECPoint[] StandbyValidators = new ECPoint[] { ECPoint.DecodePoint("03b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c".HexToBytes(), ECCurve.Secp256r1) }; + } } diff --git a/neo.UnitTests/UT_AccountState.cs b/neo.UnitTests/UT_AccountState.cs index 3954700dcc..4b93c6d371 100644 --- a/neo.UnitTests/UT_AccountState.cs +++ b/neo.UnitTests/UT_AccountState.cs @@ -5,7 +5,6 @@ using System.IO; using System.Text; using Neo.Core; -using Neo.UnitTest; namespace Neo.UnitTests { diff --git a/neo.UnitTests/UT_AssetState.cs b/neo.UnitTests/UT_AssetState.cs index ddb8ced631..2eb2675c8b 100644 --- a/neo.UnitTests/UT_AssetState.cs +++ b/neo.UnitTests/UT_AssetState.cs @@ -2,16 +2,12 @@ using Neo.Cryptography.ECC; using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; -using System; -using System.Collections.Generic; using System.Globalization; using System.IO; -using System.Linq; using System.Text; -using System.Threading.Tasks; using System.Threading; -namespace Neo.UnitTest +namespace Neo.UnitTests { [TestClass] public class UT_AssetState @@ -215,7 +211,6 @@ private void setupAssetStateWithValues(AssetState assetState, out UInt256 assetI { assetId = new UInt256(TestUtils.GetByteArray(32, 0x20)); assetState.AssetId = assetId; - assetType = AssetType.Token; assetState.AssetType = assetType; @@ -347,7 +342,6 @@ public void Deserialize() bool isFrozen; setupAssetStateWithValues(new AssetState(), out assetId, out assetType, out name, out amount, out available, out precision, out fee, out feeAddress, out owner, out admin, out issuer, out expiration, out isFrozen); - byte[] data = new byte[] { 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 96, 3, 110, 101, 111, 42, 0, 0, 0, 0, 0, 0, 0, 43, 0, 0, 0, 0, 0, 0, 0, 66, 0, 44, 0, 0, 0, 0, 0, 0, 0, 33, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 0, 34, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 35, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 42, 0, 0, 0, 1 }; int index = 0; using (MemoryStream ms = new MemoryStream(data, index, data.Length - index, false)) @@ -399,7 +393,6 @@ public void Serialize() } byte[] requiredData = new byte[] { 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 96, 3, 110, 101, 111, 42, 0, 0, 0, 0, 0, 0, 0, 43, 0, 0, 0, 0, 0, 0, 0, 66, 0, 44, 0, 0, 0, 0, 0, 0, 0, 33, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 0, 34, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 35, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 42, 0, 0, 0, 1 }; - data.Length.Should().Be(130); for (int i = 0; i < 130; i++) { diff --git a/neo.UnitTests/UT_Block.cs b/neo.UnitTests/UT_Block.cs index e142c6ae40..7950f6976c 100644 --- a/neo.UnitTests/UT_Block.cs +++ b/neo.UnitTests/UT_Block.cs @@ -5,12 +5,11 @@ using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using System; -using System.Collections.Generic; -using System.Linq; +using System.IO; using System.Text; -using System.Threading.Tasks; +using Neo.IO.Json; -namespace Neo.UnitTest +namespace Neo.UnitTests { [TestClass] public class UT_Block @@ -37,61 +36,76 @@ public void Transactions_Set() uut.Transactions.Length.Should().Be(10); } - private void setupBlockWithValues(out UInt256 val256, out uint timestampVal, out uint indexVal, out ulong consensusDataVal, out Witness scriptVal) + private void setupBlockWithValues(Block block, UInt256 val256, out UInt256 merkRootVal, out UInt160 val160, out uint timestampVal, out uint indexVal, out ulong consensusDataVal, out Witness scriptVal, out Transaction[] transactionsVal, int numberOfTransactions) { - val256 = UInt256.Zero; - uut.PrevHash = val256; - uut.MerkleRoot = val256; - timestampVal = DateTime.Now.ToTimestamp(); - uut.Timestamp = timestampVal; + block.PrevHash = val256; + merkRootVal = new UInt256(new byte[] { 214, 87, 42, 69, 155, 149, 217, 19, 107, 122, 113, 60, 84, 133, 202, 112, 159, 158, 250, 79, 8, 241, 194, 93, 215, 146, 103, 45, 43, 215, 91, 251 }); + block.MerkleRoot = merkRootVal; + timestampVal = new DateTime(1968, 06, 01, 0, 0, 0, DateTimeKind.Utc).ToTimestamp(); + block.Timestamp = timestampVal; indexVal = 0; - uut.Index = indexVal; + block.Index = indexVal; consensusDataVal = 30; - uut.ConsensusData = consensusDataVal; - UInt160 val160 = UInt160.Zero; - uut.NextConsensus = val160; - uut.Transactions = new Transaction[0]; + block.ConsensusData = consensusDataVal; + val160 = UInt160.Zero; + block.NextConsensus = val160; scriptVal = new Witness { InvocationScript = new byte[0], VerificationScript = new[] { (byte)OpCode.PUSHT } }; - uut.Script = scriptVal; + block.Script = scriptVal; + + transactionsVal = new Transaction[numberOfTransactions]; + if (numberOfTransactions > 0) + { + for (int i = 0; i < numberOfTransactions; i++) + { + transactionsVal[i] = getMinerTransaction(); + } + } + + block.Transactions = transactionsVal; } [TestMethod] public void Header_Get() { - UInt256 val256; + UInt256 val256 = UInt256.Zero; + UInt256 merkRootVal; + UInt160 val160; uint timestampVal, indexVal; ulong consensusDataVal; Witness scriptVal; - setupBlockWithValues(out val256, out timestampVal, out indexVal, out consensusDataVal, out scriptVal); + Transaction[] transactionsVal; + setupBlockWithValues(uut, val256, out merkRootVal, out val160, out timestampVal, out indexVal, out consensusDataVal, out scriptVal, out transactionsVal, 0); uut.Header.Should().NotBeNull(); uut.Header.PrevHash.Should().Be(val256); - uut.Header.MerkleRoot.Should().Be(val256); + uut.Header.MerkleRoot.Should().Be(merkRootVal); uut.Header.Timestamp.Should().Be(timestampVal); uut.Header.Index.Should().Be(indexVal); uut.Header.ConsensusData.Should().Be(consensusDataVal); uut.Header.Script.Should().Be(scriptVal); } - + [TestMethod] public void Size_Get() - { - UInt256 val256; + { + UInt256 val256 = UInt256.Zero; + UInt256 merkRootVal; + UInt160 val160; uint timestampVal, indexVal; ulong consensusDataVal; Witness scriptVal; - setupBlockWithValues(out val256, out timestampVal, out indexVal, out consensusDataVal, out scriptVal); - + Transaction[] transactionsVal; + setupBlockWithValues(uut, val256, out merkRootVal, out val160, out timestampVal, out indexVal, out consensusDataVal, out scriptVal, out transactionsVal, 0); // blockbase 4 + 32 + 32 + 4 + 4 + 8 + 20 + 1 + 3 // block 1 uut.Size.Should().Be(109); } - private static MinerTransaction getMinerTransaction() + private MinerTransaction getMinerTransaction() { return new MinerTransaction { @@ -103,28 +117,47 @@ private static MinerTransaction getMinerTransaction() }; } - private static ClaimTransaction getClaimTransaction() + private ClaimTransaction getClaimTransaction() { return new ClaimTransaction { Claims = new CoinReference[0] }; } - - private static readonly ECPoint[] StandbyValidators = new ECPoint[] { ECPoint.DecodePoint("03b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c".HexToBytes(), ECCurve.Secp256r1) }; - private static IssueTransaction getIssueTransaction(decimal outputVal) + + private IssueTransaction getIssueTransaction(bool inputVal, decimal outputVal, UInt256 assetId) { + setupTestBlockchain(assetId); + + CoinReference[] inputsVal; + if (inputVal) + { + inputsVal = new[] + { + new CoinReference + { + PrevHash = UInt256.Zero, + PrevIndex = 0 + } + }; + } + else + { + inputsVal = new CoinReference[0]; + } + + return new IssueTransaction { Attributes = new TransactionAttribute[0], - Inputs = new CoinReference[0], + Inputs = inputsVal, Outputs = new[] { new TransactionOutput { - AssetId = Blockchain.SystemCoin.Hash, + AssetId = assetId, Value = Fixed8.FromDecimal(outputVal), - ScriptHash = Contract.CreateMultiSigRedeemScript(1, new ECPoint[] { ECPoint.DecodePoint("03b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c".HexToBytes(), ECCurve.Secp256r1) }).ToScriptHash() + ScriptHash = Contract.CreateMultiSigRedeemScript(1, TestUtils.StandbyValidators).ToScriptHash() } }, Scripts = new[] @@ -138,14 +171,23 @@ private static IssueTransaction getIssueTransaction(decimal outputVal) }; } + private void setupTestBlockchain(UInt256 assetId) + { + Blockchain testBlockchain = new TestBlockchain(assetId); + Blockchain.RegisterBlockchain(testBlockchain); + } + [TestMethod] public void Size_Get_1_Transaction() { - UInt256 val256; + UInt256 val256 = UInt256.Zero; + UInt256 merkRootVal; + UInt160 val160; uint timestampVal, indexVal; ulong consensusDataVal; Witness scriptVal; - setupBlockWithValues(out val256, out timestampVal, out indexVal, out consensusDataVal, out scriptVal); + Transaction[] transactionsVal; + setupBlockWithValues(uut, val256, out merkRootVal, out val160, out timestampVal, out indexVal, out consensusDataVal, out scriptVal, out transactionsVal, 0); uut.Transactions = new Transaction[1] { getMinerTransaction() @@ -155,15 +197,18 @@ public void Size_Get_1_Transaction() // block 11 uut.Size.Should().Be(119); } - + [TestMethod] public void Size_Get_3_Transaction() { - UInt256 val256; + UInt256 val256 = UInt256.Zero; + UInt256 merkRootVal; + UInt160 val160; uint timestampVal, indexVal; ulong consensusDataVal; Witness scriptVal; - setupBlockWithValues(out val256, out timestampVal, out indexVal, out consensusDataVal, out scriptVal); + Transaction[] transactionsVal; + setupBlockWithValues(uut, val256, out merkRootVal, out val160, out timestampVal, out indexVal, out consensusDataVal, out scriptVal, out transactionsVal, 0); uut.Transactions = new Transaction[3] { getMinerTransaction(), @@ -179,11 +224,14 @@ public void Size_Get_3_Transaction() [TestMethod] public void CalculateNetFee_EmptyTransactions() { - UInt256 val256; + UInt256 val256 = UInt256.Zero; + UInt256 merkRootVal; + UInt160 val160; uint timestampVal, indexVal; ulong consensusDataVal; Witness scriptVal; - setupBlockWithValues(out val256, out timestampVal, out indexVal, out consensusDataVal, out scriptVal); + Transaction[] transactionsVal; + setupBlockWithValues(uut, val256, out merkRootVal, out val160, out timestampVal, out indexVal, out consensusDataVal, out scriptVal, out transactionsVal, 0); Block.CalculateNetFee(uut.Transactions).Should().Be(Fixed8.Zero); } @@ -191,11 +239,14 @@ public void CalculateNetFee_EmptyTransactions() [TestMethod] public void CalculateNetFee_Ignores_MinerTransactions() { - UInt256 val256; + UInt256 val256 = UInt256.Zero; + UInt256 merkRootVal; + UInt160 val160; uint timestampVal, indexVal; ulong consensusDataVal; Witness scriptVal; - setupBlockWithValues(out val256, out timestampVal, out indexVal, out consensusDataVal, out scriptVal); + Transaction[] transactionsVal; + setupBlockWithValues(uut, val256, out merkRootVal, out val160, out timestampVal, out indexVal, out consensusDataVal, out scriptVal, out transactionsVal, 0); uut.Transactions = new Transaction[1] { getMinerTransaction() @@ -207,11 +258,14 @@ public void CalculateNetFee_Ignores_MinerTransactions() [TestMethod] public void CalculateNetFee_Ignores_ClaimTransactions() { - UInt256 val256; + UInt256 val256 = UInt256.Zero; + UInt256 merkRootVal; + UInt160 val160; uint timestampVal, indexVal; ulong consensusDataVal; Witness scriptVal; - setupBlockWithValues(out val256, out timestampVal, out indexVal, out consensusDataVal, out scriptVal); + Transaction[] transactionsVal; + setupBlockWithValues(uut, val256, out merkRootVal, out val160, out timestampVal, out indexVal, out consensusDataVal, out scriptVal, out transactionsVal, 0); uut.Transactions = new Transaction[1] { getClaimTransaction() @@ -224,33 +278,382 @@ public void CalculateNetFee_Ignores_ClaimTransactions() [TestMethod] public void CalculateNetFee_Out() { - UInt256 val256; + UInt256 val256 = UInt256.Zero; + UInt256 merkRootVal; + UInt160 val160; uint timestampVal, indexVal; ulong consensusDataVal; Witness scriptVal; - setupBlockWithValues(out val256, out timestampVal, out indexVal, out consensusDataVal, out scriptVal); + Transaction[] transactionsVal; + setupBlockWithValues(uut, val256, out merkRootVal, out val160, out timestampVal, out indexVal, out consensusDataVal, out scriptVal, out transactionsVal, 0); uut.Transactions = new Transaction[1] { - getIssueTransaction(100) + getIssueTransaction(false, 100, Blockchain.SystemCoin.Hash) }; Block.CalculateNetFee(uut.Transactions).Should().Be(Fixed8.FromDecimal(-100)); } - //[TestMethod] - //public void CalculateNetFee_In() - //{ - // UInt256 val256; - // uint timestampVal, indexVal; - // ulong consensusDataVal; - // Witness scriptVal; - // setupBlockWithValues(out val256, out timestampVal, out indexVal, out consensusDataVal, out scriptVal); + [TestMethod] + public void CalculateNetFee_In() + { + UInt256 val256 = UInt256.Zero; + UInt256 merkRootVal; + UInt160 val160; + uint timestampVal, indexVal; + ulong consensusDataVal; + Witness scriptVal; + Transaction[] transactionsVal; + setupBlockWithValues(uut, val256, out merkRootVal, out val160, out timestampVal, out indexVal, out consensusDataVal, out scriptVal, out transactionsVal, 0); + + uut.Transactions = new Transaction[1] { + getIssueTransaction(true, 0, Blockchain.SystemCoin.Hash) + }; + + Block.CalculateNetFee(uut.Transactions).Should().Be(Fixed8.FromDecimal(50)); + } + + [TestMethod] + public void CalculateNetFee_In_And_Out() + { + UInt256 val256 = UInt256.Zero; + UInt256 merkRootVal; + UInt160 val160; + uint timestampVal, indexVal; + ulong consensusDataVal; + Witness scriptVal; + Transaction[] transactionsVal; + setupBlockWithValues(uut, val256, out merkRootVal, out val160, out timestampVal, out indexVal, out consensusDataVal, out scriptVal, out transactionsVal, 0); + + uut.Transactions = new Transaction[1] { + getIssueTransaction(true, 100, Blockchain.SystemCoin.Hash) + }; + + Block.CalculateNetFee(uut.Transactions).Should().Be(Fixed8.FromDecimal(-50)); + } + + [TestMethod] + public void CalculateNetFee_SystemFee() + { + UInt256 val256 = UInt256.Zero; + UInt256 merkRootVal; + UInt160 val160; + uint timestampVal, indexVal; + ulong consensusDataVal; + Witness scriptVal; + Transaction[] transactionsVal; + setupBlockWithValues(uut, val256, out merkRootVal, out val160, out timestampVal, out indexVal, out consensusDataVal, out scriptVal, out transactionsVal, 0); + + uut.Transactions = new Transaction[1] { + getIssueTransaction(true, 0, new UInt256(TestUtils.GetByteArray(32, 0x42))) + }; + + Block.CalculateNetFee(uut.Transactions).Should().Be(Fixed8.FromDecimal(-500)); + } + + [TestMethod] + public void Serialize() + { + UInt256 val256 = UInt256.Zero; + UInt256 merkRootVal; + UInt160 val160; + uint timestampVal, indexVal; + ulong consensusDataVal; + Witness scriptVal; + Transaction[] transactionsVal; + setupBlockWithValues(uut, val256, out merkRootVal, out val160, out timestampVal, out indexVal, out consensusDataVal, out scriptVal, out transactionsVal, 1); + + byte[] data; + using (MemoryStream stream = new MemoryStream()) + { + using (BinaryWriter writer = new BinaryWriter(stream, Encoding.ASCII, true)) + { + uut.Serialize(writer); + data = stream.ToArray(); + } + } + + byte[] requiredData = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 214, 87, 42, 69, 155, 149, 217, 19, 107, 122, 113, 60, 84, 133, 202, 112, 159, 158, 250, 79, 8, 241, 194, 93, 215, 146, 103, 45, 43, 215, 91, 251, 128, 171, 4, 253, 0, 0, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 81, 1, 0, 0, 29, 172, 43, 124, 0, 0, 0, 0 }; + + data.Length.Should().Be(119); + for (int i = 0; i < 119; i++) + { + data[i].Should().Be(requiredData[i]); + } + } + + [TestMethod] + public void Deserialize() + { + UInt256 val256 = UInt256.Zero; + UInt256 merkRoot; + UInt160 val160; + uint timestampVal, indexVal; + ulong consensusDataVal; + Witness scriptVal; + Transaction[] transactionsVal; + setupBlockWithValues(new Block(), val256, out merkRoot, out val160, out timestampVal, out indexVal, out consensusDataVal, out scriptVal, out transactionsVal, 1); + + uut.MerkleRoot = merkRoot; // need to set for deserialise to be valid + + byte[] data = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 214, 87, 42, 69, 155, 149, 217, 19, 107, 122, 113, 60, 84, 133, 202, 112, 159, 158, 250, 79, 8, 241, 194, 93, 215, 146, 103, 45, 43, 215, 91, 251, 128, 171, 4, 253, 0, 0, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 81, 1, 0, 0, 29, 172, 43, 124, 0, 0, 0, 0 }; + int index = 0; + using (MemoryStream ms = new MemoryStream(data, index, data.Length - index, false)) + { + using (BinaryReader reader = new BinaryReader(ms)) + { + uut.Deserialize(reader); + } + } + + assertStandardBlockTestVals(val256, merkRoot, val160, timestampVal, indexVal, consensusDataVal, scriptVal, transactionsVal); + } + + private void assertStandardBlockTestVals(UInt256 val256, UInt256 merkRoot, UInt160 val160, uint timestampVal, uint indexVal, ulong consensusDataVal, Witness scriptVal, Transaction[] transactionsVal, bool testTransactions = true) + { + uut.PrevHash.Should().Be(val256); + uut.MerkleRoot.Should().Be(merkRoot); + uut.Timestamp.Should().Be(timestampVal); + uut.Index.Should().Be(indexVal); + uut.ConsensusData.Should().Be(consensusDataVal); + uut.NextConsensus.Should().Be(val160); + uut.Script.InvocationScript.Length.Should().Be(0); + uut.Script.Size.Should().Be(scriptVal.Size); + uut.Script.VerificationScript[0].Should().Be(scriptVal.VerificationScript[0]); + if (testTransactions) + { + uut.Transactions.Length.Should().Be(1); + uut.Transactions[0].Should().Be(transactionsVal[0]); + } + } + + [TestMethod] + public void Equals_SameObj() + { + uut.Equals(uut).Should().BeTrue(); + } + + [TestMethod] + public void Equals_DiffObj() + { + Block newBlock = new Block(); + UInt256 val256 = UInt256.Zero; + UInt256 prevHash = new UInt256(TestUtils.GetByteArray(32, 0x42)); + UInt256 merkRoot; + UInt160 val160; + uint timestampVal, indexVal; + ulong consensusDataVal; + Witness scriptVal; + Transaction[] transactionsVal; + setupBlockWithValues(newBlock, val256, out merkRoot, out val160, out timestampVal, out indexVal, out consensusDataVal, out scriptVal, out transactionsVal, 1); + setupBlockWithValues(uut, prevHash, out merkRoot, out val160, out timestampVal, out indexVal, out consensusDataVal, out scriptVal, out transactionsVal, 0); + + uut.Equals(newBlock).Should().BeFalse(); + } + + [TestMethod] + public void Equals_Null() + { + uut.Equals(null).Should().BeFalse(); + } + + [TestMethod] + public void Equals_SameHash() + { + + Block newBlock = new Block(); + UInt256 prevHash = new UInt256(TestUtils.GetByteArray(32, 0x42)); + UInt256 merkRoot; + UInt160 val160; + uint timestampVal, indexVal; + ulong consensusDataVal; + Witness scriptVal; + Transaction[] transactionsVal; + setupBlockWithValues(newBlock, prevHash, out merkRoot, out val160, out timestampVal, out indexVal, out consensusDataVal, out scriptVal, out transactionsVal, 1); + setupBlockWithValues(uut, prevHash, out merkRoot, out val160, out timestampVal, out indexVal, out consensusDataVal, out scriptVal, out transactionsVal, 1); + + uut.Equals(newBlock).Should().BeTrue(); + } + + [TestMethod] + public void Trim() + { + UInt256 val256 = UInt256.Zero; + UInt256 merkRoot; + UInt160 val160; + uint timestampVal, indexVal; + ulong consensusDataVal; + Witness scriptVal; + Transaction[] transactionsVal; + setupBlockWithValues(uut, val256, out merkRoot, out val160, out timestampVal, out indexVal, out consensusDataVal, out scriptVal, out transactionsVal, 1); + + byte[] data = uut.Trim(); + byte[] requiredData = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 214, 87, 42, 69, 155, 149, 217, 19, 107, 122, 113, 60, 84, 133, 202, 112, 159, 158, 250, 79, 8, 241, 194, 93, 215, 146, 103, 45, 43, 215, 91, 251, 128, 171, 4, 253, 0, 0, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 81, 1, 214, 87, 42, 69, 155, 149, 217, 19, 107, 122, 113, 60, 84, 133, 202, 112, 159, 158, 250, 79, 8, 241, 194, 93, 215, 146, 103, 45, 43, 215, 91, 251 }; + + data.Length.Should().Be(141); + for (int i = 0; i < 141; i++) + { + data[i].Should().Be(requiredData[i]); + } + } + + [TestMethod] + public void FromTrimmedData() + { + UInt256 val256 = UInt256.Zero; + UInt256 merkRoot; + UInt160 val160; + uint timestampVal, indexVal; + ulong consensusDataVal; + Witness scriptVal; + Transaction[] transactionsVal; + setupBlockWithValues(new Block(), val256, out merkRoot, out val160, out timestampVal, out indexVal, out consensusDataVal, out scriptVal, out transactionsVal, 1); + + byte[] data = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 214, 87, 42, 69, 155, 149, 217, 19, 107, 122, 113, 60, 84, 133, 202, 112, 159, 158, 250, 79, 8, 241, 194, 93, 215, 146, 103, 45, 43, 215, 91, 251, 128, 171, 4, 253, 0, 0, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 81, 1, 214, 87, 42, 69, 155, 149, 217, 19, 107, 122, 113, 60, 84, 133, 202, 112, 159, 158, 250, 79, 8, 241, 194, 93, 215, 146, 103, 45, 43, 215, 91, 251 }; + + uut = Block.FromTrimmedData(data, 0, x => getMinerTransaction()); + + assertStandardBlockTestVals(val256, merkRoot, val160, timestampVal, indexVal, consensusDataVal, scriptVal, transactionsVal); + uut.Transactions[0].Should().Be(getMinerTransaction()); + } + + [TestMethod] + public void FromTrimmedData_MultipleTx() + { + UInt256 val256 = UInt256.Zero; + UInt256 merkRoot; + UInt160 val160; + uint timestampVal, indexVal; + ulong consensusDataVal; + Witness scriptVal; + Transaction[] transactionsVal; + setupBlockWithValues(new Block(), val256, out merkRoot, out val160, out timestampVal, out indexVal, out consensusDataVal, out scriptVal, out transactionsVal, 3); + + byte[] data = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 214, 87, 42, 69, 155, 149, 217, 19, 107, 122, 113, 60, 84, 133, 202, 112, 159, 158, 250, 79, 8, 241, 194, 93, 215, 146, 103, 45, 43, 215, 91, 251, 128, 171, 4, 253, 0, 0, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 81, 3, 214, 87, 42, 69, 155, 149, 217, 19, 107, 122, 113, 60, 84, 133, 202, 112, 159, 158, 250, 79, 8, 241, 194, 93, 215, 146, 103, 45, 43, 215, 91, 251, 214, 87, 42, 69, 155, 149, 217, 19, 107, 122, 113, 60, 84, 133, 202, 112, 159, 158, 250, 79, 8, 241, 194, 93, 215, 146, 103, 45, 43, 215, 91, 251, 214, 87, 42, 69, 155, 149, 217, 19, 107, 122, 113, 60, 84, 133, 202, 112, 159, 158, 250, 79, 8, 241, 194, 93, 215, 146, 103, 45, 43, 215, 91, 251 }; + + uut = Block.FromTrimmedData(data, 0, x => getMinerTransaction() ); + + assertStandardBlockTestVals(val256, merkRoot, val160, timestampVal, indexVal, consensusDataVal, scriptVal, transactionsVal, testTransactions: false); + uut.Transactions.Length.Should().Be(3); + uut.Transactions[0].Should().Be(getMinerTransaction()); + uut.Transactions[1].Should().Be(getMinerTransaction()); + uut.Transactions[2].Should().Be(getMinerTransaction()); + } + + [TestMethod] + public void RebuildMerkleRoot_Updates() + { + UInt256 val256 = UInt256.Zero; + UInt256 merkRoot; + UInt160 val160; + uint timestampVal, indexVal; + ulong consensusDataVal; + Witness scriptVal; + Transaction[] transactionsVal; + setupBlockWithValues(uut, val256, out merkRoot, out val160, out timestampVal, out indexVal, out consensusDataVal, out scriptVal, out transactionsVal, 1); + + UInt256 merkleRoot = uut.MerkleRoot; + + setupBlockWithValues(uut, val256, out merkRoot, out val160, out timestampVal, out indexVal, out consensusDataVal, out scriptVal, out transactionsVal, 3); + uut.RebuildMerkleRoot(); + + uut.MerkleRoot.Should().NotBe(merkleRoot); + } + + [TestMethod] + public void ToJson() + { + UInt256 val256 = UInt256.Zero; + UInt256 merkRoot; + UInt160 val160; + uint timestampVal, indexVal; + ulong consensusDataVal; + Witness scriptVal; + Transaction[] transactionsVal; + setupBlockWithValues(uut, val256, out merkRoot, out val160, out timestampVal, out indexVal, out consensusDataVal, out scriptVal, out transactionsVal, 1); + + JObject jObj = uut.ToJson(); + jObj.Should().NotBeNull(); + jObj["hash"].AsString().Should().Be("4520462a8c80056291f871da523bff0eb17e29d44ab4317e69ff7a42083cb39d"); + jObj["size"].AsNumber().Should().Be(119); + jObj["version"].AsNumber().Should().Be(0); + jObj["previousblockhash"].AsString().Should().Be("0000000000000000000000000000000000000000000000000000000000000000"); + jObj["merkleroot"].AsString().Should().Be("fb5bd72b2d6792d75dc2f1084ffa9e9f70ca85543c717a6b13d9959b452a57d6"); + jObj["time"].AsNumber().Should().Be(4244941696); + jObj["index"].AsNumber().Should().Be(0); + jObj["nonce"].AsString().Should().Be("000000000000001e"); + jObj["nextconsensus"].AsString().Should().Be("AFmseVrdL9f9oyCzZefL9tG6UbvhPbdYzM"); + + JObject scObj = jObj["script"]; + scObj["invocation"].AsString().Should().Be(""); + scObj["verification"].AsString().Should().Be("51"); + + jObj["tx"].Should().NotBeNull(); + JArray txObj = (JArray) jObj["tx"]; + txObj[0]["txid"].AsString().Should().Be("fb5bd72b2d6792d75dc2f1084ffa9e9f70ca85543c717a6b13d9959b452a57d6"); + txObj[0]["size"].AsNumber().Should().Be(10); + txObj[0]["type"].AsString().Should().Be("MinerTransaction"); + txObj[0]["version"].AsNumber().Should().Be(0); + ((JArray)txObj[0]["attributes"]).Count.Should().Be(0); + ((JArray)txObj[0]["vin"]).Count.Should().Be(0); + ((JArray)txObj[0]["vout"]).Count.Should().Be(0); + txObj[0]["sys_fee"].AsString().Should().Be("0"); + txObj[0]["net_fee"].AsString().Should().Be("0"); + ((JArray)txObj[0]["scripts"]).Count.Should().Be(0); + txObj[0]["nonce"].AsNumber().Should().Be(2083236893); + } + + [TestMethod] + public void Verify_CompletelyFalse() + { + UInt256 val256 = UInt256.Zero; + UInt256 merkRoot; + UInt160 val160; + uint timestampVal, indexVal; + ulong consensusDataVal; + Witness scriptVal; + Transaction[] transactionsVal; + setupBlockWithValues(uut, val256, out merkRoot, out val160, out timestampVal, out indexVal, out consensusDataVal, out scriptVal, out transactionsVal, 1); + + setupTestBlockchain(UInt256.Zero); + + uut.Verify(false).Should().BeTrue(); + } + + [TestMethod] + public void Verify_CompletelyFalse_MinerTransaction_After_First() + { + UInt256 val256 = UInt256.Zero; + UInt256 merkRoot; + UInt160 val160; + uint timestampVal, indexVal; + ulong consensusDataVal; + Witness scriptVal; + Transaction[] transactionsVal; + setupBlockWithValues(uut, val256, out merkRoot, out val160, out timestampVal, out indexVal, out consensusDataVal, out scriptVal, out transactionsVal, 3); + + setupTestBlockchain(UInt256.Zero); + + uut.Verify(false).Should().BeFalse(); + } + + [TestMethod] + public void Verify_CompletelyTrue_NextConsensus_Fail() + { + UInt256 val256 = UInt256.Zero; + UInt256 merkRoot; + UInt160 val160; + uint timestampVal, indexVal; + ulong consensusDataVal; + Witness scriptVal; + Transaction[] transactionsVal; + setupBlockWithValues(uut, val256, out merkRoot, out val160, out timestampVal, out indexVal, out consensusDataVal, out scriptVal, out transactionsVal, 1); + // passing NextConsensus below + // uut.NextConsensus = new UInt160(new byte[] { 23, 52, 98, 203, 0, 206, 138, 37, 140, 16, 251, 231, 61, 120, 218, 200, 182, 125, 120, 73 }); - // uut.Transactions = new Transaction[1] { - // getIssueTransaction(0) - // }; + setupTestBlockchain(UInt256.Zero); - // Block.CalculateNetFee(uut.Transactions).Should().Be(Fixed8.FromDecimal(100)); - //} + uut.Verify(true).Should().BeFalse(); + } } } diff --git a/neo.UnitTests/UT_Culture.cs b/neo.UnitTests/UT_Culture.cs new file mode 100644 index 0000000000..ae410d3af9 --- /dev/null +++ b/neo.UnitTests/UT_Culture.cs @@ -0,0 +1,88 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.Core; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Reflection; +using System.Text; + +namespace Neo.UnitTests +{ + [TestClass] + public class UT_Culture + { + + [TestMethod] + [NotReRunnable] + public void All_Tests_Cultures() + { + // get all tests in the unit test project assembly + var testClasses = (from t in typeof(NotReRunnableAttribute).GetTypeInfo().Assembly.DefinedTypes + where t.GetCustomAttribute() != null + select new + { + Constructor = t.GetConstructor(new Type[] { }), + ClassInit = t.GetMethods().Where( + m => m.GetCustomAttribute() != null).SingleOrDefault(), + TestInit = t.GetMethods().Where( + m => m.GetCustomAttribute() != null).SingleOrDefault(), + TestCleanup = t.GetMethods().Where( + m => m.GetCustomAttribute() != null).SingleOrDefault(), + ClassCleanup = t.GetMethods().Where( + m => m.GetCustomAttribute() != null).SingleOrDefault(), + TestMethods = t.GetMethods().Where( + m => m.GetCustomAttribute() != null + && m.GetCustomAttribute() == null).ToList() + }).ToList(); + + var cultures = new string[] { "en-US", "zh-CN", "de-DE", "ko-KR", "ja-JP" }; + var originalUICulture = CultureInfo.CurrentCulture; + var emtpyObjArray = new object[] { }; + + // run all the tests, varying the culture each time. + try + { + foreach (var culture in cultures) + { + CultureInfo.CurrentCulture = new CultureInfo(culture); + + foreach (var c in testClasses) + { + var instance = c.Constructor.Invoke(emtpyObjArray); + if (c.ClassInit != null) + { + c.ClassInit.Invoke(instance, emtpyObjArray); + } + foreach (var m in c.TestMethods) + { + if (c.TestInit != null) + { + c.TestInit.Invoke(instance, emtpyObjArray); + } + m.Invoke(instance, emtpyObjArray); + if (c.TestCleanup != null) + { + c.TestCleanup.Invoke(instance, emtpyObjArray); + } + } + if (c.ClassCleanup != null) + { + c.ClassCleanup.Invoke(instance, emtpyObjArray); + } + } + } + } + finally + { + CultureInfo.CurrentCulture = originalUICulture; + } + + } + } + + public class NotReRunnableAttribute : Attribute + { + + } +}