context: /**************************************************************************** 
   * Copyright 2012 David Lurton
   * This Source Code Form is subject to the terms of the Mozilla Public 
   * License, v. 2.0. If a copy of the MPL was not distributed with this file, 
   * You can obtain one at http://mozilla.org/MPL/2.0/.
   ****************************************************************************/
  
  using System;
  using System.IO;
  using Happy.ScriptEngine.Runtime;
  using Happy.ScriptEngine.Runtime.Trackers;
  using Happy.ScriptEngine.Tests.IntegrationTests.TestTypes;
  using Microsoft.Scripting;
  using NUnit.Framework;
  
  namespace Happy.ScriptEngine.Tests.IntegrationTests
  {
  	[TestFixture]
  	public class DotNetInteropTests : TestFixtureBase
  	{
  		[Test]
  		public void ReadSimpleSystemTypes()
  		{
  			const string moduleToParse = @"
  function testFunc1() { return System.Int32; }
  function testFunc2() { return System.IO.TextWriter; }
  ";
  			HappyRuntimeContext rc = CompileModule(moduleToParse);
  			Assert.AreEqual(typeof(Int32), rc.Globals.testFunc1().Type);
  			Assert.AreEqual(typeof(TextWriter), rc.Globals.testFunc2().Type);
  		}
  
  		[Test]
  		public void RootNamespace()
  		{
  			HappyRuntimeContext context = base.CompileModule(@"
  function getSystem() { return System; } 
  function getMicrosoft() { return Microsoft; }
  ");
  
  			Assert.IsInstanceOf(typeof(HappyNamespaceTracker), context.Globals.getSystem());
  			Assert.IsInstanceOf(typeof(HappyNamespaceTracker), context.Globals.getMicrosoft());
  		}
  
  		[Test]
  		public void DeepNamespaces()
  		{
  			HappyRuntimeContext context = base.CompileModule(@"
  function testFunc1() { return System.Diagnostics; }
  function testFunc2() { return System.Diagnostics.Eventing; }
  function testFunc3() { return System.Diagnostics.Eventing.Reader; }
  ");
  			HappyNamespaceTracker result = context.Globals.testFunc1();
  			Assert.AreEqual("System.Diagnostics", result.FullName);
  
  			result = context.Globals.testFunc2();
  			Assert.AreEqual("System.Diagnostics.Eventing", result.FullName);
  
  			result = context.Globals.testFunc3();
  			Assert.AreEqual("System.Diagnostics.Eventing.Reader", result.FullName);
  		}
  
  		[Test]
  		public void TypeReference()
  		{
  			HappyRuntimeContext context = base.CompileModule(@"
  function testFunc() { return System.Int32; }
  ");
  			Assert.IsInstanceOf(typeof(HappyTypeTracker), context.Globals.testFunc());
  		}
  
  		[Test]
  		public void TypeAlias()
  		{
  			HappyRuntimeContext context = base.CompileModule(@"
  def Int32 = System.Int32;
  function testFunc() { return Int32; }
  ");
  			Assert.IsInstanceOf(typeof(HappyTypeTracker), context.Globals.testFunc());
  		}
  
  		[Test]
  		public void LocalAssembly()
  		{
  			HappyRuntimeContext context = base.CompileModule(@"
  load ""Happy.ScriptEngine.Tests"";
  function testFunc() { return Happy.ScriptEngine.Tests.IntegrationTests.TestTypes.TestClass; }");
  			HappyTypeTracker tracker = context.Globals.testFunc();
  
  			Assert.AreEqual("Happy.ScriptEngine.Tests.IntegrationTests.TestTypes.TestClass", tracker.FullName);
  		}
  		[Test]
  		public void StaticMemberInvoke()
  		{
  			HappyRuntimeContext context = base.CompileExpression(@"System.Int32.Parse(""123"");");
  			Assert.AreEqual(123, context.Globals.testFunc());
  		}
  
  
  		[Test]
  		public void StaticMemberInvoke2()
  		{
  			HappyRuntimeContext context = base.CompileModule(
  @"function testFunc(input)
  { return System.Int32.Parse(input); }
  ");
  			object returnValue = context.Globals.testFunc("123");
  			Assert.IsInstanceOf(typeof(Int32), returnValue);
  			Assert.AreEqual(123, returnValue);
  		}
  
  		[Test]
  		public void StaticMemberInvoke3()
  		{
  			StringWriter writer = new StringWriter();
  			HappyRuntimeContext context = base.CompileModule(
  @"function testFunc(input)
  { System.Console.Write(""Hello, {0}!"", input); }
  ");
  			Console.SetOut(writer);
  			context.Globals.testFunc("world");
  			Assert.AreEqual("Hello, world!", writer.ToString());
  		}
  
  		[Test]
  		[Category(TestCategories.RuntimeErrorHandling)]
  		public void InvalidNamespace()
  		{
  			HappyRuntimeContext context = base.CompileModule(
  @"
  function testFunc()
  { return System.Invalid; }
  ");
  			Assert.Throws<MissingMemberException>(() => context.Globals.testFunc());
  		}
  
  		[Test]
  		[Category(TestCategories.RuntimeErrorHandling)]
  		public void InvalidMember()
  		{
  			HappyRuntimeContext context = base.CompileModule(
  @"function testFunc()
  { return System.Console.InvalidMember; }
  ");
  			Assert.Throws<MissingMemberException>(() => context.Globals.testFunc());
  		}
  
  		[Test]
  		[Category(TestCategories.RuntimeErrorHandling)]
  		public void MssingStaticMethod()
  		{
  			HappyRuntimeContext context = base.CompileModule(
  @"load ""Happy.ScriptEngine.Tests"";
  function testFunc()
  { return Happy.ScriptEngine.Tests.IntegrationTests.TestTypes.TestClass.NonExistentMethod(); }
  ");
  			Assert.Throws<MissingMethodException>(() => context.Globals.testFunc());
  		}
  
  		[Test]
  		[Category(TestCategories.RuntimeErrorHandling)]
  		public void MissingInstanceMethod()
  		{
  			HappyRuntimeContext context = base.CompileModule("function testFunc(instance) { return instance.NonExistentMethod(); }");
  			Assert.Throws<MissingMethodException>(() => context.Globals.testFunc(new object()));
  		}
  
  		[Test]
  		[Ignore("TODO:  fix this unit test")]
  		public void CantFindStaticOverride()
  		{
  			HappyRuntimeContext context = base.CompileModule(
  @"load ""Happy.ScriptEngine.Tests"";
  function testFunc()
  { return Happy.ScriptEngine.Tests.IntegrationTests.TestTypes.TestClass.SomeStaticMethod(1.0); }
  ");
  			Assert.Throws<MissingMemberException>(() => context.Globals.testFunc());
  		}
  
  		[Test]
  		[Category(TestCategories.RuntimeErrorHandling)]
  		public void CantFindInstanceOverride()
  		{
  			HappyRuntimeContext context = base.CompileModule("function testFunc(instance){ return instance.SomeInstanceMethod(1.0); }");
  			Assert.Throws<ArgumentTypeException>(() => context.Globals.testFunc(new TestClass()));
  		}
  
  		[Test]
  		public void SetStaticProperty()
  		{
  			TestClass.StaticA = 0;
  			HappyRuntimeContext context = base.CompileModule(@"
  load ""Happy.ScriptEngine.Tests"";
  function testFunc() { Happy.ScriptEngine.Tests.IntegrationTests.TestTypes.TestClass.StaticA = 111; }");
  			context.Globals.testFunc();
  			Assert.AreEqual(111, TestClass.StaticA);
  		}
  
  		[Test]
  		public void GetStaticProperty()
  		{
  			TestClass.StaticA = 222;
  			HappyRuntimeContext context = base.CompileModule(@"
  load ""Happy.ScriptEngine.Tests"";
  function testFunc() { return Happy.ScriptEngine.Tests.IntegrationTests.TestTypes.TestClass.StaticA; }");
  			Assert.AreEqual(222, context.Globals.testFunc());
  		}
  
  		[Test]
  		public void GetIntConstant()
  		{
  			TestClass.StaticA = 222;
  			HappyRuntimeContext context = base.CompileModule(@"
  load ""Happy.ScriptEngine.Tests"";
  function testFunc() { return Happy.ScriptEngine.Tests.IntegrationTests.TestTypes.TestClass.SomeIntConstant; }");
  			Assert.AreEqual(TestClass.SomeIntConstant, context.Globals.testFunc());
  		}
  
  		[Test]
  		public void GetStringConstant()
  		{
  			TestClass.StaticA = 222;
  			HappyRuntimeContext context = base.CompileModule(@"
  load ""Happy.ScriptEngine.Tests"";
  function testFunc() { return Happy.ScriptEngine.Tests.IntegrationTests.TestTypes.TestClass.SomeStringConstant; }");
  			Assert.AreEqual(TestClass.SomeStringConstant, context.Globals.testFunc());
  		}
  
  
  		[Test]
  		public void ReadValueTypedStaticProperty()
  		{
  			TestClass.StaticA = 222;
  			HappyRuntimeContext context = base.CompileModule(@"
  load ""Happy.ScriptEngine.Tests"";
  function testFunc() { return Happy.ScriptEngine.Tests.IntegrationTests.TestTypes.TestClass.StaticA; }");
  			Assert.AreEqual(222, context.Globals.testFunc());
  		}
  
  		[Test]
  		public void ReadValueTypedInstanceProperty()
  		{
  			HappyRuntimeContext context = base.CompileModule(@"function testFunc(arg) { return arg.A; }");
  			dynamic t = context.Globals.testFunc(new TestClass { A = 222 });
  			Assert.AreEqual(222, t);
  		}
  
  		[Test]
  		public void WriteValueTypedInstanceProperty()
  		{
  			HappyRuntimeContext context = base.CompileModule(@"function testFunc(arg) { ~arg.A; }");
  			context.Globals.testFunc(new TestClass { A = 222 });
  			Assert.AreEqual("222", context.OutputWriter.ToString());
  		}
  
  		[Test]
  		public void NewObject()
  		{
  			HappyRuntimeContext context = base.CompileFunction(" return new(System.Object); ");
  			object temp = context.Globals.testFunc();
  			Assert.AreEqual(typeof(object), temp.GetType());
  		}
  
  		[Test]
  		public void NewTestClass()
  		{
  
gt: 			HappyRuntimeContext context = base.CompileModule(@"