1
|
/*
|
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:
|
9
|
|
10
|
The above copyright notice and this permission notice shall be included in
|
11
|
all copies or substantial portions of the Software.
|
12
|
|
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
|
19
|
SOFTWARE.
|
20
|
*/
|
21
|
|
22
|
using System;
|
23
|
using C5;
|
24
|
using NUnit.Framework;
|
25
|
using SCG = System.Collections.Generic;
|
26
|
|
27
|
|
28
|
namespace C5UnitTests
|
29
|
{
|
30
|
class SC : SCG.IComparer<string>
|
31
|
{
|
32
|
public int Compare(string a, string b)
|
33
|
{
|
34
|
return a.CompareTo(b);
|
35
|
}
|
36
|
|
37
|
|
38
|
public void appl(String s)
|
39
|
{
|
40
|
System.Console.WriteLine("--{0}", s);
|
41
|
}
|
42
|
}
|
43
|
|
44
|
class TenEqualityComparer : SCG.IEqualityComparer<int>, SCG.IComparer<int>
|
45
|
{
|
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); }
|
51
|
}
|
52
|
|
53
|
class IC : SCG.IComparer<int>, IComparable<int>, SCG.IComparer<IC>, IComparable<IC>
|
54
|
{
|
55
|
public int Compare(int a, int b)
|
56
|
{
|
57
|
return a > b ? 1 : a < b ? -1 : 0;
|
58
|
}
|
59
|
|
60
|
|
61
|
public int Compare(IC a, IC b)
|
62
|
{
|
63
|
return a._i > b._i ? 1 : a._i < b._i ? -1 : 0;
|
64
|
}
|
65
|
|
66
|
|
67
|
private int _i;
|
68
|
|
69
|
|
70
|
public int i
|
71
|
{
|
72
|
get { return _i; }
|
73
|
set { _i = value; }
|
74
|
}
|
75
|
|
76
|
|
77
|
public IC() { }
|
78
|
|
79
|
|
80
|
public IC(int i) { _i = i; }
|
81
|
|
82
|
|
83
|
public int CompareTo(int that) { return _i > that ? 1 : _i < that ? -1 : 0; }
|
84
|
|
85
|
public bool Equals(int that) { return _i == that; }
|
86
|
|
87
|
|
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; }
|
90
|
|
91
|
|
92
|
public static bool eq(SCG.IEnumerable<int> me, params int[] that)
|
93
|
{
|
94
|
int i = 0, maxind = that.Length - 1;
|
95
|
|
96
|
foreach (int item in me)
|
97
|
if (i > maxind || item != that[i++])
|
98
|
return false;
|
99
|
|
100
|
return i == maxind + 1;
|
101
|
}
|
102
|
public static bool seteq(ICollectionValue<int> me, params int[] that)
|
103
|
{
|
104
|
int[] me2 = me.ToArray();
|
105
|
|
106
|
Array.Sort(me2);
|
107
|
|
108
|
int i = 0, maxind = that.Length - 1;
|
109
|
|
110
|
foreach (int item in me2)
|
111
|
if (i > maxind || item != that[i++])
|
112
|
return false;
|
113
|
|
114
|
return i == maxind + 1;
|
115
|
}
|
116
|
public static bool seteq(ICollectionValue<KeyValuePair<int, int>> me, params int[] that)
|
117
|
{
|
118
|
ArrayList<KeyValuePair<int, int>> first = new ArrayList<KeyValuePair<int, int>>();
|
119
|
first.AddAll(me);
|
120
|
ArrayList<KeyValuePair<int, int>> other = new ArrayList<KeyValuePair<int, int>>();
|
121
|
for (int i = 0; i < that.Length; i += 2)
|
122
|
{
|
123
|
other.Add(new KeyValuePair<int, int>(that[i], that[i + 1]));
|
124
|
}
|
125
|
return other.UnsequencedEquals(first);
|
126
|
}
|
127
|
}
|
128
|
|
129
|
class RevIC : SCG.IComparer<int>
|
130
|
{
|
131
|
public int Compare(int a, int b)
|
132
|
{
|
133
|
return a > b ? -1 : a < b ? 1 : 0;
|
134
|
}
|
135
|
}
|
136
|
|
137
|
public class FunEnumerable : SCG.IEnumerable<int>
|
138
|
{
|
139
|
int size;
|
140
|
Fun<int, int> f;
|
141
|
|
142
|
public FunEnumerable(int size, Fun<int, int> f)
|
143
|
{
|
144
|
this.size = size; this.f = f;
|
145
|
}
|
146
|
|
147
|
public SCG.IEnumerator<int> GetEnumerator()
|
148
|
{
|
149
|
for (int i = 0; i < size; i++)
|
150
|
yield return f(i);
|
151
|
}
|
152
|
|
153
|
|
154
|
#region IEnumerable Members
|
155
|
|
156
|
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
|
157
|
{
|
158
|
throw new Exception("The method or operation is not implemented.");
|
159
|
}
|
160
|
|
161
|
#endregion
|
162
|
}
|
163
|
|
164
|
public class BadEnumerableException : Exception { }
|
165
|
|
166
|
public class BadEnumerable<T> : CollectionValueBase<T>, ICollectionValue<T>
|
167
|
{
|
168
|
T[] contents;
|
169
|
Exception exception;
|
170
|
|
171
|
public BadEnumerable(Exception exception, params T[] contents)
|
172
|
{
|
173
|
this.contents = (T[])contents.Clone();
|
174
|
this.exception = exception;
|
175
|
}
|
176
|
|
177
|
public override SCG.IEnumerator<T> GetEnumerator()
|
178
|
{
|
179
|
for (int i = 0; i < contents.Length; i++)
|
180
|
yield return contents[i];
|
181
|
throw exception;
|
182
|
}
|
183
|
|
184
|
public override bool IsEmpty { get { return false; } }
|
185
|
|
186
|
public override int Count { get { return contents.Length + 1; } }
|
187
|
|
188
|
public override Speed CountSpeed { get { return Speed.Constant; } }
|
189
|
|
190
|
public override T Choose() { throw exception; }
|
191
|
}
|
192
|
|
193
|
public class CollectionEventList<T>
|
194
|
{
|
195
|
ArrayList<CollectionEvent<T>> happened;
|
196
|
EventTypeEnum listenTo;
|
197
|
SCG.IEqualityComparer<T> itemequalityComparer;
|
198
|
public CollectionEventList(SCG.IEqualityComparer<T> itemequalityComparer)
|
199
|
{
|
200
|
happened = new ArrayList<CollectionEvent<T>>();
|
201
|
this.itemequalityComparer = itemequalityComparer;
|
202
|
}
|
203
|
public void Listen(ICollectionValue<T> list, EventTypeEnum listenTo)
|
204
|
{
|
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);
|
218
|
}
|
219
|
public void Add(CollectionEvent<T> e) { happened.Add(e); }
|
220
|
/// <summary>
|
221
|
/// Check that we have seen exactly the events in expected that match listenTo.
|
222
|
/// </summary>
|
223
|
/// <param name="expected"></param>
|
224
|
public void Check(SCG.IEnumerable<CollectionEvent<T>> expected)
|
225
|
{
|
226
|
int i = 0;
|
227
|
foreach (CollectionEvent<T> expectedEvent in expected)
|
228
|
{
|
229
|
if ((expectedEvent.Act & listenTo) == 0)
|
230
|
continue;
|
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]));
|
235
|
i++;
|
236
|
}
|
237
|
if (i < happened.Count)
|
238
|
Assert.Fail(string.Format("Event number {0} seen but no event expected:\n {1}", i, happened[i]));
|
239
|
happened.Clear();
|
240
|
}
|
241
|
public void Clear() { happened.Clear(); }
|
242
|
public void Print(System.IO.TextWriter writer)
|
243
|
{
|
244
|
happened.Apply(delegate(CollectionEvent<T> e) { writer.WriteLine(e); });
|
245
|
}
|
246
|
void changed(object sender)
|
247
|
{
|
248
|
happened.Add(new CollectionEvent<T>(EventTypeEnum.Changed, new EventArgs(), sender));
|
249
|
}
|
250
|
void cleared(object sender, ClearedEventArgs eventArgs)
|
251
|
{
|
252
|
happened.Add(new CollectionEvent<T>(EventTypeEnum.Cleared, eventArgs, sender));
|
253
|
}
|
254
|
void added(object sender, ItemCountEventArgs<T> eventArgs)
|
255
|
{
|
256
|
happened.Add(new CollectionEvent<T>(EventTypeEnum.Added, eventArgs, sender));
|
257
|
}
|
258
|
void removed(object sender, ItemCountEventArgs<T> eventArgs)
|
259
|
{
|
260
|
happened.Add(new CollectionEvent<T>(EventTypeEnum.Removed, eventArgs, sender));
|
261
|
}
|
262
|
void inserted(object sender, ItemAtEventArgs<T> eventArgs)
|
263
|
{
|
264
|
happened.Add(new CollectionEvent<T>(EventTypeEnum.Inserted, eventArgs, sender));
|
265
|
}
|
266
|
void removedAt(object sender, ItemAtEventArgs<T> eventArgs)
|
267
|
{
|
268
|
happened.Add(new CollectionEvent<T>(EventTypeEnum.RemovedAt, eventArgs, sender));
|
269
|
}
|
270
|
}
|
271
|
|
272
|
public sealed class CollectionEvent<T>
|
273
|
{
|
274
|
public readonly EventTypeEnum Act;
|
275
|
public readonly EventArgs Args;
|
276
|
public readonly object Sender;
|
277
|
|
278
|
public CollectionEvent(EventTypeEnum act, EventArgs args, object sender)
|
279
|
{
|
280
|
this.Act = act;
|
281
|
this.Args = args;
|
282
|
this.Sender = sender;
|
283
|
}
|
284
|
|
285
|
public bool Equals(CollectionEvent<T> otherEvent, SCG.IEqualityComparer<T> itemequalityComparer)
|
286
|
{
|
287
|
if (otherEvent == null || Act != otherEvent.Act || !object.ReferenceEquals(Sender, otherEvent.Sender))
|
288
|
return false;
|
289
|
switch (Act)
|
290
|
{
|
291
|
case EventTypeEnum.None:
|
292
|
break;
|
293
|
case EventTypeEnum.Changed:
|
294
|
return true;
|
295
|
case EventTypeEnum.Cleared:
|
296
|
if (Args is ClearedRangeEventArgs)
|
297
|
{
|
298
|
ClearedRangeEventArgs a = Args as ClearedRangeEventArgs, o = otherEvent.Args as ClearedRangeEventArgs;
|
299
|
if (o == null)
|
300
|
return false;
|
301
|
return a.Full == o.Full && a.Start == o.Start && a.Count == o.Count;
|
302
|
}
|
303
|
else
|
304
|
{
|
305
|
if (otherEvent.Args is ClearedRangeEventArgs)
|
306
|
return false;
|
307
|
ClearedEventArgs a = Args as ClearedEventArgs, o = otherEvent.Args as ClearedEventArgs;
|
308
|
return a.Full == o.Full && a.Count == o.Count;
|
309
|
}
|
310
|
case EventTypeEnum.Added:
|
311
|
{
|
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;
|
314
|
}
|
315
|
case EventTypeEnum.Removed:
|
316
|
{
|
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;
|
319
|
}
|
320
|
case EventTypeEnum.Inserted:
|
321
|
{
|
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);
|
324
|
}
|
325
|
case EventTypeEnum.RemovedAt:
|
326
|
{
|
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);
|
329
|
}
|
330
|
}
|
331
|
throw new ApplicationException("Illegat Act: " + Act);
|
332
|
}
|
333
|
|
334
|
public override string ToString()
|
335
|
{
|
336
|
return string.Format("Act: {0}, Args : {1}, Source : {2}", Act, Args, Sender);
|
337
|
}
|
338
|
|
339
|
}
|
340
|
|
341
|
public class CHC
|
342
|
{
|
343
|
static public int unsequencedhashcode(params int[] a)
|
344
|
{
|
345
|
int h = 0;
|
346
|
foreach (int i in a)
|
347
|
{
|
348
|
h += (int)(((uint)i * 1529784657 + 1) ^ ((uint)i * 2912831877) ^ ((uint)i * 1118771817 + 2));
|
349
|
}
|
350
|
return h;
|
351
|
}
|
352
|
static public int sequencedhashcode(params int[] a)
|
353
|
{
|
354
|
int h = 0;
|
355
|
foreach (int i in a) { h = h * 31 + i; }
|
356
|
return h;
|
357
|
}
|
358
|
}
|
359
|
|
360
|
//This class is a modified sample from VS2005 beta1 documentation
|
361
|
public class RadixFormatProvider : IFormatProvider
|
362
|
{
|
363
|
RadixFormatter _radixformatter;
|
364
|
public RadixFormatProvider(int radix)
|
365
|
{
|
366
|
if (radix < 2 || radix > 36)
|
367
|
throw new ArgumentException(String.Format(
|
368
|
"The radix \"{0}\" is not in the range 2..36.",
|
369
|
radix));
|
370
|
_radixformatter = new RadixFormatter(radix);
|
371
|
}
|
372
|
public object GetFormat(Type argType)
|
373
|
{
|
374
|
if (argType == typeof(ICustomFormatter))
|
375
|
return _radixformatter;
|
376
|
else
|
377
|
return null;
|
378
|
}
|
379
|
}
|
380
|
|
381
|
//This class is a modified sample from VS2005 beta1 documentation
|
382
|
public class RadixFormatter : ICustomFormatter
|
383
|
{
|
384
|
int radix;
|
385
|
public RadixFormatter(int radix)
|
386
|
{
|
387
|
if (radix < 2 || radix > 36)
|
388
|
throw new ArgumentException(String.Format(
|
389
|
"The radix \"{0}\" is not in the range 2..36.",
|
390
|
radix));
|
391
|
this.radix = radix;
|
392
|
}
|
393
|
|
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' };
|
401
|
|
402
|
public string Format(string formatString,
|
403
|
object argToBeFormatted, IFormatProvider provider)
|
404
|
{
|
405
|
/*switch (Type.GetTypeCode(argToBeFormatted.GetType()))
|
406
|
{
|
407
|
case TypeCode.Boolean:
|
408
|
break;
|
409
|
case TypeCode.Byte:
|
410
|
break;
|
411
|
case TypeCode.Char:
|
412
|
break;
|
413
|
case TypeCode.DBNull:
|
414
|
break;
|
415
|
case TypeCode.DateTime:
|
416
|
break;
|
417
|
case TypeCode.Decimal:
|
418
|
break;
|
419
|
case TypeCode.Double:
|
420
|
break;
|
421
|
case TypeCode.Empty:
|
422
|
break;
|
423
|
case TypeCode.Int16:
|
424
|
break;
|
425
|
case TypeCode.Int32:
|
426
|
break;
|
427
|
case TypeCode.Int64:
|
428
|
break;
|
429
|
case TypeCode.Object:
|
430
|
break;
|
431
|
case TypeCode.SByte:
|
432
|
break;
|
433
|
case TypeCode.Single:
|
434
|
break;
|
435
|
case TypeCode.String:
|
436
|
break;
|
437
|
case TypeCode.UInt16:
|
438
|
break;
|
439
|
case TypeCode.UInt32:
|
440
|
break;
|
441
|
case TypeCode.UInt64:
|
442
|
break;
|
443
|
}*/
|
444
|
int intToBeFormatted;
|
445
|
try
|
446
|
{
|
447
|
intToBeFormatted = (int)argToBeFormatted;
|
448
|
}
|
449
|
catch (Exception)
|
450
|
{
|
451
|
if (argToBeFormatted is IFormattable)
|
452
|
return ((IFormattable)argToBeFormatted).
|
453
|
ToString(formatString, provider);
|
454
|
else
|
455
|
return argToBeFormatted.ToString();
|
456
|
}
|
457
|
return formatInt(intToBeFormatted);
|
458
|
}
|
459
|
|
460
|
private string formatInt(int intToBeFormatted)
|
461
|
{
|
462
|
// The formatting is handled here.
|
463
|
if (intToBeFormatted == 0)
|
464
|
return "0";
|
465
|
int digitIndex = 0;
|
466
|
int intPositive;
|
467
|
char[] outDigits = new char[31];
|
468
|
|
469
|
// Verify that the argument can be converted to a int integer.
|
470
|
// Extract the magnitude for conversion.
|
471
|
intPositive = Math.Abs(intToBeFormatted);
|
472
|
|
473
|
// Convert the magnitude to a digit string.
|
474
|
for (digitIndex = 0; digitIndex <= 32; digitIndex++)
|
475
|
{
|
476
|
if (intPositive == 0) break;
|
477
|
|
478
|
outDigits[outDigits.Length - digitIndex - 1] =
|
479
|
rDigits[intPositive % radix];
|
480
|
intPositive /= radix;
|
481
|
}
|
482
|
|
483
|
// Add a minus sign if the argument is negative.
|
484
|
if (intToBeFormatted < 0)
|
485
|
outDigits[outDigits.Length - digitIndex++ - 1] =
|
486
|
'-';
|
487
|
|
488
|
return new string(outDigits,
|
489
|
outDigits.Length - digitIndex, digitIndex);
|
490
|
}
|
491
|
}
|
492
|
|
493
|
}
|