[jit] Fix the saving of the 'cfg->ret_var_set' flag when inlining, it was set to...
[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 PropertyInfo flags = typeof (CSharpArgumentInfo).GetProperty ("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                 if (ai == null)
216                         throw new ApplicationException ("Could not find 'argumentInfo' private field on " + obj.GetType ());
217
218                 IList<CSharpArgumentInfo> values = (IList<CSharpArgumentInfo>) ai.GetValue (obj);
219                 if (values.Count != expected.Length)
220                         throw new ApplicationException (name + ": Array length does not match " + values.Count + " != " + expected.Length);
221
222                 for (int i = 0; i < expected.Length; i++) {
223                         Assert (flags.GetValue (expected[i]), flags.GetValue (values[i]), "flags");
224                 }
225         }
226
227 #pragma warning disable 168, 169, 219
228
229         void BinaryAdd_1 (dynamic d, DynamicObjectMock mock)
230         {
231                 mock.BinaryOperation = (binder, arg) => {
232                         Assert (binder.Operation, ExpressionType.Add, "Operation");
233                         AssertArgument (binder, new[] {
234                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
235                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
236                                 "ArgumentInfo");
237
238                         Assert (arg, 1, "arg");
239                 };
240
241                 d = d + 1;
242         }
243
244         void BinaryAdd_2 (dynamic d, DynamicObjectMock mock)
245         {
246                 mock.BinaryOperation = (binder, arg) => {
247                         Assert (binder.Operation, ExpressionType.Add, "Operation");
248                         AssertArgument (binder, new[] {
249                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
250                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.UseCompileTimeType, null) },
251                                 "ArgumentInfo");
252
253                         Assert (arg, null, "arg");
254                 };
255
256                 int? v = null;
257                 d = d + v;
258         }
259
260         void BinaryAdd_3 (dynamic d, DynamicObjectMock mock)
261         {
262                 mock.BinaryOperation = (binder, arg) => {
263                         Assert (binder.Operation, ExpressionType.Add, "Operation");
264                         AssertArgument (binder, new[] {
265                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
266                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.UseCompileTimeType | CSharpArgumentInfoFlags.Constant, null)
267                         }, "ArgumentInfo");
268
269                         Assert (arg, Enum.A, "arg");
270                 };
271
272                 d = d + Enum.A;
273         }
274
275         void BinaryAdd_4 (dynamic d, DynamicObjectMock mock)
276         {
277                 mock.BinaryOperation = (binder, arg) => {
278                         Assert (binder.Operation, ExpressionType.Add, "Operation");
279                         AssertArgument (binder, new[] {
280                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
281                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.UseCompileTimeType, null) },
282                                 "ArgumentInfo");
283
284                         Assert (arg, 7, "arg");
285                 };
286
287                 d = d + Tester.field;
288         }
289
290         void BinaryAddChecked_1 (dynamic d, DynamicObjectMock mock)
291         {
292                 mock.BinaryOperation = (binder, arg) => {
293                         Assert (binder.Operation, ExpressionType.Add, "Operation");
294                         AssertArgument (binder, new[] {
295                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
296                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.UseCompileTimeType | CSharpArgumentInfoFlags.Constant, null) },
297                                 "ArgumentInfo");
298
299                         Assert (arg, 3, "arg");
300                 };
301
302                 d = checked (d + 3);
303         }
304
305         void BinaryAddChecked_2 (dynamic d, DynamicObjectMock mock)
306         {
307                 mock.BinaryOperation = (binder, arg) => {
308                         Assert (binder.Operation, ExpressionType.Add, "Operation");
309                         AssertArgument (binder, new[] {
310                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
311                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.UseCompileTimeType | CSharpArgumentInfoFlags.Constant, null) },
312                                 "ArgumentInfo");
313
314                         Assert (arg, 3, "arg");
315                 };
316
317                 Func<dynamic> r;
318                 checked {
319                         r = () => d + 3;
320                 }
321
322                 r ();
323         }
324
325         void BinaryAddAssign_1 (dynamic d, DynamicObjectMock mock)
326         {
327                 mock.BinaryOperation = (binder, arg) => {
328                         Assert (binder.Operation, ExpressionType.AddAssign, "Operation");
329                         AssertArgument (binder, new[] {
330                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
331                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
332                                 "ArgumentInfo");
333
334                         Assert (arg, 1, "arg");
335                 };
336
337                 d += 1;
338         }
339
340         void BinaryAddAssignChecked_1 (dynamic d, DynamicObjectMock mock)
341         {
342                 mock.BinaryOperation = (binder, arg) => {
343                         Assert (binder.Operation, ExpressionType.AddAssign, "Operation");
344                         AssertArgument (binder, new[] {
345                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
346                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
347                                 "ArgumentInfo");
348
349                         Assert (arg, 1, "arg");
350                 };
351
352                 checked {
353                         d += 1;
354                 }
355         }
356
357         void BinaryAnd_1 (dynamic d, DynamicObjectMock mock)
358         {
359                 mock.BinaryOperation = (binder, arg) => {
360                         Assert (binder.Operation, ExpressionType.And, "Operation");
361                         AssertArgument (binder, new[] {
362                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
363                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
364                                 "ArgumentInfo");
365
366                         Assert (arg, 1, "arg");
367                 };
368
369                 d = d & 1;
370         }
371
372         void BinaryAndAssign_1 (dynamic d, DynamicObjectMock mock)
373         {
374                 mock.BinaryOperation = (binder, arg) => {
375                         Assert (binder.Operation, ExpressionType.AndAssign, "Operation");
376                         AssertArgument (binder, new[] {
377                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
378                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
379                                 "ArgumentInfo");
380
381                         Assert (arg, 1, "arg");
382                 };
383
384                 d &= 1;
385         }
386
387         void BinaryDivide_1 (dynamic d, DynamicObjectMock mock)
388         {
389                 mock.BinaryOperation = (binder, arg) => {
390                         Assert (binder.Operation, ExpressionType.Divide, "Operation");
391                         AssertArgument (binder, new[] {
392                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
393                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
394                                 "ArgumentInfo");
395
396                         Assert (arg, 1, "arg");
397                 };
398
399                 d = d / 1;
400         }
401
402         void BinaryDivideAssign_1 (dynamic d, DynamicObjectMock mock)
403         {
404                 mock.BinaryOperation = (binder, arg) => {
405                         Assert (binder.Operation, ExpressionType.DivideAssign, "Operation");
406                         AssertArgument (binder, new[] {
407                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
408                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
409                                 "ArgumentInfo");
410
411                         Assert (arg, 1, "arg");
412                 };
413
414                 d /= 1;
415         }
416
417         void BinaryEqual_1 (dynamic d, DynamicObjectMock mock)
418         {
419                 mock.BinaryOperation = (binder, arg) => {
420                         Assert (binder.Operation, ExpressionType.Equal, "Operation");
421                         AssertArgument (binder, new[] {
422                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
423                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
424                                 "ArgumentInfo");
425
426                         Assert (arg, 1, "arg");
427                 };
428
429                 d = d == 1;
430         }
431
432         void BinaryExclusiveOr_1 (dynamic d, DynamicObjectMock mock)
433         {
434                 mock.BinaryOperation = (binder, arg) => {
435                         Assert (binder.Operation, ExpressionType.ExclusiveOr, "Operation");
436                         AssertArgument (binder, new[] {
437                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
438                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
439                                 "ArgumentInfo");
440
441                         Assert (arg, 1, "arg");
442                 };
443
444                 d = d ^ 1;
445         }
446
447         void BinaryExclusiveOrAssign_1 (dynamic d, DynamicObjectMock mock)
448         {
449                 mock.BinaryOperation = (binder, arg) => {
450                         Assert (binder.Operation, ExpressionType.ExclusiveOrAssign, "Operation");
451                         AssertArgument (binder, new[] {
452                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
453                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
454                                 "ArgumentInfo");
455
456                         Assert (arg, 1, "arg");
457                 };
458
459                 d ^= 1;
460         }
461
462         void BinaryGreaterThan_1 (dynamic d, DynamicObjectMock mock)
463         {
464                 mock.BinaryOperation = (binder, arg) => {
465                         Assert (binder.Operation, ExpressionType.GreaterThan, "Operation");
466                         AssertArgument (binder, new[] {
467                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
468                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
469                                 "ArgumentInfo");
470
471                         Assert (arg, 1, "arg");
472                 };
473
474                 d = d > 1;
475         }
476
477         void BinaryGreaterThanOrEqual_1 (dynamic d, DynamicObjectMock mock)
478         {
479                 mock.BinaryOperation = (binder, arg) => {
480                         Assert (binder.Operation, ExpressionType.GreaterThanOrEqual, "Operation");
481                         AssertArgument (binder, new[] {
482                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
483                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
484                                 "ArgumentInfo");
485
486                         Assert (arg, 1, "arg");
487                 };
488
489                 d = d >= 1;
490         }
491
492         void BinaryLeftShift_1 (dynamic d, DynamicObjectMock mock)
493         {
494                 mock.BinaryOperation = (binder, arg) => {
495                         Assert (binder.Operation, ExpressionType.LeftShift, "Operation");
496                         AssertArgument (binder, new[] {
497                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
498                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
499                                 "ArgumentInfo");
500
501                         Assert (arg, 1, "arg");
502                 };
503
504                 d = d << 1;
505         }
506
507         void BinaryLeftShiftAssign_1 (dynamic d, DynamicObjectMock mock)
508         {
509                 mock.BinaryOperation = (binder, arg) => {
510                         Assert (binder.Operation, ExpressionType.LeftShiftAssign, "Operation");
511                         AssertArgument (binder, new[] {
512                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
513                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
514                                 "ArgumentInfo");
515
516                         Assert (arg, 1, "arg");
517                 };
518
519                 d <<= 1;
520         }
521
522         void BinaryLessThan_1 (dynamic d, DynamicObjectMock mock)
523         {
524                 mock.BinaryOperation = (binder, arg) => {
525                         Assert (binder.Operation, ExpressionType.LessThan, "Operation");
526                         AssertArgument (binder, new[] {
527                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
528                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
529                                 "ArgumentInfo");
530
531                         Assert (arg, 1, "arg");
532                 };
533
534                 d = d < 1;
535         }
536
537         void BinaryLessThanOrEqual_1 (dynamic d, DynamicObjectMock mock)
538         {
539                 mock.BinaryOperation = (binder, arg) => {
540                         Assert (binder.Operation, ExpressionType.LessThanOrEqual, "Operation");
541                         AssertArgument (binder, new[] {
542                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
543                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
544                                 "ArgumentInfo");
545
546                         Assert (arg, 1, "arg");
547                 };
548
549                 d = d <= 1;
550         }
551
552         void BinaryLogicalAnd_1 (dynamic d, DynamicObjectMock mock)
553         {
554                 mock.HitCounter = 1;
555                 bool b = false;
556                 d = b && d;
557         }
558
559         void BinaryLogicalOr_1 (dynamic d, DynamicObjectMock mock)
560         {
561                 mock.HitCounter = 1;
562                 bool b = true;
563                 d = b || d;
564         }
565
566         void BinaryModulo_1 (dynamic d, DynamicObjectMock mock)
567         {
568                 mock.BinaryOperation = (binder, arg) => {
569                         Assert (binder.Operation, ExpressionType.Modulo, "Operation");
570                         AssertArgument (binder, new[] {
571                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
572                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
573                                 "ArgumentInfo");
574
575                         Assert (arg, 1, "arg");
576                 };
577
578                 d = d % 1;
579         }
580
581         void BinaryModuloAssign_1 (dynamic d, DynamicObjectMock mock)
582         {
583                 mock.BinaryOperation = (binder, arg) => {
584                         Assert (binder.Operation, ExpressionType.ModuloAssign, "Operation");
585                         AssertArgument (binder, new[] {
586                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
587                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
588                                 "ArgumentInfo");
589
590                         Assert (arg, 1, "arg");
591                 };
592
593                 d %= 1;
594         }
595
596         void BinaryMultiply_1 (dynamic d, DynamicObjectMock mock)
597         {
598                 mock.BinaryOperation = (binder, arg) => {
599                         Assert (binder.Operation, ExpressionType.Multiply, "Operation");
600                         AssertArgument (binder, new[] {
601                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
602                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
603                                 "ArgumentInfo");
604
605                         Assert (arg, 1, "arg");
606                 };
607
608                 d = d * 1;
609         }
610
611         void BinaryMultiplyAssign_1 (dynamic d, DynamicObjectMock mock)
612         {
613                 mock.BinaryOperation = (binder, arg) => {
614                         Assert (binder.Operation, ExpressionType.MultiplyAssign, "Operation");
615                         AssertArgument (binder, new[] {
616                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
617                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
618                                 "ArgumentInfo");
619
620                         Assert (arg, 1, "arg");
621                 };
622
623                 d *= 1;
624         }
625
626         void BinaryNotEqual_1 (dynamic d, DynamicObjectMock mock)
627         {
628                 mock.BinaryOperation = (binder, arg) => {
629                         Assert (binder.Operation, ExpressionType.NotEqual, "Operation");
630                         AssertArgument (binder, new[] {
631                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
632                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
633                                 "ArgumentInfo");
634
635                         Assert (arg, 4, "arg");
636                 };
637
638                 d = d != 4;
639         }
640
641         void BinaryOr_1 (dynamic d, DynamicObjectMock mock)
642         {
643                 mock.BinaryOperation = (binder, arg) => {
644                         Assert (binder.Operation, ExpressionType.Or, "Operation");
645                         AssertArgument (binder, new[] {
646                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
647                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
648                                 "ArgumentInfo");
649
650                         Assert (arg, 2, "arg");
651                 };
652
653                 d = d | 2;
654         }
655
656         void BinaryOrAssign_1 (dynamic d, DynamicObjectMock mock)
657         {
658                 mock.BinaryOperation = (binder, arg) => {
659                         Assert (binder.Operation, ExpressionType.OrAssign, "Operation");
660                         AssertArgument (binder, new[] {
661                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
662                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
663                                 "ArgumentInfo");
664
665                         Assert (arg, 2, "arg");
666                 };
667
668                 d |= 2;
669         }
670
671         void BinaryRightShift_1 (dynamic d, DynamicObjectMock mock)
672         {
673                 mock.BinaryOperation = (binder, arg) => {
674                         Assert (binder.Operation, ExpressionType.RightShift, "Operation");
675                         AssertArgument (binder, new[] {
676                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
677                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
678                                 "ArgumentInfo");
679
680                         Assert (arg, 1, "arg");
681                 };
682
683                 d = d >> 1;
684         }
685
686         void BinaryRightShiftAssign_1 (dynamic d, DynamicObjectMock mock)
687         {
688                 mock.BinaryOperation = (binder, arg) => {
689                         Assert (binder.Operation, ExpressionType.RightShiftAssign, "Operation");
690                         AssertArgument (binder, new[] {
691                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
692                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
693                                 "ArgumentInfo");
694
695                         Assert (arg, 1, "arg");
696                 };
697
698                 d >>= 1;
699         }
700
701         void BinarySubtract_1 (dynamic d, DynamicObjectMock mock)
702         {
703                 mock.BinaryOperation = (binder, arg) => {
704                         Assert (binder.Operation, ExpressionType.Subtract, "Operation");
705                         AssertArgument (binder, new[] {
706                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
707                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
708                                 "ArgumentInfo");
709
710                         Assert (arg, 1, "arg");
711                 };
712
713                 d = d - 1;
714         }
715
716         void BinarySubtractAssign_1 (dynamic d, DynamicObjectMock mock)
717         {
718                 mock.BinaryOperation = (binder, arg) => {
719                         Assert (binder.Operation, ExpressionType.SubtractAssign, "Operation");
720                         AssertArgument (binder, new[] {
721                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
722                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
723                                 "ArgumentInfo");
724
725                         Assert (arg, 1, "arg");
726                 };
727
728                 d -= 1;
729         }
730
731         void Convert_1 (dynamic d, DynamicObjectMock mock)
732         {
733                 mock.ConvertOperation = (binder) => {
734                         Assert (binder.Explicit, true, "Explicit");
735                         Assert (binder.Type, typeof (byte), "Type");
736                         return (byte) 1;
737                 };
738
739                 object b = (byte) d;
740         }
741
742         void Convert_2 (dynamic d, DynamicObjectMock mock)
743         {
744                 mock.ConvertOperation = (binder) => {
745                         Assert (binder.Explicit, false, "Explicit");
746                         Assert (binder.Type, typeof (int), "Type");
747                         return 1;
748                 };
749
750                 object[] o = new object[2];
751                 d = o[d];
752         }
753
754         void Convert_3 (dynamic d, DynamicObjectMock mock)
755         {
756                 mock.ConvertOperation = (binder) => {
757                         Assert (binder.Explicit, true, "Explicit");
758 //                      Assert (binder.IsChecked, true, "IsChecked");
759                         Assert (binder.Type, typeof (byte), "Type");
760                         return (byte) 2;
761                 };
762
763                 object b = checked ((byte) d);
764         }
765
766         void Convert_4 (dynamic d, DynamicObjectMock mock)
767         {
768                 mock.ConvertOperation = (binder) => {
769                         Assert (binder.Explicit, false, "Explicit");
770                         Assert (binder.Type, typeof (int), "Type");
771                         return 5;
772                 };
773
774                 var g = new int[d];
775         }
776
777         void Convert_5 (dynamic d, DynamicObjectMock mock)
778         {
779                 int counter = 0;
780                 mock.ConvertOperation = (binder) => {
781                         Assert (binder.Explicit, false, "Explicit");
782                         Assert (binder.Type, typeof (System.Collections.IEnumerable), "Type");
783                         return new object[] { 1 };
784                 };
785
786                 foreach (int v in d) {
787 //                      Console.WriteLine (v);
788                 }
789         }
790
791         void GetIndex_1 (dynamic d, DynamicObjectMock mock)
792         {
793                 mock.GetIndexOperation = (binder, args) => {
794                         Assert (binder.CallInfo, new CallInfo (1, new string[0]), "CallInfo");
795                         AssertArgument (binder, new[] {
796                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
797                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
798                                 "ArgumentInfo");
799
800                         Assert ((IList<object>) args, new object[] { 0 }, "args");
801                 };
802
803                 var o = d[0];
804         }
805
806         void GetIndex_2 (dynamic d, DynamicObjectMock mock)
807         {
808                 mock.GetIndexOperation = (binder, args) => {
809                         Assert (binder.CallInfo, new CallInfo (2, new string[0]), "CallInfo");
810                         AssertArgument (binder, new[] {
811                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
812                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null),
813                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.UseCompileTimeType, null) },
814                         "ArgumentInfo");
815
816                         Assert ((IList<object>) args, new object[] { 2, 3 }, "args");
817                 };
818
819                 object i = 3;
820                 var o = d[2, i];
821         }
822
823         void GetIndex_3 (dynamic d, DynamicObjectMock mock)
824         {
825                 mock.GetIndexOperation = (binder, args) => {
826                         Assert (binder.CallInfo, new CallInfo (1, new string[0]), "CallInfo");
827                         AssertArgument (binder, new[] {
828                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.UseCompileTimeType, null),
829                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null) },
830                                 "ArgumentInfo");
831
832                         Assert ((IList<object>) args, new object[] { d }, "args");
833                 };
834
835                 var o = mock[d];
836         }
837
838         void GetMember_1 (dynamic d, DynamicObjectMock mock)
839         {
840                 mock.GetMemberOperation = (binder) => {
841                         Assert (binder.Name, "Foo", "Name");
842                         Assert (binder.IgnoreCase, false, "IgnoreCase");
843                         AssertArgument (binder, new[] {
844                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null) },
845                                 "ArgumentInfo");
846
847                         return null;
848                 };
849
850                 var g = d.Foo;
851         }
852
853         void Invoke_1 (dynamic d, DynamicObjectMock mock)
854         {
855                 mock.InvokeOperation = (binder, args) => {
856                         Assert (binder.CallInfo, new CallInfo (2, new string[0]), "CallInfo");
857                         AssertArgument (binder, new[] {
858                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
859                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null),
860                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant, null)
861                         }, "ArgumentInfo");
862
863                         Assert ((IList<object>) args, new object[] { "foo", null }, "args");
864                 };
865
866                 d ("foo", null);
867         }
868
869         void Invoke_2 (dynamic d, DynamicObjectMock mock)
870         {
871                 mock.InvokeOperation = (binder, args) => {
872                         Assert (binder.CallInfo, new CallInfo (0, new string[0]), "CallInfo");
873                         AssertArgument (binder, new[] {
874                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null) },
875                                 "ArgumentInfo");
876
877                         Assert ((IList<object>) args, new object[0], "args");
878                 };
879
880                 d ();
881         }
882
883         void Invoke_3 (dynamic d, DynamicObjectMock mock)
884         {
885                 try {
886                         Math.Max (d, d);
887                         Assert (true, false, "No hook expected to be hit");
888                 } catch (RuntimeBinderException) {
889                 }
890         }
891
892         void Invoke_4 (dynamic d, DynamicObjectMock mock)
893         {
894                 mock.InvokeOperation = (binder, args) => {
895                         Assert (binder.CallInfo, new CallInfo (2, new string[] { "name" }), "CallInfo");
896                         AssertArgument (binder, new[] {
897                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
898                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.UseCompileTimeType, null),
899                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.NamedArgument | CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, "name")
900                         }, "ArgumentInfo");
901
902                         Assert ((IList<object>) args, new object[] { typeof (bool), -1 }, "args");
903                 };
904
905                 d (typeof (bool), name: -1);
906         }
907
908         void Invoke_5 (dynamic d, DynamicObjectMock mock)
909         {
910                 mock.InvokeOperation = (binder, args) => {
911                         Assert (binder.CallInfo, new CallInfo (1, new string[0]), "CallInfo");
912                         AssertArgument (binder, new[] {
913                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
914                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.UseCompileTimeType | CSharpArgumentInfoFlags.Constant, null)
915                         }, "ArgumentInfo");
916
917                         Assert ((IList<object>) args, new object[] { "a" }, "args");
918                 };
919
920                 Action<dynamic> a = (i) => { i ("a"); };
921                 a (d);
922         }
923
924         void Invoke_6 (dynamic d, DynamicObjectMock mock)
925         {
926                 mock.InvokeOperation = (binder, args) => {
927                         Assert (binder.CallInfo, new CallInfo (1, new string[0]), "CallInfo");
928                         AssertArgument (binder, new[] {
929                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
930                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.UseCompileTimeType | CSharpArgumentInfoFlags.Constant, null)
931                         }, "ArgumentInfo");
932
933                         Assert ((IList<object>) args, new object[] { 3 }, "args");
934                 };
935
936                 d (1 + 2);
937         }
938
939         void InvokeMember_1 (dynamic d, DynamicObjectMock mock)
940         {
941                 mock.InvokeMemberOperation = (binder, args) => {
942                         Assert (binder.CallInfo, new CallInfo (1, new string[0]), "CallInfo");
943                         AssertArgument (binder, new[] {
944                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
945                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null)},
946                                 "ArgumentInfo");
947
948                         Assert (binder.IgnoreCase, false, "IgnoreCase");
949                         Assert ((IList<object>) args, new object[] { 'a' }, "args");
950                 };
951
952                 d.Max ('a');
953         }
954
955         void InvokeMember_2 (dynamic d, DynamicObjectMock mock)
956         {
957                 mock.InvokeMemberOperation = (binder, args) => {
958                         Assert (binder.CallInfo, new CallInfo (1, new string[0]), "CallInfo");
959                         AssertArgument (binder, new[] {
960                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.UseCompileTimeType, null),
961                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null)},
962                                 "ArgumentInfo");
963
964                         Assert (binder.IgnoreCase, false, "IgnoreCase");
965                         Assert ((IList<object>) args, new object[] { mock }, "args");
966                 };
967
968                 mock.DMethod (d);
969         }
970
971         void InvokeMember_3 (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.IsRef | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
978                                 "ArgumentInfo");
979
980                         Assert (binder.IgnoreCase, false, "IgnoreCase");
981                         Assert ((IList<object>) args, new object[] { 9 }, "args");
982                 };
983
984                 int i = 9;
985                 d.Max (ref i);
986         }
987
988         void InvokeMember_4 (dynamic d, DynamicObjectMock mock)
989         {
990                 mock.InvokeMemberOperation = (binder, args) => {
991                         Assert (binder.CallInfo, new CallInfo (1, new string[0]), "CallInfo");
992                         AssertArgument (binder, new[] {
993                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
994                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.IsOut | CSharpArgumentInfoFlags.UseCompileTimeType, null)    },
995                                 "ArgumentInfo");
996
997                         Assert (binder.IgnoreCase, false, "IgnoreCase");
998                         Assert ((IList<object>) args, new object[] { 0 }, "args");
999                 };
1000
1001                 int i;
1002                 d.Max (out i);
1003         }
1004
1005         void InvokeMember_5 (dynamic d, DynamicObjectMock mock)
1006         {
1007                 DynamicObjectMock.DStaticMethod (d);
1008         }
1009
1010         void InvokeMember_6 (dynamic d, DynamicObjectMock mock)
1011         {
1012                 InvokeMemberOperation = (binder, args) => {
1013                         Assert (binder.CallInfo, new CallInfo (2, new string[0]), "CallInfo");
1014                         AssertArgument (binder, new[] {
1015                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.UseCompileTimeType, null),
1016                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
1017                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant, null),
1018                         }, "ArgumentInfo");
1019
1020                         Assert (binder.IgnoreCase, false, "IgnoreCase");
1021                         Assert ((IList<object>) args, new object[] { d, null }, "args");
1022                 };
1023
1024                 InvokeMember_5 (d, null);
1025         }
1026
1027         void InvokeMember_7 (dynamic d, DynamicObjectMock mock)
1028         {
1029                 mock.InvokeMemberOperation = (binder, args) => {
1030                         Assert (binder.CallInfo, new CallInfo (0, new string[0]), "CallInfo");
1031                         AssertArgument (binder, new[] {
1032                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null)
1033                         }, "ArgumentInfo");
1034
1035                         Assert (binder.IgnoreCase, false, "IgnoreCase");
1036                         Assert ((IList<object>) args, new object[0], "args");
1037                 };
1038
1039                 d.Max<dynamic> ();
1040         }
1041
1042         void InvokeMember_8 (dynamic d, DynamicObjectMock mock)
1043         {
1044                 mock.InvokeMemberOperation = (binder, args) => {
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.IsRef | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
1049                                 "ArgumentInfo");
1050
1051                         Assert (binder.IgnoreCase, false, "IgnoreCase");
1052                         Assert ((IList<object>) args, new object[] { 9 }, "args");
1053                 };
1054
1055                 dynamic i = 9;
1056                 d.Max (ref i);
1057         }
1058
1059         void SetIndex_1 (dynamic d, DynamicObjectMock mock)
1060         {
1061                 mock.SetIndexOperation = (binder, args, value) => {
1062                         Assert (binder.CallInfo, new CallInfo (1, 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.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null)},
1067                                 "ArgumentInfo");
1068
1069                         Assert ((IList<object>) args, new object[] { 0 }, "args");
1070                         Assert (value, 2m, "value");
1071                 };
1072
1073                 d[0] = 2m;
1074         }
1075
1076         void SetIndex_2 (dynamic d, DynamicObjectMock mock)
1077         {
1078                 mock.SetIndexOperation = (binder, args, value) => {
1079                         Assert (binder.CallInfo, new CallInfo (2, new string[0]), "CallInfo");
1080                         AssertArgument (binder, new[] {
1081                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
1082                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null),
1083                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.UseCompileTimeType, null),
1084                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null)
1085                         }, "ArgumentInfo");
1086
1087                         Assert ((IList<object>) args, new object[] { 2, 3 }, "args");
1088                         Assert (value, -8, "value");
1089                 };
1090
1091                 object i = 3;
1092                 d[2, i] = -8;
1093         }
1094
1095         void SetIndex_3 (dynamic d, DynamicObjectMock mock)
1096         {
1097                 mock.SetIndexOperation = (binder, args, value) => {
1098                         Assert (binder.CallInfo, new CallInfo (1, new string[0]), "CallInfo");
1099                         AssertArgument (binder, new[] {
1100                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.UseCompileTimeType, null),
1101                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
1102                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.UseCompileTimeType, null)
1103                         }, "ArgumentInfo");
1104
1105                         Assert ((IList<object>) args, new object[] { d }, "args");
1106                         Assert (value, this, "value");
1107                 };
1108
1109                 mock[d] = this;
1110         }
1111
1112         void SetMember_1 (dynamic d, DynamicObjectMock mock)
1113         {
1114                 const double d_const = 2.4;
1115
1116                 mock.SetMemberOperation = (binder, value) => {
1117                         Assert (binder.Name, "Foo", "Name");
1118                         Assert (binder.IgnoreCase, false, "IgnoreCase");
1119                         AssertArgument (binder, new[] {
1120                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
1121                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.UseCompileTimeType | CSharpArgumentInfoFlags.Constant, null)
1122                         }, "ArgumentInfo");
1123
1124                         Assert (value, d_const, "value");
1125                 };
1126
1127                 d.Foo = d_const;
1128         }
1129
1130         void SetMember_2 (dynamic d, DynamicObjectMock mock)
1131         {
1132                 mock.GetMemberOperation = (binder) => {
1133                         Assert (binder.Name, "Foo", "Name");
1134                         Assert (binder.IgnoreCase, false, "IgnoreCase");
1135                         AssertArgument (binder, new[] {
1136                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null) },
1137                                 "ArgumentInfo");
1138
1139                         return mock;
1140                 };
1141
1142                 mock.BinaryOperation = (binder, arg) => {
1143                         Assert (binder.Operation, ExpressionType.MultiplyAssign, "Operation");
1144                         AssertArgument (binder, new[] {
1145                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
1146                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant, null) },
1147                                 "ArgumentInfo");
1148
1149                         Assert (arg, null, "arg");
1150                 };
1151
1152                 mock.SetMemberOperation = (binder, value) => {
1153                         Assert (binder.Name, "Foo", "Name");
1154                         Assert (binder.IgnoreCase, false, "IgnoreCase");
1155                         AssertArgument (binder, new[] {
1156                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
1157                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null)
1158                         }, "ArgumentInfo");
1159                 };
1160
1161                 d.Foo *= null;
1162         }
1163
1164         void UnaryPlus_1 (dynamic d, DynamicObjectMock mock)
1165         {
1166                 mock.UnaryOperation = (binder) => {
1167                         Assert (binder.Operation, ExpressionType.UnaryPlus, "Operation");
1168                         AssertArgument (binder, new[] {
1169                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null)
1170                         }, "ArgumentInfo");
1171
1172                         return null;
1173                 };
1174
1175                 d = +d;
1176         }
1177
1178         void UnaryMinus_1 (dynamic d, DynamicObjectMock mock)
1179         {
1180                 mock.UnaryOperation = (binder) => {
1181                         Assert (binder.Operation, ExpressionType.Negate, "Operation");
1182                         AssertArgument (binder, new[] {
1183                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null)
1184                         }, "ArgumentInfo");
1185
1186                         return null;
1187                 };
1188
1189                 d = -d;
1190         }
1191
1192         void UnaryNot_1 (dynamic d, DynamicObjectMock mock)
1193         {
1194                 mock.UnaryOperation = (binder) => {
1195                         Assert (binder.Operation, ExpressionType.Not, "Operation");
1196                         AssertArgument (binder, new[] {
1197                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null)
1198                         }, "ArgumentInfo");
1199
1200                         return null;
1201                 };
1202
1203                 d = !d;
1204         }
1205
1206         void UnaryOnesComplement_1 (dynamic d, DynamicObjectMock mock)
1207         {
1208                 mock.UnaryOperation = (binder) => {
1209                         Assert (binder.Operation, ExpressionType.OnesComplement, "Operation");
1210                         AssertArgument (binder, new[] {
1211                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null)
1212                         }, "ArgumentInfo");
1213
1214                         return null;
1215                 };
1216
1217                 d = ~d;
1218         }
1219
1220         void UnaryDecrement_1 (dynamic d, DynamicObjectMock mock)
1221         {
1222                 mock.UnaryOperation = (binder) => {
1223                         Assert (binder.Operation, ExpressionType.Decrement, "Operation");
1224                         AssertArgument (binder, new[] {
1225                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null)
1226                         }, "ArgumentInfo");
1227
1228                         return null;
1229                 };
1230
1231                 d = --d;
1232         }
1233
1234         void UnaryDecrement_2 (dynamic d, DynamicObjectMock mock)
1235         {
1236                 mock.UnaryOperation = (binder) => {
1237                         Assert (binder.Operation, ExpressionType.Decrement, "Operation");
1238                         AssertArgument (binder, new[] {
1239                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null)
1240                         }, "ArgumentInfo");
1241
1242                         return new object ();
1243                 };
1244
1245                 d = d--;
1246         }
1247
1248         void UnaryIncrement_1 (dynamic d, DynamicObjectMock mock)
1249         {
1250                 mock.UnaryOperation = (binder) => {
1251                         Assert (binder.Operation, ExpressionType.Increment, "Operation");
1252                         AssertArgument (binder, new[] {
1253                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null)
1254                         }, "ArgumentInfo");
1255
1256                         return null;
1257                 };
1258
1259                 d = ++d;
1260         }
1261
1262         void UnaryIncrement_2 (dynamic d, DynamicObjectMock mock)
1263         {
1264                 mock.UnaryOperation = (binder) => {
1265                         Assert (binder.Operation, ExpressionType.Increment, "Operation");
1266                         AssertArgument (binder, new[] {
1267                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null)
1268                         }, "ArgumentInfo");
1269
1270                         return new object ();
1271                 };
1272
1273                 d = d++;
1274         }
1275
1276         void UnaryIsFalse_1 (dynamic d, DynamicObjectMock mock)
1277         {
1278                 mock.UnaryOperation = (binder) => {
1279                         Assert (binder.Operation, ExpressionType.IsFalse, "Operation");
1280                         AssertArgument (binder, new[] {
1281                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null)
1282                         }, "ArgumentInfo");
1283
1284                         return true;
1285                 };
1286
1287                 mock.BinaryOperation = (binder, arg) => {
1288                         Assert (binder.Operation, ExpressionType.Equal, "Operation");
1289                         AssertArgument (binder, new[] {
1290                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
1291                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant, null) },
1292                                 "ArgumentInfo");
1293
1294                         Assert (arg, null, "arg");
1295                 };
1296
1297                 object x = d == null;
1298         }
1299
1300         void UnaryIsFalse_2 (dynamic d, DynamicObjectMock mock)
1301         {
1302                 mock.UnaryOperation = (binder) => {
1303                         Assert (binder.Operation, ExpressionType.IsFalse, "Operation");
1304                         AssertArgument (binder, new[] {
1305                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null)
1306                         }, "ArgumentInfo");
1307
1308                         return true;
1309                 };
1310
1311                 mock.BinaryOperation = (binder, arg) => {
1312                         Assert (binder.Operation, ExpressionType.NotEqual, "Operation");
1313                         AssertArgument (binder, new[] {
1314                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
1315                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant, null) },
1316                                 "ArgumentInfo");
1317
1318                         Assert (arg, null, "arg");
1319                 };
1320
1321                 object x = d != null;
1322         }
1323
1324         void UnaryIsFalse_3 (dynamic d, DynamicObjectMock mock)
1325         {
1326                 mock.UnaryOperation = (binder) => {
1327                         Assert (binder.Operation, ExpressionType.IsFalse, "Operation");
1328                         AssertArgument (binder, new[] {
1329                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null)
1330                         }, "ArgumentInfo");
1331
1332                         return true;
1333                 };
1334
1335                 mock.BinaryOperation = (binder, arg) => {
1336                         Assert (binder.Operation, ExpressionType.And, "Operation");
1337                         AssertArgument (binder, new[] {
1338                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
1339                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant, null) },
1340                                 "ArgumentInfo");
1341
1342                         Assert (arg, null, "arg");
1343                 };
1344
1345                 object x = d && null;
1346         }
1347
1348         void UnaryIsTrue_1 (dynamic d, DynamicObjectMock mock)
1349         {
1350                 mock.UnaryOperation = (binder) => {
1351                         Assert (binder.Operation, ExpressionType.IsTrue, "Operation");
1352                         AssertArgument (binder, new[] {
1353                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null)
1354                         }, "ArgumentInfo");
1355
1356                         return true;
1357                 };
1358
1359                 object g = d ? 1 : 4;
1360         }
1361
1362         void UnaryIsTrue_2 (dynamic d, DynamicObjectMock mock)
1363         {
1364                 mock.UnaryOperation = (binder) => {
1365                         Assert (binder.Operation, ExpressionType.IsTrue, "Operation");
1366                         AssertArgument (binder, new[] {
1367                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null)
1368                         }, "ArgumentInfo");
1369
1370                         return false;
1371                 };
1372
1373                 mock.BinaryOperation = (binder, arg) => {
1374                         Assert (binder.Operation, ExpressionType.Or, "Operation");
1375                         AssertArgument (binder, new[] {
1376                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
1377                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant, null) },
1378                                 "ArgumentInfo");
1379
1380                         Assert (arg, null, "arg");
1381                 };
1382
1383                 object x = d || null;
1384         }
1385
1386         void UnaryIsTrue_3 (dynamic d, DynamicObjectMock mock)
1387         {
1388                 mock.UnaryOperation = (binder) => {
1389                         Assert (binder.Operation, ExpressionType.IsTrue, "Operation");
1390                         AssertArgument (binder, new[] {
1391                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null)
1392                         }, "ArgumentInfo");
1393
1394                         return false;
1395                 };
1396
1397                 mock.BinaryOperation = (binder, arg) => {
1398                         Assert (binder.Operation, ExpressionType.Or, "Operation");
1399                         AssertArgument (binder, new[] {
1400                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
1401                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.UseCompileTimeType, null) },
1402                                 "ArgumentInfo");
1403
1404                         Assert (arg, false, "arg");
1405                 };
1406
1407                 bool b = false;
1408                 object x = d || b;
1409         }
1410
1411 #pragma warning restore 168, 169, 219
1412
1413         static bool RunTest (MethodInfo test)
1414         {
1415                 Console.Write ("Running test {0, -25}", test.Name);
1416                 try {
1417                         var d = new DynamicObjectMock ();
1418                         test.Invoke (new Tester (), new[] { d, d });
1419                         if (d.HitCounter < 1)
1420                                 Assert (true, false, "HitCounter");
1421
1422                         Console.WriteLine ("OK");
1423                         return true;
1424                 } catch (Exception e) {
1425                         Console.WriteLine ("FAILED");
1426                         Console.WriteLine (e.ToString ());
1427                         return false;
1428                 }
1429         }
1430
1431         public static int Main ()
1432         {
1433                 var tests = from test in typeof (Tester).GetMethods (BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.DeclaredOnly)
1434                                         where test.GetParameters ().Length == 2
1435                                         orderby test.Name
1436                                         select RunTest (test);
1437
1438                 int failures = tests.Count (a => !a);
1439                 Console.WriteLine (failures + " tests failed");
1440                 return failures;
1441         }
1442 }