Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TestEngine: Fix some snapshots problems #941

Merged
merged 11 commits into from
Feb 22, 2024
4 changes: 2 additions & 2 deletions src/Neo.SmartContract.Testing/Storage/EngineCheckpoint.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public class EngineCheckpoint
/// Constructor
/// </summary>
/// <param name="snapshot">Snapshot</param>
public EngineCheckpoint(SnapshotCache snapshot)
public EngineCheckpoint(DataCache snapshot)
{
var list = new List<(byte[], byte[])>();

Expand Down Expand Up @@ -63,7 +63,7 @@ public EngineCheckpoint(Stream stream)
/// Restore
/// </summary>
/// <param name="snapshot">Snapshot</param>
public void Restore(SnapshotCache snapshot)
public void Restore(DataCache snapshot)
{
// Clean snapshot

Expand Down
18 changes: 14 additions & 4 deletions src/Neo.SmartContract.Testing/Storage/EngineStorage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public class EngineStorage
/// <summary>
/// Snapshot
/// </summary>
public SnapshotCache Snapshot { get; private set; }
public DataCache Snapshot { get; private set; }

/// <summary>
/// Return true if native contract are initialized
Expand All @@ -33,10 +33,17 @@ public class EngineStorage
/// Constructor
/// </summary>
/// <param name="store">Store</param>
public EngineStorage(IStore store)
public EngineStorage(IStore store) : this(store, new SnapshotCache(store.GetSnapshot())) { }

/// <summary>
/// Constructor
/// </summary>
/// <param name="store">Store</param>
/// <param name="snapshotCache">Snapshot cache</param>
internal EngineStorage(IStore store, DataCache snapshotCache)
{
Store = store;
Snapshot = new SnapshotCache(Store.GetSnapshot());
Snapshot = snapshotCache;
}

/// <summary>
Expand All @@ -52,7 +59,10 @@ public void Commit()
/// </summary>
public void Rollback()
{
Snapshot.Dispose();
if (Snapshot is SnapshotCache sp)
{
sp.Dispose();
}
Snapshot = new SnapshotCache(Store.GetSnapshot());
}

Expand Down
17 changes: 1 addition & 16 deletions src/Neo.SmartContract.Testing/TestEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -305,22 +305,7 @@ public T Deploy<T>(NefFile nef, ContractManifest manifest, object? data = null,
{
// Deploy

if (EnableCoverageCapture)
{
UInt160 expectedHash = GetDeployHash(nef, manifest);

if (!Coverage.ContainsKey(expectedHash))
{
var coveredContract = new CoveredContract(MethodDetection, expectedHash, new ContractState()
{
Nef = nef,
Hash = expectedHash,
Manifest = manifest
});
Coverage[coveredContract.Hash] = coveredContract;
}
}

//UInt160 expectedHash = GetDeployHash(nef, manifest);
var state = Native.ContractManagement.Deploy(nef.ToArray(), Encoding.UTF8.GetBytes(manifest.ToJson().ToString(false)), data);

if (state is null)
Expand Down
27 changes: 25 additions & 2 deletions src/Neo.SmartContract.Testing/TestingApplicationEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using Neo.Persistence;
using Neo.SmartContract.Native;
using Neo.SmartContract.Testing.Extensions;
using Neo.SmartContract.Testing.Storage;
using Neo.VM;
using Neo.VM.Types;
using System;
Expand Down Expand Up @@ -146,7 +147,7 @@
{
// We need the contract state without pay gas

var state = NativeContract.ContractManagement.GetContract(Engine.Storage.Snapshot, contractHash);
var state = NativeContract.ContractManagement.GetContract(Snapshot, contractHash);

coveredContract = new(Engine.MethodDetection, contractHash, state);
Engine.Coverage[contractHash] = coveredContract;
Expand Down Expand Up @@ -208,8 +209,30 @@

// Invoke

EngineStorage backup = Engine.Storage;
var hasReturnValue = customMock.Method.ReturnType != typeof(void);
var returnValue = customMock.Method.Invoke(customMock.Contract, parameters);
object returnValue;

try
{
// We need to switch the Engine's snapshot in case
// that a mock want to query the storage, it's not commited
shargon marked this conversation as resolved.
Show resolved Hide resolved

Engine.Storage = new EngineStorage(backup.Store, Snapshot);

// Invoke snapshot

returnValue = customMock.Method.Invoke(customMock.Contract, parameters);

Check warning on line 225 in src/Neo.SmartContract.Testing/TestingApplicationEngine.cs

View workflow job for this annotation

GitHub Actions / Test

Converting null literal or possible null value to non-nullable type.

Check warning on line 225 in src/Neo.SmartContract.Testing/TestingApplicationEngine.cs

View workflow job for this annotation

GitHub Actions / Test

Converting null literal or possible null value to non-nullable type.
}
catch (Exception ex)
{
throw ex;

Check warning on line 229 in src/Neo.SmartContract.Testing/TestingApplicationEngine.cs

View workflow job for this annotation

GitHub Actions / Test

Re-throwing caught exception changes stack information

Check warning on line 229 in src/Neo.SmartContract.Testing/TestingApplicationEngine.cs

View workflow job for this annotation

GitHub Actions / Test

Re-throwing caught exception changes stack information
}
finally
{
Engine.Storage = backup;
}

if (hasReturnValue)
Push(Convert(returnValue));
else
Expand Down
30 changes: 20 additions & 10 deletions src/Neo.SmartContract.Testing/TestingStandards/Nep17Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -204,22 +204,37 @@ public virtual void TestTransfer()

UInt160? calledFrom = null;
BigInteger? calledAmount = null;
byte[]? calledData = null;
UInt160? calledData = null;

var mock = Engine.Deploy<onNEP17PaymentContract>(NefFile, manifest.ToJson().ToString(), null, m =>
{
m
.Setup(s => s.onNEP17Payment(It.IsAny<UInt160>(), It.IsAny<BigInteger>(), It.IsAny<object>()))
.Callback(new InvocationAction((i) =>
{
// Set variables

var me = new UInt160((i.Arguments[2] as ByteString)!.GetSpan().ToArray());
calledFrom = i.Arguments[0] as UInt160;
calledAmount = (BigInteger)i.Arguments[1];
calledData = (i.Arguments[2] as ByteString)!.GetSpan().ToArray();

// Ensure the balance

Assert.AreEqual(3, Contract.BalanceOf(me));

// Ensure the event was called

var me = new UInt160(calledData);
AssertTransferEvent(Alice.Account, me, calledAmount);

// Return the money back

Engine.SetTransactionSigners(me);
Assert.IsTrue(Contract.Transfer(me, calledFrom, calledAmount));
AssertTransferEvent(me, Alice.Account, calledAmount);

// Set success flag

calledData = me;
}));
});

Expand All @@ -229,14 +244,9 @@ public virtual void TestTransfer()
Assert.IsTrue(Contract.Transfer(Alice.Account, mock.Hash, 3, mock.Hash.ToArray()));

Assert.AreEqual(Alice.Account, calledFrom);
Assert.AreEqual(mock.Hash, new UInt160(calledData));
Assert.AreEqual(mock.Hash, calledData);
Assert.AreEqual(3, calledAmount);

// Return the money back

Engine.SetTransactionSigners(mock);
Assert.IsTrue(Contract.Transfer(mock.Hash, calledFrom, calledAmount));
AssertTransferEvent(mock.Hash, Alice.Account, calledAmount);
Assert.AreEqual(0, Contract.BalanceOf(mock.Hash));
}

#endregion
Expand Down
Loading