Skip to content

Commit

Permalink
Merge branch 'develop' into 'master'
Browse files Browse the repository at this point in the history
Develop

See merge request company-projects/Meadow!53
  • Loading branch information
zone117x committed Oct 11, 2018
2 parents 4da446f + 6be0ba5 commit af1d019
Show file tree
Hide file tree
Showing 9 changed files with 182 additions and 15 deletions.
20 changes: 20 additions & 0 deletions src/Meadow.Core.Test/UIntTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,26 @@ namespace Meadow.Core.Test
{
public class UIntTests
{
[Fact]
public void TestSignedUnsignedCast()
{
// Test an oversigned number being cast to a UInt256 and Int256.
BigInteger u264Max = ((BigInteger.One << 264) - 1);
Assert.Equal((BigInteger)UInt256.MaxValue, u264Max.ToUInt256());
Assert.Equal(-1, u264Max.ToInt256());

// Test uint256 max value being cast to UInt256 (fits, doesn't change value) and Int256 (doesn't fit, overwrites sign bit).
BigInteger u256Max = ((BigInteger.One << 256) - 1);
Assert.Equal((BigInteger)UInt256.MaxValue, u256Max.ToUInt256());
Assert.Equal(-1, u256Max.ToInt256());

// Test int256 max value being cast to UInt256 and Int256 (both should have an unchanged value).
BigInteger i256Max = BigIntegerConverter.INT256_MAX_VALUE;
BigInteger expected = (u256Max >> 1);
Assert.Equal(expected, i256Max.ToUInt256());
Assert.Equal(expected, i256Max.ToInt256());
}

[Fact]
public void UInt32Cast()
{
Expand Down
30 changes: 30 additions & 0 deletions src/Meadow.DebugAdapterServer/MeadowDebugAdapterState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,28 @@

namespace Meadow.DebugAdapterServer
{
/// <summary>
/// Represents the state/properties of a thread which is debugging solidity code.
/// </summary>
public class MeadowDebugAdapterThreadState
{
#region Fields
/// <summary>
/// Indiciates the index into the significant step list <see cref="ExecutionTraceAnalysis.SignificantStepIndices"/>.
/// This is used to walk through all significant steps.
/// </summary>
private int _significantStepIndexIndex;
#endregion

#region Properties
/// <summary>
/// The thread id of this thread state.
/// </summary>
public int ThreadId { get; }
/// <summary>
/// Indicates the current tracepoint index into the execution trace <see cref="ExecutionTrace"/>.
/// This is used to
/// </summary>
public int? CurrentStepIndex
{
get
Expand All @@ -32,6 +46,9 @@ public class MeadowDebugAdapterThreadState
}
}

/// <summary>
/// The current execution trace which is being analyzed on this thread.
/// </summary>
public ExecutionTrace ExecutionTrace
{
get
Expand All @@ -40,12 +57,25 @@ public ExecutionTrace ExecutionTrace
}
}

/// <summary>
/// The execution trace analysis currently being analyzed/walked on this thread.
/// </summary>
public ExecutionTraceAnalysis ExecutionTraceAnalysis { get; }

/// <summary>
/// The RPC client which entered the debugging session on this thread.
/// </summary>
public IJsonRpcClient RpcClient { get; }

/// <summary>
/// Indicates whether we are expecting exceptions during this execution trace's analysis.
/// Used to determine if we have unhandled exceptions we should pause for.
/// </summary>
public bool ExpectingException { get; }

/// <summary>
/// The thread locking object used to pause the test executing thread while debugging is occuring on it's execution trace.
/// </summary>
public SemaphoreSlim Semaphore { get; }
#endregion

Expand Down
12 changes: 11 additions & 1 deletion src/Meadow.DebugAdapterServer/MeadowSolidityDebugAdapter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ private void ContinueExecution(MeadowDebugAdapterThreadState threadState, Desire
return;
}

// Send our continued event to force refresh of state.
Protocol.SendEvent(new ContinuedEvent(threadState.ThreadId));

// Signal our breakpoint event has occurred for this thread.
Expand Down Expand Up @@ -297,6 +298,9 @@ private void ContinueExecution(MeadowDebugAdapterThreadState threadState, Desire
}
}

// Send our continued event to force refresh of state.
Protocol.SendEvent(new ContinuedEvent(threadState.ThreadId));

// Signal our breakpoint event has occurred for this thread.
Protocol.SendEvent(new StoppedEvent(StoppedEvent.ReasonValue.Step) { ThreadId = threadState.ThreadId });
break;
Expand Down Expand Up @@ -351,6 +355,9 @@ bool ShouldProcessException()
// If we have an exception, throw it and return the appropriate status.
if (traceException != null)
{
// Send our continued event to force refresh of state.
Protocol.SendEvent(new ContinuedEvent(threadState.ThreadId));

// Send our exception event.
var stoppedEvent = new StoppedEvent(StoppedEvent.ReasonValue.Exception)
{
Expand Down Expand Up @@ -388,6 +395,9 @@ private bool HandleBreakpoint(MeadowDebugAdapterThreadState threadState)
bool containsBreakpoint = success && breakpointLines.Any(x => x == sourceLine.LineNumber);
if (containsBreakpoint)
{
// Send our continued event to force refresh of state.
Protocol.SendEvent(new ContinuedEvent(threadState.ThreadId));

// Signal our breakpoint event has occurred for this thread.
Protocol.SendEvent(new StoppedEvent(StoppedEvent.ReasonValue.Breakpoint) { ThreadId = threadState.ThreadId });
return true;
Expand Down Expand Up @@ -839,7 +849,7 @@ protected override void HandleVariablesRequestAsync(IRequestResponder<VariablesA
responder.SetResponse(new VariablesResponse(variableList));
}

void ResolveVariables(
private void ResolveVariables(
List<Variable> variableList,
int variablesReference,
bool isLocalVariableScope,
Expand Down
95 changes: 95 additions & 0 deletions src/Meadow.DebugAdapterServer/ReferenceContainer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,25 @@ public class ReferenceContainer
#endregion

#region Properties
/// <summary>
/// Indicates we are currently debugging/stepping through an execution trace, and there is a thread currently connected.
/// </summary>
public bool IsThreadLinked { get; private set; }
/// <summary>
/// Indicates the identifier of the current thread.
/// </summary>
public int CurrentThreadId { get; private set; }
/// <summary>
/// Indicates the identifier for the current stack frame being analyzed.
/// </summary>
public int CurrentStackFrameId { get; private set; }
/// <summary>
/// Indicates the identifier for the current stack frame's local scope.
/// </summary>
public int LocalScopeId { get; private set; }
/// <summary>
/// Indicates the identifier for the current stack frame's state scope.
/// </summary>
public int StateScopeId { get; private set; }
#endregion

Expand All @@ -71,11 +86,22 @@ public ReferenceContainer()
#endregion

#region Functions
/// <summary>
/// Obtains a unique ID for a debug adapter component (stack frames, scopes, etc).
/// Used to ensure there are no collisions in chosen IDs.
/// </summary>
/// <returns>Returns a unique ID to be used for a debug adapter component.</returns>
public int GetUniqueId()
{
return Interlocked.Increment(ref _nextId);
}

/// <summary>
/// Obtains the ID for a stack frame, given an index (where 0 indicates the latest stack frame).
/// Used to ensure stack frames IDs can be recycled per index.
/// </summary>
/// <param name="index">The index of the stack frame to obtain the ID for.</param>
/// <returns>Returns the ID for the given stack frame index.</returns>
public int GetStackFrameId(int index = 0)
{
// Verify the index for our stack frame isn't outside of our allocated count
Expand All @@ -88,6 +114,12 @@ public int GetStackFrameId(int index = 0)
return _startingStackFrameId + index;
}

/// <summary>
/// Obtains all linked stack frames for a given thread ID.
/// </summary>
/// <param name="threadId">The thread ID to obtain any linked stack frames for.</param>
/// <param name="result">Returns linked stack frames for the given thread ID.</param>
/// <returns>Returns true if stack frames for the given thread ID existed.</returns>
public bool TryGetStackFrames(int threadId, out List<StackFrame> result)
{
// If we have stack frame ids for this thread
Expand All @@ -102,6 +134,12 @@ public bool TryGetStackFrames(int threadId, out List<StackFrame> result)
return false;
}

/// <summary>
/// Links a stack frame to a given thread ID, and sets that thread ID as the current/active thread.
/// </summary>
/// <param name="threadId">The ID of the thread to link the given stack frame to.</param>
/// <param name="stackFrame">The stack frame to link to the given thread ID.</param>
/// <param name="traceIndex">The last significant trace index in this frame before entering another.</param>
public void LinkStackFrame(int threadId, StackFrame stackFrame, int traceIndex)
{
// Obtain our callstack for this thread or create a new one if one doesn't exist.
Expand All @@ -123,6 +161,11 @@ public void LinkStackFrame(int threadId, StackFrame stackFrame, int traceIndex)
IsThreadLinked = true;
}

/// <summary>
/// Sets the current stack frame ID, used to resolve local/state variables in the correct context.
/// </summary>
/// <param name="stackFrameId">The ID of the stack frame which we want to set as the currently selected/active stack frame.</param>
/// <returns>Returns true if the stack frame ID was known, and current stack frame was set.</returns>
public bool SetCurrentStackFrame(int stackFrameId)
{
// If our stack frame exists in our lookup, set it as the current
Expand All @@ -136,6 +179,13 @@ public bool SetCurrentStackFrame(int stackFrameId)
return false;
}

/// <summary>
/// Links a nested/sub-variable to a parent variable reference ID.
/// </summary>
/// <param name="parentVariableReference">The parent reference ID for this nested variable.</param>
/// <param name="variableReference">The reference ID of nested/sub-variable that is being added.</param>
/// <param name="threadId">The ID of the active thread we are linking variables for.</param>
/// <param name="underlyingVariableValuePair">The underlying variable-value pair for this variable to link to the parent variable reference ID.</param>
public void LinkSubVariableReference(int parentVariableReference, int variableReference, int threadId, UnderlyingVariableValuePair underlyingVariableValuePair)
{
_variableReferenceIdToUnderlyingVariableValuePair[variableReference] = (threadId, underlyingVariableValuePair);
Expand All @@ -154,6 +204,10 @@ public void LinkSubVariableReference(int parentVariableReference, int variableRe
_subVariableReferenceIdToVariableReferenceId[variableReference] = parentVariableReference;
}

/// <summary>
/// Unlinks the nested/sub-variable from a parent variable reference ID (recursively).
/// </summary>
/// <param name="variableReference">The variable reference ID to unlink all variables/sub-variables recursively for.</param>
private void UnlinkSubVariableReference(int variableReference)
{
// Unlink our variable value pair
Expand All @@ -175,6 +229,14 @@ private void UnlinkSubVariableReference(int variableReference)
}
}

/// <summary>
/// Creates a variable object and links all relevant evaluation information for it.
/// </summary>
/// <param name="name">The name of the variable to display.</param>
/// <param name="value">The value of the variable to display.</param>
/// <param name="variablesReference">The variable reference ID for this variable.</param>
/// <param name="type">The type of the variable to create.</param>
/// <returns>Returns a variable object which represents all the provided variable information.</returns>
public Variable CreateVariable(string name, string value, int variablesReference, string type)
{
// Obtain our next variable evaluation id and set it in our lookup.
Expand All @@ -189,6 +251,11 @@ public Variable CreateVariable(string name, string value, int variablesReference
};
}

/// <summary>
/// Gets a variable evaluate response for a given expression.
/// </summary>
/// <param name="expression">The variable expression for which to obtain an evaluation response for.</param>
/// <returns>Returns a variable evaluation for the given expression, or null if one could not be found.</returns>
public EvaluateResponse GetVariableEvaluateResponse(string expression)
{
// Verify the expression starts with the variable eval type prefix.
Expand All @@ -209,6 +276,14 @@ public EvaluateResponse GetVariableEvaluateResponse(string expression)
return null;
}

/// <summary>
/// Attempts to resolve a parent variable given the parent variable reference ID, and it's corresponding thread ID.
/// Thus, this is used to resolve nested/child variables.
/// </summary>
/// <param name="variableReference">The parent variable reference ID for which we wish to obtain the variable for.</param>
/// <param name="threadId">The thread ID for the parent variable reference ID.</param>
/// <param name="variableValuePair">The variable value pair for the given variable reference ID.</param>
/// <returns>Returns true if a variable-value pair could be resolved for the given variable reference ID.</returns>
public bool ResolveParentVariable(int variableReference, out int threadId, out UnderlyingVariableValuePair variableValuePair)
{
// Try to obtain our thread id and variable value pair.
Expand All @@ -226,6 +301,14 @@ public bool ResolveParentVariable(int variableReference, out int threadId, out U
return false;
}

/// <summary>
/// Attemps to resolve a non-nested/top-level local variable given a variable reference ID. If the ID matches the local scope ID,
/// then the thread ID and current trace index is obtained for the stack frame in which this local variable resides.
/// </summary>
/// <param name="variableReference">The parent variable reference ID of the variable, to verify this is the local variable scope.</param>
/// <param name="threadId">The thread ID for the parent variable reference ID.</param>
/// <param name="traceIndex">The last trace index in the current stack frame at which this variable should be resolved.</param>
/// <returns>Returns true if the ID did reference the local variable scope, and we should resolve top level local variables at the given trace index.</returns>
public bool ResolveLocalVariable(int variableReference, out int threadId, out int traceIndex)
{
// Check the variable reference references the target scope id, and we have sufficient information.
Expand All @@ -243,6 +326,14 @@ public bool ResolveLocalVariable(int variableReference, out int threadId, out in
return false;
}

/// <summary>
/// Attemps to resolve a non-nested/top-level state variable given a variable reference ID. If the ID matches the state scope ID,
/// then the thread ID and last trace index is obtained for the stack frame in which the state variable is to be resolved.
/// </summary>
/// <param name="variableReference">The parent variable reference ID of the variable, to verify this is the state variable scope.</param>
/// <param name="threadId">The thread ID for the parent variable reference ID.</param>
/// <param name="traceIndex">The last trace index in the current stack frame at which this variable should be resolved.</param>
/// <returns>Returns true if the ID did reference the state variable scope, and we should resolve top level state variables at the given trace index.</returns>
public bool ResolveStateVariable(int variableReference, out int threadId, out int traceIndex)
{
// Check the variable reference references the target scope id, and we have sufficient information.
Expand All @@ -260,6 +351,10 @@ public bool ResolveStateVariable(int variableReference, out int threadId, out in
return false;
}

/// <summary>
/// Unlinks all references for the given thread ID, and it's underlying stack frame/scope/variable IDs (recusively).
/// </summary>
/// <param name="threadId">The thread ID to unlink all reference for (recursively).</param>
public void UnlinkThreadId(int threadId)
{
// Remove this thread id from the lookup.
Expand Down
2 changes: 1 addition & 1 deletion src/Meadow.UnitTestTemplate/Debugging.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public static IDisposable AttachSolidityDebugger(CancellationTokenSource cancelT
if (!Debugger.IsAttached)
{
cancelToken.Cancel();
Environment.Exit(0);
//Environment.Exit(0);
}
};

Expand Down
2 changes: 1 addition & 1 deletion src/Meadow.VSCode.Debugger/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "solidity-debugger",
"displayName": "Solidity Debugger",
"version": "0.0.4",
"version": "0.0.5",
"description": "Debugger for Solidity smart contracts - powered by the Meadow testing and development tool suite",
"categories": [
"Debuggers"
Expand Down
14 changes: 10 additions & 4 deletions src/Meadow.VSCode.Debugger/src/clrDebugConfigProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export class ClrDebugConfigProvider implements vscode.DebugConfigurationProvider

// Check if the solidity debugger has already been launched and set the session ID
if (debugConfiguration.env && debugConfiguration.env[DEBUG_SESSION_ID]) {
Logger.log(`Clr debugger already setup with solidity debug session ID.`);
return debugConfiguration;
}

Expand All @@ -53,18 +54,23 @@ export class ClrDebugConfigProvider implements vscode.DebugConfigurationProvider

let workspaceFolder = common.getWorkspaceFolder();

let unitTestRunnerDebugConfig: vscode.DebugConfiguration = {
let solDebugConfig: vscode.DebugConfiguration = {
name: "Solidity Debugger",
type: SOLIDITY_MEADOW_TYPE,
request: "launch",
cwd: workspaceFolder.uri.fsPath,
[DEBUG_SESSION_ID]: debugSessionID
};

Logger.log(`Launching dotnet debugger for: ${JSON.stringify(unitTestRunnerDebugConfig)}`);

vscode.debug.startDebugging(workspaceFolder, unitTestRunnerDebugConfig);
setTimeout(() => {
(async () => {
Logger.log(`Launching solidity debugger for: ${JSON.stringify(solDebugConfig)}`);
let startSolDebugResult = await vscode.debug.startDebugging(workspaceFolder, solDebugConfig);
console.log("Sol debugger result: " + startSolDebugResult);
})();
}, 1);

Logger.log(`Using clr debug config with sol debug session ID ${JSON.stringify(config)}`);
return config;
}

Expand Down

0 comments on commit af1d019

Please sign in to comment.