2 Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
3 Permission is hereby granted, free of charge, to any person obtaining a copy
4 of this software and associated documentation files (the "Software"), to deal
5 in the Software without restriction, including without limitation the rights
6 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 copies of the Software, and to permit persons to whom the Software is
8 furnished to do so, subject to the following conditions:
10 The above copyright notice and this permission notice shall be included in
11 all copies or substantial portions of the Software.
13 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 using NUnit.Framework;
25 using SCG = System.Collections.Generic;
30 class SC : SCG.IComparer<string>
32 public int Compare(string a, string b)
34 return a.CompareTo(b);
38 public void appl(String s)
40 System.Console.WriteLine("--{0}", s);
44 class TenEqualityComparer : SCG.IEqualityComparer<int>, SCG.IComparer<int>
46 TenEqualityComparer() { }
47 public static TenEqualityComparer Default { get { return new TenEqualityComparer(); } }
48 public int GetHashCode(int item) { return (item / 10).GetHashCode(); }
49 public bool Equals(int item1, int item2) { return item1 / 10 == item2 / 10; }
50 public int Compare(int a, int b) { return (a / 10).CompareTo(b / 10); }
53 class IC : SCG.IComparer<int>, IComparable<int>, SCG.IComparer<IC>, IComparable<IC>
55 public int Compare(int a, int b)
57 return a > b ? 1 : a < b ? -1 : 0;
61 public int Compare(IC a, IC b)
63 return a._i > b._i ? 1 : a._i < b._i ? -1 : 0;
80 public IC(int i) { _i = i; }
83 public int CompareTo(int that) { return _i > that ? 1 : _i < that ? -1 : 0; }
85 public bool Equals(int that) { return _i == that; }
88 public int CompareTo(IC that) { return _i > that._i ? 1 : _i < that._i ? -1 : 0; }
89 public bool Equals(IC that) { return _i == that._i; }
92 public static bool eq(SCG.IEnumerable<int> me, params int[] that)
94 int i = 0, maxind = that.Length - 1;
96 foreach (int item in me)
97 if (i > maxind || item != that[i++])
100 return i == maxind + 1;
102 public static bool seteq(ICollectionValue<int> me, params int[] that)
104 int[] me2 = me.ToArray();
108 int i = 0, maxind = that.Length - 1;
110 foreach (int item in me2)
111 if (i > maxind || item != that[i++])
114 return i == maxind + 1;
116 public static bool seteq(ICollectionValue<KeyValuePair<int, int>> me, params int[] that)
118 ArrayList<KeyValuePair<int, int>> first = new ArrayList<KeyValuePair<int, int>>();
120 ArrayList<KeyValuePair<int, int>> other = new ArrayList<KeyValuePair<int, int>>();
121 for (int i = 0; i < that.Length; i += 2)
123 other.Add(new KeyValuePair<int, int>(that[i], that[i + 1]));
125 return other.UnsequencedEquals(first);
129 class RevIC : SCG.IComparer<int>
131 public int Compare(int a, int b)
133 return a > b ? -1 : a < b ? 1 : 0;
137 public class FunEnumerable : SCG.IEnumerable<int>
142 public FunEnumerable(int size, Fun<int, int> f)
144 this.size = size; this.f = f;
147 public SCG.IEnumerator<int> GetEnumerator()
149 for (int i = 0; i < size; i++)
154 #region IEnumerable Members
156 System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
158 throw new Exception("The method or operation is not implemented.");
164 public class BadEnumerableException : Exception { }
166 public class BadEnumerable<T> : CollectionValueBase<T>, ICollectionValue<T>
171 public BadEnumerable(Exception exception, params T[] contents)
173 this.contents = (T[])contents.Clone();
174 this.exception = exception;
177 public override SCG.IEnumerator<T> GetEnumerator()
179 for (int i = 0; i < contents.Length; i++)
180 yield return contents[i];
184 public override bool IsEmpty { get { return false; } }
186 public override int Count { get { return contents.Length + 1; } }
188 public override Speed CountSpeed { get { return Speed.Constant; } }
190 public override T Choose() { throw exception; }
193 public class CollectionEventList<T>
195 ArrayList<CollectionEvent<T>> happened;
196 EventTypeEnum listenTo;
197 SCG.IEqualityComparer<T> itemequalityComparer;
198 public CollectionEventList(SCG.IEqualityComparer<T> itemequalityComparer)
200 happened = new ArrayList<CollectionEvent<T>>();
201 this.itemequalityComparer = itemequalityComparer;
203 public void Listen(ICollectionValue<T> list, EventTypeEnum listenTo)
205 this.listenTo = listenTo;
206 if ((listenTo & EventTypeEnum.Changed) != 0)
207 list.CollectionChanged += new CollectionChangedHandler<T>(changed);
208 if ((listenTo & EventTypeEnum.Cleared) != 0)
209 list.CollectionCleared += new CollectionClearedHandler<T>(cleared);
210 if ((listenTo & EventTypeEnum.Removed) != 0)
211 list.ItemsRemoved += new ItemsRemovedHandler<T>(removed);
212 if ((listenTo & EventTypeEnum.Added) != 0)
213 list.ItemsAdded += new ItemsAddedHandler<T>(added);
214 if ((listenTo & EventTypeEnum.Inserted) != 0)
215 list.ItemInserted += new ItemInsertedHandler<T>(inserted);
216 if ((listenTo & EventTypeEnum.RemovedAt) != 0)
217 list.ItemRemovedAt += new ItemRemovedAtHandler<T>(removedAt);
219 public void Add(CollectionEvent<T> e) { happened.Add(e); }
221 /// Check that we have seen exactly the events in expected that match listenTo.
223 /// <param name="expected"></param>
224 public void Check(SCG.IEnumerable<CollectionEvent<T>> expected)
227 foreach (CollectionEvent<T> expectedEvent in expected)
229 if ((expectedEvent.Act & listenTo) == 0)
231 if (i >= happened.Count)
232 Assert.Fail(string.Format("Event number {0} did not happen:\n expected {1}", i, expectedEvent));
233 if (!expectedEvent.Equals(happened[i], itemequalityComparer))
234 Assert.Fail(string.Format("Event number {0}:\n expected {1}\n but saw {2}", i, expectedEvent, happened[i]));
237 if (i < happened.Count)
238 Assert.Fail(string.Format("Event number {0} seen but no event expected:\n {1}", i, happened[i]));
241 public void Clear() { happened.Clear(); }
242 public void Print(System.IO.TextWriter writer)
244 happened.Apply(delegate(CollectionEvent<T> e) { writer.WriteLine(e); });
246 void changed(object sender)
248 happened.Add(new CollectionEvent<T>(EventTypeEnum.Changed, new EventArgs(), sender));
250 void cleared(object sender, ClearedEventArgs eventArgs)
252 happened.Add(new CollectionEvent<T>(EventTypeEnum.Cleared, eventArgs, sender));
254 void added(object sender, ItemCountEventArgs<T> eventArgs)
256 happened.Add(new CollectionEvent<T>(EventTypeEnum.Added, eventArgs, sender));
258 void removed(object sender, ItemCountEventArgs<T> eventArgs)
260 happened.Add(new CollectionEvent<T>(EventTypeEnum.Removed, eventArgs, sender));
262 void inserted(object sender, ItemAtEventArgs<T> eventArgs)
264 happened.Add(new CollectionEvent<T>(EventTypeEnum.Inserted, eventArgs, sender));
266 void removedAt(object sender, ItemAtEventArgs<T> eventArgs)
268 happened.Add(new CollectionEvent<T>(EventTypeEnum.RemovedAt, eventArgs, sender));
272 public sealed class CollectionEvent<T>
274 public readonly EventTypeEnum Act;
275 public readonly EventArgs Args;
276 public readonly object Sender;
278 public CollectionEvent(EventTypeEnum act, EventArgs args, object sender)
282 this.Sender = sender;
285 public bool Equals(CollectionEvent<T> otherEvent, SCG.IEqualityComparer<T> itemequalityComparer)
287 if (otherEvent == null || Act != otherEvent.Act || !object.ReferenceEquals(Sender, otherEvent.Sender))
291 case EventTypeEnum.None:
293 case EventTypeEnum.Changed:
295 case EventTypeEnum.Cleared:
296 if (Args is ClearedRangeEventArgs)
298 ClearedRangeEventArgs a = Args as ClearedRangeEventArgs, o = otherEvent.Args as ClearedRangeEventArgs;
301 return a.Full == o.Full && a.Start == o.Start && a.Count == o.Count;
305 if (otherEvent.Args is ClearedRangeEventArgs)
307 ClearedEventArgs a = Args as ClearedEventArgs, o = otherEvent.Args as ClearedEventArgs;
308 return a.Full == o.Full && a.Count == o.Count;
310 case EventTypeEnum.Added:
312 ItemCountEventArgs<T> a = Args as ItemCountEventArgs<T>, o = otherEvent.Args as ItemCountEventArgs<T>;
313 return itemequalityComparer.Equals(a.Item, o.Item) && a.Count == o.Count;
315 case EventTypeEnum.Removed:
317 ItemCountEventArgs<T> a = Args as ItemCountEventArgs<T>, o = otherEvent.Args as ItemCountEventArgs<T>;
318 return itemequalityComparer.Equals(a.Item, o.Item) && a.Count == o.Count;
320 case EventTypeEnum.Inserted:
322 ItemAtEventArgs<T> a = Args as ItemAtEventArgs<T>, o = otherEvent.Args as ItemAtEventArgs<T>;
323 return a.Index == o.Index && itemequalityComparer.Equals(a.Item, o.Item);
325 case EventTypeEnum.RemovedAt:
327 ItemAtEventArgs<T> a = Args as ItemAtEventArgs<T>, o = otherEvent.Args as ItemAtEventArgs<T>;
328 return a.Index == o.Index && itemequalityComparer.Equals(a.Item, o.Item);
331 throw new ApplicationException("Illegal Act: " + Act);
334 public override string ToString()
336 return string.Format("Act: {0}, Args : {1}, Source : {2}", Act, Args, Sender);
343 static public int unsequencedhashcode(params int[] a)
348 h += (int)(((uint)i * 1529784657 + 1) ^ ((uint)i * 2912831877) ^ ((uint)i * 1118771817 + 2));
352 static public int sequencedhashcode(params int[] a)
355 foreach (int i in a) { h = h * 31 + i; }
360 //This class is a modified sample from VS2005 beta1 documentation
361 public class RadixFormatProvider : IFormatProvider
363 RadixFormatter _radixformatter;
364 public RadixFormatProvider(int radix)
366 if (radix < 2 || radix > 36)
367 throw new ArgumentException(String.Format(
368 "The radix \"{0}\" is not in the range 2..36.",
370 _radixformatter = new RadixFormatter(radix);
372 public object GetFormat(Type argType)
374 if (argType == typeof(ICustomFormatter))
375 return _radixformatter;
381 //This class is a modified sample from VS2005 beta1 documentation
382 public class RadixFormatter : ICustomFormatter
385 public RadixFormatter(int radix)
387 if (radix < 2 || radix > 36)
388 throw new ArgumentException(String.Format(
389 "The radix \"{0}\" is not in the range 2..36.",
394 // The value to be formatted is returned as a signed string
395 // of digits from the rDigits array.
396 private static char[] rDigits = {
397 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
398 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
399 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
400 'U', 'V', 'W', 'X', 'Y', 'Z' };
402 public string Format(string formatString,
403 object argToBeFormatted, IFormatProvider provider)
405 /*switch (Type.GetTypeCode(argToBeFormatted.GetType()))
407 case TypeCode.Boolean:
413 case TypeCode.DBNull:
415 case TypeCode.DateTime:
417 case TypeCode.Decimal:
419 case TypeCode.Double:
429 case TypeCode.Object:
433 case TypeCode.Single:
435 case TypeCode.String:
437 case TypeCode.UInt16:
439 case TypeCode.UInt32:
441 case TypeCode.UInt64:
444 int intToBeFormatted;
447 intToBeFormatted = (int)argToBeFormatted;
451 if (argToBeFormatted is IFormattable)
452 return ((IFormattable)argToBeFormatted).
453 ToString(formatString, provider);
455 return argToBeFormatted.ToString();
457 return formatInt(intToBeFormatted);
460 private string formatInt(int intToBeFormatted)
462 // The formatting is handled here.
463 if (intToBeFormatted == 0)
467 char[] outDigits = new char[31];
469 // Verify that the argument can be converted to a int integer.
470 // Extract the magnitude for conversion.
471 intPositive = Math.Abs(intToBeFormatted);
473 // Convert the magnitude to a digit string.
474 for (digitIndex = 0; digitIndex <= 32; digitIndex++)
476 if (intPositive == 0) break;
478 outDigits[outDigits.Length - digitIndex - 1] =
479 rDigits[intPositive % radix];
480 intPositive /= radix;
483 // Add a minus sign if the argument is negative.
484 if (intToBeFormatted < 0)
485 outDigits[outDigits.Length - digitIndex++ - 1] =
488 return new string(outDigits,
489 outDigits.Length - digitIndex, digitIndex);