Skip to content
This repository has been archived by the owner on Nov 22, 2023. It is now read-only.

Commit

Permalink
Add ABORTMSG & ASSERTMSG (#491)
Browse files Browse the repository at this point in the history
* Add ABORTMSG & ASSERTMSG

* add tests

* Allow asserting on exception message.

* Update VMUTExecutionEngineState.cs

* Update TestEngine.cs

* Update OpCode.cs

---------

Co-authored-by: Shargon <shargon@gmail.com>
  • Loading branch information
ixje and shargon committed Jul 20, 2023
1 parent 5b0a398 commit 7e59968
Show file tree
Hide file tree
Showing 7 changed files with 120 additions and 3 deletions.
14 changes: 13 additions & 1 deletion src/Neo.VM/ExecutionEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1381,7 +1381,19 @@ private void ExecuteInstruction(Instruction instruction)
Push(x.ConvertTo((StackItemType)instruction.TokenU8));
break;
}

case OpCode.ABORTMSG:
{
var msg = Pop().GetString();
throw new Exception($"{OpCode.ABORTMSG} is executed. Reason: {msg}");
}
case OpCode.ASSERTMSG:
{
var msg = Pop().GetString();
var x = Pop().GetBoolean();
if (!x)
throw new Exception($"{OpCode.ASSERTMSG} is executed with false result. Reason: {msg}");
break;
}
default: throw new InvalidOperationException($"Opcode {instruction.OpCode} is undefined.");
}
}
Expand Down
13 changes: 13 additions & 0 deletions src/Neo.VM/OpCode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -886,5 +886,18 @@ public enum OpCode : byte
CONVERT = 0xDB,

#endregion

#region Extensions

/// <summary>
/// Turns the vm state to FAULT immediately, and cannot be caught. Includes a reason
/// </summary>
ABORTMSG = 0xE0,
/// <summary>
/// Pop the top value of the stack, if it false, then exit vm execution and set vm state to FAULT. Includes a reason
/// </summary>
ASSERTMSG = 0xE1

#endregion
}
}
26 changes: 26 additions & 0 deletions tests/Neo.VM.Tests/Tests/OpCodes/Control/ABORTMSG.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"category": "Control",
"name": "ABORTMSG",
"tests": [
{
"name": "Basic Test",
"script": [
"PUSHDATA1",
"0x03",
"0x4e454f",
"ABORTMSG"
],
"steps": [
{
"actions": [
"execute"
],
"result": {
"state": "FAULT",
"exceptionMessage": "ABORTMSG is executed. Reason: NEO"
}
}
]
}
]
}
47 changes: 47 additions & 0 deletions tests/Neo.VM.Tests/Tests/OpCodes/Control/ASSERTMSG.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
{
"category": "Control",
"name": "ASSERTMSG",
"tests": [
{
"name": "Fault Test",
"script": [
"PUSH0",
"PUSHDATA1",
"0x04",
"0x4641494c",
"ASSERTMSG"
],
"steps": [
{
"actions": [
"execute"
],
"result": {
"state": "FAULT",
"exceptionMessage": "ASSERTMSG is executed with false result. Reason: FAIL"
}
}
]
},
{
"name": "Halt Test",
"script": [
"PUSH1",
"PUSHDATA1",
"0x04",
"0x50415353",
"ASSERTMSG"
],
"steps": [
{
"actions": [
"execute"
],
"result": {
"state": "HALT"
}
}
]
}
]
}
9 changes: 9 additions & 0 deletions tests/Neo.VM.Tests/Types/TestEngine.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
using System;
using Neo.VM;
using Neo.VM.Types;

namespace Neo.Test.Types
{
class TestEngine : ExecutionEngine
{
public Exception FaultException { get; private set; }

protected override void OnSysCall(uint method)
{
if (method == 0x77777777)
Expand All @@ -21,5 +24,11 @@ protected override void OnSysCall(uint method)

throw new System.Exception();
}

protected override void OnFault(Exception ex)
{
FaultException = ex;
base.OnFault(ex);
}
}
}
3 changes: 3 additions & 0 deletions tests/Neo.VM.Tests/Types/VMUTExecutionEngineState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,8 @@ public class VMUTExecutionEngineState

[JsonProperty]
public VMUTExecutionContextState[] InvocationStack { get; set; }

[JsonProperty]
public string ExceptionMessage { get; set; }
}
}
11 changes: 9 additions & 2 deletions tests/Neo.VM.Tests/VMJsonTestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,17 @@ public void ExecuteTest(VMUT ut)
/// <param name="engine">Engine</param>
/// <param name="result">Result</param>
/// <param name="message">Message</param>
private void AssertResult(VMUTExecutionEngineState result, ExecutionEngine engine, string message)
private void AssertResult(VMUTExecutionEngineState result, TestEngine engine, string message)
{
AssertAreEqual(result.State.ToString().ToLowerInvariant(), engine.State.ToString().ToLowerInvariant(), message + "State is different");
if (engine.State == VMState.FAULT) return;
if (engine.State == VMState.FAULT)
{
if (result.ExceptionMessage != null)
{
AssertAreEqual(result.ExceptionMessage, engine.FaultException.Message, message + " [Exception]");
}
return;
}
AssertResult(result.InvocationStack, engine.InvocationStack, message + " [Invocation stack]");
AssertResult(result.ResultStack, engine.ResultStack, message + " [Result stack] ");
}
Expand Down

0 comments on commit 7e59968

Please sign in to comment.