#region License
// Copyright (c) 2004 Choy Rim. All rights reserved.
#endregion
#region Imports
using System;
using System.Reflection;
using System.Reflection.Emit;
using DotNetMock.Core;
using NUnit.Framework;

using DotNetMock.TestFramework;
#endregion

namespace DotNetMock.TestFramework.Tests
{
	[TestFixture]
	public class MbUnitStubMakerTests 
	{
		static readonly Assembly providerAssembly = Assembly.GetExecutingAssembly();
		const string EXPECTED_MESSAGE = "MESSAGE";
		const string NOT_NULL = "NOT-NULL";
		ITestFramework tf;

		static string MethodName {
			get { return MbUnit.Core.Framework.Assert.MethodName; }
		}
		static object[] Arguments 
		{
			get { return MbUnit.Core.Framework.Assert.Arguments; }
		}
		[Test] public void CheckAssert() 
		{
			tf.Assert(true);
			Assert.AreEqual("IsTrue", MethodName);
			Assert.AreEqual(1, Arguments.Length);
			Assert.AreEqual(true, Arguments[0]);
			tf.Assert(false);
			Assert.AreEqual("IsTrue", MethodName);
			Assert.AreEqual(1, Arguments.Length);
			Assert.AreEqual(false, Arguments[0]);
		}
		[Test] public void CheckAssertWithMessage() 
		{
			tf.Assert(EXPECTED_MESSAGE, true);
			Assert.AreEqual("IsTrue", MethodName);
			Assert.AreEqual(3, Arguments.Length);
			Assert.AreEqual(true, Arguments[0]);
			Assert.AreEqual(EXPECTED_MESSAGE, Arguments[1]);
			tf.Assert(EXPECTED_MESSAGE, false);
			Assert.AreEqual("IsTrue", MethodName);
			Assert.AreEqual(3, Arguments.Length);
			Assert.AreEqual(false, Arguments[0]);
			Assert.AreEqual(EXPECTED_MESSAGE, Arguments[1]);
		}
		[Test] public void CheckAssertNotNull() 
		{
			tf.AssertNotNull(NOT_NULL);
			Assert.AreEqual("IsNotNull", MethodName);
			Assert.AreEqual(1, Arguments.Length);
			Assert.AreSame(NOT_NULL, Arguments[0]);
			tf.AssertNotNull(null);
			Assert.AreEqual("IsNotNull", MethodName);
			Assert.AreEqual(1, Arguments.Length);
			Assert.IsNull(Arguments[0]);
		}
		[Test] public void CheckAssertNotNullWithMessage() 
		{
			tf.AssertNotNull(EXPECTED_MESSAGE, NOT_NULL);
			Assert.AreEqual("IsNotNull", MethodName);
			Assert.AreEqual(3, Arguments.Length);
			Assert.AreSame(NOT_NULL, Arguments[0]);
			Assert.AreEqual(EXPECTED_MESSAGE, Arguments[1]);
			tf.AssertNotNull(EXPECTED_MESSAGE, null);
			Assert.AreEqual("IsNotNull", MethodName);
			Assert.AreEqual(3, Arguments.Length);
			Assert.IsNull(Arguments[0]);
			Assert.AreEqual(EXPECTED_MESSAGE, Arguments[1]);
		}
		[Test] public void CheckAssertNull() 
		{
			tf.AssertNull(NOT_NULL);
			Assert.AreEqual("IsNull", MethodName);
			Assert.AreEqual(1, Arguments.Length);
			Assert.AreSame(NOT_NULL, Arguments[0]);
			tf.AssertNull(null);
			Assert.AreEqual("IsNull", MethodName);
			Assert.AreEqual(1, Arguments.Length);
			Assert.IsNull(Arguments[0]);
		}
		[Test] public void CheckAssertNullWithMessage() 
		{
			tf.AssertNull(EXPECTED_MESSAGE, NOT_NULL);
			Assert.AreEqual("IsNull", MethodName);
			Assert.AreEqual(3, Arguments.Length);
			Assert.AreSame(NOT_NULL, Arguments[0]);
			Assert.AreEqual(EXPECTED_MESSAGE, Arguments[1]);
			tf.AssertNull(EXPECTED_MESSAGE, null);
			Assert.AreEqual("IsNull", MethodName);
			Assert.AreEqual(3, Arguments.Length);
			Assert.IsNull(Arguments[0]);
			Assert.AreEqual(EXPECTED_MESSAGE, Arguments[1]);
		}
		[Test] public void CheckFail() 
		{
			tf.Fail();
			Assert.AreEqual("Fail", MethodName);
			Assert.AreEqual(0, Arguments.Length);
		}
		[Test] public void CheckFailWithMessage() 
		{
			tf.Fail(EXPECTED_MESSAGE);
			Assert.AreEqual("Fail", MethodName);
			Assert.AreEqual(2, Arguments.Length);
			Assert.AreEqual(EXPECTED_MESSAGE, Arguments[0]);
		}
		[Test] public void CheckAssertEquals() 
		{
			tf.AssertEquals(1, 1);
			Assert.AreEqual("AreEqual", MethodName);
			Assert.AreEqual(2, Arguments.Length);
			Assert.AreEqual(1, Arguments[0]);
			Assert.AreEqual(1, Arguments[1]);
		}
		[Test] public void CheckAssertEqualsWithMessage() 
		{
			tf.AssertEquals(EXPECTED_MESSAGE, 1, 1);
			Assert.AreEqual("AreEqual", MethodName);
			Assert.AreEqual(4, Arguments.Length);
			Assert.AreEqual(1, Arguments[0]);
			Assert.AreEqual(1, Arguments[1]);
			Assert.AreEqual(EXPECTED_MESSAGE, Arguments[2]);
			Assert.IsNotNull(Arguments[3]);
			object[] args = Arguments[3] as object[];
			Assert.IsNotNull(args);
			Assert.AreEqual(0, args.Length);
		}
		[SetUp] public void BeforeEachTest() 
		{
			// reset mock MbUnit implementation
			MbUnit.Core.Framework.Assert.Reset();

			// make provider stub instance
			tf = MakeProviderStubInstance();
		}

		ITestFramework MakeProviderStubInstance() 
		{
			MbUnitStubMaker stubMaker = new MbUnitStubMaker(
				providerAssembly, 
				new SystemDynamicLinker()
				);
			StubClassMaker scm = new StubClassMaker();
			Type stubClass =
				scm.MakeStubClass(typeof(ITestFramework), stubMaker);
			ITestFramework stub = (ITestFramework)
				Activator.CreateInstance(stubClass);
			return stub;
		}
	}
}

namespace MbUnit.Core.Framework 
{
	/// <summary>
	/// Mock implementation of MbUnit.Core.Framework.Assert for testing.
	/// </summary>
	public class Assert 
	{
		static string _methodName;
		static object[] _args = null;

		public static string MethodName { get { return _methodName; } }

		public static object[] Arguments { get { return _args; } }

		public static void Reset() 
		{
			_methodName = null;
			_args = null;
		}

		public static void IsTrue(bool assertion) 
		{
			_methodName = "IsTrue";
			_args = new object[] { assertion };
		}
		public static void IsTrue(bool assertion, string format, params object[] args) 
		{
			_methodName = "IsTrue";
			_args = new object[] { assertion, format, args };
		}
		public static void IsNotNull(object nullable) 
		{
			_methodName = "IsNotNull";
			_args = new object[] { nullable };
		}
		public static void IsNotNull(object nullable, string format, params object[] args) 
		{
			_methodName = "IsNotNull";
			_args = new object[] { nullable, format, args };
		}
		public static void AreEqual(object expected, object actual) 
		{
			_methodName = "AreEqual";
			_args = new object[] { expected, actual };
		}
		public static void AreEqual(
			object expected, object actual,
			string format, params object[] args
			) 
		{
			_methodName = "AreEqual";
			_args = new object[] { expected, actual, format, args };
		}
		public static void Fail() 
		{
			_methodName = "Fail";
			_args = new object[0];
		}
		public static void Fail(string format, params object[] args) 
		{
			_methodName = "Fail";
			_args = new object[] { format, args };
		}
		public static void IsNull(object nullable) 
		{
			_methodName = "IsNull";
			_args = new object[] { nullable };
		}
		public static void IsNull(object nullable, string format, params object[] args) 
		{
			_methodName = "IsNull";
			_args = new object[] { nullable, format, args };
		}
	}
}