Skip to content

Commit

Permalink
Merge pull request #10 from simplitech/Boa-263
Browse files Browse the repository at this point in the history
Boa 263 - Include CheckWitness in the TestEngine
  • Loading branch information
melanke authored Nov 25, 2020
2 parents 18e4ee9 + 2a5a9f7 commit 44d7ff2
Show file tree
Hide file tree
Showing 6 changed files with 179 additions and 11 deletions.
24 changes: 21 additions & 3 deletions src/TestEngine/Engine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using Neo.VM.Types;
using System;
using System.Collections.Generic;
using System.Linq;

namespace Neo.TestingEngine
{
Expand All @@ -27,6 +28,7 @@ public static Engine Instance
}

private TestEngine engine = null;
private Transaction currentTx = null;
private byte[] PubKey => HexString2Bytes("03ea01cb94bdaf0cd1c01b159d474f9604f4af35a3e2196f6bdfdb33b2aa4961fa");

private Engine()
Expand Down Expand Up @@ -110,6 +112,11 @@ public void SetStorage(Dictionary<PrimitiveType, StackItem> 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);
Expand All @@ -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())
{
Expand Down
15 changes: 11 additions & 4 deletions src/TestEngine/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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);
}
Expand Down
10 changes: 6 additions & 4 deletions src/TestEngine/SmartContractTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,19 @@ public class SmartContractTest
public string nefPath;
public string methodName;
public JArray methodParameters;
public Dictionary<PrimitiveType, StackItem> storage = new Dictionary<PrimitiveType, StackItem>();
public List<TestContract> contracts = new List<TestContract>();
public Dictionary<PrimitiveType, StackItem> storage;
public List<TestContract> 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<PrimitiveType, StackItem>();
contracts = new List<TestContract>();
signers = new UInt160[] { };
}
}
}
13 changes: 13 additions & 0 deletions tests/TestEngine.UnitTests/TestClasses/Contract_CheckWitness.cs
Original file line number Diff line number Diff line change
@@ -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);
}
}
}
19 changes: 19 additions & 0 deletions tests/TestEngine.UnitTests/TestEngine.UnitTests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,14 @@
<ItemGroup>
<Compile Remove="TestClasses\Contract1.cs" />
<Compile Remove="TestClasses\Contract2.cs" />
<Compile Remove="TestClasses\Contract_CheckWitness.cs" />
<Compile Remove="TestClasses\Contract_ContractCall.cs" />
</ItemGroup>

<ItemGroup>
<None Include="TestClasses\Contract_CheckWitness.cs">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="TestClasses\Contract1.cs">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
Expand All @@ -35,4 +39,19 @@
<ProjectReference Include="..\..\src\TestEngine\TestEngine.csproj" />
</ItemGroup>

<Target Name="ChangeAliasesOfStrongNameAssemblies" BeforeTargets="FindReferenceAssembliesForReferences;ResolveReferences">
<!--
The unified Neo domain model defines types with the same fully namespace qualified name in different assemblies.
Specifying a reference alias allows us to disambiguate types with colliding names.
Official docs: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/extern-alias
For NuGet imported packages, specifying an alias requires this target tag to work properly.
-->
<ItemGroup>
<ReferencePath Condition="'%(FileName)' == 'Neo.SmartContract.Framework'">
<Aliases>neo</Aliases>
</ReferencePath>
</ItemGroup>
</Target>

</Project>
109 changes: 109 additions & 0 deletions tests/TestEngine.UnitTests/UnitTest_CheckWitness.cs
Original file line number Diff line number Diff line change
@@ -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());
}
}
}

0 comments on commit 44d7ff2

Please sign in to comment.