diff --git a/src/TestEngine/Engine.cs b/src/TestEngine/Engine.cs index a4b5e2e45..f39e7afbf 100644 --- a/src/TestEngine/Engine.cs +++ b/src/TestEngine/Engine.cs @@ -8,6 +8,7 @@ using Neo.VM.Types; using System; using System.Collections.Generic; +using System.Linq; namespace Neo.TestingEngine { @@ -27,6 +28,7 @@ public static Engine Instance } private TestEngine engine = null; + private Transaction currentTx = null; private byte[] PubKey => HexString2Bytes("03ea01cb94bdaf0cd1c01b159d474f9604f4af35a3e2196f6bdfdb33b2aa4961fa"); private Engine() @@ -110,6 +112,11 @@ public void SetStorage(Dictionary storage) } } + public void SetSigners(UInt160[] signerAccounts) + { + currentTx.Signers = signerAccounts.Select(p => new Signer() { Account = p, Scopes = WitnessScope.CalledByEntry }).ToArray(); + } + public JObject Run(string method, StackItem[] args) { engine.GetMethod(method).RunEx(args); @@ -119,9 +126,20 @@ public JObject Run(string method, StackItem[] args) private TestEngine SetupNativeContracts() { SetConsensus(); - var block = Blockchain.GenesisBlock; - TestEngine engine = new TestEngine(TriggerType.Application, block); - ((TestSnapshot)engine.Snapshot).SetPersistingBlock(block); + currentTx = new Transaction() + { + Attributes = new TransactionAttribute[0], + Script = new byte[0], + Signers = new Signer[] { new Signer() { Account = UInt160.Zero } }, + Witnesses = new Witness[0], + NetworkFee = 1, + Nonce = 2, + SystemFee = 3, + ValidUntilBlock = 4, + Version = 5 + }; + TestEngine engine = new TestEngine(TriggerType.Application, currentTx); + ((TestSnapshot)engine.Snapshot).SetPersistingBlock(Blockchain.GenesisBlock); using (var script = new ScriptBuilder()) { diff --git a/src/TestEngine/Program.cs b/src/TestEngine/Program.cs index 453fcca34..8d02c1d51 100644 --- a/src/TestEngine/Program.cs +++ b/src/TestEngine/Program.cs @@ -143,6 +143,11 @@ public static JObject RunWithJson(JObject json) { smartContractTestCase.currentHeight = uint.Parse(json["height"].AsString()); } + + if (json.ContainsProperty("signerAccounts") && json["signerAccounts"] is JArray accounts) + { + smartContractTestCase.signers = accounts.Select(p => UInt160.Parse(p.AsString())).ToArray(); + } return Run(smartContractTestCase); } catch (Exception e) @@ -169,16 +174,18 @@ public static JObject Run(SmartContractTest smartContractTest) Engine.Instance.SetStorage(smartContractTest.storage); } - foreach (var contract in smartContractTest.contracts) + if (smartContractTest.currentHeight > 0) { - Engine.Instance.AddSmartContract(contract.nefPath); + Engine.Instance.IncreaseBlockCount(smartContractTest.currentHeight); } - if (smartContractTest.currentHeight > 0) + foreach (var contract in smartContractTest.contracts) { - Engine.Instance.IncreaseBlockCount(smartContractTest.currentHeight); + Engine.Instance.AddSmartContract(contract.nefPath); } + Engine.Instance.SetSigners(smartContractTest.signers); + var stackParams = GetStackItemParameters(smartContractTest.methodParameters); return Engine.Instance.Run(smartContractTest.methodName, stackParams); } diff --git a/src/TestEngine/SmartContractTest.cs b/src/TestEngine/SmartContractTest.cs index a89fdda9b..fd73b93f7 100644 --- a/src/TestEngine/SmartContractTest.cs +++ b/src/TestEngine/SmartContractTest.cs @@ -9,17 +9,19 @@ public class SmartContractTest public string nefPath; public string methodName; public JArray methodParameters; - public Dictionary storage = new Dictionary(); - public List contracts = new List(); + public Dictionary storage; + public List contracts; public uint currentHeight = 0; + public UInt160[] signers; public SmartContractTest(string path, string method, JArray parameters) { nefPath = path; methodName = method; methodParameters = parameters; - storage.Clear(); - contracts.Clear(); + storage = new Dictionary(); + contracts = new List(); + signers = new UInt160[] { }; } } } diff --git a/tests/TestEngine.UnitTests/TestClasses/Contract_CheckWitness.cs b/tests/TestEngine.UnitTests/TestClasses/Contract_CheckWitness.cs new file mode 100644 index 000000000..19e921246 --- /dev/null +++ b/tests/TestEngine.UnitTests/TestClasses/Contract_CheckWitness.cs @@ -0,0 +1,13 @@ +using Neo; +using Neo.SmartContract.Framework.Services.Neo; + +namespace Neo.Compiler.MSIL.UnitTests.TestClasses +{ + public class Contract_CheckWitness : SmartContract.Framework.SmartContract + { + public static bool testWitness(UInt160 signature) + { + return Runtime.CheckWitness(signature); + } + } +} diff --git a/tests/TestEngine.UnitTests/TestEngine.UnitTests.csproj b/tests/TestEngine.UnitTests/TestEngine.UnitTests.csproj index e34c77c5e..9f9e300e7 100644 --- a/tests/TestEngine.UnitTests/TestEngine.UnitTests.csproj +++ b/tests/TestEngine.UnitTests/TestEngine.UnitTests.csproj @@ -9,10 +9,14 @@ + + + PreserveNewest + PreserveNewest @@ -35,4 +39,19 @@ + + + + + neo + + + + diff --git a/tests/TestEngine.UnitTests/UnitTest_CheckWitness.cs b/tests/TestEngine.UnitTests/UnitTest_CheckWitness.cs new file mode 100644 index 000000000..39539ceed --- /dev/null +++ b/tests/TestEngine.UnitTests/UnitTest_CheckWitness.cs @@ -0,0 +1,109 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo; +using Neo.IO.Json; +using Neo.SmartContract; +using Neo.TestingEngine; +using Neo.VM; +using Neo.VM.Types; +using Neo.Wallets; +using System.IO; +using Compiler = Neo.Compiler.Program; + +namespace TestEngine.UnitTests +{ + [TestClass] + public class UnitTest_CheckWitness + { + [TestInitialize] + public void Init() + { + string path = Directory.GetCurrentDirectory(); + var option = new Compiler.Options() + { + File = path + "/TestClasses/Contract_CheckWitness.cs" + }; + Compiler.Compile(option); + + //Compile changes the path, reseting so that other UT won't break + Directory.SetCurrentDirectory(path); + Engine.Instance.Reset(); + } + + [TestMethod] + public void Test_Check_Witness() + { + var scripthash = "NiNmXL8FjEUEs1nfX9uHFBNaenxDHJtmuB".ToScriptHash(); + var param = new ContractParameter(ContractParameterType.Hash160) + { + Value = scripthash.ToString().Substring(2) + }; + + var json = new JObject(); + json["path"] = "./TestClasses/Contract_CheckWitness.nef"; + json["method"] = "testWitness"; + json["arguments"] = new JArray() { param.ToJson() }; + + var args = new string[] { + json.AsString() + }; + var result = Program.Run(args); + + // mustn't have an error + Assert.IsTrue(result.ContainsProperty("error")); + Assert.IsNull(result["error"]); + + // vm state must've faulted + Assert.IsTrue(result.ContainsProperty("vm_state")); + Assert.AreEqual(result["vm_state"].AsString(), VMState.HALT.ToString()); + + // result stack must be empty + StackItem wantresult = false; + Assert.IsTrue(result.ContainsProperty("result_stack")); + Assert.IsInstanceOfType(result["result_stack"], typeof(JArray)); + + var resultStack = result["result_stack"] as JArray; + Assert.IsTrue(resultStack.Count == 1); + Assert.IsTrue(resultStack[0].ContainsProperty("value")); + Assert.AreEqual(resultStack[0]["value"].AsString(), wantresult.ToJson()["value"].AsString()); + } + + [TestMethod] + public void Test_Check_Witness_With_Sign() + { + var scripthash = "NiNmXL8FjEUEs1nfX9uHFBNaenxDHJtmuB".ToScriptHash(); + var param = new ContractParameter(ContractParameterType.Hash160) + { + Value = scripthash.ToString().Substring(2) + }; + + var json = new JObject(); + json["path"] = "./TestClasses/Contract_CheckWitness.nef"; + json["method"] = "testWitness"; + json["arguments"] = new JArray() { param.ToJson() }; + json["signerAccounts"] = new JArray() { scripthash.ToString() }; + + var args = new string[] { + json.AsString() + }; + var result = Program.Run(args); + + // mustn't have an error + Assert.IsTrue(result.ContainsProperty("error")); + Assert.IsNull(result["error"]); + + // vm state must've faulted + Assert.IsTrue(result.ContainsProperty("vm_state")); + Assert.AreEqual(result["vm_state"].AsString(), VMState.HALT.ToString()); + + // result stack must be empty + StackItem wantresult = true; + Assert.IsTrue(result.ContainsProperty("result_stack")); + Assert.IsInstanceOfType(result["result_stack"], typeof(JArray)); + + var resultStack = result["result_stack"] as JArray; + Assert.IsTrue(resultStack.Count == 1); + Assert.IsTrue(resultStack[0].ContainsProperty("value")); + Assert.AreEqual(resultStack[0]["value"].AsString(), wantresult.ToJson()["value"].AsString()); + } + } +}