#region License
// Copyright (c) 2004 Griffin Caprio, Roman V. Gavrilov & Choy Rim. All rights reserved.
#endregion
#region Imports
using System;
using System.Reflection;

using NUnit.Framework;

using DotNetMock.Dynamic;
#endregion

namespace DotNetMock.Tests.Dynamic
{
	/// <summary>
	/// Unit tests for <see cref="MethodCall"/>.
	/// </summary>
	[TestFixture]
	public class MethodCallTests 
	{
		interface IMethods 
		{
			void Method3(int x, string y, double z);
			void Method4();
			void Method4(int a);

			int Property0 { get; set; }

			void Method5(ToStringThrows x);
		}
		interface IMethodsA 
		{
			void Method3(int x, string y, double z);
		}
		class ToStringThrows
		{
			public override string ToString()
			{
				throw new Exception();
			}

		}

		static readonly MethodInfo method3 = typeof(IMethods).GetMethod("Method3");
		static readonly MethodInfo method4 = typeof(IMethods).GetMethod("Method4", new Type[0]);
		static readonly MethodInfo methodA3 = typeof(IMethodsA).GetMethod("Method3");
		static readonly MethodInfo method4a =
			typeof(IMethods).GetMethod(
			"Method4",
			new Type[] { typeof(int) }
			);
		static readonly MethodInfo property0_get = typeof(IMethods).GetMethod("get_Property0");
		static readonly MethodInfo property0_set = typeof(IMethods).GetMethod("set_Property0");
		static readonly MethodInfo method5 = typeof(IMethods).GetMethod("Method5");

		[Test] public void MethodNameStripsPrefixOnProperties() 
		{
			MethodCall gc = new MethodCall(property0_get);
			Assert.AreEqual("Property0", gc.MethodName);
			MethodCall sc = new MethodCall(property0_set, 1);
			Assert.AreEqual("Property0", sc.MethodName);
		}

		[Test] public void MethodCallToString() 
		{
			MethodCall mc = new MethodCall(method3, 1, "two", 3.4);
			Assert.AreEqual("Method3(x=1, y=\"two\", z=3.4)", mc.ToString());
			mc = new MethodCall(method4);
			Assert.AreEqual("Method4()", mc.ToString());
			mc = new MethodCall(method5, new ToStringThrows());
			Assert.AreEqual("Method5(x=N/A)", mc.ToString());
		}
		[Test] public void MethodCallEqualsMethodCall() 
		{
			MethodCall mc1 = new MethodCall(method3, 1, "two", 3.4);
			MethodCall mc2 = new MethodCall(method3, 1, "two", 3.4);
			MethodCall mc3 = new MethodCall(method3, 1, "2", 3.4);
			MethodCall mc4 = new MethodCall(method4);
			MethodCall mc5 = new MethodCall(methodA3, 1, "two", 3.4);
			MethodCall mc6 = new MethodCall(method4a, 1);

			Assert.AreEqual(mc1, mc2);
			Assert.IsFalse(mc1.Equals(mc3));
			Assert.IsFalse(mc1.Equals(mc4));
			Assert.IsFalse(mc1.Equals(mc5));
			Assert.IsFalse(mc1.Equals(null), "MethodCall not equal to null");
			Assert.IsFalse(mc1.Equals("text"), "MethodCall not equal to string");
			Assert.IsFalse(mc4.Equals(mc6), "overloaded methods don't match");
		}
		[ExpectedException(
			 typeof(InvalidOperationException),
			 "Method Method4 takes 0 arguments but received 1."
			 )]
		[Test] public void TooManyArguments() 
		{
			MethodCall mc = new MethodCall(method4, 1);
		}
		[ExpectedException(
			 typeof(InvalidOperationException),
			 "Method Method3 takes 3 arguments but received 1."
			 )]
		[Test] public void TooFewArguments() 
		{
			MethodCall mc = new MethodCall(method3, 1);
		}
	}
}
