#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 csUnitStubMakerTests 
	{
		static readonly Assembly providerAssembly = Assembly.GetExecutingAssembly();
		const string EXPECTED_MESSAGE = "MESSAGE";
		const string NOT_NULL = "NOT-NULL";
		ITestFramework tf;

		static string MethodName {
			get { return csUnit.Assert.MethodName; }
		}
		static object[] Arguments 
		{
			get { return csUnit.Assert.Arguments; }
		}
		[Test] public void CheckAssert() 
		{
			tf.Assert(true);
			Assert.AreEqual("True", MethodName);
			Assert.AreEqual(1, Arguments.Length);
			Assert.AreEqual(true, Arguments[0]);
			tf.Assert(false);
			Assert.AreEqual("True", MethodName);
			Assert.AreEqual(1, Arguments.Length);
			Assert.AreEqual(false, Arguments[0]);
		}
		[Test] public void CheckAssertWithMessage() 
		{
			tf.Assert(EXPECTED_MESSAGE, true);
			Assert.AreEqual("True", MethodName);
			Assert.AreEqual(2, Arguments.Length);
			Assert.AreEqual(true, Arguments[0]);
			Assert.AreEqual(EXPECTED_MESSAGE, Arguments[1]);
			tf.Assert(EXPECTED_MESSAGE, false);
			Assert.AreEqual("True", MethodName);
			Assert.AreEqual(2, Arguments.Length);
			Assert.AreEqual(false, Arguments[0]);
			Assert.AreEqual(EXPECTED_MESSAGE, Arguments[1]);
		}
		[Test] public void CheckAssertNotNull() 
		{
			tf.AssertNotNull(NOT_NULL);
			Assert.AreEqual("NotNull", MethodName);
			Assert.AreEqual(1, Arguments.Length);
			Assert.AreSame(NOT_NULL, Arguments[0]);
			tf.AssertNotNull(null);
			Assert.AreEqual("NotNull", MethodName);
			Assert.AreEqual(1, Arguments.Length);
			Assert.IsNull(Arguments[0]);
		}
		[Test] public void CheckAssertNotNullWithMessage() 
		{
			tf.AssertNotNull(EXPECTED_MESSAGE, NOT_NULL);
			Assert.AreEqual("NotNull", MethodName);
			Assert.AreEqual(2, Arguments.Length);
			Assert.AreSame(NOT_NULL, Arguments[0]);
			Assert.AreEqual(EXPECTED_MESSAGE, Arguments[1]);
			tf.AssertNotNull(EXPECTED_MESSAGE, null);
			Assert.AreEqual("NotNull", MethodName);
			Assert.AreEqual(2, Arguments.Length);
			Assert.IsNull(Arguments[0]);
			Assert.AreEqual(EXPECTED_MESSAGE, Arguments[1]);
		}
		[Test] public void CheckAssertNull() 
		{
			tf.AssertNull(NOT_NULL);
			Assert.AreEqual("Null", MethodName);
			Assert.AreEqual(1, Arguments.Length);
			Assert.AreSame(NOT_NULL, Arguments[0]);
			tf.AssertNull(null);
			Assert.AreEqual("Null", MethodName);
			Assert.AreEqual(1, Arguments.Length);
			Assert.IsNull(Arguments[0]);
		}
		[Test] public void CheckAssertNullWithMessage() 
		{
			tf.AssertNull(EXPECTED_MESSAGE, NOT_NULL);
			Assert.AreEqual("Null", MethodName);
			Assert.AreEqual(2, Arguments.Length);
			Assert.AreSame(NOT_NULL, Arguments[0]);
			Assert.AreEqual(EXPECTED_MESSAGE, Arguments[1]);
			tf.AssertNull(EXPECTED_MESSAGE, null);
			Assert.AreEqual("Null", MethodName);
			Assert.AreEqual(2, 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(1, Arguments.Length);
			Assert.AreEqual(EXPECTED_MESSAGE, Arguments[0]);
		}
		[Test] public void CheckAssertEquals() 
		{
			tf.AssertEquals(1, 1);
			Assert.AreEqual("Equals", 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("Equals", MethodName);
			Assert.AreEqual(3, Arguments.Length);
			Assert.AreEqual(1, Arguments[0]);
			Assert.AreEqual(1, Arguments[1]);
			Assert.AreEqual(EXPECTED_MESSAGE, Arguments[2]);
		}
		[SetUp] public void BeforeEachTest() 
		{
			// reset mock csUnit implementation
			csUnit.Assert.Reset();

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

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

namespace csUnit
{
	/// <summary>
	/// Mock implementation of csUnit.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 True(bool expression) 
		{
			_methodName = "True";
			_args = new object[] { expression };
		}
		public static void True(bool expression, string message) 
		{
			_methodName = "True";
			_args = new object[] { expression, message };
		}
		public static void NotNull(object obj) 
		{
			_methodName = "NotNull";
			_args = new object[] { obj };
		}
		public static void NotNull(object obj, string message) 
		{
			_methodName = "NotNull";
			_args = new object[] { obj, message };
		}
		public static new void Equals(object expected, object actual) 
		{
			_methodName = "Equals";
			_args = new object[] { expected, actual };
		}
		public static void Equals(
			object expected, object actual,
			string message
			) 
		{
			_methodName = "Equals";
			_args = new object[] { expected, actual, message };
		}
		public static void Fail() 
		{
			_methodName = "Fail";
			_args = new object[0];
		}
		public static void Fail(string message) 
		{
			_methodName = "Fail";
			_args = new object[] { message };
		}
		public static void Null(object obj) 
		{
			_methodName = "Null";
			_args = new object[] { obj };
		}
		public static void Null(object obj, string message) 
		{
			_methodName = "Null";
			_args = new object[] { obj, message };
		}
	}
}