From edac084b3d2d37cfc7c8ebee49e912be55a47be3 Mon Sep 17 00:00:00 2001 From: mterwoord_cp <7cd3fd84a0151ea055c2f79e4d2eef9576fe9afesxUZAwxD> Date: Wed, 27 Feb 2008 18:17:59 +0000 Subject: [PATCH] Fixed exceptions --- source/Indy.IL2CPU.Assembler/Assembler.cs | 1 - source/Indy.IL2CPU.IL.X86/Box.cs | 10 +- source/Indy.IL2CPU.IL.X86/Call.cs | 26 +- source/Indy.IL2CPU.IL.X86/Callvirt.cs | 6 +- source/Indy.IL2CPU.IL.X86/Castclass.cs | 6 +- source/Indy.IL2CPU.IL.X86/Ceq.cs | 2 +- source/Indy.IL2CPU.IL.X86/Cgt.cs | 2 +- source/Indy.IL2CPU.IL.X86/Clt.cs | 2 +- source/Indy.IL2CPU.IL.X86/Clt_Un.cs | 2 +- source/Indy.IL2CPU.IL.X86/Isinst.cs | 8 +- source/Indy.IL2CPU.IL.X86/Newobj.cs | 12 +- source/Indy.IL2CPU.IL.X86/Op.cs | 8 +- source/Indy.IL2CPU.IL.X86/Starg.cs | 1 + source/Indy.IL2CPU.IL.X86/Throw.cs | 8 +- source/Indy.IL2CPU.IL.X86/Unbox.cs | 19 +- .../X86CustomMethodImplementationOp.cs | 2 +- .../X86CustomMethodImplementationProxyOp.cs | 2 +- source/Indy.IL2CPU.IL/ILReader.cs | 22 +- source/Indy.IL2CPU.IL/Op.cs | 2 +- source/Indy.IL2CPU/Engine.cs | 18 +- source/TestKernel/Assertion.cs | 36 + source/TestKernel/Attributes.cs | 23 +- source/TestKernel/Program.cs | 82 +- source/TestKernel/TestKernel.csproj | 2 + source/TestKernel/Tests/NoInit/StringTests.cs | 22 +- .../NoInit/mscorlib/System/ArrayListTest.cs | 1963 +++++++++++++++++ 26 files changed, 2175 insertions(+), 112 deletions(-) create mode 100644 source/TestKernel/Assertion.cs create mode 100644 source/TestKernel/Tests/NoInit/mscorlib/System/ArrayListTest.cs diff --git a/source/Indy.IL2CPU.Assembler/Assembler.cs b/source/Indy.IL2CPU.Assembler/Assembler.cs index e44188b89..6a06dba7d 100644 --- a/source/Indy.IL2CPU.Assembler/Assembler.cs +++ b/source/Indy.IL2CPU.Assembler/Assembler.cs @@ -54,7 +54,6 @@ namespace Indy.IL2CPU.Assembler { } public static void ExceptionOccurred() { - Console.WriteLine("Exception Occurred!"); System.Diagnostics.Debugger.Break(); } diff --git a/source/Indy.IL2CPU.IL.X86/Box.cs b/source/Indy.IL2CPU.IL.X86/Box.cs index ed3307f6e..55f1c2f46 100644 --- a/source/Indy.IL2CPU.IL.X86/Box.cs +++ b/source/Indy.IL2CPU.IL.X86/Box.cs @@ -22,20 +22,20 @@ namespace Indy.IL2CPU.IL.X86 { //} else { mTheSize = Engine.GetFieldStorageSize(xTypeRef); //} - if (((mTheSize / 4) * 4) != mTheSize) { - throw new Exception("Incorrect Datasize. ( ((mTheSize / 4) * 4) === mTheSize should evaluate to true!"); - } + //if (((mTheSize / 4) * 4) != mTheSize) { + // throw new Exception("Incorrect Datasize. ( ((mTheSize / 4) * 4) === mTheSize should evaluate to true!"); + //} //if (!(xTypeRef is GenericParameter)) { mTypeId = Engine.RegisterType(xTypeRef); //} } public override void DoAssemble() { - new CPUx86.Pushd("0x" + (4 + ObjectImpl.FieldDataOffset).ToString("X").ToUpper()); + new CPUx86.Pushd("0x" + (ObjectImpl.FieldDataOffset + mTheSize + (4 - (mTheSize % 4))).ToString("X").ToUpper()); new CPUx86.Call(CPU.Label.GenerateLabelName(RuntimeEngineRefs.Heap_AllocNewObjectRef)); new CPUx86.Move("dword", CPUx86.Registers.AtEAX, "0x" + mTypeId.ToString("X")); new CPUx86.Move("dword", "[eax + 4]", "0x" + InstanceTypeEnum.BoxedValueType.ToString("X")); - for (int i = 0; i < (mTheSize / 4); i++) { + for (int i = 0; i < ((mTheSize + (4 - (mTheSize % 4))) / 4); i++) { new CPUx86.Pop(CPUx86.Registers.EDX); new CPUx86.Move("dword", "[eax + 0x" + (ObjectImpl.FieldDataOffset + (i * 4)).ToString("X") + "]", "edx"); } diff --git a/source/Indy.IL2CPU.IL.X86/Call.cs b/source/Indy.IL2CPU.IL.X86/Call.cs index b48ba8b05..b50b1cea3 100644 --- a/source/Indy.IL2CPU.IL.X86/Call.cs +++ b/source/Indy.IL2CPU.IL.X86/Call.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.IO; using System.Linq; - using CPU = Indy.IL2CPU.Assembler; using CPUx86 = Indy.IL2CPU.Assembler.X86; using System.Reflection; @@ -20,17 +19,21 @@ namespace Indy.IL2CPU.IL.X86 { private MethodInformation mMethodInfo; private MethodInformation mTargetMethodInfo; private string mNextLabelName; - public Call(MethodBase aMethod) + private int mCurrentILOffset; + public Call(MethodBase aMethod, int aCurrentILOffset) : base(null, null) { if (aMethod == null) { throw new ArgumentNullException("aMethod"); } - Initialize(aMethod); + Initialize(aMethod, aCurrentILOffset); } - public static void EmitExceptionLogic(Assembler.Assembler aAssembler, MethodInformation aMethodInfo, string aNextLabel, bool aDoTest) { + public static void EmitExceptionLogic(Assembler.Assembler aAssembler, int aCurrentOpOffset, MethodInformation aMethodInfo, string aNextLabel, bool aDoTest) { string xJumpTo = MethodFooterOp.EndOfMethodLabelNameException; if (aMethodInfo != null && aMethodInfo.CurrentHandler != null) { + if (aMethodInfo.CurrentHandler.HandlerOffset >= aCurrentOpOffset && (aMethodInfo.CurrentHandler.HandlerLength + aMethodInfo.CurrentHandler.HandlerOffset) <= aCurrentOpOffset) { + return; + } switch (aMethodInfo.CurrentHandler.Flags) { case ExceptionHandlingClauseOptions.Clause: { xJumpTo = Op.GetInstructionLabel(aMethodInfo.CurrentHandler.HandlerOffset); @@ -52,20 +55,15 @@ namespace Indy.IL2CPU.IL.X86 { new CPUx86.Test("ecx", "2"); new CPUx86.JumpIfNotEquals(xJumpTo); } - // } - // new CPUx86.JumpAlways(xJumpTo); - //} } - - private void Initialize(MethodBase aMethod) { + private void Initialize(MethodBase aMethod, int aCurrentILOffset) { mIsDebugger_Break = aMethod.GetFullName() == "System.Void System.Diagnostics.Debugger.Break()"; if (mIsDebugger_Break) { return; } + mCurrentILOffset = aCurrentILOffset; mTargetMethodInfo = Engine.GetMethodInfo(aMethod, aMethod, Label.GenerateLabelName(aMethod), Engine.GetTypeInfo(aMethod.DeclaringType)); - - mResultSize = 0; if (mTargetMethodInfo != null) { mResultSize = mTargetMethodInfo.ReturnSize; @@ -102,13 +100,13 @@ namespace Indy.IL2CPU.IL.X86 { MethodBase xMethod = aReader.OperandValueMethod; mMethodInfo = aMethodInfo; if (!aReader.EndOfStream) { - mNextLabelName = GetInstructionLabel(aReader.Position); + mNextLabelName = GetInstructionLabel(aReader.NextPosition); } - Initialize(xMethod); + Initialize(xMethod, (int)aReader.Position); } public void Assemble(string aMethod, int aArgumentCount) { new CPUx86.Call(aMethod); - EmitExceptionLogic(Assembler, mMethodInfo, mNextLabelName, true); + EmitExceptionLogic(Assembler, mCurrentILOffset, mMethodInfo, mNextLabelName, true); for (int i = 0; i < aArgumentCount; i++) { Assembler.StackContents.Pop(); } diff --git a/source/Indy.IL2CPU.IL.X86/Callvirt.cs b/source/Indy.IL2CPU.IL.X86/Callvirt.cs index 3c9bb9c9e..fab31b2be 100644 --- a/source/Indy.IL2CPU.IL.X86/Callvirt.cs +++ b/source/Indy.IL2CPU.IL.X86/Callvirt.cs @@ -19,6 +19,7 @@ namespace Indy.IL2CPU.IL.X86 { private readonly string mLabelName; private readonly MethodInformation mCurrentMethodInfo; private readonly MethodInformation mTargetMethodInfo; + private readonly int mCurrentILOffset; public Callvirt(ILReader aReader, MethodInformation aMethodInfo) : base(aReader, aMethodInfo) { mLabelName = GetInstructionLabel(aReader); @@ -43,6 +44,7 @@ namespace Indy.IL2CPU.IL.X86 { mArgumentCount = mTargetMethodInfo.Arguments.Length; mReturnSize = mTargetMethodInfo.ReturnSize; mThisOffset = mTargetMethodInfo.Arguments[0].Offset; + mCurrentILOffset = aReader.Position; } public override void DoAssemble() { @@ -59,13 +61,13 @@ namespace Indy.IL2CPU.IL.X86 { } //Assembler.Add(new CPUx86.Pop("eax")); //Assembler.Add(new CPUx86.Pushd("eax")); - EmitCompareWithNull(Assembler, mCurrentMethodInfo, "[esp + 0x" + mThisOffset.ToString("X") + "]", mLabelName, mLabelName + "_AfterNullRefCheck", xEmitCleanup); + EmitCompareWithNull(Assembler, mCurrentMethodInfo, "[esp + 0x" + mThisOffset.ToString("X") + "]", mLabelName, mLabelName + "_AfterNullRefCheck", xEmitCleanup, mCurrentILOffset); new CPU.Label(mLabelName + "_AfterNullRefCheck"); new CPUx86.Move(CPUx86.Registers.EAX, "[esp + 0x" + mThisOffset.ToString("X") + "]"); new CPUx86.Pushd(CPUx86.Registers.AtEAX); new CPUx86.Pushd("0" + mMethodIdentifier.ToString("X") + "h"); new CPUx86.Call(CPU.Label.GenerateLabelName(VTablesImplRefs.GetMethodAddressForTypeRef)); - Call.EmitExceptionLogic(Assembler, mCurrentMethodInfo, mLabelName + "_AfterAddressCheck", true); + Call.EmitExceptionLogic(Assembler, mCurrentILOffset, mCurrentMethodInfo, mLabelName + "_AfterAddressCheck", true); new CPU.Label(mLabelName + "_AfterAddressCheck"); if (mTargetMethodInfo.Arguments[0].ArgumentType == typeof(object)) { new CPUx86.Push("eax"); diff --git a/source/Indy.IL2CPU.IL.X86/Castclass.cs b/source/Indy.IL2CPU.IL.X86/Castclass.cs index f6b5097de..a736800e9 100644 --- a/source/Indy.IL2CPU.IL.X86/Castclass.cs +++ b/source/Indy.IL2CPU.IL.X86/Castclass.cs @@ -14,6 +14,7 @@ namespace Indy.IL2CPU.IL.X86 { private string mThisLabel; private string mNextOpLabel; private Type mCastAsType; + private int mCurrentILOffset; public Castclass(ILReader aReader, MethodInformation aMethodInfo) : base(aReader, aMethodInfo) { Type xType = aReader.OperandValueType; @@ -23,7 +24,8 @@ namespace Indy.IL2CPU.IL.X86 { mCastAsType = xType; mTypeId = Engine.RegisterType(mCastAsType); mThisLabel = GetInstructionLabel(aReader); - mNextOpLabel = GetInstructionLabel(aReader.Position); + mNextOpLabel = GetInstructionLabel(aReader.NextPosition); + mCurrentILOffset = (int)aReader.Position; } public override void DoAssemble() { @@ -39,7 +41,7 @@ namespace Indy.IL2CPU.IL.X86 { Assembler.StackContents.Push(new StackContent(4, true, false, false)); MethodBase xMethodIsInstance = Engine.GetMethodBase(Engine.GetType("", "Indy.IL2CPU.VTablesImpl"), "IsInstance", "System.Int32", "System.Int32"); Engine.QueueMethod(xMethodIsInstance); - Op xOp = new Call(xMethodIsInstance); + Op xOp = new Call(xMethodIsInstance, mCurrentILOffset); xOp.Assembler = Assembler; xOp.Assemble(); new CPUx86.Pop(CPUx86.Registers.EAX); diff --git a/source/Indy.IL2CPU.IL.X86/Ceq.cs b/source/Indy.IL2CPU.IL.X86/Ceq.cs index b8c3f82f7..afbdecfd8 100644 --- a/source/Indy.IL2CPU.IL.X86/Ceq.cs +++ b/source/Indy.IL2CPU.IL.X86/Ceq.cs @@ -12,7 +12,7 @@ namespace Indy.IL2CPU.IL.X86 { private readonly string CurInstructionLabel; public Ceq(ILReader aReader, MethodInformation aMethodInfo) : base(aReader, aMethodInfo) { - NextInstructionLabel = GetInstructionLabel(aReader.Position); + NextInstructionLabel = GetInstructionLabel(aReader.NextPosition); CurInstructionLabel = GetInstructionLabel(aReader); } private void Assemble4Byte() { diff --git a/source/Indy.IL2CPU.IL.X86/Cgt.cs b/source/Indy.IL2CPU.IL.X86/Cgt.cs index d70b6182c..a920cc673 100644 --- a/source/Indy.IL2CPU.IL.X86/Cgt.cs +++ b/source/Indy.IL2CPU.IL.X86/Cgt.cs @@ -13,7 +13,7 @@ namespace Indy.IL2CPU.IL.X86 { private readonly string CurInstructionLabel; public Cgt(ILReader aReader, MethodInformation aMethodInfo) : base(aReader, aMethodInfo) { - NextInstructionLabel = GetInstructionLabel(aReader.Position); + NextInstructionLabel = GetInstructionLabel(aReader.NextPosition); CurInstructionLabel = GetInstructionLabel(aReader); } public override void DoAssemble() { diff --git a/source/Indy.IL2CPU.IL.X86/Clt.cs b/source/Indy.IL2CPU.IL.X86/Clt.cs index bf913efde..8508f017c 100644 --- a/source/Indy.IL2CPU.IL.X86/Clt.cs +++ b/source/Indy.IL2CPU.IL.X86/Clt.cs @@ -13,7 +13,7 @@ namespace Indy.IL2CPU.IL.X86 { private readonly string CurInstructionLabel; public Clt(ILReader aReader, MethodInformation aMethodInfo) : base(aReader, aMethodInfo) { - NextInstructionLabel = GetInstructionLabel(aReader.Position); + NextInstructionLabel = GetInstructionLabel(aReader.NextPosition); CurInstructionLabel = GetInstructionLabel(aReader); } public override void DoAssemble() { diff --git a/source/Indy.IL2CPU.IL.X86/Clt_Un.cs b/source/Indy.IL2CPU.IL.X86/Clt_Un.cs index 7eff44e2b..56361dd69 100644 --- a/source/Indy.IL2CPU.IL.X86/Clt_Un.cs +++ b/source/Indy.IL2CPU.IL.X86/Clt_Un.cs @@ -13,7 +13,7 @@ namespace Indy.IL2CPU.IL.X86 { private readonly string CurInstructionLabel; public Clt_Un(ILReader aReader, MethodInformation aMethodInfo) : base(aReader, aMethodInfo) { - NextInstructionLabel = GetInstructionLabel(aReader.Position); + NextInstructionLabel = GetInstructionLabel(aReader.NextPosition); CurInstructionLabel = GetInstructionLabel(aReader); } public override void DoAssemble() { diff --git a/source/Indy.IL2CPU.IL.X86/Isinst.cs b/source/Indy.IL2CPU.IL.X86/Isinst.cs index 1547d85a7..e8e556196 100644 --- a/source/Indy.IL2CPU.IL.X86/Isinst.cs +++ b/source/Indy.IL2CPU.IL.X86/Isinst.cs @@ -13,6 +13,7 @@ namespace Indy.IL2CPU.IL.X86 { private int mTypeId; private string mThisLabel; private string mNextOpLabel; + private int mCurrentILOffset; public Isinst(ILReader aReader, MethodInformation aMethodInfo) : base(aReader, aMethodInfo) { Type xType = aReader.OperandValueType; @@ -21,8 +22,9 @@ namespace Indy.IL2CPU.IL.X86 { } Type xTypeDef = xType; mTypeId = Engine.RegisterType(xTypeDef); - mThisLabel = GetInstructionLabel(aReader.OldPosition); - mNextOpLabel = GetInstructionLabel(aReader.Position); + mThisLabel = GetInstructionLabel(aReader.Position); + mNextOpLabel = GetInstructionLabel(aReader.NextPosition); + mCurrentILOffset = (int)aReader.Position; } public override void DoAssemble() { @@ -35,7 +37,7 @@ namespace Indy.IL2CPU.IL.X86 { Assembler.StackContents.Push(new StackContent(4, typeof(object))); MethodBase xMethodIsInstance = Engine.GetMethodBase(typeof(VTablesImpl), "IsInstance", "System.Int32", "System.Int32"); Engine.QueueMethod(xMethodIsInstance); - Op xOp = new Call(xMethodIsInstance); + Op xOp = new Call(xMethodIsInstance, mCurrentILOffset); xOp.Assembler = Assembler; xOp.Assemble(); new CPUx86.Pop(CPUx86.Registers.EAX); diff --git a/source/Indy.IL2CPU.IL.X86/Newobj.cs b/source/Indy.IL2CPU.IL.X86/Newobj.cs index 68d0c5ee9..96ddfe39b 100644 --- a/source/Indy.IL2CPU.IL.X86/Newobj.cs +++ b/source/Indy.IL2CPU.IL.X86/Newobj.cs @@ -15,22 +15,20 @@ namespace Indy.IL2CPU.IL.X86 { public MethodBase CtorDef; public string CurrentLabel; public MethodInformation MethodInformation; - public Newobj() - : base(null, null) { - } - + public int ILOffset; public Newobj(ILReader aReader, MethodInformation aMethodInfo) : base(aReader, aMethodInfo) { CtorDef = aReader.OperandValueMethod; CurrentLabel = GetInstructionLabel(aReader); MethodInformation = aMethodInfo; + ILOffset = (int)aReader.Position; } public override void DoAssemble() { - Assemble(Assembler, ObjectUtilities.GetObjectStorageSize(CtorDef.DeclaringType), CtorDef, Engine.RegisterType(CtorDef.DeclaringType), CurrentLabel, MethodInformation); + Assemble(Assembler, ObjectUtilities.GetObjectStorageSize(CtorDef.DeclaringType), CtorDef, Engine.RegisterType(CtorDef.DeclaringType), CurrentLabel, MethodInformation, ILOffset); } - public static void Assemble(Assembler.Assembler aAssembler, int aObjectSize, MethodBase aCtorDef, int aTypeId, string aCurrentLabel, MethodInformation aCurrentMethodInformation) { + public static void Assemble(Assembler.Assembler aAssembler, int aObjectSize, MethodBase aCtorDef, int aTypeId, string aCurrentLabel, MethodInformation aCurrentMethodInformation, int aCurrentILOffset) { if (aCtorDef != null) { Engine.QueueMethod(aCtorDef); } else { @@ -103,7 +101,7 @@ namespace Indy.IL2CPU.IL.X86 { foreach (var xStackInt in aAssembler.StackContents) { new CPUx86.Add("esp", xStackInt.Size.ToString()); } - Call.EmitExceptionLogic(aAssembler, aCurrentMethodInformation, aCurrentLabel + "_NO_ERROR_4", false); + Call.EmitExceptionLogic(aAssembler, aCurrentILOffset, aCurrentMethodInformation, aCurrentLabel + "_NO_ERROR_4", false); new CPU.Label(aCurrentLabel + "_NO_ERROR_4"); new CPUx86.Pop(CPUx86.Registers.EAX); // aAssembler.StackSizes.Pop(); diff --git a/source/Indy.IL2CPU.IL.X86/Op.cs b/source/Indy.IL2CPU.IL.X86/Op.cs index c83a79a5e..450dcb5ee 100644 --- a/source/Indy.IL2CPU.IL.X86/Op.cs +++ b/source/Indy.IL2CPU.IL.X86/Op.cs @@ -19,18 +19,18 @@ namespace Indy.IL2CPU.IL.X86 { /// /// /// - public static void EmitCompareWithNull(Assembler.Assembler aAssembler, MethodInformation aMethodInfo, string aAddress, string aCurrentLabel, string aNextLabel, Action aEmitCleanupMethod) { + public static void EmitCompareWithNull(Assembler.Assembler aAssembler, MethodInformation aMethodInfo, string aAddress, string aCurrentLabel, string aNextLabel, Action aEmitCleanupMethod, int aCurrentILOffset) { new CPUx86.Compare("dword " + aAddress, "0"); new CPUx86.JumpIfNotEquals(aNextLabel); Type xNullRefExcType = typeof(NullReferenceException); - Newobj.Assemble(aAssembler, Engine.GetTypeInfo(xNullRefExcType).StorageSize, xNullRefExcType.GetConstructor(new Type[0]), Engine.RegisterType(xNullRefExcType), aCurrentLabel, aMethodInfo); + Newobj.Assemble(aAssembler, Engine.GetTypeInfo(xNullRefExcType).StorageSize, xNullRefExcType.GetConstructor(new Type[0]), Engine.RegisterType(xNullRefExcType), aCurrentLabel, aMethodInfo, aCurrentILOffset); aAssembler.StackContents.Pop(); new CPUx86.Move("[" + DataMember.GetStaticFieldName(CPU.Assembler.CurrentExceptionRef) + "]", "eax"); Engine.QueueMethod(CPU.Assembler.CurrentExceptionOccurredRef); new CPUx86.Call(Label.GenerateLabelName(CPU.Assembler.CurrentExceptionOccurredRef)); new CPUx86.Move("ecx", "3"); aEmitCleanupMethod(); - Call.EmitExceptionLogic(aAssembler, aMethodInfo, aNextLabel, false); + Call.EmitExceptionLogic(aAssembler, aCurrentILOffset, aMethodInfo, aNextLabel, false); } public Op(ILReader aReader, MethodInformation aMethodInfo) @@ -65,7 +65,7 @@ namespace Indy.IL2CPU.IL.X86 { mCatchType = null; } if (mCatchType != null && aMethodInfo != null && aMethodInfo.CurrentHandler != null && aMethodInfo.CurrentHandler.HandlerOffset > 0) { - mNeedsTypeCheck = aMethodInfo.CurrentHandler.HandlerOffset == aReader.Position; + mNeedsTypeCheck = aMethodInfo.CurrentHandler.HandlerOffset == aReader.NextPosition; } } diff --git a/source/Indy.IL2CPU.IL.X86/Starg.cs b/source/Indy.IL2CPU.IL.X86/Starg.cs index ecee9080b..da8adbc56 100644 --- a/source/Indy.IL2CPU.IL.X86/Starg.cs +++ b/source/Indy.IL2CPU.IL.X86/Starg.cs @@ -9,6 +9,7 @@ namespace Indy.IL2CPU.IL.X86 { private string[] mAddresses; protected void SetArgIndex(int aIndex, MethodInformation aMethodInfo) { mAddresses = aMethodInfo.Arguments[aIndex].VirtualAddresses; + } public Starg(ILReader aReader, MethodInformation aMethodInfo) : base(aReader, aMethodInfo) { diff --git a/source/Indy.IL2CPU.IL.X86/Throw.cs b/source/Indy.IL2CPU.IL.X86/Throw.cs index 70f4c8ff5..7de89d676 100644 --- a/source/Indy.IL2CPU.IL.X86/Throw.cs +++ b/source/Indy.IL2CPU.IL.X86/Throw.cs @@ -10,23 +10,25 @@ namespace Indy.IL2CPU.IL.X86 { [OpCode(OpCodeEnum.Throw, false)] public class Throw: Op { private MethodInformation mMethodInfo; + private int mCurrentILOffset; public Throw(ILReader aReader, MethodInformation aMethodInfo) : base(aReader, aMethodInfo) { mMethodInfo = aMethodInfo; + mCurrentILOffset = (int)aReader.Position; } - public static void Assemble(Assembler.Assembler aAssembler, MethodInformation aMethodInfo) { + public static void Assemble(Assembler.Assembler aAssembler, MethodInformation aMethodInfo, int aCurrentILOffset) { new CPUx86.Pop("eax"); new CPUx86.Move("[" + CPU.DataMember.GetStaticFieldName(CPU.Assembler.CurrentExceptionRef) + "]", "eax"); Engine.QueueMethod(CPU.Assembler.CurrentExceptionOccurredRef); new CPUx86.Call(CPU.Label.GenerateLabelName(CPU.Assembler.CurrentExceptionOccurredRef)); new CPUx86.Move("ecx", "3"); - Call.EmitExceptionLogic(aAssembler, aMethodInfo, null, false); + Call.EmitExceptionLogic(aAssembler,aCurrentILOffset, aMethodInfo, null, false); aAssembler.StackContents.Pop(); } public override void DoAssemble() { - Assemble(Assembler, mMethodInfo); + Assemble(Assembler, mMethodInfo, mCurrentILOffset); } } } \ No newline at end of file diff --git a/source/Indy.IL2CPU.IL.X86/Unbox.cs b/source/Indy.IL2CPU.IL.X86/Unbox.cs index deac9470e..a70df19c2 100644 --- a/source/Indy.IL2CPU.IL.X86/Unbox.cs +++ b/source/Indy.IL2CPU.IL.X86/Unbox.cs @@ -15,6 +15,7 @@ namespace Indy.IL2CPU.IL.X86 { private string mNextOpLabel; private Type mType; private int mTypeSize; + private int mCurrentILOffset; public Unbox(ILReader aReader, MethodInformation aMethodInfo) : base(aReader, aMethodInfo) { mType = aReader.OperandValueType; @@ -24,11 +25,12 @@ namespace Indy.IL2CPU.IL.X86 { mTypeSize = Engine.GetFieldStorageSize(mType); mTypeId = Engine.RegisterType(mType); mThisLabel = GetInstructionLabel(aReader); - mNextOpLabel = GetInstructionLabel(aReader.Position); + mNextOpLabel = GetInstructionLabel(aReader.NextPosition); + mCurrentILOffset = aReader.Position; } public override void DoAssemble() { string mReturnNullLabel = mThisLabel + "_ReturnNull"; - new CPUx86.Pop(CPUx86.Registers.EAX); + new CPUx86.Move(CPUx86.Registers.EAX, CPUx86.Registers.AtESP); new CPUx86.Compare(CPUx86.Registers.EAX, "0"); new CPUx86.JumpIfZero(mReturnNullLabel); new CPUx86.Pushd(CPUx86.Registers.AtEAX); @@ -37,17 +39,26 @@ namespace Indy.IL2CPU.IL.X86 { Assembler.StackContents.Push(new StackContent(4, typeof(uint))); MethodBase xMethodIsInstance = Engine.GetMethodBase(Engine.GetType("", "Indy.IL2CPU.VTablesImpl"), "IsInstance", "System.Int32", "System.Int32"); Engine.QueueMethod(xMethodIsInstance); - Op xOp = new Call(xMethodIsInstance); + Op xOp = new Call(xMethodIsInstance, mCurrentILOffset); xOp.Assembler = Assembler; xOp.Assemble(); new CPUx86.Pop(CPUx86.Registers.EAX); Assembler.StackContents.Pop(); new CPUx86.Compare(CPUx86.Registers.EAX, "0"); new CPUx86.JumpIfEquals(mReturnNullLabel); - new CPUx86.Pushd(CPUx86.Registers.EAX); + new CPUx86.Pop(CPUx86.Registers.EAX); + int xSize = mTypeSize; + if (xSize % 4 > 0) { + xSize += 4 - (xSize % 4); + } + int xItems = xSize /4; + for (int i = xItems - 1; i >= 0; i--) { + new CPUx86.Push("[eax + " + ((i * 4) + ObjectImpl.FieldDataOffset) + "]"); + } Assembler.StackContents.Push(new StackContent(mTypeSize, mType)); new CPUx86.JumpAlways(mNextOpLabel); new CPU.Label(mReturnNullLabel); + new CPUx86.Add(CPUx86.Registers.ESP, "4"); new CPUx86.Pushd("0"); Assembler.StackContents.Push(new StackContent(4, typeof(object))); } diff --git a/source/Indy.IL2CPU.IL.X86/X86CustomMethodImplementationOp.cs b/source/Indy.IL2CPU.IL.X86/X86CustomMethodImplementationOp.cs index c60d8f3ec..ee5ac4933 100644 --- a/source/Indy.IL2CPU.IL.X86/X86CustomMethodImplementationOp.cs +++ b/source/Indy.IL2CPU.IL.X86/X86CustomMethodImplementationOp.cs @@ -21,7 +21,7 @@ namespace Indy.IL2CPU.IL.X86 { Ldarg.Ldarg(Assembler, MethodInfo.Arguments[i]); } Engine.QueueMethod(aMethod); - Op xOp = new Call(aMethod); + Op xOp = new Call(aMethod,0); xOp.Assembler = Assembler; xOp.Assemble(); } diff --git a/source/Indy.IL2CPU.IL.X86/X86CustomMethodImplementationProxyOp.cs b/source/Indy.IL2CPU.IL.X86/X86CustomMethodImplementationProxyOp.cs index c6df03dc6..a6507fd7d 100644 --- a/source/Indy.IL2CPU.IL.X86/X86CustomMethodImplementationProxyOp.cs +++ b/source/Indy.IL2CPU.IL.X86/X86CustomMethodImplementationProxyOp.cs @@ -20,7 +20,7 @@ namespace Indy.IL2CPU.IL.X86 { } protected override void CallProxiedMethod() { - Op x = new Call(ProxiedMethod); + Op x = new Call(ProxiedMethod, 0); x.Assembler = Assembler; x.Assemble(); } diff --git a/source/Indy.IL2CPU.IL/ILReader.cs b/source/Indy.IL2CPU.IL/ILReader.cs index 8f692709f..da0ffd6cd 100644 --- a/source/Indy.IL2CPU.IL/ILReader.cs +++ b/source/Indy.IL2CPU.IL/ILReader.cs @@ -21,14 +21,14 @@ namespace Indy.IL2CPU.IL { private byte[] mOperand; private bool mHasOperand; - public long OldPosition { + public int Position { get; private set; } - public long Position { + public int NextPosition { get { - return mStream.Position; + return (int)mStream.Position; } } @@ -91,17 +91,17 @@ namespace Indy.IL2CPU.IL { if (mOperandValueBranchPosition == null) { //sbyte xTemp = (sbyte)mOperand; //if (xTemp == mOperand) { - // mOperandValueBranchPosition = Position + xTemp; + // mOperandValueBranchPosition = NextPosition + xTemp; //} else { - // if (mStream.Length < (Position + mOperand + 1)) { + // if (mStream.Length < (NextPosition + mOperand + 1)) { // mOperandValueBranchPosition = (uint)mOperand; // } else { - // mOperandValueBranchPosition = (uint)(Position + mOperand); + // mOperandValueBranchPosition = (uint)(NextPosition + mOperand); // } if (!mIsShortcut) { - mOperandValueBranchPosition = (uint?)(Position + OperandValueInt32); + mOperandValueBranchPosition = (uint?)(NextPosition + OperandValueInt32); } else { - mOperandValueBranchPosition = (uint?)(Position + (sbyte)OperandValueInt32); + mOperandValueBranchPosition = (uint?)(NextPosition + (sbyte)OperandValueInt32); } //} } @@ -183,7 +183,7 @@ namespace Indy.IL2CPU.IL { } public bool Read() { - OldPosition = Position; + Position = NextPosition; int xByteValueInt = mStream.ReadByte(); OpCodeEnum xOpCode; if (xByteValueInt == -1) { @@ -231,10 +231,10 @@ namespace Indy.IL2CPU.IL { } uint[] xResult = new uint[xBranchLocations1.Length]; for (int i = 0; i < xBranchLocations1.Length; i++) { - if ((Position + xBranchLocations1[i]) < 0) { + if ((NextPosition + xBranchLocations1[i]) < 0) { xResult[i] = (uint)xBranchLocations1[i]; } else { - xResult[i] = (uint)(Position + xBranchLocations1[i]); + xResult[i] = (uint)(NextPosition + xBranchLocations1[i]); } } OperandValueBranchLocations = xResult; diff --git a/source/Indy.IL2CPU.IL/Op.cs b/source/Indy.IL2CPU.IL/Op.cs index 6afdd8861..37de6c1bc 100644 --- a/source/Indy.IL2CPU.IL/Op.cs +++ b/source/Indy.IL2CPU.IL/Op.cs @@ -12,7 +12,7 @@ namespace Indy.IL2CPU.IL { private readonly string mILComment; private readonly bool mSupportsMetalMode; public static string GetInstructionLabel(ILReader aReader) { - return GetInstructionLabel(aReader.OldPosition); + return GetInstructionLabel(aReader.Position); } public static string GetInstructionLabel(long aPosition) { return ".L" + aPosition.ToString("X8"); diff --git a/source/Indy.IL2CPU/Engine.cs b/source/Indy.IL2CPU/Engine.cs index 6e504da84..538b96914 100644 --- a/source/Indy.IL2CPU/Engine.cs +++ b/source/Indy.IL2CPU/Engine.cs @@ -411,7 +411,7 @@ namespace Indy.IL2CPU { // GenericParameter xGenericParam = xArray.ElementType as GenericParameter; // GenericParameter xFoundGenericParam = xFoundArray.ElementType as GenericParameter; // if (xGenericParam != null && xFoundGenericParam != null) { - // if (xGenericParam.Position != xFoundGenericParam.Position) { + // if (xGenericParam.NextPosition != xFoundGenericParam.NextPosition) { // continue; // } // } @@ -551,8 +551,8 @@ namespace Indy.IL2CPU { public static int GetFieldStorageSize(Type aType) { if (aType.FullName == "System.Void") { return 0; - } - if (!aType.IsValueType && aType.IsClass) { + } + if ((!aType.IsValueType && aType.IsClass) || aType.IsInterface) { return 4; } switch (aType.FullName) { @@ -766,12 +766,6 @@ namespace Indy.IL2CPU { MethodBody xBody = xCurrentMethod.GetMethodBody(); // todo: add better detection of implementation state if (xBody != null) { - // todo: add support for types which need different stack size - //foreach (LocalVariableInfo xLocal in xBody.LocalVariables) { - // if (xLocal.LocalType.IsValueType && !xLocal.LocalType.IsPrimitive && !xLocal.LocalType.IsEnum && !xLocal.LocalType.IsPointer) { - // throw new Exception("Structs as locals not yet supported!"); - // } - //} mInstructionsToSkip = 0; mAssembler.StackContents.Clear(); ILReader xReader = new ILReader(xCurrentMethod); @@ -783,7 +777,7 @@ namespace Indy.IL2CPU { ExceptionHandlingClause xCurrentHandler = null; foreach (ExceptionHandlingClause xHandler in xBody.ExceptionHandlingClauses) { if (xHandler.TryOffset > 0) { - if (xHandler.TryOffset <= xReader.Position && (xHandler.TryLength + xHandler.TryOffset) > xReader.Position) { + if (xHandler.TryOffset <= xReader.NextPosition && (xHandler.TryLength + xHandler.TryOffset) > xReader.NextPosition) { if (xCurrentHandler == null) { xCurrentHandler = xHandler; continue; @@ -796,7 +790,7 @@ namespace Indy.IL2CPU { } } if (xHandler.HandlerOffset > 0) { - if (xHandler.HandlerOffset <= xReader.Position && (xHandler.HandlerOffset + xHandler.HandlerLength) > xReader.Position) { + if (xHandler.HandlerOffset <= xReader.NextPosition && (xHandler.HandlerOffset + xHandler.HandlerLength) > xReader.NextPosition) { if (xCurrentHandler == null) { xCurrentHandler = xHandler; continue; @@ -810,7 +804,7 @@ namespace Indy.IL2CPU { } if ((xHandler.Flags & ExceptionHandlingClauseOptions.Filter) > 0) { if (xHandler.FilterOffset > 0) { - if (xHandler.FilterOffset <= xReader.Position) { + if (xHandler.FilterOffset <= xReader.NextPosition) { if (xCurrentHandler == null) { xCurrentHandler = xHandler; continue; diff --git a/source/TestKernel/Assertion.cs b/source/TestKernel/Assertion.cs new file mode 100644 index 000000000..4636a445b --- /dev/null +++ b/source/TestKernel/Assertion.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace NUnit.Framework { + public class Assertion { + public class AssertException:Exception { + public AssertException(string aMessage):base(aMessage) { + } + } + public static void AssertNotNull(string aMessage, object aObject) { + if (aObject == null) { + throw new AssertException(aMessage); + } + } + public static void Assert(string aMessage, bool aAssert) { + if (!aAssert) { + throw new AssertException(aMessage); + } + } + + public static void Fail(string aMessage) { + throw new AssertException(aMessage); + } + public static void AssertEquals(string aMessage, int a, int b) { + if (a != b) { + Fail(aMessage); + } + } + public static void AssertEquals(string aMessage, object a, object b) { + if (!Object.Equals(a, b)) { + Fail(aMessage); + } + } + } +} \ No newline at end of file diff --git a/source/TestKernel/Attributes.cs b/source/TestKernel/Attributes.cs index ef3217e3e..68298ab71 100644 --- a/source/TestKernel/Attributes.cs +++ b/source/TestKernel/Attributes.cs @@ -1,11 +1,20 @@ using System; using System.Collections.Generic; using System.Linq; +using TestKernel; -namespace TestKernel { +namespace System { + [AttributeUsage(AttributeTargets.Class)] + public sealed class TestFixtureAttribute:Attribute { + public string BaseName { + get; + set; + } + } [AttributeUsage(AttributeTargets.Method)] public sealed class TestAttribute: Attribute { public TestAttribute() { + TestGroup = TestGroups.NoInit; } public string TestGroup { @@ -13,7 +22,7 @@ namespace TestKernel { set; } - public string Description { + public string Name{ get; set; } @@ -23,4 +32,14 @@ namespace TestKernel { set; } } + [AttributeUsage(AttributeTargets.Method)] + public sealed class ExpectedExceptionAttribute: Attribute { + public ExpectedExceptionAttribute(Type aException) { + Exception = aException; + } + public Type Exception { + get; + set; + } + } } diff --git a/source/TestKernel/Program.cs b/source/TestKernel/Program.cs index 23f7bdbfd..9d27d23bb 100644 --- a/source/TestKernel/Program.cs +++ b/source/TestKernel/Program.cs @@ -6,36 +6,75 @@ using Cosmos.Build.Windows; namespace TestKernel { class Program { + private class TestInfo { + public Type ExpectedException; + public string Name; + public string TestGroup; + public bool IsExperimental; + } [STAThread] public static void Main(string[] aArgs) { if (aArgs.Length == 0) { var xBuilder = new Builder(); xBuilder.Build(); } else { - List> xTests = new List>(); + List> xTests = new List>(); #region detect all current tests foreach (var xType in typeof(Program).Assembly.GetTypes()) { + string xBaseName = ""; + var xFixture = xType.GetCustomAttributes(typeof(TestFixtureAttribute), true).FirstOrDefault() as TestFixtureAttribute; + if (xFixture != null) { + xBaseName = xFixture.BaseName; + } + if (String.IsNullOrEmpty(xBaseName)) { + xBaseName = xType.FullName; + } foreach (var xMethod in xType.GetMethods()) { var xAttrib = xMethod.GetCustomAttributes(typeof(TestAttribute), true).FirstOrDefault() as TestAttribute; if (xAttrib != null) { - xTests.Add(new KeyValuePair(xType.FullName.Replace('+', '.') + "." + xMethod.Name, xAttrib)); + string xName = xAttrib.Name; + if (String.IsNullOrEmpty(xName)) { + xName = xBaseName + "." + xMethod.Name; + } + Type xExpectedException = null; + var xExpException = xMethod.GetCustomAttributes(typeof(ExpectedExceptionAttribute), true).FirstOrDefault() as ExpectedExceptionAttribute; + if (xExpException != null) { + xExpectedException = xExpException.Exception; + } + xTests.Add(new KeyValuePair(xType.FullName.Replace('+', '.') + "." + xMethod.Name, new TestInfo() { + ExpectedException = xExpectedException, + Name = xName, + IsExperimental = xAttrib.IsExperimental, + TestGroup = xAttrib.TestGroup + })); } } } #endregion Console.WriteLine("public static void Init() {"); Console.WriteLine("string xTestResult=null;"); + Console.WriteLine("bool xError;"); foreach (var xTest in (from item in xTests - where item.Value.TestGroup == aArgs[0] && ((!item.Value.IsExperimental) || ((aArgs.Length > 1) && (aArgs[1] == "-experimental"))) - select item)) { - Console.WriteLine("Console.WriteLine(\"Running test '{0}'\");", xTest.Value.Description); - Console.WriteLine("xTestResult = {0}();", xTest.Key); + where item.Value.TestGroup == aArgs[0] && ((!item.Value.IsExperimental) || ((aArgs.Length > 1) && (aArgs[1] == "-experimental"))) + select item)) { + Console.WriteLine("Console.WriteLine(\"Running test '{0}'\");", xTest.Value.Name); + Console.WriteLine("try{"); + Console.WriteLine("xError = false;"); + Console.WriteLine("{0}();", xTest.Key); + if (xTest.Value.ExpectedException != null) { + Console.WriteLine("}}catch({0}){{", xTest.Value.ExpectedException.FullName.Replace("+", ".")); + } + if (xTest.Value.ExpectedException != typeof(Exception)) { + Console.WriteLine("}catch(Exception E){"); + Console.WriteLine("Console.Write(\" \");"); + Console.WriteLine("Console.WriteLine(E.Message);"); + Console.WriteLine("xError = true;"); + } + Console.WriteLine("}"); + Console.WriteLine("if(!xError){"); Console.WriteLine("Console.Write(\" \");"); - Console.WriteLine("if (xTestResult == null) {"); Console.WriteLine("Console.WriteLine(\"Success\");"); - Console.WriteLine("} else {"); - Console.WriteLine("Console.Write(\"Error: \");"); - Console.WriteLine("Console.WriteLine(xTestResult);}"); + Console.WriteLine("}"); } Console.WriteLine("Console.WriteLine(\"All tests executed!\");"); @@ -47,14 +86,23 @@ namespace TestKernel { public static void Init() { string xTestResult = null; - Console.WriteLine("Running test 'System.String_EmbeddedStringContents'"); - xTestResult = TestKernel.Tests.NoInit.StringTests.TestEmbedded(); - Console.Write(" "); - if (xTestResult == null) { + bool xError; + Console.WriteLine("Running test 'Whoohoo'"); + try { + xError = false; + TestKernel.Tests.NoInit.StringTests.OurTest(); + } catch (Exception E) { + Console.Write(" "); + if (E == null) { + Console.WriteLine("<>"); + } else { + Console.WriteLine(E.Message); + } + xError = true; + } + if (!xError) { + Console.Write(" "); Console.WriteLine("Success"); - } else { - Console.Write("Error: "); - Console.WriteLine(xTestResult); } Console.WriteLine("All tests executed!"); while (true) diff --git a/source/TestKernel/TestKernel.csproj b/source/TestKernel/TestKernel.csproj index ee1cc81d5..bf7cf270a 100644 --- a/source/TestKernel/TestKernel.csproj +++ b/source/TestKernel/TestKernel.csproj @@ -49,10 +49,12 @@ + + diff --git a/source/TestKernel/Tests/NoInit/StringTests.cs b/source/TestKernel/Tests/NoInit/StringTests.cs index 28b645393..afa335486 100644 --- a/source/TestKernel/Tests/NoInit/StringTests.cs +++ b/source/TestKernel/Tests/NoInit/StringTests.cs @@ -4,24 +4,10 @@ using System.Linq; namespace TestKernel.Tests.NoInit { public static class StringTests { - [Test(TestGroup=TestGroups.NoInit, Description="System.String_EmbeddedStringContents", IsExperimental=false)] - public static string TestEmbedded() { - string MyString = "Hello"; - if (MyString == null) - return "MyString is null"; - if (MyString.Length != 5) - return "MyString Length is not 5"; - if (MyString[0] != 'H') - return "MyString[0] != 'H'"; - if (MyString[1] != 'e') - return "MyString[1] != 'e'"; - if (MyString[2] != 'l') - return "MyString[2] != 'l'"; - if (MyString[3] != 'l') - return "MyString[3] != 'l'"; - if (MyString[4] != 'o') - return "MyString[4] != 'o'"; - return null; + [Test(Name="Whoohoo", TestGroup="Test")] + public static void OurTest() { + // succeeds + throw new Exception("Error"); } } } \ No newline at end of file diff --git a/source/TestKernel/Tests/NoInit/mscorlib/System/ArrayListTest.cs b/source/TestKernel/Tests/NoInit/mscorlib/System/ArrayListTest.cs new file mode 100644 index 000000000..50b20b7a3 --- /dev/null +++ b/source/TestKernel/Tests/NoInit/mscorlib/System/ArrayListTest.cs @@ -0,0 +1,1963 @@ +// ArrayListTest.cs - NUnit Test Cases for the System.Collections.ArrayList class +// +// David Brandt (bucky@keystreams.com) +// +// (C) Ximian, Inc. http://www.ximian.com +// Copyright (C) 2005 Novell (http://www.novell.com) +// + +using System; +using System.Collections; + +using NUnit.Framework; + +namespace MonoTests.System.Collections +{ + [TestFixture] + public class ArrayListTest : Assertion + { + [Test] + public static void TestCtor () + { + { + ArrayList al1 = new ArrayList (); + AssertNotNull ("no basic ArrayList", al1); + } + { + bool errorThrown = false; + try { + ArrayList a = new ArrayList (null); + } catch (ArgumentNullException) { + errorThrown = true; + } + Assert ("null icollection error not thrown", + errorThrown); + } + { + try { + Char [,] c1 = new Char [2, 2]; + ArrayList al1 = new ArrayList (c1); + Fail ("Should fail with multi-dimensional array in constructor."); + } catch (RankException) { + } + } + + { + bool errorThrown = false; + try { + ArrayList a = new ArrayList (-1); + } catch (ArgumentOutOfRangeException) { + errorThrown = true; + } + Assert ("negative capacity error not thrown", + errorThrown); + } + } + + [Test] + public static void TestCapacity () + { +#if NET_2_0 + int default_capacity = 4; + int unspecified_capacity = 0; +#else + int default_capacity = 16; + int unspecified_capacity = 16; +#endif + for (int i = 1; i < 100; i++) { + ArrayList al1 = new ArrayList (i); + AssertEquals ("Bad capacity of " + i, + i, al1.Capacity); + } + { + ArrayList al1 = new ArrayList (0); + // LAMESPEC: + // AssertEquals("Bad capacity when set to 0", + // 16, al1.Capacity); + al1.Add ("?"); + AssertEquals ("Bad capacity when set to 0", + default_capacity, al1.Capacity); + } + { + ArrayList al1 = new ArrayList (); + AssertEquals ("Bad default capacity", + unspecified_capacity, al1.Capacity); + } + } + + [Test] + public static void TestCount () + { + { + ArrayList al1 = new ArrayList (); + AssertEquals ("Bad initial count", + 0, al1.Count); + for (int i = 1; i <= 100; i++) { + al1.Add (i); + AssertEquals ("Bad count " + i, + i, al1.Count); + } + } + for (int i = 0; i < 100; i++) { + char [] coll = new Char [i]; + ArrayList al1 = new ArrayList (coll); + AssertEquals ("Bad count for " + i, + i, al1.Count); + } + } + + [Test] + public static void TestIsFixed () + { + ArrayList al1 = new ArrayList (); + Assert ("should not be fixed by default", !al1.IsFixedSize); + ArrayList al2 = ArrayList.FixedSize (al1); + Assert ("fixed-size wrapper not working", al2.IsFixedSize); + } + + [Test] + public static void TestIsReadOnly () + { + ArrayList al1 = new ArrayList (); + Assert ("should not be ReadOnly by default", !al1.IsReadOnly); + ArrayList al2 = ArrayList.ReadOnly (al1); + Assert ("read-only wrapper not working", al2.IsReadOnly); + } + + [Test] + public static void TestIsSynchronized () + { + ArrayList al1 = new ArrayList (); + Assert ("should not be synchronized by default", + !al1.IsSynchronized); + ArrayList al2 = ArrayList.Synchronized (al1); + Assert ("synchronized wrapper not working", al2.IsSynchronized); + } + + [Test] + public static void TestItem () + { + ArrayList al1 = new ArrayList (); + { + bool errorThrown = false; + try { + object o = al1 [-1]; + } catch (ArgumentOutOfRangeException) { + errorThrown = true; + } + Assert ("negative item error not thrown", + errorThrown); + } + { + bool errorThrown = false; + try { + object o = al1 [1]; + } catch (ArgumentOutOfRangeException) { + errorThrown = true; + } + Assert ("past-end item error not thrown", + errorThrown); + } + for (int i = 0; i <= 100; i++) { + al1.Add (i); + } + for (int i = 0; i <= 100; i++) { + AssertEquals ("item not fetched for " + i, + i, al1 [i]); + } + } + + [Test] + public static void TestAdapter () + { + { + bool errorThrown = false; + try { + ArrayList al1 = ArrayList.Adapter (null); + } catch (ArgumentNullException) { + errorThrown = true; + } catch (Exception e) { + Fail ("Incorrect exception thrown at 1: " + e.ToString ()); + } + Assert ("null adapter error not thrown", + errorThrown); + } + { + char [] list = { 'a', 'b', 'c', 'd' }; + ArrayList al1 = ArrayList.Adapter (list); + AssertNotNull ("Couldn't get an adapter", al1); + for (int i = 0; i < list.Length; i++) { + AssertEquals ("adapter not adapting", list [i], al1 [i]); + } + list [0] = 'z'; + for (int i = 0; i < list.Length; i++) { + AssertEquals ("adapter not adapting", list [i], al1 [i]); + } + } + // Test Binary Search + { + bool errorThrown = false; + try { + + String [] s1 = { "This", "is", "a", "test" }; + ArrayList al1 = ArrayList.Adapter (s1); + al1.BinarySearch (42); + } catch (InvalidOperationException) { + // this is what .NET throws + errorThrown = true; + } catch (ArgumentException) { + // this is what the docs say it should throw + errorThrown = true; + } catch (Exception e) { + Fail ("Incorrect exception thrown at 1: " + e.ToString ()); + } + Assert ("search-for-wrong-type error not thrown", + errorThrown); + } + + { + char [] arr = { 'a', 'b', 'b', 'c', 'c', 'c', 'd', 'd' }; + ArrayList al1 = ArrayList.Adapter (arr); + Assert ("couldn't find elem #1", + al1.BinarySearch ('c') >= 3); + Assert ("couldn't find elem #2", + al1.BinarySearch ('c') < 6); + } + { + char [] arr = { 'a', 'b', 'b', 'd', 'd', 'd', 'e', 'e' }; + ArrayList al1 = ArrayList.Adapter (arr); + AssertEquals ("couldn't find next-higher elem", + -4, al1.BinarySearch ('c')); + } + { + char [] arr = { 'a', 'b', 'b', 'c', 'c', 'c', 'd', 'd' }; + ArrayList al1 = ArrayList.Adapter (arr); + AssertEquals ("couldn't find end", + -9, al1.BinarySearch ('e')); + } + // Sort + { + char [] starter = { 'd', 'b', 'f', 'e', 'a', 'c' }; + ArrayList al1 = ArrayList.Adapter (starter); + al1.Sort (); + AssertEquals ("Should be sorted", 'a', al1 [0]); + AssertEquals ("Should be sorted", 'b', al1 [1]); + AssertEquals ("Should be sorted", 'c', al1 [2]); + AssertEquals ("Should be sorted", 'd', al1 [3]); + AssertEquals ("Should be sorted", 'e', al1 [4]); + AssertEquals ("Should be sorted", 'f', al1 [5]); + } + + // TODO - test other adapter types? + } + + [Test] + public static void TestAdd () + { + { + bool errorThrown = false; + try { + ArrayList al1 = + ArrayList.FixedSize (new ArrayList ()); + al1.Add ("Hi!"); + } catch (NotSupportedException) { + errorThrown = true; + } catch (Exception e) { + Fail ("Incorrect exception thrown at 1: " + e.ToString ()); + } + Assert ("add to fixed size error not thrown", + errorThrown); + } + { + bool errorThrown = false; + try { + ArrayList al1 = + ArrayList.ReadOnly (new ArrayList ()); + al1.Add ("Hi!"); + } catch (NotSupportedException) { + errorThrown = true; + } catch (Exception e) { + Fail ("Incorrect exception thrown at 2: " + e.ToString ()); + } + Assert ("add to read only error not thrown", + errorThrown); + } + { + ArrayList al1 = new ArrayList (); + for (int i = 1; i <= 100; i++) { + al1.Add (i); + AssertEquals ("add failed " + i, + i, al1.Count); + AssertEquals ("add failed " + i, + i, al1 [i - 1]); + + } + } + { + string [] strArray = new string [] { }; + ArrayList al1 = new ArrayList (strArray); + al1.Add ("Hi!"); + al1.Add ("Hi!"); + AssertEquals ("add failed", 2, al1.Count); + } + } + + [Test] + public static void TestAddRange () + { + { + bool errorThrown = false; + try { + ArrayList al1 = + ArrayList.FixedSize (new ArrayList ()); + String [] s1 = { "Hi!" }; + al1.AddRange (s1); + } catch (NotSupportedException) { + errorThrown = true; + } catch (Exception e) { + Fail ("Incorrect exception thrown at 1: " + e.ToString ()); + } + Assert ("add to fixed size error not thrown", + errorThrown); + } + { + bool errorThrown = false; + try { + ArrayList al1 = + ArrayList.ReadOnly (new ArrayList ()); + String [] s1 = { "Hi!" }; + al1.AddRange (s1); + } catch (NotSupportedException) { + errorThrown = true; + } catch (Exception e) { + Fail ("Incorrect exception thrown at 2: " + e.ToString ()); + } + Assert ("add to read only error not thrown", + errorThrown); + } + { + bool errorThrown = false; + try { + ArrayList al1 = new ArrayList (); + al1.AddRange (null); + } catch (ArgumentNullException) { + errorThrown = true; + } catch (Exception e) { + Fail ("Incorrect exception thrown at 3: " + e.ToString ()); + } + Assert ("add to read only error not thrown", + errorThrown); + } + + { + ArrayList a1 = new ArrayList (); + AssertEquals ("ArrayList should start empty", + 0, a1.Count); + char [] coll = { 'a', 'b', 'c' }; + a1.AddRange (coll); + AssertEquals ("ArrayList has wrong elements", + 3, a1.Count); + a1.AddRange (coll); + AssertEquals ("ArrayList has wrong elements", + 6, a1.Count); + } + + { + ArrayList list = new ArrayList (); + + for (int i = 0; i < 100; i++) { + list.Add (1); + } + + AssertEquals ("BinarySearch off-by-one bug", + 49, list.BinarySearch (1)); + } + } + + [Test] + public static void TestBinarySearch () + { + { + bool errorThrown = false; + try { + ArrayList al1 = new ArrayList (); + String [] s1 = { "This", "is", "a", "test" }; + al1.AddRange (s1); + al1.BinarySearch (42); + } catch (InvalidOperationException) { + // this is what .NET throws + errorThrown = true; + } catch (ArgumentException) { + // this is what the docs say it should throw + errorThrown = true; + } catch (Exception e) { + Fail ("Incorrect exception thrown at 1: " + e.ToString ()); + } + Assert ("search-for-wrong-type error not thrown", + errorThrown); + } + + { + char [] arr = { 'a', 'b', 'b', 'c', 'c', 'c', 'd', 'd' }; + ArrayList al1 = new ArrayList (arr); + Assert ("couldn't find elem #1", + al1.BinarySearch ('c') >= 3); + Assert ("couldn't find elem #2", + al1.BinarySearch ('c') < 6); + } + { + char [] arr = { 'a', 'b', 'b', 'd', 'd', 'd', 'e', 'e' }; + ArrayList al1 = new ArrayList (arr); + AssertEquals ("couldn't find next-higher elem", + -4, al1.BinarySearch ('c')); + } + { + char [] arr = { 'a', 'b', 'b', 'c', 'c', 'c', 'd', 'd' }; + ArrayList al1 = new ArrayList (arr); + AssertEquals ("couldn't find end", + -9, al1.BinarySearch ('e')); + } + + } + + [Test] + [ExpectedException (typeof (ArgumentException))] + public static void BinarySearch_IndexOverflow () + { + ArrayList al = new ArrayList (); + object o = new object(); + al.Add (o); + al.BinarySearch (Int32.MaxValue, 1, o, null); + } + + [Test] + [ExpectedException (typeof (ArgumentException))] + public static void BinarySearch_CountOverflow () + { + ArrayList al = new ArrayList (); + var o = new object(); + al.Add (o); + al.BinarySearch (1, Int32.MaxValue, o, null); + } + + [Test] + public static void BinarySearch_Null () + { + ArrayList al = new ArrayList (); + var o = new object(); + al.Add (o); + AssertEquals ("null", -1, al.BinarySearch (null)); + } + + // TODO - BinarySearch with IComparer + + [Test] + public static void TestClear () + { + { + bool errorThrown = false; + try { + ArrayList al1 = + ArrayList.FixedSize (new ArrayList ()); + al1.Clear (); + } catch (NotSupportedException) { + errorThrown = true; + } + Assert ("add to fixed size error not thrown", + errorThrown); + } + { + bool errorThrown = false; + try { + ArrayList al1 = + ArrayList.ReadOnly (new ArrayList ()); + al1.Clear (); + } catch (NotSupportedException) { + errorThrown = true; + } + Assert ("add to read only error not thrown", + errorThrown); + } + { + ArrayList al1 = new ArrayList (); + al1.Add ('c'); + AssertEquals ("should have one element", + 1, al1.Count); + al1.Clear (); + AssertEquals ("should be empty", + 0, al1.Count); + } + { + int [] i1 = { 1, 2, 3, 4 }; + ArrayList al1 = new ArrayList (i1); + AssertEquals ("should have elements", + i1.Length, al1.Count); + int capacity = al1.Capacity; + al1.Clear (); + AssertEquals ("should be empty again", + 0, al1.Count); + AssertEquals ("capacity shouldn't have changed", + capacity, al1.Capacity); + } + } + + [Test] + public static void TestClone () + { + { + char [] c1 = { 'a', 'b', 'c' }; + ArrayList al1 = new ArrayList (c1); + ArrayList al2 = (ArrayList) al1.Clone (); + AssertEquals ("ArrayList match", al1 [0], al2 [0]); + AssertEquals ("ArrayList match", al1 [1], al2 [1]); + AssertEquals ("ArrayList match", al1 [2], al2 [2]); + } + { + char [] d10 = { 'a', 'b' }; + char [] d11 = { 'a', 'c' }; + char [] d12 = { 'b', 'c' }; + char [] [] d1 = { d10, d11, d12 }; + ArrayList al1 = new ArrayList (d1); + ArrayList al2 = (ArrayList) al1.Clone (); + AssertEquals ("Array match", al1 [0], al2 [0]); + AssertEquals ("Array match", al1 [1], al2 [1]); + AssertEquals ("Array match", al1 [2], al2 [2]); + + ((char []) al1 [0]) [0] = 'z'; + AssertEquals ("shallow copy", al1 [0], al2 [0]); + } + } + + [Test] + public static void TestContains () + { + char [] c1 = { 'a', 'b', 'c' }; + ArrayList al1 = new ArrayList (c1); + Assert ("never find a null", !al1.Contains (null)); + Assert ("can't find value", al1.Contains ('b')); + Assert ("shouldn't find value", !al1.Contains ('?')); + } + + [Test] + public static void TestCopyTo () + { + { + bool errorThrown = false; + try { + Char [] c1 = new Char [2]; + ArrayList al1 = new ArrayList (c1); + al1.CopyTo (null, 2); + } catch (ArgumentNullException) { + errorThrown = true; + } catch (Exception e) { + Fail ("Incorrect exception thrown at 1: " + e.ToString ()); + } + Assert ("error not thrown 1", errorThrown); + } + { + bool errorThrown = false; + try { + Char [] c1 = new Char [2]; + ArrayList al1 = new ArrayList (c1); + Char [,] c2 = new Char [2, 2]; + al1.CopyTo (c2, 2); + } catch (ArgumentException) { + errorThrown = true; + } catch (Exception e) { + Fail ("Incorrect exception thrown at 2: " + e.ToString ()); + } + Assert ("error not thrown 2", errorThrown); + } + { + bool errorThrown = false; + try { + // This appears to be a bug in the ArrayList Constructor. + // It throws a RankException if a multidimensional Array + // is passed. The docs imply that an IEnumerator is used + // to retrieve the items from the collection, so this should + // work. In anycase this test is for CopyTo, so use what + // works on both platforms. + //Char[,] c1 = new Char[2,2]; + Char [] c1 = new Char [2]; + ArrayList al1 = new ArrayList (c1); + Char [] c2 = new Char [2]; + al1.CopyTo (c2, 2); + } catch (ArgumentException) { + errorThrown = true; + } catch (Exception e) { + Fail ("Incorrect exception thrown at 3: " + e.ToString ()); + } + Assert ("error not thrown 3", errorThrown); + } + { + bool errorThrown = false; + try { + Char [] c1 = new Char [2]; + ArrayList al1 = new ArrayList (c1); + Char [] c2 = new Char [2]; + al1.CopyTo (c2, -1); + } catch (ArgumentOutOfRangeException) { + errorThrown = true; + } catch (Exception e) { + Fail ("Incorrect exception thrown at 4: " + e.ToString ()); + } + Assert ("error not thrown 4", errorThrown); + } + { + bool errorThrown = false; + try { + Char [] c1 = new Char [2]; + ArrayList al1 = new ArrayList (c1); + Char [] c2 = new Char [2]; + al1.CopyTo (c2, 3); + } catch (ArgumentException) { + errorThrown = true; + } catch (Exception e) { + Fail ("Incorrect exception thrown at 5: " + e.ToString ()); + } + Assert ("error not thrown 5", errorThrown); + } + { + bool errorThrown = false; + try { + Char [] c1 = new Char [2]; + ArrayList al1 = new ArrayList (c1); + Char [] c2 = new Char [2]; + al1.CopyTo (c2, 1); + } catch (ArgumentException) { + errorThrown = true; + } catch (Exception e) { + Fail ("Incorrect exception thrown at 6: " + e.ToString ()); + } + Assert ("error not thrown 6", errorThrown); + } + { + bool errorThrown = false; + try { + String [] c1 = { "String", "array" }; + ArrayList al1 = new ArrayList (c1); + Char [] c2 = new Char [2]; + al1.CopyTo (c2, 0); + } catch (InvalidCastException) { + errorThrown = true; + } catch (Exception e) { + Fail ("Incorrect exception thrown at 7: " + e.ToString ()); + } + Assert ("error not thrown 7", errorThrown); + } + + Char [] orig = { 'a', 'b', 'c', 'd' }; + ArrayList al = new ArrayList (orig); + Char [] copy = new Char [10]; + Array.Clear (copy, 0, copy.Length); + al.CopyTo (copy, 3); + AssertEquals ("Wrong CopyTo 0", (char) 0, copy [0]); + AssertEquals ("Wrong CopyTo 1", (char) 0, copy [1]); + AssertEquals ("Wrong CopyTo 2", (char) 0, copy [2]); + AssertEquals ("Wrong CopyTo 3", orig [0], copy [3]); + AssertEquals ("Wrong CopyTo 4", orig [1], copy [4]); + AssertEquals ("Wrong CopyTo 5", orig [2], copy [5]); + AssertEquals ("Wrong CopyTo 6", orig [3], copy [6]); + AssertEquals ("Wrong CopyTo 7", (char) 0, copy [7]); + AssertEquals ("Wrong CopyTo 8", (char) 0, copy [8]); + AssertEquals ("Wrong CopyTo 9", (char) 0, copy [9]); + } + + [Test] + [ExpectedException (typeof (ArgumentException))] + public static void CopyTo_IndexOverflow () + { + ArrayList al = new ArrayList (); + al.Add (new object()); + al.CopyTo (Int32.MaxValue, new byte [2], 0, 0); + } + + [Test] + [ExpectedException (typeof (ArgumentException))] + public static void CopyTo_ArrayIndexOverflow () + { + ArrayList al = new ArrayList (); + al.Add(new object()); + al.CopyTo (0, new byte [2], Int32.MaxValue, 0); + } + + [Test] + [ExpectedException (typeof (ArgumentException))] + public static void CopyTo_CountOverflow () + { + ArrayList al = new ArrayList (); + al.Add(new object()); + al.CopyTo (0, new byte [2], 0, Int32.MaxValue); + } + + [Test] + public static void TestFixedSize () + { + { + bool errorThrown = false; + try { + ArrayList al1 = ArrayList.FixedSize (null); + } catch (ArgumentNullException) { + errorThrown = true; + } + Assert ("null arg error not thrown", errorThrown); + } + { + ArrayList al1 = new ArrayList (); + AssertEquals ("arrays start un-fixed.", + false, al1.IsFixedSize); + ArrayList al2 = ArrayList.FixedSize (al1); + AssertEquals ("should be fixed.", + true, al2.IsFixedSize); + } + } + + [Test] + public static void TestEnumerator () + { + String [] s1 = { "this", "is", "a", "test" }; + ArrayList al1 = new ArrayList (s1); + IEnumerator en = al1.GetEnumerator (); + en.MoveNext (); + al1.Add ("something"); + try { + en.MoveNext (); + Fail ("Add() didn't invalidate the enumerator"); + } catch (InvalidOperationException) { + // do nothing...this is what we expect + } + + en = al1.GetEnumerator (); + en.MoveNext (); + al1.AddRange (al1); + try { + en.MoveNext (); + Fail ("AddRange() didn't invalidate the enumerator"); + } catch (InvalidOperationException) { + // do nothing...this is what we expect + } + + en = al1.GetEnumerator (); + en.MoveNext (); + al1.Clear (); + try { + en.MoveNext (); + Fail ("Clear() didn't invalidate the enumerator"); + } catch (InvalidOperationException) { + // do nothing...this is what we expect + } + + al1 = new ArrayList (s1); + en = al1.GetEnumerator (); + en.MoveNext (); + al1.Insert (0, "new first"); + try { + en.MoveNext (); + Fail ("Insert() didn't invalidate the enumerator"); + } catch (InvalidOperationException) { + // do nothing...this is what we expect + } + + en = al1.GetEnumerator (); + en.MoveNext (); + al1.InsertRange (0, al1); + try { + en.MoveNext (); + Fail ("InsertRange() didn't invalidate the enumerator"); + } catch (InvalidOperationException) { + // do nothing...this is what we expect + } + + en = al1.GetEnumerator (); + en.MoveNext (); + al1.Remove ("this"); + try { + en.MoveNext (); + Fail ("Remove() didn't invalidate the enumerator"); + } catch (InvalidOperationException) { + // do nothing...this is what we expect + } + + en = al1.GetEnumerator (); + en.MoveNext (); + al1.RemoveAt (2); + try { + en.MoveNext (); + Fail ("RemoveAt() didn't invalidate the enumerator"); + } catch (InvalidOperationException) { + // do nothing...this is what we expect + } + + en = al1.GetEnumerator (); + en.MoveNext (); + al1.RemoveRange (1, 1); + try { + en.MoveNext (); + Fail ("RemoveRange() didn't invalidate the enumerator"); + } catch (InvalidOperationException) { + // do nothing...this is what we expect + } + + en = al1.GetEnumerator (); + en.MoveNext (); + al1.Reverse (); + try { + en.MoveNext (); + Fail ("Reverse() didn't invalidate the enumerator"); + } catch (InvalidOperationException) { + // do nothing...this is what we expect + } + + en = al1.GetEnumerator (); + en.MoveNext (); + al1.Sort (); + try { + en.MoveNext (); + Fail ("Sort() didn't invalidate the enumerator"); + } catch (InvalidOperationException) { + // do nothing...this is what we expect + } + } + + [Test] + public static void TestGetEnumerator () + { + { + bool errorThrown = false; + try { + ArrayList a = new ArrayList (); + IEnumerator en = a.GetEnumerator (-1, 1); + } catch (ArgumentOutOfRangeException) { + errorThrown = true; + } + Assert ("negative index error not thrown", + errorThrown); + } + { + bool errorThrown = false; + try { + ArrayList a = new ArrayList (); + IEnumerator en = a.GetEnumerator (1, -1); + } catch (ArgumentOutOfRangeException) { + errorThrown = true; + } + Assert ("negative index error not thrown", + errorThrown); + } + { + bool errorThrown = false; + try { + ArrayList a = new ArrayList (); + IEnumerator en = a.GetEnumerator (1, 1); + } catch (ArgumentException) { + errorThrown = true; + } + Assert ("out-of-range index error not thrown", + errorThrown); + } + { + String [] s1 = { "this", "is", "a", "test" }; + ArrayList al1 = new ArrayList (s1); + IEnumerator en = al1.GetEnumerator (); + AssertNotNull ("No enumerator", en); + + for (int i = 0; i < s1.Length; i++) { + en.MoveNext (); + AssertEquals ("Not enumerating", + al1 [i], en.Current); + } + } + { + String [] s1 = { "this", "is", "a", "test" }; + ArrayList al1 = new ArrayList (s1); + IEnumerator en = al1.GetEnumerator (1, 2); + AssertNotNull ("No enumerator", en); + + for (int i = 0; i < 2; i++) { + en.MoveNext (); + AssertEquals ("Not enumerating", + al1 [i + 1], en.Current); + } + } + } + + [Test] + [ExpectedException (typeof (ArgumentException))] + public static void GetEnumerator_IndexOverflow () + { + ArrayList al = new ArrayList (); + al.Add(new object()); + al.GetEnumerator (Int32.MaxValue, 0); + } + + [Test] + [ExpectedException (typeof (ArgumentException))] + public static void GetEnumerator_CountOverflow () + { + ArrayList al = new ArrayList (); + al.Add(new object()); + al.GetEnumerator (0, Int32.MaxValue); + } + + [Test] + public static void TestGetRange () + { + { + bool errorThrown = false; + try { + ArrayList a = new ArrayList (); + ArrayList b = a.GetRange (-1, 1); + } catch (ArgumentOutOfRangeException) { + errorThrown = true; + } + Assert ("negative index error not thrown", + errorThrown); + } + { + bool errorThrown = false; + try { + ArrayList a = new ArrayList (); + ArrayList b = a.GetRange (1, -1); + } catch (ArgumentOutOfRangeException) { + errorThrown = true; + } + Assert ("negative index error not thrown", + errorThrown); + } + { + bool errorThrown = false; + try { + ArrayList a = new ArrayList (); + ArrayList b = a.GetRange (1, 1); + } catch (ArgumentException) { + errorThrown = true; + } + Assert ("out-of-range index error not thrown", + errorThrown); + } + { + char [] chars = { 'a', 'b', 'c', 'd', 'e', 'f' }; + ArrayList a = new ArrayList (chars); + ArrayList b = a.GetRange (1, 3); + AssertEquals ("GetRange returned wrong size ArrayList", 3, b.Count); + for (int i = 0; i < b.Count; i++) { + AssertEquals ("range didn't work", + chars [i + 1], b [i]); + } + + a [2] = '?'; // should screw up ArrayList b. + bool errorThrown = false; + try { + int i = b.Count; + } catch (InvalidOperationException) { + errorThrown = true; + } + AssertEquals ("Munging 'a' should mess up 'b'", + true, errorThrown); + } + } + + [Test] + [ExpectedException (typeof (ArgumentException))] + public static void GetRange_IndexOverflow () + { + ArrayList al = new ArrayList (); + al.Add(new object()); + al.GetRange (Int32.MaxValue, 0); + } + + [Test] + [ExpectedException (typeof (ArgumentException))] + public static void GetRange_CountOverflow () + { + ArrayList al = new ArrayList (); + al.Add(new object()); + al.GetRange (0, Int32.MaxValue); + } + + [Test] + public static void TestIndexOf () + { + { + bool errorThrown = false; + try { + ArrayList a = new ArrayList (1); + int i = a.IndexOf ('a', -1); + } catch (ArgumentOutOfRangeException) { + errorThrown = true; + } + Assert ("negative indexof error not thrown", + errorThrown); + } + { + bool errorThrown = false; + try { + ArrayList a = new ArrayList (1); + int i = a.IndexOf ('a', 2); + } catch (ArgumentOutOfRangeException) { + errorThrown = true; + } + Assert ("past-end indexof error not thrown", + errorThrown); + } + { + bool errorThrown = false; + try { + ArrayList a = new ArrayList (1); + int i = a.IndexOf ('a', 0, -1); + } catch (ArgumentOutOfRangeException) { + errorThrown = true; + } + Assert ("negative indexof error not thrown", + errorThrown); + } + { + bool errorThrown = false; + try { + ArrayList a = new ArrayList (1); + int i = a.IndexOf ('a', 0, 2); + } catch (ArgumentOutOfRangeException) { + errorThrown = true; + } + Assert ("past-end indexof error not thrown", + errorThrown); + } + { + bool errorThrown = false; + try { + ArrayList a = new ArrayList (2); + int i = a.IndexOf ('a', 1, 2); + } catch (ArgumentOutOfRangeException) { + errorThrown = true; + } + Assert ("past-end indexof error not thrown", + errorThrown); + } + { + char [] c = { 'a', 'b', 'c', 'd', 'e' }; + ArrayList a = new ArrayList (c); + AssertEquals ("never find null", + -1, a.IndexOf (null)); + AssertEquals ("never find null", + -1, a.IndexOf (null, 0)); + AssertEquals ("never find null", + -1, a.IndexOf (null, 0, 5)); + AssertEquals ("can't find elem", + 2, a.IndexOf ('c')); + AssertEquals ("can't find elem", + 2, a.IndexOf ('c', 2)); + AssertEquals ("can't find elem", + 2, a.IndexOf ('c', 2, 2)); + AssertEquals ("shouldn't find elem", + -1, a.IndexOf ('c', 3, 2)); + AssertEquals ("shouldn't find", -1, a.IndexOf ('?')); + AssertEquals ("shouldn't find", -1, a.IndexOf (3)); + } + } + + [Test] + [ExpectedException (typeof (ArgumentOutOfRangeException))] + public static void IndexOf_StartIndexOverflow () + { + ArrayList al = new ArrayList (); + al.Add(new object()); + al.IndexOf ('a', Int32.MaxValue, 1); + } + + [Test] + [ExpectedException (typeof (ArgumentOutOfRangeException))] + public static void IndexOf_CountOverflow () + { + ArrayList al = new ArrayList (); + al.Add(new object()); + al.IndexOf ('a', 1, Int32.MaxValue); + } + + [Test] + public static void TestInsert () + { + { + bool errorThrown = false; + try { + ArrayList al1 = + ArrayList.FixedSize (new ArrayList ()); + al1.Insert (0, "Hi!"); + } catch (NotSupportedException) { + errorThrown = true; + } + Assert ("insert to fixed size error not thrown", + errorThrown); + } + { + bool errorThrown = false; + try { + ArrayList al1 = + ArrayList.ReadOnly (new ArrayList ()); + al1.Insert (0, "Hi!"); + } catch (NotSupportedException) { + errorThrown = true; + } + Assert ("insert to read only error not thrown", + errorThrown); + } + { + bool errorThrown = false; + try { + ArrayList al1 = new ArrayList (3); + al1.Insert (-1, "Hi!"); + } catch (ArgumentOutOfRangeException) { + errorThrown = true; + } + Assert ("insert to read only error not thrown", + errorThrown); + } + { + bool errorThrown = false; + try { + ArrayList al1 = new ArrayList (3); + al1.Insert (4, "Hi!"); + } catch (ArgumentOutOfRangeException) { + errorThrown = true; + } + Assert ("insert to read only error not thrown", + errorThrown); + } + { + ArrayList al1 = new ArrayList (); + AssertEquals ("arraylist starts empty", 0, al1.Count); + al1.Insert (0, 'a'); + al1.Insert (1, 'b'); + al1.Insert (0, 'c'); + AssertEquals ("arraylist needs stuff", 3, al1.Count); + AssertEquals ("arraylist got stuff", 'c', al1 [0]); + AssertEquals ("arraylist got stuff", 'a', al1 [1]); + AssertEquals ("arraylist got stuff", 'b', al1 [2]); + } + } + + [Test] + public static void TestInsertRange () + { + { + bool errorThrown = false; + try { + ArrayList al1 = + ArrayList.FixedSize (new ArrayList ()); + string [] s = { "Hi!" }; + al1.InsertRange (0, s); + } catch (NotSupportedException) { + errorThrown = true; + } + Assert ("insert to fixed size error not thrown", + errorThrown); + } + { + bool errorThrown = false; + try { + ArrayList al1 = + ArrayList.ReadOnly (new ArrayList ()); + string [] s = { "Hi!" }; + al1.InsertRange (0, s); + } catch (NotSupportedException) { + errorThrown = true; + } + Assert ("insert to read only error not thrown", + errorThrown); + } + { + bool errorThrown = false; + try { + ArrayList al1 = new ArrayList (3); + string [] s = { "Hi!" }; + al1.InsertRange (-1, s); + } catch (ArgumentOutOfRangeException) { + errorThrown = true; + } + Assert ("negative index insert error not thrown", + errorThrown); + } + { + bool errorThrown = false; + try { + ArrayList al1 = new ArrayList (3); + string [] s = { "Hi!" }; + al1.InsertRange (4, s); + } catch (ArgumentOutOfRangeException) { + errorThrown = true; + } + Assert ("out-of-range insert error not thrown", + errorThrown); + } + { + bool errorThrown = false; + try { + ArrayList al1 = new ArrayList (3); + al1.InsertRange (0, null); + } catch (ArgumentNullException) { + errorThrown = true; + } + Assert ("null insert error not thrown", + errorThrown); + } + { + char [] c = { 'a', 'b', 'c' }; + ArrayList a = new ArrayList (c); + a.InsertRange (1, c); + AssertEquals ("bad insert 1", 'a', a [0]); + AssertEquals ("bad insert 2", 'a', a [1]); + AssertEquals ("bad insert 3", 'b', a [2]); + AssertEquals ("bad insert 4", 'c', a [3]); + AssertEquals ("bad insert 5", 'b', a [4]); + AssertEquals ("bad insert 6", 'c', a [5]); + } + } + + [Test] + public static void TestLastIndexOf () + { + //{ + //bool errorThrown = false; + //try { + //ArrayList a = new ArrayList(1); + //int i = a.LastIndexOf('a', -1); + //} catch (ArgumentOutOfRangeException) { + //errorThrown = true; + //} + //Assert("first negative lastindexof error not thrown", + //errorThrown); + //} + { + bool errorThrown = false; + try { + ArrayList a = new ArrayList (1); + int i = a.LastIndexOf ('a', 2); + } catch (ArgumentOutOfRangeException) { + errorThrown = true; + } + Assert ("past-end lastindexof error not thrown", + errorThrown); + } + //{ + //bool errorThrown = false; + //try { + //ArrayList a = new ArrayList(1); + //int i = a.LastIndexOf('a', 0, -1); + //} catch (ArgumentOutOfRangeException) { + //errorThrown = true; + //} + //Assert("second negative lastindexof error not thrown", + //errorThrown); + //} + //{ + //bool errorThrown = false; + //try { + //ArrayList a = new ArrayList(1); + //int i = a.LastIndexOf('a', 0, 2); + //} catch (ArgumentOutOfRangeException) { + //errorThrown = true; + //} + //Assert("past-end lastindexof error not thrown", + //errorThrown); + //} + //{ + //bool errorThrown = false; + //try { + //ArrayList a = new ArrayList(2); + //int i = a.LastIndexOf('a', 0, 2); + //} catch (ArgumentOutOfRangeException) { + //errorThrown = true; + //} + //Assert("past-end lastindexof error not thrown", + //errorThrown); + //} + int iTest = 0; + try { + char [] c = { 'a', 'b', 'c', 'd', 'e' }; + ArrayList a = new ArrayList (c); + AssertEquals ("never find null", + -1, a.LastIndexOf (null)); + iTest++; + AssertEquals ("never find null", + -1, a.LastIndexOf (null, 4)); + iTest++; + AssertEquals ("never find null", + -1, a.LastIndexOf (null, 4, 5)); + iTest++; + AssertEquals ("can't find elem", + 2, a.LastIndexOf ('c')); + iTest++; + AssertEquals ("can't find elem", + 2, a.LastIndexOf ('c', 4)); + iTest++; + AssertEquals ("can't find elem", + 2, a.LastIndexOf ('c', 3, 2)); + iTest++; + AssertEquals ("shouldn't find elem", + -1, a.LastIndexOf ('c', 4, 2)); + iTest++; + AssertEquals ("shouldn't find", -1, a.LastIndexOf ('?')); + iTest++; + AssertEquals ("shouldn't find", -1, a.LastIndexOf (1)); + } catch (Exception e) { + Fail ("Unexpected exception caught when iTest=" + iTest + ". e=" + e); + } + } + + [Test] + [ExpectedException (typeof (ArgumentOutOfRangeException))] + public static void LastIndexOf_StartIndexOverflow () + { + ArrayList al = new ArrayList (); + al.Add(new object()); + al.LastIndexOf ('a', Int32.MaxValue, 1); + } + + [Test] + [ExpectedException (typeof (ArgumentOutOfRangeException))] + public static void LastIndexOf_CountOverflow () + { + ArrayList al = new ArrayList (); + al.Add(new object()); + al.LastIndexOf ('a', 1, Int32.MaxValue); + } + + [Test] + public static void TestReadOnly () + { + { + bool errorThrown = false; + try { + ArrayList al1 = ArrayList.ReadOnly (null); + } catch (ArgumentNullException) { + errorThrown = true; + } + Assert ("null arg error not thrown", errorThrown); + } + { + ArrayList al1 = new ArrayList (); + AssertEquals ("arrays start writeable.", + false, al1.IsReadOnly); + ArrayList al2 = ArrayList.ReadOnly (al1); + AssertEquals ("should be readonly.", + true, al2.IsReadOnly); + } + } + + [Test] + public static void TestRemove () + { + { + bool errorThrown = false; + try { + ArrayList al1 = + ArrayList.FixedSize (new ArrayList (3)); + al1.Remove (1); + } catch (NotSupportedException) { + errorThrown = true; + } + Assert ("remove fixed size error not thrown", + errorThrown); + } + { + bool errorThrown = false; + try { + ArrayList al1 = + ArrayList.ReadOnly (new ArrayList (3)); + al1.Remove (1); + } catch (NotSupportedException) { + errorThrown = true; + } + Assert ("remove read only error not thrown", + errorThrown); + } + { + char [] c = { 'a', 'b', 'c' }; + ArrayList a = new ArrayList (c); + a.Remove (1); + a.Remove ('?'); + AssertEquals ("should be unchanged", c.Length, a.Count); + a.Remove ('a'); + AssertEquals ("should be changed", 2, a.Count); + AssertEquals ("should have shifted", 'b', a [0]); + AssertEquals ("should have shifted", 'c', a [1]); + } + } + + [Test] + public static void TestRemoveAt () + { + { + bool errorThrown = false; + try { + ArrayList al1 = + ArrayList.FixedSize (new ArrayList (3)); + al1.RemoveAt (1); + } catch (NotSupportedException) { + errorThrown = true; + } + Assert ("remove from fixed size error not thrown", + errorThrown); + } + { + bool errorThrown = false; + try { + ArrayList al1 = + ArrayList.ReadOnly (new ArrayList (3)); + al1.RemoveAt (1); + } catch (NotSupportedException) { + errorThrown = true; + } + Assert ("remove from read only error not thrown", + errorThrown); + } + { + bool errorThrown = false; + try { + ArrayList al1 = new ArrayList (3); + al1.RemoveAt (-1); + } catch (ArgumentOutOfRangeException) { + errorThrown = true; + } + Assert ("remove at negative index error not thrown", + errorThrown); + } + { + bool errorThrown = false; + try { + ArrayList al1 = new ArrayList (3); + al1.RemoveAt (4); + } catch (ArgumentOutOfRangeException) { + errorThrown = true; + } + Assert ("remove at out-of-range index error not thrown", + errorThrown); + } + { + char [] c = { 'a', 'b', 'c' }; + ArrayList a = new ArrayList (c); + a.RemoveAt (0); + AssertEquals ("should be changed", 2, a.Count); + AssertEquals ("should have shifted", 'b', a [0]); + AssertEquals ("should have shifted", 'c', a [1]); + } + } + + [Test] + public static void TestRemoveRange () + { + { + bool errorThrown = false; + try { + ArrayList al1 = + ArrayList.FixedSize (new ArrayList (3)); + al1.RemoveRange (0, 1); + } catch (NotSupportedException) { + errorThrown = true; + } + Assert ("removerange from fixed size error not thrown", + errorThrown); + } + { + bool errorThrown = false; + try { + ArrayList al1 = + ArrayList.ReadOnly (new ArrayList (3)); + al1.RemoveRange (0, 1); + } catch (NotSupportedException) { + errorThrown = true; + } + Assert ("removerange from read only error not thrown", + errorThrown); + } + { + bool errorThrown = false; + try { + ArrayList al1 = new ArrayList (3); + al1.RemoveRange (-1, 1); + } catch (ArgumentOutOfRangeException) { + errorThrown = true; + } + Assert ("removerange at negative index error not thrown", + errorThrown); + } + { + bool errorThrown = false; + try { + ArrayList al1 = new ArrayList (3); + al1.RemoveRange (0, -1); + } catch (ArgumentOutOfRangeException) { + errorThrown = true; + } + Assert ("removerange at negative index error not thrown", + errorThrown); + } + { + bool errorThrown = false; + try { + ArrayList al1 = new ArrayList (3); + al1.RemoveRange (2, 3); + } catch (ArgumentException) { + errorThrown = true; + } + Assert ("removerange at bad range error not thrown", + errorThrown); + } + { + char [] c = { 'a', 'b', 'c' }; + ArrayList a = new ArrayList (c); + a.RemoveRange (1, 2); + AssertEquals ("should be changed", 1, a.Count); + AssertEquals ("should have shifted", 'a', a [0]); + } + } + + [Test] + [ExpectedException (typeof (ArgumentException))] + public static void RemoveRange_IndexOverflow () + { + ArrayList al = new ArrayList (); + al.Add(new object()); + al.RemoveRange (Int32.MaxValue, 1); + } + + [Test] + [ExpectedException (typeof (ArgumentException))] + public static void RemoveRange_CountOverflow () + { + ArrayList al = new ArrayList (); + al.Add(new object()); + al.RemoveRange (1, Int32.MaxValue); + } + + [Test] + public static void TestRepeat () + { + { + bool errorThrown = false; + try { + ArrayList al1 = ArrayList.Repeat ('c', -1); + } catch (ArgumentOutOfRangeException) { + errorThrown = true; + } + Assert ("repeat negative copies error not thrown", + errorThrown); + } + { + ArrayList al1 = ArrayList.Repeat ("huh?", 0); + AssertEquals ("should be nothing in array", + 0, al1.Count); + } + { + ArrayList al1 = ArrayList.Repeat ("huh?", 3); + AssertEquals ("should be something in array", + 3, al1.Count); + AssertEquals ("array elem doesn't check", + "huh?", al1 [0]); + AssertEquals ("array elem doesn't check", + "huh?", al1 [1]); + AssertEquals ("array elem doesn't check", + "huh?", al1 [2]); + } + } + + [Test] + public static void TestReverse () + { + { + bool errorThrown = false; + try { + ArrayList al1 = + ArrayList.ReadOnly (new ArrayList ()); + al1.Reverse (); + } catch (NotSupportedException) { + errorThrown = true; + } + Assert ("reverse on read only error not thrown", + errorThrown); + } + { + bool errorThrown = false; + try { + char [] c = new Char [2]; + ArrayList al1 = new ArrayList (c); + al1.Reverse (0, 3); + } catch (ArgumentException) { + errorThrown = true; + } + Assert ("error not thrown", errorThrown); + } + { + bool errorThrown = false; + try { + char [] c = new Char [2]; + ArrayList al1 = new ArrayList (c); + al1.Reverse (3, 0); + } catch (ArgumentException) { + errorThrown = true; + } + Assert ("error not thrown", errorThrown); + } + { + char [] c = { 'a', 'b', 'c', 'd', 'e' }; + ArrayList al1 = new ArrayList (c); + al1.Reverse (2, 1); + for (int i = 0; i < al1.Count; i++) { + AssertEquals ("Should be no change yet", + c [i], al1 [i]); + } + al1.Reverse (); + for (int i = 0; i < al1.Count; i++) { + AssertEquals ("Should be reversed", + c [i], al1 [4 - i]); + } + al1.Reverse (); + for (int i = 0; i < al1.Count; i++) { + AssertEquals ("Should be back to normal", + c [i], al1 [i]); + } + al1.Reverse (1, 3); + AssertEquals ("Should be back to normal", c [0], al1 [0]); + AssertEquals ("Should be back to normal", c [3], al1 [1]); + AssertEquals ("Should be back to normal", c [2], al1 [2]); + AssertEquals ("Should be back to normal", c [1], al1 [3]); + AssertEquals ("Should be back to normal", c [4], al1 [4]); + } + } + + [Test] + [ExpectedException (typeof (ArgumentException))] + public static void Reverse_IndexOverflow () + { + ArrayList al = new ArrayList (); + al.Add(new object()); + al.Reverse (Int32.MaxValue, 1); + } + + [Test] + [ExpectedException (typeof (ArgumentException))] + public static void Reverse_CountOverflow () + { + ArrayList al = new ArrayList (); + al.Add(new object()); + al.Reverse (1, Int32.MaxValue); + } + + [Test] + public static void TestSetRange () + { + { + bool errorThrown = false; + try { + char [] c = { 'a', 'b', 'c' }; + ArrayList al1 = + ArrayList.ReadOnly (new ArrayList (3)); + al1.SetRange (0, c); + } catch (NotSupportedException) { + errorThrown = true; + } catch (Exception e) { + Fail ("Incorrect exception thrown at 1: " + e.ToString ()); + } + Assert ("setrange on read only error not thrown", + errorThrown); + } + { + bool errorThrown = false; + try { + ArrayList al1 = new ArrayList (3); + al1.SetRange (0, null); + } catch (ArgumentNullException) { + errorThrown = true; + } catch (ArgumentOutOfRangeException) { + errorThrown = true; + } catch (Exception e) { + Fail ("Incorrect exception thrown at 2: " + e.ToString ()); + } + Assert ("setrange with null error not thrown", + errorThrown); + } + { + bool errorThrown = false; + try { + char [] c = { 'a', 'b', 'c' }; + ArrayList al1 = new ArrayList (3); + al1.SetRange (-1, c); + } catch (ArgumentOutOfRangeException) { + errorThrown = true; + } catch (Exception e) { + Fail ("Incorrect exception thrown at 3: " + e.ToString ()); + } + Assert ("setrange with negative index error not thrown", + errorThrown); + } + { + bool errorThrown = false; + try { + char [] c = { 'a', 'b', 'c' }; + ArrayList al1 = new ArrayList (3); + al1.SetRange (2, c); + } catch (ArgumentOutOfRangeException) { + errorThrown = true; + } catch (Exception e) { + Fail ("Incorrect exception thrown at 4: " + e.ToString ()); + } + Assert ("setrange with too much error not thrown", + errorThrown); + } + + { + char [] c = { 'a', 'b', 'c' }; + ArrayList al1 = ArrayList.Repeat ('?', 3); + Assert ("no match yet", c [0] != (char) al1 [0]); + Assert ("no match yet", c [1] != (char) al1 [1]); + Assert ("no match yet", c [2] != (char) al1 [2]); + al1.SetRange (0, c); + AssertEquals ("should match", c [0], al1 [0]); + AssertEquals ("should match", c [1], al1 [1]); + AssertEquals ("should match", c [2], al1 [2]); + } + } + + [Test] + [ExpectedException (typeof (ArgumentOutOfRangeException))] + public static void SetRange_Overflow () + { + ArrayList al = new ArrayList (); + al.Add(new object()); + al.SetRange (Int32.MaxValue, new ArrayList ()); + } + + [Test] + public static void TestInsertRange_this () + { + String [] s1 = { "this", "is", "a", "test" }; + ArrayList al = new ArrayList (s1); + al.InsertRange (2, al); + String [] s2 = { "this", "is", "this", "is", "a", "test", "a", "test" }; + for (int i = 0; i < al.Count; i++) { + AssertEquals ("at i=" + i, s2 [i], al [i]); + } + } + + [Test] + public static void TestSort () + { + { + bool errorThrown = false; + try { + ArrayList al1 = + ArrayList.ReadOnly (new ArrayList ()); + al1.Sort (); + } catch (NotSupportedException) { + errorThrown = true; + } + Assert ("sort on read only error not thrown", + errorThrown); + } + { + char [] starter = { 'd', 'b', 'f', 'e', 'a', 'c' }; + ArrayList al1 = new ArrayList (starter); + al1.Sort (); + AssertEquals ("Should be sorted", 'a', al1 [0]); + AssertEquals ("Should be sorted", 'b', al1 [1]); + AssertEquals ("Should be sorted", 'c', al1 [2]); + AssertEquals ("Should be sorted", 'd', al1 [3]); + AssertEquals ("Should be sorted", 'e', al1 [4]); + AssertEquals ("Should be sorted", 'f', al1 [5]); + } + { + ArrayList al1 = new ArrayList (); + al1.Add (null); + al1.Add (null); + al1.Add (32); + al1.Add (33); + al1.Add (null); + al1.Add (null); + + al1.Sort (); + AssertEquals ("Should be null", null, al1 [0]); + AssertEquals ("Should be 2. null", null, al1 [1]); + AssertEquals ("Should be 3. null", null, al1 [2]); + AssertEquals ("Should be 4. null", null, al1 [3]); + AssertEquals ("Should be 32", 32, al1 [4]); + AssertEquals ("Should be 33", 33, al1 [5]); + } + } + + [Test] + [ExpectedException (typeof (ArgumentException))] + public static void Sort_IndexOverflow () + { + ArrayList al = new ArrayList (); + al.Add(new object()); + al.Sort (Int32.MaxValue, 1, null); + } + + [Test] + [ExpectedException (typeof (ArgumentException))] + public static void Sort_CountOverflow () + { + ArrayList al = new ArrayList (); + al.Add(new object()); + al.Sort (1, Int32.MaxValue, null); + } + + // TODO - Sort with IComparers + + // TODO - Synchronize + + //[Test] + //public static void TestToArray () + //{ + // { + // bool errorThrown = false; + // try { + // ArrayList al1 = new ArrayList (3); + // al1.ToArray (null); + // } catch (ArgumentNullException) { + // errorThrown = true; + // } + // Assert ("toarray with null error not thrown", + // errorThrown); + // } + // { + // bool errorThrown = false; + // try { + // char [] c = { 'a', 'b', 'c' }; + // string s = "huh?"; + // ArrayList al1 = new ArrayList (c); + // al1.ToArray (s.GetType ()); + // } catch (InvalidCastException) { + // errorThrown = true; + // } + // Assert ("toarray with bad type error not thrown", + // errorThrown); + // } + // { + // char [] c1 = { 'a', 'b', 'c', 'd', 'e' }; + // ArrayList al1 = new ArrayList (c1); + // object [] o2 = al1.ToArray (); + // for (int i = 0; i < c1.Length; i++) { + // AssertEquals ("should be copy", c1 [i], o2 [i]); + // } + // Array c2 = al1.ToArray (c1 [0].GetType ()); + // for (int i = 0; i < c1.Length; i++) { + // AssertEquals ("should be copy", + // c1 [i], c2.GetValue (i)); + // } + // } + //} + + [Test] + [ExpectedException (typeof (NotSupportedException))] + public static void TrimToSize_ReadOnly () + { + ArrayList al1 = ArrayList.ReadOnly (new ArrayList ()); + al1.TrimToSize (); + } + + [Test] + public static void TrimToSize () + { + ArrayList al1 = new ArrayList (); +#if NET_2_0 + // Capacity is 0 under 2.0 + int capacity = 4; +#else + int capacity = al1.Capacity; +#endif + int size = capacity / 2; + for (int i = 1; i <= size; i++) { + al1.Add ('?'); + } + al1.RemoveAt (0); + al1.TrimToSize (); + AssertEquals ("no capacity match", size - 1, al1.Capacity); + + al1.Clear (); + al1.TrimToSize (); + AssertEquals ("no default capacity", capacity, al1.Capacity); + } + + class Comparer : IComparer + { + + private bool called = false; + + public bool Called + { + get + { + bool result = called; + called = false; + return called; + } + } + + public int Compare (object x, object y) + { + called = true; + return 0; + } + } + + [Test] + public static void BinarySearch1_EmptyList () + { + ArrayList list = new ArrayList (); + AssertEquals ("BinarySearch", -1, list.BinarySearch (0)); + } + + [Test] + public static void BinarySearch2_EmptyList () + { + Comparer comparer = new Comparer (); + ArrayList list = new ArrayList (); + AssertEquals ("BinarySearch", -1, list.BinarySearch (0, comparer)); + // bug 77030 - the comparer isn't called for an empty array/list + Assert ("Called", !comparer.Called); + } + + [Test] + public static void BinarySearch3_EmptyList () + { + Comparer comparer = new Comparer (); + ArrayList list = new ArrayList (); + AssertEquals ("BinarySearch", -1, list.BinarySearch (0, 0, 0, comparer)); + // bug 77030 - the comparer isn't called for an empty array/list + Assert ("Called", !comparer.Called); + } + + [Test] +#if ONLY_1_1 + [Category ("NotDotNet")] // MS bug +#endif + public static void AddRange_GetRange () + { + ArrayList source = ArrayList.Adapter (new object [] { "1", "2" }); + AssertEquals ("#1", 2, source.Count); + AssertEquals ("#2", "1", source [0]); + AssertEquals ("#3", "2", source [1]); + ArrayList range = source.GetRange (1, 1); + AssertEquals ("#4", 1, range.Count); + AssertEquals ("#5", "2", range [0]); + ArrayList target = new ArrayList (); + target.AddRange (range); + AssertEquals ("#6", 1, target.Count); + AssertEquals ("#7", "2", target [0]); + } + + [Test] +#if ONLY_1_1 + [Category ("NotDotNet")] // MS bug +#endif + public static void IterateSelf () + { + ArrayList list = new ArrayList (); + list.Add (list); + IEnumerator enumerator = list.GetEnumerator (); + Assert ("#1", enumerator.MoveNext ()); + Assert ("#2", object.ReferenceEquals (list, enumerator.Current)); + Assert ("#3", !enumerator.MoveNext ()); + } + } +}