[asp.net] Optimize memory usage a bit. String hashes are cached in thread-local storage.
[mono.git] / mcs / tests / dtest-003.cs
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Reflection;
5 using System.Dynamic;
6 using System.Linq.Expressions;
7 using Microsoft.CSharp.RuntimeBinder;
8 using System.Runtime.CompilerServices;
9
10 enum Enum
11 {
12         A = 3
13 }
14
15 class AssertDynamicObject : DynamicMetaObject
16 {
17         DynamicObjectMock mock;
18
19         public AssertDynamicObject (DynamicObjectMock mock, Expression parameter)
20                 : base (parameter, BindingRestrictions.Empty, mock)
21         {
22                 this.mock = mock;
23         }
24
25         DynamicMetaObject GetFakeMetaObject (object value)
26         {
27                 Type t = value == null ? typeof (object) : value.GetType ();
28                 Expression<Func<object>> et = () => value;
29
30                 Expression restr = Expression.Constant (true);
31                 return new DynamicMetaObject (Expression.Convert (et.Body, t), BindingRestrictions.GetExpressionRestriction (restr));
32         }
33
34         public override DynamicMetaObject BindBinaryOperation (BinaryOperationBinder binder, DynamicMetaObject arg)
35         {
36                 if (mock.BinaryOperation == null)
37                         throw new ApplicationException ("Unexpected BindBinaryOperation");
38
39                 mock.BinaryOperation (binder, arg.Value);
40
41                 return GetFakeMetaObject (new object ());
42         }
43
44         public override DynamicMetaObject BindConvert (ConvertBinder binder)
45         {
46                 if (mock.ConvertOperation == null)
47                         throw new ApplicationException ("Unexpected BindConvert");
48
49                 var r = mock.ConvertOperation (binder);
50
51                 return GetFakeMetaObject (r);
52         }
53
54         public override DynamicMetaObject BindGetIndex (GetIndexBinder binder, DynamicMetaObject[] indexes)
55         {
56                 if (mock.GetIndexOperation == null)
57                         throw new ApplicationException ("Unexpected TryGetIndex");
58
59                 mock.GetIndexOperation (binder, indexes.Select (l => l.Value).ToArray ());
60
61                 return GetFakeMetaObject (new object ());
62         }
63
64         public override DynamicMetaObject BindGetMember (GetMemberBinder binder)
65         {
66                 if (mock.GetMemberOperation == null)
67                         throw new ApplicationException ("Unexpected BindGetMember");
68
69                 var r = mock.GetMemberOperation (binder);
70
71                 return GetFakeMetaObject (r);
72         }
73
74         public override DynamicMetaObject BindInvoke (InvokeBinder binder, DynamicMetaObject[] args)
75         {
76                 if (mock.InvokeOperation == null)
77                         throw new ApplicationException ("Unexpected BindInvoke");
78
79                 mock.InvokeOperation (binder, args.Select (l => l.Value).ToArray ());
80
81                 return GetFakeMetaObject (new object ());
82         }
83
84         public override DynamicMetaObject BindInvokeMember (InvokeMemberBinder binder, DynamicMetaObject[] args)
85         {
86                 if (mock.InvokeMemberOperation == null)
87                         throw new ApplicationException ("Unexpected BindInvokeMember");
88
89                 mock.InvokeMemberOperation (binder, args.Select (l => l.Value).ToArray ());
90
91                 return GetFakeMetaObject (new object ());
92         }
93
94         public override DynamicMetaObject BindSetIndex (SetIndexBinder binder, DynamicMetaObject[] indexes, DynamicMetaObject value)
95         {
96                 if (mock.SetIndexOperation == null)
97                         throw new ApplicationException ("Unexpected TrySetIndex");
98
99                 mock.SetIndexOperation (binder, indexes.Select (l => l.Value).ToArray (), value.Value);
100
101                 return GetFakeMetaObject (new object ());
102         }
103
104         public override DynamicMetaObject BindSetMember (SetMemberBinder binder, DynamicMetaObject value)
105         {
106                 if (mock.SetMemberOperation == null)
107                         throw new ApplicationException ("Unexpected BindSetMember");
108
109                 mock.SetMemberOperation (binder, value.Value);
110
111                 return GetFakeMetaObject (new object ());
112         }
113
114         public override DynamicMetaObject BindUnaryOperation (UnaryOperationBinder binder)
115         {
116                 if (mock.UnaryOperation == null)
117                         throw new ApplicationException ("Unexpected BindUnaryOperation");
118
119                 var r = mock.UnaryOperation (binder);
120
121                 return GetFakeMetaObject (r);
122         }
123
124 }
125
126 class DynamicObjectMock : DynamicObject
127 {
128         public int HitCounter;
129
130         public DynamicObjectMock ()
131         {
132         }
133
134         public override DynamicMetaObject GetMetaObject (System.Linq.Expressions.Expression parameter)
135         {
136                 HitCounter++;
137                 return new AssertDynamicObject (this, parameter);
138         }
139
140         public Action<BinaryOperationBinder, object> BinaryOperation;
141         public Func<ConvertBinder, object> ConvertOperation;
142         public Action<GetIndexBinder, object[]> GetIndexOperation;
143         public Func<GetMemberBinder, object> GetMemberOperation;
144         public Action<InvokeBinder, object[]> InvokeOperation;
145         public Action<InvokeMemberBinder, object[]> InvokeMemberOperation;
146         public Action<SetIndexBinder, object[], object> SetIndexOperation;
147         public Action<SetMemberBinder, object> SetMemberOperation;
148         public Func<UnaryOperationBinder, object> UnaryOperation;
149
150         // Dynamic arguments methods
151         public DynamicObjectMock (int i)
152         {
153         }
154
155         public void DMethod (int a)
156         {
157         }
158
159         public static void DStaticMethod (object t)
160         {
161         }
162
163         public int this[int i] {
164                 get {
165                         return i;
166                 }
167                 set { }
168         }
169
170 }
171
172 class Tester : DynamicObjectMock
173 {
174         static readonly int field = 7;
175
176         public Tester ()
177         {
178         }
179
180         public Tester (dynamic d)
181         {
182         }
183
184         static void Assert<T> (T expected, T value, string name)
185         {
186                 if (!EqualityComparer<T>.Default.Equals (expected, value)) {
187                         if (!string.IsNullOrEmpty (name))
188                                 name += ": ";
189                         throw new ApplicationException (name + "Expected " + expected + " != " + value);
190                 }
191         }
192
193         static void Assert<T> (IList<T> expected, IList<T> value, string name)
194         {
195                 if (expected == null) {
196                         if (value != null)
197                                 throw new ApplicationException (name + ": Both arrays expected to be null");
198                         return;
199                 }
200
201                 if (expected.Count != value.Count)
202                         throw new ApplicationException (name + ": Array length does not match " + expected.Count + " != " + value.Count);
203
204                 for (int i = 0; i < expected.Count; ++i) {
205                         if (!EqualityComparer<T>.Default.Equals (expected[i], value[i]))
206                                 throw new ApplicationException (name + ": Index " + i + ": " + expected[i] + " != " + value[i]);
207                 }
208         }
209
210         static FieldInfo flags = typeof (CSharpArgumentInfo).GetField ("flags", BindingFlags.NonPublic | BindingFlags.Instance);
211
212         static void AssertArgument (CallSiteBinder obj, CSharpArgumentInfo[] expected, string name)
213         {
214                 var ai = obj.GetType ().GetField ("argumentInfo", BindingFlags.NonPublic | BindingFlags.Instance);
215                 IList<CSharpArgumentInfo> values = (IList<CSharpArgumentInfo>) ai.GetValue (obj);
216                 if (values.Count != expected.Length)
217                         throw new ApplicationException (name + ": Array length does not match " + values.Count + " != " + expected.Length);
218
219                 for (int i = 0; i < expected.Length; i++) {
220                         Assert (flags.GetValue (expected[i]), flags.GetValue (values[i]), "flags");
221                 }
222         }
223
224 #pragma warning disable 168, 169, 219
225
226         void BinaryAdd_1 (dynamic d, DynamicObjectMock mock)
227         {
228                 mock.BinaryOperation = (binder, arg) => {
229                         Assert (binder.Operation, ExpressionType.Add, "Operation");
230                         AssertArgument (binder, new[] {
231                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
232                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
233                                 "ArgumentInfo");
234
235                         Assert (arg, 1, "arg");
236                 };
237
238                 d = d + 1;
239         }
240
241         void BinaryAdd_2 (dynamic d, DynamicObjectMock mock)
242         {
243                 mock.BinaryOperation = (binder, arg) => {
244                         Assert (binder.Operation, ExpressionType.Add, "Operation");
245                         AssertArgument (binder, new[] {
246                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
247                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.UseCompileTimeType, null) },
248                                 "ArgumentInfo");
249
250                         Assert (arg, null, "arg");
251                 };
252
253                 int? v = null;
254                 d = d + v;
255         }
256
257         void BinaryAdd_3 (dynamic d, DynamicObjectMock mock)
258         {
259                 mock.BinaryOperation = (binder, arg) => {
260                         Assert (binder.Operation, ExpressionType.Add, "Operation");
261                         AssertArgument (binder, new[] {
262                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
263                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.UseCompileTimeType | CSharpArgumentInfoFlags.Constant, null)
264                         }, "ArgumentInfo");
265
266                         Assert (arg, Enum.A, "arg");
267                 };
268
269                 d = d + Enum.A;
270         }
271
272         void BinaryAdd_4 (dynamic d, DynamicObjectMock mock)
273         {
274                 mock.BinaryOperation = (binder, arg) => {
275                         Assert (binder.Operation, ExpressionType.Add, "Operation");
276                         AssertArgument (binder, new[] {
277                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
278                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.UseCompileTimeType, null) },
279                                 "ArgumentInfo");
280
281                         Assert (arg, 7, "arg");
282                 };
283
284                 d = d + Tester.field;
285         }
286
287         void BinaryAddChecked_1 (dynamic d, DynamicObjectMock mock)
288         {
289                 mock.BinaryOperation = (binder, arg) => {
290                         Assert (binder.Operation, ExpressionType.Add, "Operation");
291                         AssertArgument (binder, new[] {
292                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
293                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.UseCompileTimeType | CSharpArgumentInfoFlags.Constant, null) },
294                                 "ArgumentInfo");
295
296                         Assert (arg, 3, "arg");
297                 };
298
299                 d = checked (d + 3);
300         }
301
302         void BinaryAddChecked_2 (dynamic d, DynamicObjectMock mock)
303         {
304                 mock.BinaryOperation = (binder, arg) => {
305                         Assert (binder.Operation, ExpressionType.Add, "Operation");
306                         AssertArgument (binder, new[] {
307                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
308                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.UseCompileTimeType | CSharpArgumentInfoFlags.Constant, null) },
309                                 "ArgumentInfo");
310
311                         Assert (arg, 3, "arg");
312                 };
313
314                 Func<dynamic> r;
315                 checked {
316                         r = () => d + 3;
317                 }
318
319                 r ();
320         }
321
322         void BinaryAddAssign_1 (dynamic d, DynamicObjectMock mock)
323         {
324                 mock.BinaryOperation = (binder, arg) => {
325                         Assert (binder.Operation, ExpressionType.AddAssign, "Operation");
326                         AssertArgument (binder, new[] {
327                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
328                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
329                                 "ArgumentInfo");
330
331                         Assert (arg, 1, "arg");
332                 };
333
334                 d += 1;
335         }
336
337         void BinaryAddAssignChecked_1 (dynamic d, DynamicObjectMock mock)
338         {
339                 mock.BinaryOperation = (binder, arg) => {
340                         Assert (binder.Operation, ExpressionType.AddAssign, "Operation");
341                         AssertArgument (binder, new[] {
342                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
343                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
344                                 "ArgumentInfo");
345
346                         Assert (arg, 1, "arg");
347                 };
348
349                 checked {
350                         d += 1;
351                 }
352         }
353
354         void BinaryAnd_1 (dynamic d, DynamicObjectMock mock)
355         {
356                 mock.BinaryOperation = (binder, arg) => {
357                         Assert (binder.Operation, ExpressionType.And, "Operation");
358                         AssertArgument (binder, new[] {
359                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
360                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
361                                 "ArgumentInfo");
362
363                         Assert (arg, 1, "arg");
364                 };
365
366                 d = d & 1;
367         }
368
369         void BinaryAndAssign_1 (dynamic d, DynamicObjectMock mock)
370         {
371                 mock.BinaryOperation = (binder, arg) => {
372                         Assert (binder.Operation, ExpressionType.AndAssign, "Operation");
373                         AssertArgument (binder, new[] {
374                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
375                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
376                                 "ArgumentInfo");
377
378                         Assert (arg, 1, "arg");
379                 };
380
381                 d &= 1;
382         }
383
384         void BinaryDivide_1 (dynamic d, DynamicObjectMock mock)
385         {
386                 mock.BinaryOperation = (binder, arg) => {
387                         Assert (binder.Operation, ExpressionType.Divide, "Operation");
388                         AssertArgument (binder, new[] {
389                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
390                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
391                                 "ArgumentInfo");
392
393                         Assert (arg, 1, "arg");
394                 };
395
396                 d = d / 1;
397         }
398
399         void BinaryDivideAssign_1 (dynamic d, DynamicObjectMock mock)
400         {
401                 mock.BinaryOperation = (binder, arg) => {
402                         Assert (binder.Operation, ExpressionType.DivideAssign, "Operation");
403                         AssertArgument (binder, new[] {
404                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
405                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
406                                 "ArgumentInfo");
407
408                         Assert (arg, 1, "arg");
409                 };
410
411                 d /= 1;
412         }
413
414         void BinaryEqual_1 (dynamic d, DynamicObjectMock mock)
415         {
416                 mock.BinaryOperation = (binder, arg) => {
417                         Assert (binder.Operation, ExpressionType.Equal, "Operation");
418                         AssertArgument (binder, new[] {
419                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
420                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
421                                 "ArgumentInfo");
422
423                         Assert (arg, 1, "arg");
424                 };
425
426                 d = d == 1;
427         }
428
429         void BinaryExclusiveOr_1 (dynamic d, DynamicObjectMock mock)
430         {
431                 mock.BinaryOperation = (binder, arg) => {
432                         Assert (binder.Operation, ExpressionType.ExclusiveOr, "Operation");
433                         AssertArgument (binder, new[] {
434                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
435                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
436                                 "ArgumentInfo");
437
438                         Assert (arg, 1, "arg");
439                 };
440
441                 d = d ^ 1;
442         }
443
444         void BinaryExclusiveOrAssign_1 (dynamic d, DynamicObjectMock mock)
445         {
446                 mock.BinaryOperation = (binder, arg) => {
447                         Assert (binder.Operation, ExpressionType.ExclusiveOrAssign, "Operation");
448                         AssertArgument (binder, new[] {
449                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
450                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
451                                 "ArgumentInfo");
452
453                         Assert (arg, 1, "arg");
454                 };
455
456                 d ^= 1;
457         }
458
459         void BinaryGreaterThan_1 (dynamic d, DynamicObjectMock mock)
460         {
461                 mock.BinaryOperation = (binder, arg) => {
462                         Assert (binder.Operation, ExpressionType.GreaterThan, "Operation");
463                         AssertArgument (binder, new[] {
464                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
465                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
466                                 "ArgumentInfo");
467
468                         Assert (arg, 1, "arg");
469                 };
470
471                 d = d > 1;
472         }
473
474         void BinaryGreaterThanOrEqual_1 (dynamic d, DynamicObjectMock mock)
475         {
476                 mock.BinaryOperation = (binder, arg) => {
477                         Assert (binder.Operation, ExpressionType.GreaterThanOrEqual, "Operation");
478                         AssertArgument (binder, new[] {
479                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
480                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
481                                 "ArgumentInfo");
482
483                         Assert (arg, 1, "arg");
484                 };
485
486                 d = d >= 1;
487         }
488
489         void BinaryLeftShift_1 (dynamic d, DynamicObjectMock mock)
490         {
491                 mock.BinaryOperation = (binder, arg) => {
492                         Assert (binder.Operation, ExpressionType.LeftShift, "Operation");
493                         AssertArgument (binder, new[] {
494                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
495                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
496                                 "ArgumentInfo");
497
498                         Assert (arg, 1, "arg");
499                 };
500
501                 d = d << 1;
502         }
503
504         void BinaryLeftShiftAssign_1 (dynamic d, DynamicObjectMock mock)
505         {
506                 mock.BinaryOperation = (binder, arg) => {
507                         Assert (binder.Operation, ExpressionType.LeftShiftAssign, "Operation");
508                         AssertArgument (binder, new[] {
509                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
510                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
511                                 "ArgumentInfo");
512
513                         Assert (arg, 1, "arg");
514                 };
515
516                 d <<= 1;
517         }
518
519         void BinaryLessThan_1 (dynamic d, DynamicObjectMock mock)
520         {
521                 mock.BinaryOperation = (binder, arg) => {
522                         Assert (binder.Operation, ExpressionType.LessThan, "Operation");
523                         AssertArgument (binder, new[] {
524                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
525                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
526                                 "ArgumentInfo");
527
528                         Assert (arg, 1, "arg");
529                 };
530
531                 d = d < 1;
532         }
533
534         void BinaryLessThanOrEqual_1 (dynamic d, DynamicObjectMock mock)
535         {
536                 mock.BinaryOperation = (binder, arg) => {
537                         Assert (binder.Operation, ExpressionType.LessThanOrEqual, "Operation");
538                         AssertArgument (binder, new[] {
539                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
540                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
541                                 "ArgumentInfo");
542
543                         Assert (arg, 1, "arg");
544                 };
545
546                 d = d <= 1;
547         }
548
549         void BinaryModulo_1 (dynamic d, DynamicObjectMock mock)
550         {
551                 mock.BinaryOperation = (binder, arg) => {
552                         Assert (binder.Operation, ExpressionType.Modulo, "Operation");
553                         AssertArgument (binder, new[] {
554                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
555                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
556                                 "ArgumentInfo");
557
558                         Assert (arg, 1, "arg");
559                 };
560
561                 d = d % 1;
562         }
563
564         void BinaryModuloAssign_1 (dynamic d, DynamicObjectMock mock)
565         {
566                 mock.BinaryOperation = (binder, arg) => {
567                         Assert (binder.Operation, ExpressionType.ModuloAssign, "Operation");
568                         AssertArgument (binder, new[] {
569                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
570                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
571                                 "ArgumentInfo");
572
573                         Assert (arg, 1, "arg");
574                 };
575
576                 d %= 1;
577         }
578
579         void BinaryMultiply_1 (dynamic d, DynamicObjectMock mock)
580         {
581                 mock.BinaryOperation = (binder, arg) => {
582                         Assert (binder.Operation, ExpressionType.Multiply, "Operation");
583                         AssertArgument (binder, new[] {
584                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
585                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
586                                 "ArgumentInfo");
587
588                         Assert (arg, 1, "arg");
589                 };
590
591                 d = d * 1;
592         }
593
594         void BinaryMultiplyAssign_1 (dynamic d, DynamicObjectMock mock)
595         {
596                 mock.BinaryOperation = (binder, arg) => {
597                         Assert (binder.Operation, ExpressionType.MultiplyAssign, "Operation");
598                         AssertArgument (binder, new[] {
599                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
600                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
601                                 "ArgumentInfo");
602
603                         Assert (arg, 1, "arg");
604                 };
605
606                 d *= 1;
607         }
608
609         void BinaryNotEqual_1 (dynamic d, DynamicObjectMock mock)
610         {
611                 mock.BinaryOperation = (binder, arg) => {
612                         Assert (binder.Operation, ExpressionType.NotEqual, "Operation");
613                         AssertArgument (binder, new[] {
614                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
615                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
616                                 "ArgumentInfo");
617
618                         Assert (arg, 4, "arg");
619                 };
620
621                 d = d != 4;
622         }
623
624         void BinaryOr_1 (dynamic d, DynamicObjectMock mock)
625         {
626                 mock.BinaryOperation = (binder, arg) => {
627                         Assert (binder.Operation, ExpressionType.Or, "Operation");
628                         AssertArgument (binder, new[] {
629                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
630                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
631                                 "ArgumentInfo");
632
633                         Assert (arg, 2, "arg");
634                 };
635
636                 d = d | 2;
637         }
638
639         void BinaryOrAssign_1 (dynamic d, DynamicObjectMock mock)
640         {
641                 mock.BinaryOperation = (binder, arg) => {
642                         Assert (binder.Operation, ExpressionType.OrAssign, "Operation");
643                         AssertArgument (binder, new[] {
644                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
645                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
646                                 "ArgumentInfo");
647
648                         Assert (arg, 2, "arg");
649                 };
650
651                 d |= 2;
652         }
653
654         void BinaryRightShift_1 (dynamic d, DynamicObjectMock mock)
655         {
656                 mock.BinaryOperation = (binder, arg) => {
657                         Assert (binder.Operation, ExpressionType.RightShift, "Operation");
658                         AssertArgument (binder, new[] {
659                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
660                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
661                                 "ArgumentInfo");
662
663                         Assert (arg, 1, "arg");
664                 };
665
666                 d = d >> 1;
667         }
668
669         void BinaryRightShiftAssign_1 (dynamic d, DynamicObjectMock mock)
670         {
671                 mock.BinaryOperation = (binder, arg) => {
672                         Assert (binder.Operation, ExpressionType.RightShiftAssign, "Operation");
673                         AssertArgument (binder, new[] {
674                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
675                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
676                                 "ArgumentInfo");
677
678                         Assert (arg, 1, "arg");
679                 };
680
681                 d >>= 1;
682         }
683
684         void BinarySubtract_1 (dynamic d, DynamicObjectMock mock)
685         {
686                 mock.BinaryOperation = (binder, arg) => {
687                         Assert (binder.Operation, ExpressionType.Subtract, "Operation");
688                         AssertArgument (binder, new[] {
689                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
690                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
691                                 "ArgumentInfo");
692
693                         Assert (arg, 1, "arg");
694                 };
695
696                 d = d - 1;
697         }
698
699         void BinarySubtractAssign_1 (dynamic d, DynamicObjectMock mock)
700         {
701                 mock.BinaryOperation = (binder, arg) => {
702                         Assert (binder.Operation, ExpressionType.SubtractAssign, "Operation");
703                         AssertArgument (binder, new[] {
704                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
705                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
706                                 "ArgumentInfo");
707
708                         Assert (arg, 1, "arg");
709                 };
710
711                 d -= 1;
712         }
713
714         void Convert_1 (dynamic d, DynamicObjectMock mock)
715         {
716                 mock.ConvertOperation = (binder) => {
717                         Assert (binder.Explicit, true, "Explicit");
718                         Assert (binder.Type, typeof (byte), "Type");
719                         return (byte) 1;
720                 };
721
722                 object b = (byte) d;
723         }
724
725         void Convert_2 (dynamic d, DynamicObjectMock mock)
726         {
727                 mock.ConvertOperation = (binder) => {
728                         Assert (binder.Explicit, false, "Explicit");
729                         Assert (binder.Type, typeof (int), "Type");
730                         return 1;
731                 };
732
733                 object[] o = new object[2];
734                 d = o[d];
735         }
736
737         void Convert_3 (dynamic d, DynamicObjectMock mock)
738         {
739                 mock.ConvertOperation = (binder) => {
740                         Assert (binder.Explicit, true, "Explicit");
741 //                      Assert (binder.IsChecked, true, "IsChecked");
742                         Assert (binder.Type, typeof (byte), "Type");
743                         return (byte) 2;
744                 };
745
746                 object b = checked ((byte) d);
747         }
748
749         void Convert_4 (dynamic d, DynamicObjectMock mock)
750         {
751                 mock.ConvertOperation = (binder) => {
752                         Assert (binder.Explicit, false, "Explicit");
753                         Assert (binder.Type, typeof (int), "Type");
754                         return 5;
755                 };
756
757                 var g = new int[d];
758         }
759
760         void Convert_5 (dynamic d, DynamicObjectMock mock)
761         {
762                 int counter = 0;
763                 mock.ConvertOperation = (binder) => {
764                         Assert (binder.Explicit, false, "Explicit");
765                         Assert (binder.Type, typeof (System.Collections.IEnumerable), "Type");
766                         return new object[] { 1 };
767                 };
768
769                 foreach (int v in d) {
770 //                      Console.WriteLine (v);
771                 }
772         }
773
774         void GetIndex_1 (dynamic d, DynamicObjectMock mock)
775         {
776                 mock.GetIndexOperation = (binder, args) => {
777                         Assert (binder.CallInfo, new CallInfo (1, new string[0]), "CallInfo");
778                         AssertArgument (binder, new[] {
779                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
780                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
781                                 "ArgumentInfo");
782
783                         Assert ((IList<object>) args, new object[] { 0 }, "args");
784                 };
785
786                 var o = d[0];
787         }
788
789         void GetIndex_2 (dynamic d, DynamicObjectMock mock)
790         {
791                 mock.GetIndexOperation = (binder, args) => {
792                         Assert (binder.CallInfo, new CallInfo (2, new string[0]), "CallInfo");
793                         AssertArgument (binder, new[] {
794                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
795                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null),
796                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.UseCompileTimeType, null) },
797                         "ArgumentInfo");
798
799                         Assert ((IList<object>) args, new object[] { 2, 3 }, "args");
800                 };
801
802                 object i = 3;
803                 var o = d[2, i];
804         }
805
806         void GetIndex_3 (dynamic d, DynamicObjectMock mock)
807         {
808                 mock.GetIndexOperation = (binder, args) => {
809                         Assert (binder.CallInfo, new CallInfo (1, new string[0]), "CallInfo");
810                         AssertArgument (binder, new[] {
811                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.UseCompileTimeType, null),
812                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null) },
813                                 "ArgumentInfo");
814
815                         Assert ((IList<object>) args, new object[] { d }, "args");
816                 };
817
818                 var o = mock[d];
819         }
820
821         void GetMember_1 (dynamic d, DynamicObjectMock mock)
822         {
823                 mock.GetMemberOperation = (binder) => {
824                         Assert (binder.Name, "Foo", "Name");
825                         Assert (binder.IgnoreCase, false, "IgnoreCase");
826                         AssertArgument (binder, new[] {
827                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null) },
828                                 "ArgumentInfo");
829
830                         return null;
831                 };
832
833                 var g = d.Foo;
834         }
835
836         void Invoke_1 (dynamic d, DynamicObjectMock mock)
837         {
838                 mock.InvokeOperation = (binder, args) => {
839                         Assert (binder.CallInfo, new CallInfo (2, new string[0]), "CallInfo");
840                         AssertArgument (binder, new[] {
841                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
842                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null),
843                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant, null)
844                         }, "ArgumentInfo");
845
846                         Assert ((IList<object>) args, new object[] { "foo", null }, "args");
847                 };
848
849                 d ("foo", null);
850         }
851
852         void Invoke_2 (dynamic d, DynamicObjectMock mock)
853         {
854                 mock.InvokeOperation = (binder, args) => {
855                         Assert (binder.CallInfo, new CallInfo (0, new string[0]), "CallInfo");
856                         AssertArgument (binder, new[] {
857                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null) },
858                                 "ArgumentInfo");
859
860                         Assert ((IList<object>) args, new object[0], "args");
861                 };
862
863                 d ();
864         }
865
866         void Invoke_3 (dynamic d, DynamicObjectMock mock)
867         {
868                 try {
869                         Math.Max (d, d);
870                         Assert (true, false, "No hook expected to be hit");
871                 } catch (RuntimeBinderException) {
872                 }
873         }
874
875         void Invoke_4 (dynamic d, DynamicObjectMock mock)
876         {
877                 mock.InvokeOperation = (binder, args) => {
878                         Assert (binder.CallInfo, new CallInfo (2, new string[] { "name" }), "CallInfo");
879                         AssertArgument (binder, new[] {
880                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
881                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.UseCompileTimeType, null),
882                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.NamedArgument | CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, "name")
883                         }, "ArgumentInfo");
884
885                         Assert ((IList<object>) args, new object[] { typeof (bool), -1 }, "args");
886                 };
887
888                 d (typeof (bool), name: -1);
889         }
890
891         void Invoke_5 (dynamic d, DynamicObjectMock mock)
892         {
893                 mock.InvokeOperation = (binder, args) => {
894                         Assert (binder.CallInfo, new CallInfo (1, new string[0]), "CallInfo");
895                         AssertArgument (binder, new[] {
896                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
897                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.UseCompileTimeType | CSharpArgumentInfoFlags.Constant, null)
898                         }, "ArgumentInfo");
899
900                         Assert ((IList<object>) args, new object[] { "a" }, "args");
901                 };
902
903                 Action<dynamic> a = (i) => { i ("a"); };
904                 a (d);
905         }
906
907         void Invoke_6 (dynamic d, DynamicObjectMock mock)
908         {
909                 mock.InvokeOperation = (binder, args) => {
910                         Assert (binder.CallInfo, new CallInfo (1, new string[0]), "CallInfo");
911                         AssertArgument (binder, new[] {
912                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
913                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.UseCompileTimeType | CSharpArgumentInfoFlags.Constant, null)
914                         }, "ArgumentInfo");
915
916                         Assert ((IList<object>) args, new object[] { 3 }, "args");
917                 };
918
919                 d (1 + 2);
920         }
921
922         void InvokeMember_1 (dynamic d, DynamicObjectMock mock)
923         {
924                 mock.InvokeMemberOperation = (binder, args) => {
925                         Assert (binder.CallInfo, new CallInfo (1, new string[0]), "CallInfo");
926                         AssertArgument (binder, new[] {
927                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
928                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null)},
929                                 "ArgumentInfo");
930
931                         Assert (binder.IgnoreCase, false, "IgnoreCase");
932                         Assert ((IList<object>) args, new object[] { 'a' }, "args");
933                 };
934
935                 d.Max ('a');
936         }
937
938         void InvokeMember_2 (dynamic d, DynamicObjectMock mock)
939         {
940                 mock.InvokeMemberOperation = (binder, args) => {
941                         Assert (binder.CallInfo, new CallInfo (1, new string[0]), "CallInfo");
942                         AssertArgument (binder, new[] {
943                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.UseCompileTimeType, null),
944                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null)},
945                                 "ArgumentInfo");
946
947                         Assert (binder.IgnoreCase, false, "IgnoreCase");
948                         Assert ((IList<object>) args, new object[] { mock }, "args");
949                 };
950
951                 mock.DMethod (d);
952         }
953
954         void InvokeMember_3 (dynamic d, DynamicObjectMock mock)
955         {
956                 mock.InvokeMemberOperation = (binder, args) => {
957                         Assert (binder.CallInfo, new CallInfo (1, new string[0]), "CallInfo");
958                         AssertArgument (binder, new[] {
959                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
960                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.IsRef | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
961                                 "ArgumentInfo");
962
963                         Assert (binder.IgnoreCase, false, "IgnoreCase");
964                         Assert ((IList<object>) args, new object[] { 9 }, "args");
965                 };
966
967                 int i = 9;
968                 d.Max (ref i);
969         }
970
971         void InvokeMember_4 (dynamic d, DynamicObjectMock mock)
972         {
973                 mock.InvokeMemberOperation = (binder, args) => {
974                         Assert (binder.CallInfo, new CallInfo (1, new string[0]), "CallInfo");
975                         AssertArgument (binder, new[] {
976                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
977                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.IsOut | CSharpArgumentInfoFlags.UseCompileTimeType, null)    },
978                                 "ArgumentInfo");
979
980                         Assert (binder.IgnoreCase, false, "IgnoreCase");
981                         Assert ((IList<object>) args, new object[] { 0 }, "args");
982                 };
983
984                 int i;
985                 d.Max (out i);
986         }
987
988         void InvokeMember_5 (dynamic d, DynamicObjectMock mock)
989         {
990                 DynamicObjectMock.DStaticMethod (d);
991         }
992
993         void InvokeMember_6 (dynamic d, DynamicObjectMock mock)
994         {
995                 InvokeMemberOperation = (binder, args) => {
996                         Assert (binder.CallInfo, new CallInfo (2, new string[0]), "CallInfo");
997                         AssertArgument (binder, new[] {
998                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.UseCompileTimeType, null),
999                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
1000                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant, null),
1001                         }, "ArgumentInfo");
1002
1003                         Assert (binder.IgnoreCase, false, "IgnoreCase");
1004                         Assert ((IList<object>) args, new object[] { d, null }, "args");
1005                 };
1006
1007                 InvokeMember_5 (d, null);
1008         }
1009
1010         void InvokeMember_7 (dynamic d, DynamicObjectMock mock)
1011         {
1012                 mock.InvokeMemberOperation = (binder, args) => {
1013                         Assert (binder.CallInfo, new CallInfo (0, new string[0]), "CallInfo");
1014                         AssertArgument (binder, new[] {
1015                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null)
1016                         }, "ArgumentInfo");
1017
1018                         Assert (binder.IgnoreCase, false, "IgnoreCase");
1019                         Assert ((IList<object>) args, new object[0], "args");
1020                 };
1021
1022                 d.Max<dynamic> ();
1023         }
1024         
1025         void InvokeMember_8 (dynamic d, DynamicObjectMock mock)
1026         {
1027                 mock.InvokeMemberOperation = (binder, args) => {
1028                         Assert (binder.CallInfo, new CallInfo (1, new string[0]), "CallInfo");
1029                         AssertArgument (binder, new[] {
1030                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
1031                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.IsRef | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
1032                                 "ArgumentInfo");
1033
1034                         Assert (binder.IgnoreCase, false, "IgnoreCase");
1035                         Assert ((IList<object>) args, new object[] { 9 }, "args");
1036                 };
1037
1038                 dynamic i = 9;
1039                 d.Max (ref i);
1040         }
1041
1042         void SetIndex_1 (dynamic d, DynamicObjectMock mock)
1043         {
1044                 mock.SetIndexOperation = (binder, args, value) => {
1045                         Assert (binder.CallInfo, new CallInfo (1, new string[0]), "CallInfo");
1046                         AssertArgument (binder, new[] {
1047                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
1048                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null),
1049                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null)},
1050                                 "ArgumentInfo");
1051
1052                         Assert ((IList<object>) args, new object[] { 0 }, "args");
1053                         Assert (value, 2m, "value");
1054                 };
1055
1056                 d[0] = 2m;
1057         }
1058
1059         void SetIndex_2 (dynamic d, DynamicObjectMock mock)
1060         {
1061                 mock.SetIndexOperation = (binder, args, value) => {
1062                         Assert (binder.CallInfo, new CallInfo (2, new string[0]), "CallInfo");
1063                         AssertArgument (binder, new[] {
1064                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
1065                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null),
1066                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.UseCompileTimeType, null),
1067                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null)
1068                         }, "ArgumentInfo");
1069
1070                         Assert ((IList<object>) args, new object[] { 2, 3 }, "args");
1071                         Assert (value, -8, "value");
1072                 };
1073
1074                 object i = 3;
1075                 d[2, i] = -8;
1076         }
1077
1078         void SetIndex_3 (dynamic d, DynamicObjectMock mock)
1079         {
1080                 mock.SetIndexOperation = (binder, args, value) => {
1081                         Assert (binder.CallInfo, new CallInfo (1, new string[0]), "CallInfo");
1082                         AssertArgument (binder, new[] {
1083                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.UseCompileTimeType, null),
1084                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
1085                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.UseCompileTimeType, null)
1086                         }, "ArgumentInfo");
1087
1088                         Assert ((IList<object>) args, new object[] { d }, "args");
1089                         Assert (value, this, "value");
1090                 };
1091
1092                 mock[d] = this;
1093         }
1094
1095         void SetMember_1 (dynamic d, DynamicObjectMock mock)
1096         {
1097                 const double d_const = 2.4;
1098
1099                 mock.SetMemberOperation = (binder, value) => {
1100                         Assert (binder.Name, "Foo", "Name");
1101                         Assert (binder.IgnoreCase, false, "IgnoreCase");
1102                         AssertArgument (binder, new[] {
1103                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
1104                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.UseCompileTimeType | CSharpArgumentInfoFlags.Constant, null)
1105                         }, "ArgumentInfo");
1106
1107                         Assert (value, d_const, "value");
1108                 };
1109
1110                 d.Foo = d_const;
1111         }
1112
1113         void SetMember_2 (dynamic d, DynamicObjectMock mock)
1114         {
1115                 mock.GetMemberOperation = (binder) => {
1116                         Assert (binder.Name, "Foo", "Name");
1117                         Assert (binder.IgnoreCase, false, "IgnoreCase");
1118                         AssertArgument (binder, new[] {
1119                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null) },
1120                                 "ArgumentInfo");
1121
1122                         return mock;
1123                 };
1124
1125                 mock.BinaryOperation = (binder, arg) => {
1126                         Assert (binder.Operation, ExpressionType.MultiplyAssign, "Operation");
1127                         AssertArgument (binder, new[] {
1128                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
1129                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant, null) },
1130                                 "ArgumentInfo");
1131
1132                         Assert (arg, null, "arg");
1133                 };
1134
1135                 mock.SetMemberOperation = (binder, value) => {
1136                         Assert (binder.Name, "Foo", "Name");
1137                         Assert (binder.IgnoreCase, false, "IgnoreCase");
1138                         AssertArgument (binder, new[] {
1139                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
1140                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null)
1141                         }, "ArgumentInfo");
1142                 };
1143
1144                 d.Foo *= null;
1145         }
1146
1147         void UnaryPlus_1 (dynamic d, DynamicObjectMock mock)
1148         {
1149                 mock.UnaryOperation = (binder) => {
1150                         Assert (binder.Operation, ExpressionType.UnaryPlus, "Operation");
1151                         AssertArgument (binder, new[] {
1152                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null)
1153                         }, "ArgumentInfo");
1154
1155                         return null;
1156                 };
1157
1158                 d = +d;
1159         }
1160
1161         void UnaryMinus_1 (dynamic d, DynamicObjectMock mock)
1162         {
1163                 mock.UnaryOperation = (binder) => {
1164                         Assert (binder.Operation, ExpressionType.Negate, "Operation");
1165                         AssertArgument (binder, new[] {
1166                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null)
1167                         }, "ArgumentInfo");
1168
1169                         return null;
1170                 };
1171
1172                 d = -d;
1173         }
1174
1175         void UnaryNot_1 (dynamic d, DynamicObjectMock mock)
1176         {
1177                 mock.UnaryOperation = (binder) => {
1178                         Assert (binder.Operation, ExpressionType.Not, "Operation");
1179                         AssertArgument (binder, new[] {
1180                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null)
1181                         }, "ArgumentInfo");
1182
1183                         return null;
1184                 };
1185
1186                 d = !d;
1187         }
1188
1189         void UnaryOnesComplement_1 (dynamic d, DynamicObjectMock mock)
1190         {
1191                 mock.UnaryOperation = (binder) => {
1192                         Assert (binder.Operation, ExpressionType.OnesComplement, "Operation");
1193                         AssertArgument (binder, new[] {
1194                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null)
1195                         }, "ArgumentInfo");
1196
1197                         return null;
1198                 };
1199
1200                 d = ~d;
1201         }
1202
1203         void UnaryDecrement_1 (dynamic d, DynamicObjectMock mock)
1204         {
1205                 mock.UnaryOperation = (binder) => {
1206                         Assert (binder.Operation, ExpressionType.Decrement, "Operation");
1207                         AssertArgument (binder, new[] {
1208                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null)
1209                         }, "ArgumentInfo");
1210
1211                         return null;
1212                 };
1213
1214                 d = --d;
1215         }
1216
1217         void UnaryDecrement_2 (dynamic d, DynamicObjectMock mock)
1218         {
1219                 mock.UnaryOperation = (binder) => {
1220                         Assert (binder.Operation, ExpressionType.Decrement, "Operation");
1221                         AssertArgument (binder, new[] {
1222                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null)
1223                         }, "ArgumentInfo");
1224
1225                         return new object ();
1226                 };
1227
1228                 d = d--;
1229         }
1230
1231         void UnaryIncrement_1 (dynamic d, DynamicObjectMock mock)
1232         {
1233                 mock.UnaryOperation = (binder) => {
1234                         Assert (binder.Operation, ExpressionType.Increment, "Operation");
1235                         AssertArgument (binder, new[] {
1236                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null)
1237                         }, "ArgumentInfo");
1238
1239                         return null;
1240                 };
1241
1242                 d = ++d;
1243         }
1244
1245         void UnaryIncrement_2 (dynamic d, DynamicObjectMock mock)
1246         {
1247                 mock.UnaryOperation = (binder) => {
1248                         Assert (binder.Operation, ExpressionType.Increment, "Operation");
1249                         AssertArgument (binder, new[] {
1250                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null)
1251                         }, "ArgumentInfo");
1252
1253                         return new object ();
1254                 };
1255
1256                 d = d++;
1257         }
1258
1259         void UnaryIsFalse_1 (dynamic d, DynamicObjectMock mock)
1260         {
1261                 mock.UnaryOperation = (binder) => {
1262                         Assert (binder.Operation, ExpressionType.IsFalse, "Operation");
1263                         AssertArgument (binder, new[] {
1264                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null)
1265                         }, "ArgumentInfo");
1266
1267                         return true;
1268                 };
1269
1270                 mock.BinaryOperation = (binder, arg) => {
1271                         Assert (binder.Operation, ExpressionType.Equal, "Operation");
1272                         AssertArgument (binder, new[] {
1273                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
1274                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant, null) },
1275                                 "ArgumentInfo");
1276
1277                         Assert (arg, null, "arg");
1278                 };
1279
1280                 object x = d == null;
1281         }
1282
1283         void UnaryIsFalse_2 (dynamic d, DynamicObjectMock mock)
1284         {
1285                 mock.UnaryOperation = (binder) => {
1286                         Assert (binder.Operation, ExpressionType.IsFalse, "Operation");
1287                         AssertArgument (binder, new[] {
1288                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null)
1289                         }, "ArgumentInfo");
1290
1291                         return true;
1292                 };
1293
1294                 mock.BinaryOperation = (binder, arg) => {
1295                         Assert (binder.Operation, ExpressionType.NotEqual, "Operation");
1296                         AssertArgument (binder, new[] {
1297                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
1298                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant, null) },
1299                                 "ArgumentInfo");
1300
1301                         Assert (arg, null, "arg");
1302                 };
1303
1304                 object x = d != null;
1305         }
1306
1307         void UnaryIsFalse_3 (dynamic d, DynamicObjectMock mock)
1308         {
1309                 mock.UnaryOperation = (binder) => {
1310                         Assert (binder.Operation, ExpressionType.IsFalse, "Operation");
1311                         AssertArgument (binder, new[] {
1312                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null)
1313                         }, "ArgumentInfo");
1314
1315                         return true;
1316                 };
1317
1318                 mock.BinaryOperation = (binder, arg) => {
1319                         Assert (binder.Operation, ExpressionType.And, "Operation");
1320                         AssertArgument (binder, new[] {
1321                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
1322                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant, null) },
1323                                 "ArgumentInfo");
1324
1325                         Assert (arg, null, "arg");
1326                 };
1327
1328                 object x = d && null;
1329         }
1330
1331         void UnaryIsTrue_1 (dynamic d, DynamicObjectMock mock)
1332         {
1333                 mock.UnaryOperation = (binder) => {
1334                         Assert (binder.Operation, ExpressionType.IsTrue, "Operation");
1335                         AssertArgument (binder, new[] {
1336                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null)
1337                         }, "ArgumentInfo");
1338
1339                         return true;
1340                 };
1341
1342                 object g = d ? 1 : 4;
1343         }
1344
1345         void UnaryIsTrue_2 (dynamic d, DynamicObjectMock mock)
1346         {
1347                 mock.UnaryOperation = (binder) => {
1348                         Assert (binder.Operation, ExpressionType.IsTrue, "Operation");
1349                         AssertArgument (binder, new[] {
1350                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null)
1351                         }, "ArgumentInfo");
1352
1353                         return false;
1354                 };
1355
1356                 mock.BinaryOperation = (binder, arg) => {
1357                         Assert (binder.Operation, ExpressionType.Or, "Operation");
1358                         AssertArgument (binder, new[] {
1359                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
1360                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant, null) },
1361                                 "ArgumentInfo");
1362
1363                         Assert (arg, null, "arg");
1364                 };
1365
1366                 object x = d || null;
1367         }
1368
1369 #pragma warning restore 168, 169, 219
1370
1371         static bool RunTest (MethodInfo test)
1372         {
1373                 Console.Write ("Running test {0, -25}", test.Name);
1374                 try {
1375                         var d = new DynamicObjectMock ();
1376                         test.Invoke (new Tester (), new[] { d, d });
1377                         if (d.HitCounter < 1)
1378                                 Assert (true, false, "HitCounter");
1379
1380                         Console.WriteLine ("OK");
1381                         return true;
1382                 } catch (Exception e) {
1383                         Console.WriteLine ("FAILED");
1384                         Console.WriteLine (e.ToString ());
1385                         return false;
1386                 }
1387         }
1388
1389         public static int Main ()
1390         {
1391                 var tests = from test in typeof (Tester).GetMethods (BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.DeclaredOnly)
1392                                         where test.GetParameters ().Length == 2
1393                                         orderby test.Name
1394                                         select RunTest (test);
1395
1396                 int failures = tests.Count (a => !a);
1397                 Console.WriteLine (failures + " tests failed");
1398                 return failures;
1399         }
1400 }