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

Migrate BasicExpressionEvaluator Integration Tests from Tao #19529

Merged
merged 3 commits into from
May 16, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using Microsoft.CodeAnalysis;
using Microsoft.VisualStudio.IntegrationTest.Utilities;
using Xunit;
using ProjectUtils = Microsoft.VisualStudio.IntegrationTest.Utilities.Common.ProjectUtils;

namespace Roslyn.VisualStudio.IntegrationTests.VisualBasic
{
[Collection(nameof(SharedIntegrationHostFixture))]
public class BasicExpressionEvaluator : AbstractEditorTest
{
protected override string LanguageName => LanguageNames.VisualBasic;

public BasicExpressionEvaluator(VisualStudioInstanceFactory instanceFactory) : base(instanceFactory)
{
VisualStudio.SolutionExplorer.CreateSolution(nameof(BasicBuild));
var testProj = new ProjectUtils.Project("TestProj");
VisualStudio.SolutionExplorer.AddProject(testProj, WellKnownProjectTemplates.ConsoleApplication, LanguageNames.VisualBasic);

VisualStudio.Editor.SetText(@"Imports System

Module Module1

Sub Main()
Dim mySByte As SByte = SByte.MaxValue / 2
Dim myShort As Short = Short.MaxValue / 2
Dim myInt As Integer = Integer.MaxValue / 2
Dim myLong As Long = Long.MaxValue / 2

Dim myByte As Byte = Byte.MaxValue / 2
Dim myUShort As UShort = UShort.MaxValue / 2
Dim myUInt As UInteger = UInteger.MaxValue / 2
Dim myULong As ULong = ULong.MaxValue / 2

Dim myFloat As Single = Single.MaxValue / 2
Dim myDouble As Double = Double.MaxValue / 2
Dim myDecimal As Decimal = Decimal.MaxValue / 2

Dim myChar As Char = ""A""c
Dim myBool As Boolean = True

Dim myObject As Object = Nothing
Dim myString As String = String.Empty

Dim myValueType As System.ValueType = myShort
Dim myEnum As System.Enum = Nothing
Dim myArray As System.Array = Nothing
Dim myDelegate As System.Delegate = Nothing
Dim myMulticastDelegate As System.MulticastDelegate = Nothing

System.Diagnostics.Debugger.Break()
End Sub

End Module");
}

[Fact]
public void ValidateLocalsWindow()
{
VisualStudio.Debugger.Go(waitForBreakMode: true);

VisualStudio.LocalsWindow.Verify.CheckCount(20);
VisualStudio.LocalsWindow.Verify.CheckEntry("mySByte", "SByte", "64");
VisualStudio.LocalsWindow.Verify.CheckEntry("myShort", "Short", "16384");
VisualStudio.LocalsWindow.Verify.CheckEntry("myInt", "Integer", "1073741824");
VisualStudio.LocalsWindow.Verify.CheckEntry("myLong", "Long", "4611686018427387904");
VisualStudio.LocalsWindow.Verify.CheckEntry("myByte", "Byte", "128");
VisualStudio.LocalsWindow.Verify.CheckEntry("myUShort", "UShort", "32768");
VisualStudio.LocalsWindow.Verify.CheckEntry("myUInt", "UInteger", "2147483648");
VisualStudio.LocalsWindow.Verify.CheckEntry("myULong", "ULong", "9223372036854775808");
VisualStudio.LocalsWindow.Verify.CheckEntry("myFloat", "Single", "1.70141173E+38");
VisualStudio.LocalsWindow.Verify.CheckEntry("myDouble", "Double", "8.9884656743115785E+307");
VisualStudio.LocalsWindow.Verify.CheckEntry("myDecimal", "Decimal", "39614081257132168796771975168");
VisualStudio.LocalsWindow.Verify.CheckEntry("myChar", "Char", "\"A\"c");
VisualStudio.LocalsWindow.Verify.CheckEntry("myBool", "Boolean", "True");
VisualStudio.LocalsWindow.Verify.CheckEntry("myObject", "Object", "Nothing");
VisualStudio.LocalsWindow.Verify.CheckEntry("myString", "String", "\"\"");
VisualStudio.LocalsWindow.Verify.CheckEntry("myValueType", "System.ValueType {Short}", "16384");
VisualStudio.LocalsWindow.Verify.CheckEntry("myEnum", "System.Enum", "Nothing");
VisualStudio.LocalsWindow.Verify.CheckEntry("myArray", "System.Array", "Nothing");
VisualStudio.LocalsWindow.Verify.CheckEntry("myDelegate", "System.Delegate", "Nothing");
VisualStudio.LocalsWindow.Verify.CheckEntry("myMulticastDelegate", "System.MulticastDelegate", "Nothing");
}

[Fact]
public void EvaluatePrimitiveValues()
{
VisualStudio.Debugger.Go(waitForBreakMode: true);

// It is better to use the Immediate Window but DTE does not provide an access to it.
VisualStudio.Debugger.CheckExpression("myByte", "Byte", "128");
VisualStudio.Debugger.CheckExpression("myFloat", "Single", "1.70141173E+38");
VisualStudio.Debugger.CheckExpression("myChar", "Char", "\"A\"c");
VisualStudio.Debugger.CheckExpression("myObject", "Object", "Nothing");
VisualStudio.Debugger.CheckExpression("myString", "String", "\"\"");
}

[Fact(Skip = "https://github.com/dotnet/roslyn/issues/19526")]
public void EvaluateLambdaExpressions()
{
VisualStudio.Debugger.Go(waitForBreakMode: true);
// It is better to use the Immediate Window but DTE does not provide an access to it.
VisualStudio.Debugger.CheckExpression("(Function(val)(val+val))(1)", "Integer", "2");
}

[Fact]
public void EvaluateInvalidExpressions()
{
VisualStudio.Debugger.Go(waitForBreakMode: true);
VisualStudio.Debugger.CheckExpression("myNonsense", "", "error BC30451: 'myNonsense' is not declared. It may be inaccessible due to its protection level.");
}

[Fact]
public void StateMachineTypeParameters()
{
VisualStudio.Editor.SetText(@"
Imports System
Imports System.Collections.Generic

Module Module1
Sub Main()
For Each arg In I({ ""a"", ""b""})
Console.WriteLine(arg)
Next
End Sub

Iterator Function I(Of T)(tt As T()) As IEnumerable(Of T)
For Each item In tt
Stop
Yield item
Next
End Function

End Module
");
VisualStudio.Debugger.Go(waitForBreakMode: true);
VisualStudio.LocalsWindow.Verify.CheckEntry( new string[] { "Type variables", "T" }, "String", "String");

// It is better to use the Immediate Window but DTE does not provide an access to it.
VisualStudio.Debugger.CheckExpression("GetType(T) = GetType(String)", "Boolean", "True");
}

public new void Dispose()
{
VisualStudio.Debugger.StepOver(waitForBreakOrEnd: true);
base.Dispose();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
<Compile Include="CSharp\CSharpAddMissingReference.cs" />
<Compile Include="VisualBasic\BasicEditAndContinue.cs" />
<Compile Include="VisualBasic\BasicEndConstruct.cs" />
<Compile Include="VisualBasic\BasicExpressionEvaluator.cs" />
<Compile Include="VisualBasic\BasicReferenceHighlighting.cs" />
<Compile Include="VisualBasic\BasicKeywordHighlighting.cs" />
<Compile Include="VisualBasic\BasicEncapsulateField.cs" />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.Collections.Generic;
using System.Linq;
using EnvDTE80;

namespace Microsoft.VisualStudio.IntegrationTest.Utilities.InProcess
Expand All @@ -9,22 +11,62 @@ internal class LocalsWindow_InProc : InProcComponent
{
public static LocalsWindow_InProc Create() => new LocalsWindow_InProc();

public int GetCount()
{
var dte = ((DTE2)GetDTE());
if (dte.Debugger.CurrentStackFrame != null) // Ensure that debugger is running
{
EnvDTE.Expressions locals = dte.Debugger.CurrentStackFrame.Locals;
return locals.Count;
}

return 0;
}

public Common.Expression GetEntry(string entryName)
{
return new Common.Expression(GetEntryInternal(entryName));
}

public Common.Expression GetEntry(params string[] entryNames)
{
return new Common.Expression(GetEntryInternal(entryNames));
}

private EnvDTE.Expression GetEntryInternal(params string[] entryNames)
{
var entry = GetEntryInternal(entryNames[0]);
for (int i = 1; i < entryNames.Length; i++)
{
entry = GetEntryInternal(entryNames[i], entry.DataMembers);
}

return entry;
}

private EnvDTE.Expression GetEntryInternal(string entryName, EnvDTE.Expressions expressions)
{
var expressionCollection = expressions.Cast<EnvDTE.Expression>();
var expressionMatched = expressionCollection.FirstOrDefault(e => e.Name == entryName);
if (expressionMatched != null)
{
return expressionMatched;
}

string nestedExpressionNamesString = string.Join(",", expressionCollection.Select(e => e.Name));
throw new Exception($"Could not find the local named {entryName}. Available locals are {nestedExpressionNamesString}.");
}

private EnvDTE.Expression GetEntryInternal(string entryName)
{
var dte = ((DTE2)GetDTE());
if (dte.Debugger.CurrentStackFrame != null) // Ensure that debugger is running
{
EnvDTE.Expressions locals = dte.Debugger.CurrentStackFrame.Locals;
foreach (EnvDTE.Expression local in locals)
{
if (local.Name == entryName)
{
return new Common.Expression(local);
}
}
return GetEntryInternal(entryName, locals);
}

throw new Exception($"Could not find the local named {entryName}.");
throw new Exception($"Could not find locals. Debugger is not running.");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,19 @@ public void CheckEntry(string entryName, string expectedType, string expectedVal
Assert.Equal(expectedType, entry.Type);
Assert.Equal(expectedValue, entry.Value);
}

public void CheckEntry(string[] entryNames, string expectedType, string expectedValue)
{
var entry = _localsWindow._localsWindowInProc.GetEntry(entryNames);
Assert.Equal(expectedType, entry.Type);
Assert.Equal(expectedValue, entry.Value);
}

public void CheckCount(int expectedCount)
{
var actualCount = _localsWindow._localsWindowInProc.GetCount();
Assert.Equal(expectedCount, actualCount);
}
}
}
}