// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics.CodeAnalysis;
using System.Dynamic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Windows.Threading;
using Microsoft.CSharp.RuntimeBinder;
using Microsoft.ClearScript.Util;
using Microsoft.ClearScript.Windows;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace Microsoft.ClearScript.Test
{
[TestClass]
[SuppressMessage("Microsoft.Design", "CA1001:TypesThatOwnDisposableFieldsShouldBeDisposable", Justification = "Test classes use TestCleanupAttribute for deterministic teardown.")]
public class VBScriptEngineTest : ClearScriptTest
{
#region setup / teardown
private VBScriptEngine engine;
[TestInitialize]
public void TestInitialize()
{
engine = new VBScriptEngine(WindowsScriptEngineFlags.EnableDebugging);
engine.Execute("function pi : pi = 4 * atn(1) : end function");
engine.Execute("function e : e = exp(1) : end function");
}
[TestCleanup]
public void TestCleanup()
{
engine.Dispose();
BaseTestCleanup();
}
#endregion
#region test methods
// ReSharper disable InconsistentNaming
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_AddHostObject()
{
var host = new HostFunctions();
engine.AddHostObject("host", host);
Assert.AreSame(host, engine.Evaluate("host"));
}
[TestMethod, TestCategory("VBScriptEngine")]
[ExpectedException(typeof(InvalidOperationException))]
public void VBScriptEngine_AddHostObject_Scalar()
{
engine.AddHostObject("value", 123);
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_AddHostObject_Enum()
{
const DayOfWeek value = DayOfWeek.Wednesday;
engine.AddHostObject("value", value);
Assert.AreEqual(value, engine.Evaluate("value"));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_AddHostObject_Struct()
{
var date = new DateTime(2007, 5, 22, 6, 15, 43);
engine.AddHostObject("date", date);
Assert.AreEqual(date, engine.Evaluate("date"));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_AddHostObject_GlobalMembers()
{
var host = new HostFunctions();
engine.AddHostObject("host", HostItemFlags.GlobalMembers, host);
Assert.IsInstanceOfType(engine.Evaluate("newObj()"), typeof(PropertyBag));
engine.AddHostObject("test", HostItemFlags.GlobalMembers, this);
engine.Execute("TestProperty = newObj()");
Assert.IsInstanceOfType(TestProperty, typeof(PropertyBag));
}
[TestMethod, TestCategory("VBScriptEngine")]
[ExpectedException(typeof(ScriptEngineException))]
public void VBScriptEngine_AddHostObject_DefaultAccess()
{
engine.AddHostObject("test", this);
engine.Execute("test.PrivateMethod()");
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_AddHostObject_PrivateAccess()
{
engine.AddHostObject("test", HostItemFlags.PrivateAccess, this);
engine.Execute("test.PrivateMethod()");
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_AddRestrictedHostObject_BaseClass()
{
var host = new ExtendedHostFunctions() as HostFunctions;
engine.AddRestrictedHostObject("host", host);
Assert.IsInstanceOfType(engine.Evaluate("host.newObj()"), typeof(PropertyBag));
TestUtil.AssertException(() => engine.Evaluate("host.type(\"System.Int32\")"));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_AddRestrictedHostObject_Interface()
{
const double value = 123.45;
engine.AddRestrictedHostObject("convertible", value as IConvertible);
engine.AddHostObject("culture", CultureInfo.InvariantCulture);
Assert.AreEqual(value, engine.Evaluate("convertible.ToDouble(culture)"));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_AddHostType()
{
engine.AddHostObject("host", new HostFunctions());
engine.AddHostType("Random", typeof(Random));
Assert.IsInstanceOfType(engine.Evaluate("host.newObj(Random)"), typeof(Random));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_AddHostType_GlobalMembers()
{
engine.AddHostType("Guid", HostItemFlags.GlobalMembers, typeof(Guid));
Assert.IsInstanceOfType(engine.Evaluate("NewGuid()"), typeof(Guid));
engine.AddHostType("Test", HostItemFlags.GlobalMembers, GetType());
engine.Execute("StaticTestProperty = NewGuid()");
Assert.IsInstanceOfType(StaticTestProperty, typeof(Guid));
}
[TestMethod, TestCategory("VBScriptEngine")]
[ExpectedException(typeof(ScriptEngineException))]
public void VBScriptEngine_AddHostType_DefaultAccess()
{
engine.AddHostType("Test", GetType());
engine.Execute("Test.PrivateStaticMethod()");
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_AddHostType_PrivateAccess()
{
engine.AddHostType("Test", HostItemFlags.PrivateAccess, GetType());
engine.Execute("Test.PrivateStaticMethod()");
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_AddHostType_Static()
{
engine.AddHostType("Enumerable", typeof(Enumerable));
Assert.IsInstanceOfType(engine.Evaluate("Enumerable.Range(0, 5).ToArray()"), typeof(int[]));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_AddHostType_OpenGeneric()
{
engine.AddHostObject("host", new HostFunctions());
engine.AddHostType("List", typeof(List<>));
engine.AddHostType("Guid", typeof(Guid));
Assert.IsInstanceOfType(engine.Evaluate("host.newObj(List(Guid))"), typeof(List));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_AddHostType_ByName()
{
engine.AddHostObject("host", new HostFunctions());
engine.AddHostType("Random", "System.Random");
Assert.IsInstanceOfType(engine.Evaluate("host.newObj(Random)"), typeof(Random));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_AddHostType_ByNameWithAssembly()
{
engine.AddHostType("Enumerable", "System.Linq.Enumerable", "System.Core");
Assert.IsInstanceOfType(engine.Evaluate("Enumerable.Range(0, 5).ToArray()"), typeof(int[]));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_AddHostType_ByNameWithTypeArgs()
{
engine.AddHostObject("host", new HostFunctions());
engine.AddHostType("Dictionary", "System.Collections.Generic.Dictionary", typeof(string), typeof(int));
Assert.IsInstanceOfType(engine.Evaluate("host.newObj(Dictionary)"), typeof(Dictionary));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_AddHostType_DefaultName()
{
engine.AddHostObject("host", new HostFunctions());
engine.AddHostType(typeof(Random));
Assert.IsInstanceOfType(engine.Evaluate("host.newObj(Random)"), typeof(Random));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_AddHostType_DefaultNameGeneric()
{
engine.AddHostObject("host", new HostFunctions());
engine.AddHostType(typeof(List));
Assert.IsInstanceOfType(engine.Evaluate("host.newObj(List)"), typeof(List));
engine.AddHostType(typeof(Dictionary<,>));
engine.AddHostType(typeof(int));
engine.AddHostType(typeof(decimal));
Assert.IsInstanceOfType(engine.Evaluate("host.newObj(Dictionary(Int32, Decimal), 100)"), typeof(Dictionary));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_Evaluate()
{
Assert.AreEqual(Math.E * Math.PI, engine.Evaluate("e * pi"));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_Evaluate_Array()
{
// ReSharper disable ImplicitlyCapturedClosure
var lengths = new[] { 3, 5, 7 };
var formatParams = string.Join(", ", Enumerable.Range(0, lengths.Length).Select(position => "{" + position + "}"));
var hosts = Array.CreateInstance(typeof(object), lengths);
hosts.Iterate(indices => hosts.SetValue(new HostFunctions(), indices));
engine.AddHostObject("hostArray", hosts);
engine.Execute(MiscHelpers.FormatInvariant("dim hosts(" + formatParams + ")", lengths.Select(length => (object)(length - 1)).ToArray()));
hosts.Iterate(indices => engine.Execute(MiscHelpers.FormatInvariant("set hosts(" + formatParams + ") = hostArray.GetValue(" + formatParams + ")", indices.Select(index => (object)index).ToArray())));
hosts.Iterate(indices => Assert.AreSame(hosts.GetValue(indices), engine.Evaluate(MiscHelpers.FormatInvariant("hosts(" + formatParams + ")", indices.Select(index => (object)index).ToArray()))));
var result = engine.Evaluate("hosts");
Assert.IsInstanceOfType(result, typeof(object[,,]));
var hostArray = (object[,,])result;
hosts.Iterate(indices => Assert.AreSame(hosts.GetValue(indices), hostArray.GetValue(indices)));
// ReSharper restore ImplicitlyCapturedClosure
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_Evaluate_WithDocumentName()
{
const string documentName = "DoTheMath";
Assert.AreEqual(Math.E * Math.PI, engine.Evaluate(documentName, "e * pi"));
Assert.IsFalse(engine.GetDebugDocumentNames().Any(name => name.StartsWith(documentName, StringComparison.Ordinal)));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_Evaluate_DiscardDocument()
{
const string documentName = "DoTheMath";
Assert.AreEqual(Math.E * Math.PI, engine.Evaluate(documentName, true, "e * pi"));
Assert.IsFalse(engine.GetDebugDocumentNames().Any(name => name.StartsWith(documentName, StringComparison.Ordinal)));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_Evaluate_RetainDocument()
{
const string documentName = "DoTheMath";
Assert.AreEqual(Math.E * Math.PI, engine.Evaluate(documentName, false, "e * pi"));
Assert.IsTrue(engine.GetDebugDocumentNames().Any(name => name.StartsWith(documentName, StringComparison.Ordinal)));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_Evaluate_DocumentInfo_WithDocumentName()
{
const string documentName = "DoTheMath";
Assert.AreEqual(Math.E * Math.PI, engine.Evaluate(new DocumentInfo(documentName), "e * pi"));
Assert.IsFalse(engine.GetDebugDocumentNames().Any(name => name.StartsWith(documentName, StringComparison.Ordinal)));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_Evaluate_DocumentInfo_WithDocumentUri()
{
const string documentName = "DoTheMath";
var documentUri = new Uri(@"c:\foo\bar\baz\" + documentName);
Assert.AreEqual(Math.E * Math.PI, engine.Evaluate(new DocumentInfo(documentUri) { Flags = DocumentFlags.None }, "e * pi"));
Assert.IsTrue(engine.GetDebugDocumentNames().Any(name => name.StartsWith(documentName, StringComparison.Ordinal)));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_Evaluate_DocumentInfo_WithDocumentUri_Relative()
{
const string documentName = "DoTheMath";
var documentUri = new Uri(documentName, UriKind.Relative);
Assert.AreEqual(Math.E * Math.PI, engine.Evaluate(new DocumentInfo(documentUri) { Flags = DocumentFlags.None }, "e * pi"));
Assert.IsTrue(engine.GetDebugDocumentNames().Any(name => name.StartsWith(documentName, StringComparison.Ordinal)));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_Evaluate_DocumentInfo_DiscardDocument()
{
const string documentName = "DoTheMath";
Assert.AreEqual(Math.E * Math.PI, engine.Evaluate(new DocumentInfo(documentName) { Flags = DocumentFlags.IsTransient }, "e * pi"));
Assert.IsFalse(engine.GetDebugDocumentNames().Any(name => name.StartsWith(documentName, StringComparison.Ordinal)));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_Evaluate_DocumentInfo_RetainDocument()
{
const string documentName = "DoTheMath";
Assert.AreEqual(Math.E * Math.PI, engine.Evaluate(new DocumentInfo(documentName) { Flags = DocumentFlags.None }, "e * pi"));
Assert.IsTrue(engine.GetDebugDocumentNames().Any(name => name.StartsWith(documentName, StringComparison.Ordinal)));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_Execute()
{
engine.Execute("epi = e * pi");
Assert.AreEqual(Math.E * Math.PI, engine.Script.epi);
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_Execute_WithDocumentName()
{
const string documentName = "DoTheMath";
engine.Execute(documentName, "epi = e * pi");
Assert.AreEqual(Math.E * Math.PI, engine.Script.epi);
Assert.IsTrue(engine.GetDebugDocumentNames().Any(name => name.StartsWith(documentName, StringComparison.Ordinal)));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_Execute_DiscardDocument()
{
const string documentName = "DoTheMath";
engine.Execute(documentName, true, "epi = e * pi");
Assert.AreEqual(Math.E * Math.PI, engine.Script.epi);
Assert.IsFalse(engine.GetDebugDocumentNames().Any(name => name.StartsWith(documentName, StringComparison.Ordinal)));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_Execute_RetainDocument()
{
const string documentName = "DoTheMath";
engine.Execute(documentName, false, "epi = e * pi");
Assert.AreEqual(Math.E * Math.PI, engine.Script.epi);
Assert.IsTrue(engine.GetDebugDocumentNames().Any(name => name.StartsWith(documentName, StringComparison.Ordinal)));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_Execute_DocumentInfo_WithDocumentName()
{
const string documentName = "DoTheMath";
engine.Execute(new DocumentInfo(documentName), "epi = e * pi");
Assert.AreEqual(Math.E * Math.PI, engine.Script.epi);
Assert.IsTrue(engine.GetDebugDocumentNames().Any(name => name.StartsWith(documentName, StringComparison.Ordinal)));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_Execute_DocumentInfo_WithDocumentUri()
{
const string documentName = "DoTheMath";
var documentUri = new Uri(@"c:\foo\bar\baz\" + documentName);
engine.Execute(new DocumentInfo(documentUri), "epi = e * pi");
Assert.AreEqual(Math.E * Math.PI, engine.Script.epi);
Assert.IsTrue(engine.GetDebugDocumentNames().Any(name => name.StartsWith(documentName, StringComparison.Ordinal)));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_Execute_DocumentInfo_WithDocumentUri_Relative()
{
const string documentName = "DoTheMath";
var documentUri = new Uri(documentName, UriKind.Relative);
engine.Execute(new DocumentInfo(documentUri), "epi = e * pi");
Assert.AreEqual(Math.E * Math.PI, engine.Script.epi);
Assert.IsTrue(engine.GetDebugDocumentNames().Any(name => name.StartsWith(documentName, StringComparison.Ordinal)));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_Execute_DocumentInfo_DiscardDocument()
{
const string documentName = "DoTheMath";
engine.Execute(new DocumentInfo(documentName) { Flags = DocumentFlags.IsTransient }, "epi = e * pi");
Assert.AreEqual(Math.E * Math.PI, engine.Script.epi);
Assert.IsFalse(engine.GetDebugDocumentNames().Any(name => name.StartsWith(documentName, StringComparison.Ordinal)));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_Execute_DocumentInfo_RetainDocument()
{
const string documentName = "DoTheMath";
engine.Execute(new DocumentInfo(documentName) { Flags = DocumentFlags.None }, "epi = e * pi");
Assert.AreEqual(Math.E * Math.PI, engine.Script.epi);
Assert.IsTrue(engine.GetDebugDocumentNames().Any(name => name.StartsWith(documentName, StringComparison.Ordinal)));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_ExecuteCommand_EngineConvert()
{
Assert.AreEqual("[ScriptObject:EngineInternalImpl]", engine.ExecuteCommand("eval EngineInternal"));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_ExecuteCommand_HostConvert()
{
var dateHostItem = HostItem.Wrap(engine, new DateTime(2007, 5, 22, 6, 15, 43));
engine.AddHostObject("date", dateHostItem);
Assert.AreEqual(dateHostItem.ToString(), engine.ExecuteCommand("eval date"));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_ExecuteCommand_HostVariable()
{
engine.Script.host = new HostFunctions();
Assert.AreEqual("[HostVariable:String]", engine.ExecuteCommand("eval host.newVar(\"foo\")"));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_Invoke_ScriptFunction()
{
engine.Execute("function foo(x) : foo = x * pi : end function");
Assert.AreEqual(Math.E * Math.PI, engine.Invoke("foo", Math.E));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_Invoke_HostDelegate()
{
engine.Script.foo = new Func(x => x * Math.PI);
Assert.AreEqual(Math.E * Math.PI, engine.Invoke("foo", Math.E));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_Interrupt()
{
var checkpoint = new ManualResetEvent(false);
ThreadPool.QueueUserWorkItem(state =>
{
checkpoint.WaitOne();
engine.Interrupt();
});
engine.AddHostObject("checkpoint", checkpoint);
TestUtil.AssertException(() => engine.Execute("call checkpoint.Set() : while true : foo = \"hello\" : wend"));
Assert.AreEqual(Math.E * Math.PI, engine.Evaluate("e * pi"));
}
[TestMethod, TestCategory("VBScriptEngine")]
[ExpectedException(typeof(ScriptEngineException))]
public void VBScriptEngine_AccessContext_Default()
{
engine.AddHostObject("test", this);
engine.Execute("test.PrivateMethod()");
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_AccessContext_Private()
{
engine.AddHostObject("test", this);
engine.AccessContext = GetType();
engine.Execute("test.PrivateMethod()");
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_ContinuationCallback()
{
engine.ContinuationCallback = () => false;
TestUtil.AssertException(() => engine.Execute("while true : foo = \"hello\" : wend"));
engine.ContinuationCallback = null;
Assert.AreEqual(Math.E * Math.PI, engine.Evaluate("e * pi"));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_FileNameExtension()
{
Assert.AreEqual("vbs", engine.FileNameExtension);
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_Script_Variable()
{
var host = new HostFunctions();
engine.Script.host = host;
Assert.AreSame(host, engine.Script.host);
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_Script_Variable_Scalar()
{
const int value = 123;
engine.Script.value = value;
Assert.AreEqual(value, engine.Script.value);
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_Script_Variable_Enum()
{
const DayOfWeek value = DayOfWeek.Wednesday;
engine.Script.value = value;
Assert.AreEqual(value, engine.Script.value);
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_Script_Array()
{
// ReSharper disable ImplicitlyCapturedClosure
var lengths = new[] { 3, 5, 7 };
var formatParams = string.Join(", ", Enumerable.Range(0, lengths.Length).Select(position => "{" + position + "}"));
var hosts = Array.CreateInstance(typeof(object), lengths);
hosts.Iterate(indices => hosts.SetValue(new HostFunctions(), indices));
engine.Script.hostArray = hosts;
engine.Execute(MiscHelpers.FormatInvariant("dim hosts(" + formatParams + ")", lengths.Select(length => (object)(length - 1)).ToArray()));
hosts.Iterate(indices => engine.Execute(MiscHelpers.FormatInvariant("set hosts(" + formatParams + ") = hostArray.GetValue(" + formatParams + ")", indices.Select(index => (object)index).ToArray())));
hosts.Iterate(indices => Assert.AreSame(hosts.GetValue(indices), engine.Script.hosts.GetValue(indices)));
var result = engine.Script.hosts;
Assert.IsInstanceOfType(result, typeof(object[,,]));
var hostArray = (object[,,])result;
hosts.Iterate(indices => Assert.AreSame(hosts.GetValue(indices), hostArray.GetValue(indices)));
// ReSharper restore ImplicitlyCapturedClosure
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_Script_Variable_Struct()
{
var stamp = new DateTime(2007, 5, 22, 6, 15, 43);
engine.Script.stamp = stamp;
Assert.AreEqual(stamp, engine.Script.stamp);
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_Script_Function()
{
engine.Execute("function test(x, y) : test = x * y : end function");
Assert.AreEqual(Math.E * Math.PI, engine.Script.test(Math.E, Math.PI));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_Script_Sub()
{
var callbackInvoked = false;
Action callback = () => callbackInvoked = true;
engine.Execute("sub test(x) : call x() : end sub");
engine.Script.test(callback);
Assert.IsTrue(callbackInvoked);
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_Script_Variable_VB()
{
TestUtil.InvokeVBTestSub(@"
Using engine As New VBScriptEngine
Dim host As New HostFunctions
engine.Script.host = host
Assert.AreSame(host, engine.Script.host)
End Using
");
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_Script_Variable_Scalar_VB()
{
TestUtil.InvokeVBTestSub(@"
Using engine As New VBScriptEngine
Dim value = 123
engine.Script.value = value
Assert.AreEqual(value, engine.Script.value)
End Using
");
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_Script_Variable_Enum_VB()
{
TestUtil.InvokeVBTestSub(@"
Using engine As New VBScriptEngine
Dim value = DayOfWeek.Wednesday
engine.Script.value = value
Assert.AreEqual(value, engine.Script.value)
End Using
");
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_Script_Array_VB()
{
TestUtil.InvokeVBTestSub(@"
Using engine As New VBScriptEngine
Dim lengths As Integer() = { 3, 5, 7 }
Dim formatParams = String.Join("", "", Enumerable.Range(0, lengths.Length).Select(Function(position) ""{"" & position & ""}""))
Dim hosts = Array.CreateInstance(GetType(Object), lengths)
TestUtil.Iterate(hosts, Sub(indices) hosts.SetValue(New HostFunctions, indices))
engine.Script.hostArray = hosts
engine.Execute(TestUtil.FormatInvariant(""dim hosts("" & formatParams & "")"", lengths.Select(Function(length) CType(length - 1, Object)).ToArray()))
TestUtil.Iterate(hosts, Sub(indices) engine.Execute(TestUtil.FormatInvariant(""set hosts("" & formatParams & "") = hostArray.GetValue("" & formatParams & "")"", indices.Select(Function(index) CType(index, Object)).ToArray())))
TestUtil.Iterate(hosts, Sub(indices) Assert.AreSame(hosts.GetValue(indices), engine.Script.hosts.GetValue(indices)))
Dim result = engine.Script.hosts
Assert.IsInstanceOfType(result, GetType(Object(,,)))
Dim hostArray As Object(,,) = result
TestUtil.Iterate(hosts, Sub(indices) Assert.AreSame(hosts.GetValue(indices), hostArray.GetValue(indices)))
End Using
");
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_Script_Variable_Struct_VB()
{
TestUtil.InvokeVBTestSub(@"
Using engine As New VBScriptEngine
Dim stamp = New DateTime(2007, 5, 22, 6, 15, 43)
engine.Script.stamp = stamp
Assert.AreEqual(stamp, engine.Script.stamp)
End Using
");
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_Script_Function_VB()
{
TestUtil.InvokeVBTestSub(@"
Using engine As New VBScriptEngine
engine.Execute(""function test(x, y) : test = x * y : end function"")
Assert.AreEqual(Math.E * Math.PI, engine.Script.test(Math.E, Math.PI))
End Using
");
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_Script_Sub_VB()
{
TestUtil.InvokeVBTestSub(@"
Using engine As New VBScriptEngine
Dim callbackInvoked = False
Dim callback = Sub() callbackInvoked = True
engine.Execute(""sub test(x) : call x() : end sub"")
engine.Script.test(callback)
Assert.IsTrue(callbackInvoked)
End Using
");
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_CollectGarbage()
{
// VBScript doesn't support GC
engine.CollectGarbage(true);
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_General()
{
using (var console = new StringWriter())
{
var clr = new HostTypeCollection(type => type != typeof(Console), "mscorlib", "System", "System.Core");
clr.GetNamespaceNode("System").SetPropertyNoCheck("Console", console);
engine.AddHostObject("host", new ExtendedHostFunctions());
engine.AddHostObject("clr", clr);
engine.Execute(generalScript);
Assert.AreEqual(MiscHelpers.FormatCode(generalScriptOutput), console.ToString().Replace("\r\n", "\n"));
}
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_ErrorHandling_ScriptError()
{
TestUtil.AssertException(() =>
{
try
{
engine.Execute("foo = {}; foo();");
}
catch (ScriptEngineException exception)
{
TestUtil.AssertValidException(engine, exception);
Assert.IsNull(exception.InnerException);
throw;
}
});
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_ErrorHandling_HostException()
{
engine.AddHostObject("host", new HostFunctions());
TestUtil.AssertException(() =>
{
try
{
engine.Evaluate("host.proc(0)");
}
catch (ScriptEngineException exception)
{
TestUtil.AssertValidException(engine, exception);
Assert.IsNotNull(exception.InnerException);
var hostException = exception.InnerException;
Assert.IsInstanceOfType(hostException, typeof(RuntimeBinderException));
TestUtil.AssertValidException(hostException);
Assert.IsNull(hostException.InnerException);
Assert.AreEqual(hostException.Message, exception.Message);
throw;
}
});
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_ErrorHandling_IgnoredHostException()
{
engine.AddHostObject("host", new HostFunctions());
TestUtil.AssertException(() =>
{
try
{
engine.Execute("on error resume next : host.newObj(null) : on error goto 0 : foo = \"foo\" : foo()");
}
catch (ScriptEngineException exception)
{
TestUtil.AssertValidException(engine, exception);
Assert.IsNull(exception.InnerException);
throw;
}
});
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_ErrorHandling_NestedScriptError()
{
using (var innerEngine = new JScriptEngine("inner", WindowsScriptEngineFlags.EnableDebugging))
{
engine.AddHostObject("engine", innerEngine);
TestUtil.AssertException(() =>
{
try
{
engine.Execute("engine.Execute(\"foo = {}; foo();\")");
}
catch (ScriptEngineException exception)
{
TestUtil.AssertValidException(engine, exception);
Assert.IsNotNull(exception.InnerException);
var hostException = exception.InnerException;
Assert.IsInstanceOfType(hostException, typeof(TargetInvocationException));
TestUtil.AssertValidException(hostException);
Assert.IsNotNull(hostException.InnerException);
var nestedException = hostException.InnerException as ScriptEngineException;
Assert.IsNotNull(nestedException);
// ReSharper disable once AccessToDisposedClosure
TestUtil.AssertValidException(innerEngine, nestedException);
// ReSharper disable once PossibleNullReferenceException
Assert.IsNull(nestedException.InnerException);
Assert.AreEqual(hostException.Message, exception.Message);
throw;
}
});
}
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_ErrorHandling_NestedHostException()
{
using (var innerEngine = new JScriptEngine("inner", WindowsScriptEngineFlags.EnableDebugging))
{
innerEngine.AddHostObject("host", new HostFunctions());
engine.AddHostObject("engine", innerEngine);
TestUtil.AssertException(() =>
{
try
{
engine.Execute("engine.Evaluate(\"host.proc(0)\")");
}
catch (ScriptEngineException exception)
{
TestUtil.AssertValidException(engine, exception);
Assert.IsNotNull(exception.InnerException);
var hostException = exception.InnerException;
Assert.IsInstanceOfType(hostException, typeof(TargetInvocationException));
TestUtil.AssertValidException(hostException);
Assert.IsNotNull(hostException.InnerException);
var nestedException = hostException.InnerException as ScriptEngineException;
Assert.IsNotNull(nestedException);
// ReSharper disable once AccessToDisposedClosure
TestUtil.AssertValidException(innerEngine, nestedException);
// ReSharper disable once PossibleNullReferenceException
Assert.IsNotNull(nestedException.InnerException);
var nestedHostException = nestedException.InnerException;
Assert.IsInstanceOfType(nestedHostException, typeof(RuntimeBinderException));
TestUtil.AssertValidException(nestedHostException);
Assert.IsNull(nestedHostException.InnerException);
Assert.AreEqual(nestedHostException.Message, nestedException.Message);
Assert.AreEqual(hostException.Message, exception.Message);
throw;
}
});
}
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_DynamicHostObject_CreateInstance()
{
engine.Script.testObject = new DynamicTestObject();
engine.Script.host = new HostFunctions();
Assert.AreEqual("foo bar baz qux", engine.Evaluate("host.newObj(testObject, \"foo\", \"bar\", \"baz\", \"qux\")"));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_DynamicHostObject_CreateInstance_Fail()
{
engine.Script.testObject = new DynamicTestObject();
engine.Script.host = new HostFunctions();
TestUtil.AssertException(() => engine.Evaluate("host.newObj(testObject)"));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_DynamicHostObject_Invoke()
{
engine.Script.testObject = new DynamicTestObject();
Assert.AreEqual("foo,bar,baz,qux", engine.Evaluate("testObject(\"foo\", \"bar\", \"baz\", \"qux\")"));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_DynamicHostObject_Invoke_Fail()
{
engine.Script.testObject = new DynamicTestObject();
TestUtil.AssertException(() => engine.Evaluate("testObject()"));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_DynamicHostObject_InvokeMethod()
{
engine.Script.testObject = new DynamicTestObject();
Assert.AreEqual("foo-bar-baz-qux", engine.Evaluate("testObject.DynamicMethod(\"foo\", \"bar\", \"baz\", \"qux\")"));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_DynamicHostObject_InvokeMethod_Fail()
{
engine.Script.testObject = new DynamicTestObject();
TestUtil.AssertException(() => engine.Evaluate("testObject.DynamicMethod()"));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_DynamicHostObject_InvokeMethod_FieldOverride()
{
engine.Script.testObject = new DynamicTestObject();
Assert.AreEqual("foo.bar.baz.qux", engine.Evaluate("testObject.SomeField(\"foo\", \"bar\", \"baz\", \"qux\")"));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_DynamicHostObject_InvokeMethod_FieldOverride_Fail()
{
engine.Script.testObject = new DynamicTestObject();
TestUtil.AssertException(() => engine.Evaluate("testObject.SomeField()"));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_DynamicHostObject_InvokeMethod_PropertyOverride()
{
engine.Script.testObject = new DynamicTestObject();
Assert.AreEqual("foo:bar:baz:qux", engine.Evaluate("testObject.SomeProperty(\"foo\", \"bar\", \"baz\", \"qux\")"));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_DynamicHostObject_InvokeMethod_PropertyOverride_Fail()
{
engine.Script.testObject = new DynamicTestObject();
TestUtil.AssertException(() => engine.Evaluate("testObject.SomeProperty()"));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_DynamicHostObject_InvokeMethod_DynamicOverload()
{
engine.Script.testObject = new DynamicTestObject();
Assert.AreEqual("foo;bar;baz;qux", engine.Evaluate("testObject.SomeMethod(\"foo\", \"bar\", \"baz\", \"qux\")"));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_DynamicHostObject_InvokeMethod_NonDynamicOverload()
{
engine.Script.testObject = new DynamicTestObject();
Assert.AreEqual(Math.PI, engine.Evaluate("testObject.SomeMethod()"));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_DynamicHostObject_InvokeMethod_NonDynamic()
{
engine.Script.testObject = new DynamicTestObject();
Assert.AreEqual("Super Bass-O-Matic '76", engine.Evaluate("testObject.ToString()"));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_DynamicHostObject_StaticType_Field()
{
engine.Script.testObject = new DynamicTestObject();
engine.Script.host = new HostFunctions();
Assert.IsInstanceOfType(engine.Evaluate("testObject.SomeField"), typeof(HostMethod));
Assert.AreEqual(12345, engine.Evaluate("host.toStaticType(testObject).SomeField"));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_DynamicHostObject_StaticType_Property()
{
engine.Script.testObject = new DynamicTestObject();
engine.Script.host = new HostFunctions();
Assert.IsInstanceOfType(engine.Evaluate("testObject.SomeProperty"), typeof(HostMethod));
Assert.AreEqual("Bogus", engine.Evaluate("host.toStaticType(testObject).SomeProperty"));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_DynamicHostObject_StaticType_Method()
{
engine.Script.testObject = new DynamicTestObject();
engine.Script.host = new HostFunctions();
Assert.AreEqual("bar+baz+qux", engine.Evaluate("host.toStaticType(testObject).SomeMethod(\"foo\", \"bar\", \"baz\", \"qux\")"));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_DynamicHostObject_StaticType_Invoke()
{
engine.Script.testObject = new DynamicTestObject();
engine.Script.host = new HostFunctions();
TestUtil.AssertException(() => engine.Evaluate("host.toStaticType(testObject)(\"foo\", \"bar\", \"baz\", \"qux\")"));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_DynamicHostObject_Property()
{
engine.Script.testObject = new DynamicTestObject();
engine.Script.host = new HostFunctions();
Assert.IsInstanceOfType(engine.Evaluate("host.getProperty(testObject, \"foo\")"), typeof(Undefined));
Assert.AreEqual(123, engine.Evaluate("host.setProperty(testObject, \"foo\", clng(123))"));
Assert.AreEqual(123, engine.Evaluate("testObject.foo"));
Assert.IsTrue((bool)engine.Evaluate("host.removeProperty(testObject, \"foo\")"));
Assert.IsInstanceOfType(engine.Evaluate("host.getProperty(testObject, \"foo\")"), typeof(Undefined));
Assert.IsFalse((bool)engine.Evaluate("host.removeProperty(testObject, \"foo\")"));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_DynamicHostObject_Property_Fail()
{
engine.Script.testObject = new DynamicTestObject();
engine.Script.host = new HostFunctions();
Assert.IsInstanceOfType(engine.Evaluate("host.getProperty(testObject, \"Zfoo\")"), typeof(Undefined));
TestUtil.AssertException(() => engine.Evaluate("host.setProperty(testObject, \"Zfoo\", clng(123))"));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_DynamicHostObject_Property_Invoke()
{
engine.Script.testObject = new DynamicTestObject();
engine.Script.host = new HostFunctions();
engine.Execute("function secret(x) : secret = len(x) : end function");
Assert.IsInstanceOfType(engine.Evaluate("host.getProperty(testObject, \"foo\")"), typeof(Undefined));
Assert.IsInstanceOfType(engine.Evaluate("host.setProperty(testObject, \"foo\", GetRef(\"secret\"))"), typeof(DynamicObject));
Assert.AreEqual("floccinaucinihilipilification".Length, engine.Evaluate("testObject.foo(\"floccinaucinihilipilification\")"));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_DynamicHostObject_Property_Invoke_Nested()
{
engine.Script.testObject = new DynamicTestObject();
engine.Script.host = new HostFunctions();
Assert.IsInstanceOfType(engine.Evaluate("host.getProperty(testObject, \"foo\")"), typeof(Undefined));
Assert.IsInstanceOfType(engine.Evaluate("host.setProperty(testObject, \"foo\", testObject)"), typeof(DynamicObject));
Assert.AreEqual("foo,bar,baz,qux", engine.Evaluate("testObject.foo(\"foo\", \"bar\", \"baz\", \"qux\")"));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_DynamicHostObject_Element()
{
engine.Script.testObject = new DynamicTestObject();
engine.Script.host = new HostFunctions();
Assert.IsInstanceOfType(engine.Evaluate("host.getElement(testObject, clng(1), clng(2), clng(3), \"foo\")"), typeof(Undefined));
Assert.AreEqual("bar", engine.Evaluate("host.setElement(testObject, \"bar\", clng(1), clng(2), clng(3), \"foo\")"));
Assert.AreEqual("bar", engine.Evaluate("host.getElement(testObject, clng(1), clng(2), clng(3), \"foo\")"));
Assert.IsTrue((bool)engine.Evaluate("host.removeElement(testObject, clng(1), clng(2), clng(3), \"foo\")"));
Assert.IsInstanceOfType(engine.Evaluate("host.getElement(testObject, clng(1), clng(2), clng(3), \"foo\")"), typeof(Undefined));
Assert.IsFalse((bool)engine.Evaluate("host.removeElement(testObject, clng(1), clng(2), clng(3), \"foo\")"));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_DynamicHostObject_Element_Fail()
{
engine.Script.testObject = new DynamicTestObject();
engine.Script.host = new HostFunctions();
Assert.IsInstanceOfType(engine.Evaluate("host.getElement(testObject, clng(1), clng(2), clng(3), pi)"), typeof(Undefined));
TestUtil.AssertException(() => engine.Evaluate("host.setElement(testObject, \"bar\", clng(1), clng(2), clng(3), pi)"));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_DynamicHostObject_Element_Index()
{
engine.Script.testObject = new DynamicTestObject { DisableInvocation = true, DisableDynamicMembers = true };
engine.Script.host = new HostFunctions();
Assert.IsInstanceOfType(engine.Evaluate("testObject(clng(123))"), typeof(Undefined));
Assert.IsInstanceOfType(engine.Evaluate("host.getElement(testObject, clng(123))"), typeof(Undefined));
engine.Execute("testObject(clng(123)) = 456");
Assert.AreEqual((short)456, engine.Evaluate("testObject(clng(123))"));
Assert.AreEqual((short)456, engine.Evaluate("host.getElement(testObject, clng(123))"));
engine.Execute("testObject(clng(123)) = nothing");
Assert.IsInstanceOfType(engine.Evaluate("testObject(clng(123))"), typeof(Undefined));
Assert.IsInstanceOfType(engine.Evaluate("host.getElement(testObject, clng(123))"), typeof(Undefined));
Assert.IsInstanceOfType(engine.Evaluate("testObject(\"foo\")"), typeof(Undefined));
Assert.IsInstanceOfType(engine.Evaluate("host.getElement(testObject, \"foo\")"), typeof(Undefined));
engine.Execute("testObject(\"foo\") = \"bar\"");
Assert.AreEqual("bar", engine.Evaluate("testObject(\"foo\")"));
Assert.AreEqual("bar", engine.Evaluate("host.getElement(testObject, \"foo\")"));
engine.Execute("testObject(\"foo\") = nothing");
Assert.IsInstanceOfType(engine.Evaluate("testObject(\"foo\")"), typeof(Undefined));
Assert.IsInstanceOfType(engine.Evaluate("host.getElement(testObject, \"foo\")"), typeof(Undefined));
Assert.IsInstanceOfType(engine.Evaluate("testObject(\"foo\", \"bar\", \"baz\")"), typeof(Undefined));
Assert.IsInstanceOfType(engine.Evaluate("host.getElement(testObject, \"foo\", \"bar\", \"baz\")"), typeof(Undefined));
engine.Execute("testObject(\"foo\", \"bar\", \"baz\") = \"qux\"");
Assert.AreEqual("qux", engine.Evaluate("testObject(\"foo\", \"bar\", \"baz\")"));
Assert.AreEqual("qux", engine.Evaluate("host.getElement(testObject, \"foo\", \"bar\", \"baz\")"));
engine.Execute("testObject(\"foo\", \"bar\", \"baz\") = nothing");
Assert.IsInstanceOfType(engine.Evaluate("testObject(\"foo\", \"bar\", \"baz\")"), typeof(Undefined));
Assert.IsInstanceOfType(engine.Evaluate("host.getElement(testObject, \"foo\", \"bar\", \"baz\")"), typeof(Undefined));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_DynamicHostObject_Convert()
{
engine.Script.testObject = new DynamicTestObject();
engine.Script.host = new HostFunctions();
engine.AddHostType("int_t", typeof(int));
engine.AddHostType("string_t", typeof(string));
Assert.AreEqual(98765, engine.Evaluate("host.cast(int_t, testObject)"));
Assert.AreEqual("Booyakasha!", engine.Evaluate("host.cast(string_t, testObject)"));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_HostIndexers()
{
engine.Script.testObject = new TestObject();
TestUtil.AssertException(() => engine.Evaluate("testObject.Item(clng(123))"));
TestUtil.AssertException(() => engine.Evaluate("testObject.Item.get(clng(123))"));
engine.Execute("testObject.Item(clng(123)) = pi");
Assert.AreEqual(Math.PI, engine.Evaluate("testObject.Item(clng(123))"));
Assert.AreEqual(Math.E, engine.Evaluate("testObject.Item.set(clng(123), e)"));
Assert.AreEqual(Math.E, engine.Evaluate("testObject.Item.get(clng(123))"));
TestUtil.AssertException(() => engine.Evaluate("testObject.Item(\"456\")"));
TestUtil.AssertException(() => engine.Evaluate("testObject.Item.get(\"456\")"));
engine.Execute("testObject.Item(\"456\") = sqr(2)");
Assert.AreEqual(Math.Sqrt(2), engine.Evaluate("testObject.Item(\"456\")"));
Assert.AreEqual(Math.Sqrt(3), engine.Evaluate("testObject.Item.set(\"456\", sqr(3))"));
Assert.AreEqual(Math.Sqrt(3), engine.Evaluate("testObject.Item.get(\"456\")"));
TestUtil.AssertException(() => engine.Evaluate("testObject.Item(clng(123), \"456\", 789.987, -0.12345)"));
TestUtil.AssertException(() => engine.Evaluate("testObject.Item.get(clng(123), \"456\", 789.987, -0.12345)"));
engine.Execute("testObject.Item(clng(123), \"456\", 789.987, -0.12345) = sqr(5)");
Assert.AreEqual(Math.Sqrt(5), engine.Evaluate("testObject.Item(clng(123), \"456\", 789.987, -0.12345)"));
Assert.AreEqual(Math.Sqrt(7), engine.Evaluate("testObject.Item.set(clng(123), \"456\", 789.987, -0.12345, sqr(7))"));
Assert.AreEqual(Math.Sqrt(7), engine.Evaluate("testObject.Item.get(clng(123), \"456\", 789.987, -0.12345)"));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_FormatCode()
{
try
{
engine.Execute("a", "\n\n\n x = 3.a");
}
catch (ScriptEngineException exception)
{
Assert.IsTrue(exception.ErrorDetails.Contains("(a:3:11)"));
}
engine.FormatCode = true;
try
{
engine.Execute("b", "\n\n\n x = 3.a");
}
catch (ScriptEngineException exception)
{
Assert.IsTrue(exception.ErrorDetails.Contains("(b:0:6)"));
}
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_GetStackTrace()
{
engine.AddHostObject("qux", new Func