//
// SqlDecimalTest.cs - NUnit Test Cases for System.Data.SqlTypes.SqlDecimal
//
// Authors:
//   Ville Palo (vi64pa@koti.soon.fi)
//   Martin Willemoes Hansen
//
// (C) 2002 Ville Palo
// (C) 2003 Martin Willemoes Hansen
// 

//
// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
// 
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//

using NUnit.Framework;
using System;
using System.Xml;
using System.Data.SqlTypes;
using System.Threading;
using System.Globalization;
#if NET_2_0
using System.Xml.Serialization;
using System.IO;
#endif 

namespace MonoTests.System.Data.SqlTypes
{
	[TestFixture]
        public class SqlDecimalTest 
	{

		private SqlDecimal Test1;
        	private SqlDecimal Test2;
        	private SqlDecimal Test3;
        	private SqlDecimal Test4;
        	private SqlDecimal Test5;
		[SetUp]
                public void GetReady() 
                {
                	Thread.CurrentThread.CurrentCulture = new CultureInfo ("en-US");
                	Test1 = new SqlDecimal (6464.6464m);
                	Test2 = new SqlDecimal (10000.00m); 
                	Test3 = new SqlDecimal (10000.00m);                 
                	Test4 = new SqlDecimal (-6m); 
			Test5 = new SqlDecimal (Decimal.MaxValue);                
                }

                // Test constructor
		[Test]
                public void Create()
                {
                	// SqlDecimal (decimal)
			SqlDecimal Test = new SqlDecimal (30.3098m);
                	Assert.AreEqual ((decimal)30.3098, Test.Value, "#A01");
                	
                	try {
                                decimal d = Decimal.MaxValue;
                		SqlDecimal test = new SqlDecimal (d + 1);
                		Assert.Fail ("#A02");                		
                	} catch (Exception e) {
                		Assert.AreEqual (typeof (OverflowException), e.GetType (), "#A03");
                	}
                	
                	// SqlDecimal (double)
                	Test = new SqlDecimal (10E+10d);
                	Assert.AreEqual (100000000000.00000m, Test.Value, "#A05");
                	
                	try {
                		SqlDecimal test = new SqlDecimal (10E+200d);
                		Assert.Fail ("#A06");                		
                	} catch (Exception e) {
                		Assert.AreEqual (typeof (OverflowException), e.GetType (), "#A07");
                	}
                	
                	// SqlDecimal (int)
                	Test = new SqlDecimal (-1);
                	Assert.AreEqual (-1m, Test.Value, "#A08");
                
			// SqlDecimal (long)
                	Test = new SqlDecimal ((long)(-99999));
                	Assert.AreEqual (-99999m, Test.Value, "#A09");
                
                	// SqlDecimal (byte, byte, bool. int[]
                 	Test = new SqlDecimal (10, 3, false, new int [4] {200, 1, 0, 0});
                	Assert.AreEqual (-4294967.496m, Test.Value, "#A10");
                	
                	try {                		
                		Test = new SqlDecimal (100, 100, false, 
                		                       new int [4] {Int32.MaxValue, 
                		                       Int32.MaxValue, Int32.MaxValue, 
                		                       Int32.MaxValue});
                		Assert.Fail ("#A11");
                	} catch (SqlTypeException) {
                	}

			// sqlDecimal (byte, byte, bool, int, int, int, int)
			Test = new SqlDecimal (12, 2, true, 100, 100, 0, 0);
                	Assert.AreEqual (4294967297.00m, Test.Value, "#A13");
                	
                	try {                		
                		Test = new SqlDecimal (100, 100, false, 
                		                       Int32.MaxValue, 
                		                       Int32.MaxValue, Int32.MaxValue, 
                		                       Int32.MaxValue);
                		Assert.Fail ("#A14");
                	} catch (SqlTypeException) {
                	}                	
                }

                // Test public fields
		[Test]
                public void PublicFields()
                {
                        Assert.AreEqual ((byte)38, SqlDecimal.MaxPrecision, "#B01");
                        Assert.AreEqual ((byte)38, SqlDecimal.MaxScale, "#B02");
                        
                        // FIXME: on windows: Conversion overflow
			Assert.AreEqual  (1262177448, SqlDecimal.MaxValue.Data [3], "#B03a");


                        Assert.AreEqual (1262177448, SqlDecimal.MinValue.Data [3], "#B04");
                	Assert.IsTrue (SqlDecimal.Null.IsNull, "#B05");
                	Assert.IsTrue (!Test1.IsNull, "#B06");
                }

                // Test properties
		[Test]
                public void Properties()
                {
                	byte[] b = Test1.BinData;
                	Assert.AreEqual ((byte)64, b [0], "#C01");
                	
                	int[] i = Test1.Data;
                	Assert.AreEqual (64646464, i [0], "#C02");
                
                        Assert.IsTrue (SqlDecimal.Null.IsNull, "#C03");
                        Assert.IsTrue (Test1.IsPositive, "#C04");
                        Assert.IsTrue (!Test4.IsPositive, "#C05");
                        Assert.AreEqual ((byte)8, Test1.Precision, "#C06");
                	Assert.AreEqual ((byte)2, Test2.Scale, "#C07");
                	Assert.AreEqual (6464.6464m, Test1.Value, "#C08"); 
                	Assert.AreEqual ((byte)4, Test1.Scale, "#C09");
                        Assert.AreEqual ((byte)7, Test2.Precision, "#C10");
                        Assert.AreEqual ((byte)1, Test4.Precision, "#C11");
                }

                // PUBLIC METHODS
		[Test]
                public void ArithmeticMethods()
                {

			// Abs
			Assert.AreEqual ((SqlDecimal)6m, SqlDecimal.Abs (Test4), "#D01");
                	Assert.AreEqual (new SqlDecimal (6464.6464m).Value, SqlDecimal.Abs (Test1).Value, "#D02");
                	
                	Assert.AreEqual (SqlDecimal.Null, SqlDecimal.Abs (SqlDecimal.Null), "#D03");
                	
                        // Add()
			SqlDecimal test2 = new SqlDecimal (-2000m);
                        Assert.AreEqual (16464.6464m, SqlDecimal.Add (Test1, Test2).Value, "#D04");
			Assert.AreEqual ("158456325028528675187087900670", SqlDecimal.Add (Test5, Test5).ToString (), "#D04.1");
			Assert.AreEqual ((SqlDecimal)9994.00m, SqlDecimal.Add (Test3, Test4), "#D04.2");
			Assert.AreEqual ((SqlDecimal)(-2006m), SqlDecimal.Add (Test4, test2), "#D04.3");
			Assert.AreEqual ((SqlDecimal)8000.00m, SqlDecimal.Add (test2, Test3), "#D04.4");

                        try {
                                SqlDecimal test = SqlDecimal.Add (SqlDecimal.MaxValue, SqlDecimal.MaxValue);
                                Assert.Fail ("#D05");
                        } catch (OverflowException) { }
                        
			Assert.AreEqual ((SqlDecimal)6465m, SqlDecimal.Ceiling(Test1), "#D07");
                	Assert.AreEqual (SqlDecimal.Null, SqlDecimal.Ceiling(SqlDecimal.Null), "#D08");
                	
                        // Divide()
			// Notworking..
			/*
                        Assert.AreEqual ((SqlDecimal)(-1077.441066m), SqlDecimal.Divide (Test1, Test4), "#D09");
                        Assert.AreEqual (1.54687501546m, SqlDecimal.Divide (Test2, Test1).Value, "#D10");

                        try {
                                SqlDecimal test = SqlDecimal.Divide(Test1, new SqlDecimal(0)).Value;
                                Assert.Fail ("#D11");
                        } catch(Exception e) {
                                Assert.AreEqual (typeof (DivideByZeroException), e.GetType (), "#D12");
                        }
			*/

			Assert.AreEqual ((SqlDecimal)6464m, SqlDecimal.Floor (Test1), "#D13");
                	
                        // Multiply()
			SqlDecimal Test;
			SqlDecimal test1 = new SqlDecimal (2m);
                        Assert.AreEqual (64646464.000000m, SqlDecimal.Multiply (Test1, Test2).Value, "#D14");
                        Assert.AreEqual (-38787.8784m, SqlDecimal.Multiply (Test1, Test4).Value, "#D15");
			Test = SqlDecimal.Multiply (Test5, test1);
			Assert.AreEqual ("158456325028528675187087900670", Test.ToString (), "#D15.1");


                        try {
                                SqlDecimal test = SqlDecimal.Multiply (SqlDecimal.MaxValue, Test1);
                                Assert.Fail ("#D16");
                        } catch (Exception e) {
                                Assert.AreEqual (typeof (OverflowException), e.GetType (), "#D17");
                        }
                        
			/*
                        // Power
                        Assert.AreEqual ((SqlDecimal)41791653.0770m, SqlDecimal.Power (Test1, 2), "#D18");
                       
                       	// Round
                      	Assert.AreEqual ((SqlDecimal)6464.65m, SqlDecimal.Round (Test1, 2), "#D19");
			*/
                	
                        // Subtract()
                        Assert.AreEqual (-3535.3536m, SqlDecimal.Subtract (Test1, Test3).Value, "#D20");
			Assert.AreEqual (10006.00m, SqlDecimal.Subtract (Test3, Test4).Value, "#D20.1");
			Assert.AreEqual ("99999999920771837485735662406456049664", 
					SqlDecimal.Subtract(SqlDecimal.MaxValue, Decimal.MaxValue).ToString(),
					"#D20.2");

                        try {
                                SqlDecimal test = SqlDecimal.Subtract(SqlDecimal.MinValue, SqlDecimal.MaxValue);
                                Assert.Fail ("#D21");
                        } catch (Exception e) {
                                Assert.AreEqual (typeof (OverflowException), e.GetType (), "#D22");
                        }                           
                        
                        Assert.AreEqual ((SqlInt32)1, SqlDecimal.Sign (Test1), "#D23");
                        Assert.AreEqual (new SqlInt32(-1), SqlDecimal.Sign (Test4), "#D24");
                }

		[Test]
		public void AdjustScale()
		{
			Assert.AreEqual ("6464.646400", SqlDecimal.AdjustScale (Test1, 2, false).Value.ToString (), "#E01");
			Assert.AreEqual ("6464.65", SqlDecimal.AdjustScale (Test1, -2, true).Value.ToString (), "#E02");
			Assert.AreEqual ("6464.64", SqlDecimal.AdjustScale (Test1, -2, false).Value.ToString (), "#E03");
			Assert.AreEqual ("10000.000000000000", SqlDecimal.AdjustScale (Test2, 10, false).Value.ToString (), "#E01");
			Assert.AreEqual ("79228162514264337593543950335.00", SqlDecimal.AdjustScale (Test5, 2, false).ToString (), "#E04");
			try{
				SqlDecimal test = SqlDecimal.AdjustScale (Test1, -5, false);
				Assert.Fail ("#E05");
			}catch (SqlTruncateException) { }
		}

		[Test]
		public void ConvertToPrecScale()
		{
			Assert.AreEqual (new SqlDecimal(6464.6m).Value, SqlDecimal.ConvertToPrecScale (Test1, 5, 1).Value, "#F01");
			
			try {
				SqlDecimal test =  SqlDecimal.ConvertToPrecScale (Test1, 6, 4);
				Assert.Fail ("#F02");
			} catch (Exception e) {
				Assert.AreEqual (typeof (SqlTruncateException), e.GetType (), "#F03");
			}
			
			Assert.AreEqual ((SqlString)"10000.00", SqlDecimal.ConvertToPrecScale (Test2, 7, 2).ToSqlString (), "#F04");

			SqlDecimal tmp = new SqlDecimal (38, 4, true, 64646464, 0, 0, 0);
			Assert.AreEqual ("6465", SqlDecimal.ConvertToPrecScale (tmp, 4, 0).ToString (), "#F05");
		}
		
		[Test]
                public void CompareTo()
                {
                        SqlString TestString = new SqlString ("This is a test");

                        Assert.IsTrue (Test1.CompareTo (Test3) < 0, "#G01");
                        Assert.IsTrue (Test2.CompareTo (Test1) > 0, "#G02");
                        Assert.IsTrue (Test2.CompareTo (Test3) == 0, "#G03");
                        Assert.IsTrue (Test4.CompareTo (SqlDecimal.Null) > 0, "#G04");

                        try {
                                Test1.CompareTo (TestString);
                                Assert.Fail("#G05");
                        } catch(Exception e) {
                                Assert.AreEqual (typeof (ArgumentException), e.GetType (), "#G06");
                        }
                }

		[Test]
                public void EqualsMethods()
                {
                        Assert.IsTrue (!Test1.Equals (Test2), "#H01");
                        Assert.IsTrue (!Test2.Equals (new SqlString ("TEST")), "#H02");
                        Assert.IsTrue (Test2.Equals (Test3), "#H03");

                        // Static Equals()-method
                        Assert.IsTrue (SqlDecimal.Equals (Test2, Test2).Value, "#H05");
                        Assert.IsTrue (!SqlDecimal.Equals (Test1, Test2).Value, "#H06");
                	
                	// NotEquals
                        Assert.IsTrue (SqlDecimal.NotEquals (Test1, Test2).Value, "#H07");
                        Assert.IsTrue (SqlDecimal.NotEquals (Test4, Test1).Value, "#H08");
                        Assert.IsTrue (!SqlDecimal.NotEquals (Test2, Test3).Value, "#H09");
                        Assert.IsTrue (SqlDecimal.NotEquals (SqlDecimal.Null, Test3).IsNull, "#H10");                 
                }

		/* Don't do such environment-dependent test. It will never succeed under Portable.NET and MS.NET
		[Test]
                public void GetHashCodeTest()
                {
                        // FIXME: Better way to test HashCode
                        Assert.AreEqual (-1281249885, Test1.GetHashCode (), "#I01");
                }
		*/

		[Test]
                public void GetTypeTest()
                {
                        Assert.AreEqual ("System.Data.SqlTypes.SqlDecimal", 
                                      Test1.GetType ().ToString (), "#J01");
                        Assert.AreEqual ("System.Decimal", Test1.Value.GetType ().ToString (), "#J02");
                }

		[Test]
                public void Greaters()
                {
                        // GreateThan ()
                        Assert.IsTrue (!SqlDecimal.GreaterThan (Test1, Test2).Value, "#K01");
                        Assert.IsTrue (SqlDecimal.GreaterThan (Test2, Test1).Value, "#K02");
                        Assert.IsTrue (!SqlDecimal.GreaterThan (Test2, Test3).Value, "#K03");

                        // GreaterTharOrEqual ()
                        Assert.IsTrue (!SqlDecimal.GreaterThanOrEqual (Test1, Test2).Value, "#K04");
                        Assert.IsTrue (SqlDecimal.GreaterThanOrEqual (Test2, Test1).Value, "#K05");
                        Assert.IsTrue (SqlDecimal.GreaterThanOrEqual (Test2, Test3).Value, "#K06");
                }

		[Test]
                public void Lessers()
                {
                        // LessThan()
                        Assert.IsTrue (!SqlDecimal.LessThan (Test3, Test2).Value, "#L01");
                        Assert.IsTrue (!SqlDecimal.LessThan (Test2, Test1).Value, "#L02");
                        Assert.IsTrue (SqlDecimal.LessThan (Test1, Test2).Value, "#L03");

                        // LessThanOrEqual ()
                        Assert.IsTrue (SqlDecimal.LessThanOrEqual (Test1, Test2).Value, "#L04");
                        Assert.IsTrue (!SqlDecimal.LessThanOrEqual (Test2, Test1).Value, "#L05");
                        Assert.IsTrue (SqlDecimal.LessThanOrEqual (Test2, Test3).Value, "#L06");
                        Assert.IsTrue (SqlDecimal.LessThanOrEqual (Test1, SqlDecimal.Null).IsNull, "#L07");
                }

		[Test]
		[Category ("NotWorking")]
                public void Parse()
                {
                        try {
                                SqlDecimal.Parse (null);
                                Assert.Fail ("#m01");
                        } catch (Exception e) {
                                Assert.AreEqual (typeof (ArgumentNullException), e.GetType (), "#M02");
                        }

                        try {
                                SqlDecimal.Parse ("not-a-number");
                                Assert.Fail ("#M03");
                        } catch (Exception e) {
                                Assert.AreEqual (typeof (FormatException), e.GetType (), "#M04");
                        }

                         try {
                                SqlDecimal test = SqlDecimal.Parse ("9e300");
                                Assert.Fail ("#M05");
                        } catch (FormatException) {
                        }

                        Assert.AreEqual(150m, SqlDecimal.Parse ("150").Value, "#M07");

			// decimal.Parse() does not pass this string.
			string max  = "99999999999999999999999999999999999999";
			SqlDecimal dx = SqlDecimal.Parse (max);
			Assert.AreEqual (max, dx.ToString (), "#M08");

			try {
				dx = SqlDecimal.Parse (max + ".0");
				Assert.Fail ("#M09");
			} catch (FormatException) {
			}
                }

		[Test]
                public void Conversions()
                {
                	// ToDouble
                	Assert.AreEqual (6464.6464, Test1.ToDouble (), "N01");
                	
                        // ToSqlBoolean ()
                       	Assert.AreEqual (new SqlBoolean(1), Test1.ToSqlBoolean (), "#N02");
                        
                        SqlDecimal Test = new SqlDecimal (0);
                        Assert.IsTrue (!Test.ToSqlBoolean ().Value, "#N03");
                	
                	Test = new SqlDecimal (0);
                	Assert.IsTrue (!Test.ToSqlBoolean ().Value, "#N04");
                        Assert.IsTrue (SqlDecimal.Null.ToSqlBoolean ().IsNull, "#N05");

                        // ToSqlByte ()
                        Test = new SqlDecimal (250);
                        Assert.AreEqual ((byte)250, Test.ToSqlByte ().Value, "#N06");

                        try {
                                SqlByte b = (byte)Test2.ToSqlByte ();
                                Assert.Fail ("#N07");
                        } catch (Exception e) {
                                Assert.AreEqual (typeof (OverflowException), e.GetType (), "#N08");
                        }

                        // ToSqlDouble ()
                        Assert.AreEqual ((SqlDouble)6464.6464, Test1.ToSqlDouble (), "#N09");

                        // ToSqlInt16 ()
                        Assert.AreEqual ((short)1, new SqlDecimal (1).ToSqlInt16 ().Value, "#N10");

                        try {
                                SqlInt16 test = SqlDecimal.MaxValue.ToSqlInt16().Value;
                                Assert.Fail ("#N11");
                        } catch (Exception e) {
                                Assert.AreEqual (typeof (OverflowException), e.GetType (), "#N12");
                        }        

                        // ToSqlInt32 () 
                        // LAMESPEC: 6464.6464 --> 64646464 ??? with windows
			// MS.NET seems to return the first 32 bit integer (i.e. 
			// Data [0]) but we don't have to follow such stupidity.
//			Assert.AreEqual ((int)64646464, Test1.ToSqlInt32 ().Value, "#N13a");
//			Assert.AreEqual ((int)1212, new SqlDecimal(12.12m).ToSqlInt32 ().Value, "#N13b");
                	
                        try {
                                SqlInt32 test = SqlDecimal.MaxValue.ToSqlInt32 ().Value;
                                Assert.Fail ("#N14");
                        } catch (Exception e) { 
                                Assert.AreEqual (typeof (OverflowException), e.GetType (), "#N15");
                        }

                        // ToSqlInt64 ()
                        Assert.AreEqual ((long)6464, Test1.ToSqlInt64 ().Value, "#N16");

                        // ToSqlMoney ()
                        Assert.AreEqual ((decimal)6464.6464, Test1.ToSqlMoney ().Value, "#N17");

                        try {
                                SqlMoney test = SqlDecimal.MaxValue.ToSqlMoney ().Value;
                                Assert.Fail ("#N18");
                        } catch (Exception e) {
                                Assert.AreEqual (typeof (OverflowException), e.GetType (), "#N19");
                        }        

                        // ToSqlSingle ()
                        Assert.AreEqual ((float)6464.6464, Test1.ToSqlSingle ().Value, "#N20");

                        // ToSqlString ()
                        Assert.AreEqual ("6464.6464", Test1.ToSqlString ().Value, "#N21");

                        // ToString ()
                        Assert.AreEqual ("6464.6464", Test1.ToString (), "#N22");                        
			//Assert.AreEqual ("792281625142643375935439503350000.00", SqlDecimal.Multiply (Test5 , Test2).ToString () , "#N22.1");
			Assert.AreEqual ((SqlDouble)1E+38, SqlDecimal.MaxValue.ToSqlDouble (), "#N23");

                }
                
		[Test]
                public void Truncate()
                {
//                	Assert.AreEqual (new SqlDecimal (6464.6400m).Value, SqlDecimal.Truncate (Test1, 2).Value, "#O01");
                	Assert.AreEqual (6464.6400m, SqlDecimal.Truncate (Test1, 2).Value, "#O01");
                }
                
                // OPERATORS

		[Test]
                public void ArithmeticOperators()
                {
                        // "+"-operator
                        Assert.AreEqual (new SqlDecimal(16464.6464m), Test1 + Test2, "#P01");
			Assert.AreEqual ("79228162514264337593543960335.00", (Test5 + Test3).ToString (), "#P01.1");

			SqlDecimal test2 = new SqlDecimal (-2000m);
			Assert.AreEqual ((SqlDecimal)8000.00m, Test3 + test2, "#P01.2");
			Assert.AreEqual ((SqlDecimal)(-2006m), Test4 + test2, "#P01.3");
			Assert.AreEqual ((SqlDecimal)8000.00m, test2 + Test3, "#P01.4");
     
                        try {
                                SqlDecimal test = SqlDecimal.MaxValue + SqlDecimal.MaxValue;
                                Assert.Fail ("#P02");
                        } catch (OverflowException) {}

			/*
                        // "/"-operator
                        Assert.AreEqual ((SqlDecimal)1.54687501546m, Test2 / Test1, "#P04");

                        try {
                                SqlDecimal test = Test3 / new SqlDecimal (0);
                                Assert.Fail ("#P05");
                        } catch (Exception e) {
                                Assert.AreEqual (typeof (DivideByZeroException), e.GetType (), "#P06");
                        }
			*/

                        // "*"-operator
			Assert.AreEqual ((SqlDecimal)64646464.000000m, Test1 * Test2, "#P07");

			SqlDecimal Test = Test5 * (new SqlDecimal (2m));
			Assert.AreEqual ("158456325028528675187087900670", Test.ToString (), "#P7.1");

                        try {
                                SqlDecimal test = SqlDecimal.MaxValue * Test1;
                                Assert.Fail ("#P08");
                        } catch (Exception e) {
                                Assert.AreEqual (typeof (OverflowException), e.GetType (), "#P09");
                        }

                        // "-"-operator
                        Assert.AreEqual ((SqlDecimal)3535.3536m, Test2 - Test1, "#P10");
			Assert.AreEqual ((SqlDecimal)(-10006.00m), Test4 - Test3, "#P10.1");

                        try {
                                SqlDecimal test = SqlDecimal.MinValue - SqlDecimal.MaxValue;
                                Assert.Fail ("#P11");
                        } catch  (Exception e) {
                                Assert.AreEqual (typeof (OverflowException), e.GetType (), "#P12");
                        }
                        
                        Assert.AreEqual (SqlDecimal.Null, SqlDecimal.Null + Test1, "#P13");
                }

		[Test]
                public void ThanOrEqualOperators()
                {
			SqlDecimal pval = new SqlDecimal (10m);
			SqlDecimal nval = new SqlDecimal (-10m);
			SqlDecimal val = new SqlDecimal (5m);

                        // == -operator
                        Assert.IsTrue ((Test2 == Test3).Value, "#Q01");
                        Assert.IsTrue (!(Test1 == Test2).Value, "#Q02");
                        Assert.IsTrue ((Test1 == SqlDecimal.Null).IsNull, "#Q03");
			Assert.IsFalse ((pval == nval).Value, "#Q03.1");
                        
                        // != -operator
                        Assert.IsTrue (!(Test2 != Test3).Value, "#Q04");
                        Assert.IsTrue ((Test1 != Test3).Value, "#Q05");
                        Assert.IsTrue ((Test4 != Test3).Value, "#Q06");
                        Assert.IsTrue ((Test1 != SqlDecimal.Null).IsNull, "#Q07");
			Assert.IsTrue ((pval != nval).Value, "#Q07.1");

                        // > -operator
                        Assert.IsTrue ((Test2 > Test1).Value, "#Q08");
                        Assert.IsTrue (!(Test1 > Test3).Value, "#Q09");
                        Assert.IsTrue (!(Test2 > Test3).Value, "#Q10");
                        Assert.IsTrue ((Test1 > SqlDecimal.Null).IsNull, "#Q11");
			Assert.IsFalse ((nval > val).Value, "#Q11.1");

                        // >=  -operator
                        Assert.IsTrue (!(Test1 >= Test3).Value, "#Q12");
                        Assert.IsTrue ((Test3 >= Test1).Value, "#Q13");
                        Assert.IsTrue ((Test2 >= Test3).Value, "#Q14");
                        Assert.IsTrue ((Test1 >= SqlDecimal.Null).IsNull, "#Q15");
			Assert.IsFalse ((nval > val).Value, "#Q15.1");

                        // < -operator
                        Assert.IsTrue (!(Test2 < Test1).Value, "#Q16");
                        Assert.IsTrue ((Test1 < Test3).Value, "#Q17");
                        Assert.IsTrue (!(Test2 < Test3).Value, "#Q18");
                        Assert.IsTrue ((Test1 < SqlDecimal.Null).IsNull, "#Q19");
			Assert.IsFalse ((val < nval).Value, "#Q19.1");

                        // <= -operator
                        Assert.IsTrue ((Test1 <= Test3).Value, "#Q20");
                        Assert.IsTrue (!(Test3 <= Test1).Value, "#Q21");
                        Assert.IsTrue ((Test2 <= Test3).Value, "#Q22");
                        Assert.IsTrue ((Test1 <= SqlDecimal.Null).IsNull, "#Q23");
			Assert.IsFalse ((val <= nval).Value, "#Q23.1");
                }

		[Test]
                public void UnaryNegation()
                {
                        Assert.AreEqual (6m, -Test4.Value, "#R01");
                        Assert.AreEqual (-6464.6464m, -Test1.Value, "#R02");
                        Assert.AreEqual (SqlDecimal.Null, SqlDecimal.Null, "#R03");
                }

		[Test]
                public void SqlBooleanToSqlDecimal()
                {
                        SqlBoolean TestBoolean = new SqlBoolean (true);
                        SqlDecimal Result;

                        Result = (SqlDecimal)TestBoolean;

                        Assert.AreEqual (1m, Result.Value, "#S01");

                        Result = (SqlDecimal)SqlBoolean.Null;
                        Assert.IsTrue (Result.IsNull, "#S02");
                	Assert.AreEqual (SqlDecimal.Null, (SqlDecimal)SqlBoolean.Null, "#S03");
                }
		
		[Test]
		public void SqlDecimalToDecimal()
		{
			Assert.AreEqual (6464.6464m, (Decimal)Test1, "#T01");
		}

		[Test]
                public void SqlDoubleToSqlDecimal()
                {
                        SqlDouble Test = new SqlDouble (12E+10);
                        Assert.AreEqual (120000000000.00000m, ((SqlDecimal)Test).Value, "#U01");
                }
                
		[Test]
                public void SqlSingleToSqlDecimal()
                {
                	SqlSingle Test = new SqlSingle (1E+9);
                	Assert.AreEqual (1000000000.0000000m, ((SqlDecimal)Test).Value, "#V01");
                	
                	try {
                		SqlDecimal test = (SqlDecimal)SqlSingle.MaxValue;
                		Assert.Fail ("#V02");
                	} catch (Exception e) {
                		Assert.AreEqual (typeof (OverflowException), e.GetType (), "#V03");
                	}
                }

		[Test]
                public void SqlStringToSqlDecimal()
                {
                        SqlString TestString = new SqlString ("Test string");
                        SqlString TestString100 = new SqlString ("100");

                        Assert.AreEqual (100m, ((SqlDecimal)TestString100).Value, "#W01");

                        try {
                                SqlDecimal test = (SqlDecimal)TestString;
                                Assert.Fail ("#W02");
                        } catch(Exception e) {
                                Assert.AreEqual (typeof (FormatException), e.GetType (), "#W03");
                        }
                        
                        try {
                        	SqlDecimal test = (SqlDecimal)new SqlString("9E+100");
                        	Assert.Fail ("#W04");
                        } catch (Exception e) {
                        	Assert.AreEqual (typeof (FormatException), e.GetType(), "#W05");
                        }
                }

		[Test]
		public void DecimalToSqlDecimal()
		{
			decimal d = 1000.1m;
			Assert.AreEqual ((SqlDecimal)1000.1m, (SqlDecimal)d, "#X01");		
		}
		
		[Test]
                public void ByteToSqlDecimal()
                {                      
                        Assert.AreEqual (255m, ((SqlDecimal)SqlByte.MaxValue).Value, "#Y01");
                }
                
		[Test]
                public void SqlIntToSqlDouble()
                {
                        SqlInt16 Test64 = new SqlInt16 (64);
                        SqlInt32 Test640 = new SqlInt32 (640);
                        SqlInt64 Test64000 = new SqlInt64 (64000);
                        Assert.AreEqual (64m, ((SqlDecimal)Test64).Value, "#Z01");
                        Assert.AreEqual (640m,((SqlDecimal)Test640).Value, "#Z02");
                        Assert.AreEqual (64000m, ((SqlDecimal)Test64000).Value, "#Z03");
                }

		[Test]
                public void SqlMoneyToSqlDecimal()
                {
                        SqlMoney TestMoney64 = new SqlMoney(64);
                        Assert.AreEqual (64.0000M, ((SqlDecimal)TestMoney64).Value, "#AA01");
                }

		[Test]
		public void ToStringTest ()
		{
			Assert.AreEqual ("Null", SqlDecimal.Null.ToString (), "#01");
			Assert.AreEqual ("-99999999999999999999999999999999999999", SqlDecimal.MinValue.ToString (), "#02");
			Assert.AreEqual ("99999999999999999999999999999999999999", SqlDecimal.MaxValue.ToString (), "#03");
		}

		[Test]
		public void Value ()
		{
			decimal d = decimal.Parse ("9999999999999999999999999999");
		}
#if NET_2_0
		[Test]
		public void GetXsdTypeTest ()
		{
			XmlQualifiedName qualifiedName = SqlDecimal.GetXsdType (null);
			NUnit.Framework.Assert.AreEqual ("decimal", qualifiedName.Name, "#A01");
		}

		internal void ReadWriteXmlTestInternal (string xml, 
						       decimal testval, 
						       string unit_test_id)
		{
			SqlDecimal test;
			SqlDecimal test1;
			XmlSerializer ser;
			StringWriter sw;
			XmlTextWriter xw;
			StringReader sr;
			XmlTextReader xr;

			test = new SqlDecimal (testval);
			Console.WriteLine ("SqlDecimalTest.ReadWriteXml: Value = {0}, Data={1}", test.Value, test.Data);
			ser = new XmlSerializer(typeof(SqlDecimal));
			sw = new StringWriter ();
			xw = new XmlTextWriter (sw);
			
			ser.Serialize (xw, test);

			// Assert.AreEqual (xml, sw.ToString (), unit_test_id);
			Console.WriteLine ("{0} - Got: {1}", unit_test_id, sw.ToString ());

			sr = new StringReader (xml);
			xr = new XmlTextReader (sr);
			test1 = (SqlDecimal)ser.Deserialize (xr);

			Assert.AreEqual (testval, test1.Value, unit_test_id);
			Console.WriteLine ("{0} - Got: {1}", unit_test_id, test1.Value);
		}

		[Test]
		public void ReadWriteXmlTest ()
		{
			string xml1 = "<?xml version=\"1.0\" encoding=\"utf-16\"?><decimal>4556.89756</decimal>";
			string xml2 = "<?xml version=\"1.0\" encoding=\"utf-16\"?><decimal>-6445.9999</decimal>";
			string xml3 = "<?xml version=\"1.0\" encoding=\"utf-16\"?><decimal>0x455687AB3E4D56F</decimal>";
			decimal test1 = new Decimal (4556.89756);
			// This one fails because of a possible conversion bug
			//decimal test2 = new Decimal (-6445.999999999999999999999);
			decimal test2 = new Decimal (-6445.9999);
			decimal test3 = new Decimal (0x455687AB3E4D56F);

			ReadWriteXmlTestInternal (xml1, test1, "BA01");
			ReadWriteXmlTestInternal (xml2, test2, "BA02");
		
			try {
				ReadWriteXmlTestInternal (xml3, test3, "BA03");
					Assert.Fail ("BA03");
                        } catch(Exception e) {
                                Assert.AreEqual (typeof (FormatException), e.GetType (), "#BA03");
			}
		}
#endif
        }
}

