[runtime] Fix memory leak in mono_save_seq_point_info().
[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 BinaryLogicalAnd_1 (dynamic d, DynamicObjectMock mock)
550         {
551                 mock.HitCounter = 1;
552                 bool b = false;
553                 d = b && d;
554         }
555
556         void BinaryLogicalOr_1 (dynamic d, DynamicObjectMock mock)
557         {
558                 mock.HitCounter = 1;
559                 bool b = true;
560                 d = b || d;
561         }
562
563         void BinaryModulo_1 (dynamic d, DynamicObjectMock mock)
564         {
565                 mock.BinaryOperation = (binder, arg) => {
566                         Assert (binder.Operation, ExpressionType.Modulo, "Operation");
567                         AssertArgument (binder, new[] {
568                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
569                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
570                                 "ArgumentInfo");
571
572                         Assert (arg, 1, "arg");
573                 };
574
575                 d = d % 1;
576         }
577
578         void BinaryModuloAssign_1 (dynamic d, DynamicObjectMock mock)
579         {
580                 mock.BinaryOperation = (binder, arg) => {
581                         Assert (binder.Operation, ExpressionType.ModuloAssign, "Operation");
582                         AssertArgument (binder, new[] {
583                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
584                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
585                                 "ArgumentInfo");
586
587                         Assert (arg, 1, "arg");
588                 };
589
590                 d %= 1;
591         }
592
593         void BinaryMultiply_1 (dynamic d, DynamicObjectMock mock)
594         {
595                 mock.BinaryOperation = (binder, arg) => {
596                         Assert (binder.Operation, ExpressionType.Multiply, "Operation");
597                         AssertArgument (binder, new[] {
598                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
599                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
600                                 "ArgumentInfo");
601
602                         Assert (arg, 1, "arg");
603                 };
604
605                 d = d * 1;
606         }
607
608         void BinaryMultiplyAssign_1 (dynamic d, DynamicObjectMock mock)
609         {
610                 mock.BinaryOperation = (binder, arg) => {
611                         Assert (binder.Operation, ExpressionType.MultiplyAssign, "Operation");
612                         AssertArgument (binder, new[] {
613                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
614                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
615                                 "ArgumentInfo");
616
617                         Assert (arg, 1, "arg");
618                 };
619
620                 d *= 1;
621         }
622
623         void BinaryNotEqual_1 (dynamic d, DynamicObjectMock mock)
624         {
625                 mock.BinaryOperation = (binder, arg) => {
626                         Assert (binder.Operation, ExpressionType.NotEqual, "Operation");
627                         AssertArgument (binder, new[] {
628                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
629                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
630                                 "ArgumentInfo");
631
632                         Assert (arg, 4, "arg");
633                 };
634
635                 d = d != 4;
636         }
637
638         void BinaryOr_1 (dynamic d, DynamicObjectMock mock)
639         {
640                 mock.BinaryOperation = (binder, arg) => {
641                         Assert (binder.Operation, ExpressionType.Or, "Operation");
642                         AssertArgument (binder, new[] {
643                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
644                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
645                                 "ArgumentInfo");
646
647                         Assert (arg, 2, "arg");
648                 };
649
650                 d = d | 2;
651         }
652
653         void BinaryOrAssign_1 (dynamic d, DynamicObjectMock mock)
654         {
655                 mock.BinaryOperation = (binder, arg) => {
656                         Assert (binder.Operation, ExpressionType.OrAssign, "Operation");
657                         AssertArgument (binder, new[] {
658                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
659                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
660                                 "ArgumentInfo");
661
662                         Assert (arg, 2, "arg");
663                 };
664
665                 d |= 2;
666         }
667
668         void BinaryRightShift_1 (dynamic d, DynamicObjectMock mock)
669         {
670                 mock.BinaryOperation = (binder, arg) => {
671                         Assert (binder.Operation, ExpressionType.RightShift, "Operation");
672                         AssertArgument (binder, new[] {
673                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
674                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
675                                 "ArgumentInfo");
676
677                         Assert (arg, 1, "arg");
678                 };
679
680                 d = d >> 1;
681         }
682
683         void BinaryRightShiftAssign_1 (dynamic d, DynamicObjectMock mock)
684         {
685                 mock.BinaryOperation = (binder, arg) => {
686                         Assert (binder.Operation, ExpressionType.RightShiftAssign, "Operation");
687                         AssertArgument (binder, new[] {
688                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
689                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
690                                 "ArgumentInfo");
691
692                         Assert (arg, 1, "arg");
693                 };
694
695                 d >>= 1;
696         }
697
698         void BinarySubtract_1 (dynamic d, DynamicObjectMock mock)
699         {
700                 mock.BinaryOperation = (binder, arg) => {
701                         Assert (binder.Operation, ExpressionType.Subtract, "Operation");
702                         AssertArgument (binder, new[] {
703                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
704                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
705                                 "ArgumentInfo");
706
707                         Assert (arg, 1, "arg");
708                 };
709
710                 d = d - 1;
711         }
712
713         void BinarySubtractAssign_1 (dynamic d, DynamicObjectMock mock)
714         {
715                 mock.BinaryOperation = (binder, arg) => {
716                         Assert (binder.Operation, ExpressionType.SubtractAssign, "Operation");
717                         AssertArgument (binder, new[] {
718                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
719                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
720                                 "ArgumentInfo");
721
722                         Assert (arg, 1, "arg");
723                 };
724
725                 d -= 1;
726         }
727
728         void Convert_1 (dynamic d, DynamicObjectMock mock)
729         {
730                 mock.ConvertOperation = (binder) => {
731                         Assert (binder.Explicit, true, "Explicit");
732                         Assert (binder.Type, typeof (byte), "Type");
733                         return (byte) 1;
734                 };
735
736                 object b = (byte) d;
737         }
738
739         void Convert_2 (dynamic d, DynamicObjectMock mock)
740         {
741                 mock.ConvertOperation = (binder) => {
742                         Assert (binder.Explicit, false, "Explicit");
743                         Assert (binder.Type, typeof (int), "Type");
744                         return 1;
745                 };
746
747                 object[] o = new object[2];
748                 d = o[d];
749         }
750
751         void Convert_3 (dynamic d, DynamicObjectMock mock)
752         {
753                 mock.ConvertOperation = (binder) => {
754                         Assert (binder.Explicit, true, "Explicit");
755 //                      Assert (binder.IsChecked, true, "IsChecked");
756                         Assert (binder.Type, typeof (byte), "Type");
757                         return (byte) 2;
758                 };
759
760                 object b = checked ((byte) d);
761         }
762
763         void Convert_4 (dynamic d, DynamicObjectMock mock)
764         {
765                 mock.ConvertOperation = (binder) => {
766                         Assert (binder.Explicit, false, "Explicit");
767                         Assert (binder.Type, typeof (int), "Type");
768                         return 5;
769                 };
770
771                 var g = new int[d];
772         }
773
774         void Convert_5 (dynamic d, DynamicObjectMock mock)
775         {
776                 int counter = 0;
777                 mock.ConvertOperation = (binder) => {
778                         Assert (binder.Explicit, false, "Explicit");
779                         Assert (binder.Type, typeof (System.Collections.IEnumerable), "Type");
780                         return new object[] { 1 };
781                 };
782
783                 foreach (int v in d) {
784 //                      Console.WriteLine (v);
785                 }
786         }
787
788         void GetIndex_1 (dynamic d, DynamicObjectMock mock)
789         {
790                 mock.GetIndexOperation = (binder, args) => {
791                         Assert (binder.CallInfo, new CallInfo (1, new string[0]), "CallInfo");
792                         AssertArgument (binder, new[] {
793                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
794                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
795                                 "ArgumentInfo");
796
797                         Assert ((IList<object>) args, new object[] { 0 }, "args");
798                 };
799
800                 var o = d[0];
801         }
802
803         void GetIndex_2 (dynamic d, DynamicObjectMock mock)
804         {
805                 mock.GetIndexOperation = (binder, args) => {
806                         Assert (binder.CallInfo, new CallInfo (2, new string[0]), "CallInfo");
807                         AssertArgument (binder, new[] {
808                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
809                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null),
810                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.UseCompileTimeType, null) },
811                         "ArgumentInfo");
812
813                         Assert ((IList<object>) args, new object[] { 2, 3 }, "args");
814                 };
815
816                 object i = 3;
817                 var o = d[2, i];
818         }
819
820         void GetIndex_3 (dynamic d, DynamicObjectMock mock)
821         {
822                 mock.GetIndexOperation = (binder, args) => {
823                         Assert (binder.CallInfo, new CallInfo (1, new string[0]), "CallInfo");
824                         AssertArgument (binder, new[] {
825                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.UseCompileTimeType, null),
826                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null) },
827                                 "ArgumentInfo");
828
829                         Assert ((IList<object>) args, new object[] { d }, "args");
830                 };
831
832                 var o = mock[d];
833         }
834
835         void GetMember_1 (dynamic d, DynamicObjectMock mock)
836         {
837                 mock.GetMemberOperation = (binder) => {
838                         Assert (binder.Name, "Foo", "Name");
839                         Assert (binder.IgnoreCase, false, "IgnoreCase");
840                         AssertArgument (binder, new[] {
841                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null) },
842                                 "ArgumentInfo");
843
844                         return null;
845                 };
846
847                 var g = d.Foo;
848         }
849
850         void Invoke_1 (dynamic d, DynamicObjectMock mock)
851         {
852                 mock.InvokeOperation = (binder, args) => {
853                         Assert (binder.CallInfo, new CallInfo (2, new string[0]), "CallInfo");
854                         AssertArgument (binder, new[] {
855                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
856                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null),
857                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant, null)
858                         }, "ArgumentInfo");
859
860                         Assert ((IList<object>) args, new object[] { "foo", null }, "args");
861                 };
862
863                 d ("foo", null);
864         }
865
866         void Invoke_2 (dynamic d, DynamicObjectMock mock)
867         {
868                 mock.InvokeOperation = (binder, args) => {
869                         Assert (binder.CallInfo, new CallInfo (0, new string[0]), "CallInfo");
870                         AssertArgument (binder, new[] {
871                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null) },
872                                 "ArgumentInfo");
873
874                         Assert ((IList<object>) args, new object[0], "args");
875                 };
876
877                 d ();
878         }
879
880         void Invoke_3 (dynamic d, DynamicObjectMock mock)
881         {
882                 try {
883                         Math.Max (d, d);
884                         Assert (true, false, "No hook expected to be hit");
885                 } catch (RuntimeBinderException) {
886                 }
887         }
888
889         void Invoke_4 (dynamic d, DynamicObjectMock mock)
890         {
891                 mock.InvokeOperation = (binder, args) => {
892                         Assert (binder.CallInfo, new CallInfo (2, new string[] { "name" }), "CallInfo");
893                         AssertArgument (binder, new[] {
894                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
895                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.UseCompileTimeType, null),
896                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.NamedArgument | CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, "name")
897                         }, "ArgumentInfo");
898
899                         Assert ((IList<object>) args, new object[] { typeof (bool), -1 }, "args");
900                 };
901
902                 d (typeof (bool), name: -1);
903         }
904
905         void Invoke_5 (dynamic d, DynamicObjectMock mock)
906         {
907                 mock.InvokeOperation = (binder, args) => {
908                         Assert (binder.CallInfo, new CallInfo (1, new string[0]), "CallInfo");
909                         AssertArgument (binder, new[] {
910                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
911                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.UseCompileTimeType | CSharpArgumentInfoFlags.Constant, null)
912                         }, "ArgumentInfo");
913
914                         Assert ((IList<object>) args, new object[] { "a" }, "args");
915                 };
916
917                 Action<dynamic> a = (i) => { i ("a"); };
918                 a (d);
919         }
920
921         void Invoke_6 (dynamic d, DynamicObjectMock mock)
922         {
923                 mock.InvokeOperation = (binder, args) => {
924                         Assert (binder.CallInfo, new CallInfo (1, new string[0]), "CallInfo");
925                         AssertArgument (binder, new[] {
926                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
927                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.UseCompileTimeType | CSharpArgumentInfoFlags.Constant, null)
928                         }, "ArgumentInfo");
929
930                         Assert ((IList<object>) args, new object[] { 3 }, "args");
931                 };
932
933                 d (1 + 2);
934         }
935
936         void InvokeMember_1 (dynamic d, DynamicObjectMock mock)
937         {
938                 mock.InvokeMemberOperation = (binder, args) => {
939                         Assert (binder.CallInfo, new CallInfo (1, new string[0]), "CallInfo");
940                         AssertArgument (binder, new[] {
941                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
942                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null)},
943                                 "ArgumentInfo");
944
945                         Assert (binder.IgnoreCase, false, "IgnoreCase");
946                         Assert ((IList<object>) args, new object[] { 'a' }, "args");
947                 };
948
949                 d.Max ('a');
950         }
951
952         void InvokeMember_2 (dynamic d, DynamicObjectMock mock)
953         {
954                 mock.InvokeMemberOperation = (binder, args) => {
955                         Assert (binder.CallInfo, new CallInfo (1, new string[0]), "CallInfo");
956                         AssertArgument (binder, new[] {
957                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.UseCompileTimeType, null),
958                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null)},
959                                 "ArgumentInfo");
960
961                         Assert (binder.IgnoreCase, false, "IgnoreCase");
962                         Assert ((IList<object>) args, new object[] { mock }, "args");
963                 };
964
965                 mock.DMethod (d);
966         }
967
968         void InvokeMember_3 (dynamic d, DynamicObjectMock mock)
969         {
970                 mock.InvokeMemberOperation = (binder, args) => {
971                         Assert (binder.CallInfo, new CallInfo (1, new string[0]), "CallInfo");
972                         AssertArgument (binder, new[] {
973                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
974                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.IsRef | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
975                                 "ArgumentInfo");
976
977                         Assert (binder.IgnoreCase, false, "IgnoreCase");
978                         Assert ((IList<object>) args, new object[] { 9 }, "args");
979                 };
980
981                 int i = 9;
982                 d.Max (ref i);
983         }
984
985         void InvokeMember_4 (dynamic d, DynamicObjectMock mock)
986         {
987                 mock.InvokeMemberOperation = (binder, args) => {
988                         Assert (binder.CallInfo, new CallInfo (1, new string[0]), "CallInfo");
989                         AssertArgument (binder, new[] {
990                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
991                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.IsOut | CSharpArgumentInfoFlags.UseCompileTimeType, null)    },
992                                 "ArgumentInfo");
993
994                         Assert (binder.IgnoreCase, false, "IgnoreCase");
995                         Assert ((IList<object>) args, new object[] { 0 }, "args");
996                 };
997
998                 int i;
999                 d.Max (out i);
1000         }
1001
1002         void InvokeMember_5 (dynamic d, DynamicObjectMock mock)
1003         {
1004                 DynamicObjectMock.DStaticMethod (d);
1005         }
1006
1007         void InvokeMember_6 (dynamic d, DynamicObjectMock mock)
1008         {
1009                 InvokeMemberOperation = (binder, args) => {
1010                         Assert (binder.CallInfo, new CallInfo (2, new string[0]), "CallInfo");
1011                         AssertArgument (binder, new[] {
1012                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.UseCompileTimeType, null),
1013                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
1014                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant, null),
1015                         }, "ArgumentInfo");
1016
1017                         Assert (binder.IgnoreCase, false, "IgnoreCase");
1018                         Assert ((IList<object>) args, new object[] { d, null }, "args");
1019                 };
1020
1021                 InvokeMember_5 (d, null);
1022         }
1023
1024         void InvokeMember_7 (dynamic d, DynamicObjectMock mock)
1025         {
1026                 mock.InvokeMemberOperation = (binder, args) => {
1027                         Assert (binder.CallInfo, new CallInfo (0, new string[0]), "CallInfo");
1028                         AssertArgument (binder, new[] {
1029                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null)
1030                         }, "ArgumentInfo");
1031
1032                         Assert (binder.IgnoreCase, false, "IgnoreCase");
1033                         Assert ((IList<object>) args, new object[0], "args");
1034                 };
1035
1036                 d.Max<dynamic> ();
1037         }
1038
1039         void InvokeMember_8 (dynamic d, DynamicObjectMock mock)
1040         {
1041                 mock.InvokeMemberOperation = (binder, args) => {
1042                         Assert (binder.CallInfo, new CallInfo (1, new string[0]), "CallInfo");
1043                         AssertArgument (binder, new[] {
1044                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
1045                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.IsRef | CSharpArgumentInfoFlags.UseCompileTimeType, null) },
1046                                 "ArgumentInfo");
1047
1048                         Assert (binder.IgnoreCase, false, "IgnoreCase");
1049                         Assert ((IList<object>) args, new object[] { 9 }, "args");
1050                 };
1051
1052                 dynamic i = 9;
1053                 d.Max (ref i);
1054         }
1055
1056         void SetIndex_1 (dynamic d, DynamicObjectMock mock)
1057         {
1058                 mock.SetIndexOperation = (binder, args, value) => {
1059                         Assert (binder.CallInfo, new CallInfo (1, new string[0]), "CallInfo");
1060                         AssertArgument (binder, new[] {
1061                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
1062                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null),
1063                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null)},
1064                                 "ArgumentInfo");
1065
1066                         Assert ((IList<object>) args, new object[] { 0 }, "args");
1067                         Assert (value, 2m, "value");
1068                 };
1069
1070                 d[0] = 2m;
1071         }
1072
1073         void SetIndex_2 (dynamic d, DynamicObjectMock mock)
1074         {
1075                 mock.SetIndexOperation = (binder, args, value) => {
1076                         Assert (binder.CallInfo, new CallInfo (2, new string[0]), "CallInfo");
1077                         AssertArgument (binder, new[] {
1078                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
1079                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null),
1080                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.UseCompileTimeType, null),
1081                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null)
1082                         }, "ArgumentInfo");
1083
1084                         Assert ((IList<object>) args, new object[] { 2, 3 }, "args");
1085                         Assert (value, -8, "value");
1086                 };
1087
1088                 object i = 3;
1089                 d[2, i] = -8;
1090         }
1091
1092         void SetIndex_3 (dynamic d, DynamicObjectMock mock)
1093         {
1094                 mock.SetIndexOperation = (binder, args, value) => {
1095                         Assert (binder.CallInfo, new CallInfo (1, new string[0]), "CallInfo");
1096                         AssertArgument (binder, new[] {
1097                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.UseCompileTimeType, null),
1098                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
1099                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.UseCompileTimeType, null)
1100                         }, "ArgumentInfo");
1101
1102                         Assert ((IList<object>) args, new object[] { d }, "args");
1103                         Assert (value, this, "value");
1104                 };
1105
1106                 mock[d] = this;
1107         }
1108
1109         void SetMember_1 (dynamic d, DynamicObjectMock mock)
1110         {
1111                 const double d_const = 2.4;
1112
1113                 mock.SetMemberOperation = (binder, value) => {
1114                         Assert (binder.Name, "Foo", "Name");
1115                         Assert (binder.IgnoreCase, false, "IgnoreCase");
1116                         AssertArgument (binder, new[] {
1117                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
1118                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.UseCompileTimeType | CSharpArgumentInfoFlags.Constant, null)
1119                         }, "ArgumentInfo");
1120
1121                         Assert (value, d_const, "value");
1122                 };
1123
1124                 d.Foo = d_const;
1125         }
1126
1127         void SetMember_2 (dynamic d, DynamicObjectMock mock)
1128         {
1129                 mock.GetMemberOperation = (binder) => {
1130                         Assert (binder.Name, "Foo", "Name");
1131                         Assert (binder.IgnoreCase, false, "IgnoreCase");
1132                         AssertArgument (binder, new[] {
1133                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null) },
1134                                 "ArgumentInfo");
1135
1136                         return mock;
1137                 };
1138
1139                 mock.BinaryOperation = (binder, arg) => {
1140                         Assert (binder.Operation, ExpressionType.MultiplyAssign, "Operation");
1141                         AssertArgument (binder, new[] {
1142                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
1143                             CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant, null) },
1144                                 "ArgumentInfo");
1145
1146                         Assert (arg, null, "arg");
1147                 };
1148
1149                 mock.SetMemberOperation = (binder, value) => {
1150                         Assert (binder.Name, "Foo", "Name");
1151                         Assert (binder.IgnoreCase, false, "IgnoreCase");
1152                         AssertArgument (binder, new[] {
1153                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
1154                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null)
1155                         }, "ArgumentInfo");
1156                 };
1157
1158                 d.Foo *= null;
1159         }
1160
1161         void UnaryPlus_1 (dynamic d, DynamicObjectMock mock)
1162         {
1163                 mock.UnaryOperation = (binder) => {
1164                         Assert (binder.Operation, ExpressionType.UnaryPlus, "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 UnaryMinus_1 (dynamic d, DynamicObjectMock mock)
1176         {
1177                 mock.UnaryOperation = (binder) => {
1178                         Assert (binder.Operation, ExpressionType.Negate, "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 UnaryNot_1 (dynamic d, DynamicObjectMock mock)
1190         {
1191                 mock.UnaryOperation = (binder) => {
1192                         Assert (binder.Operation, ExpressionType.Not, "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 UnaryOnesComplement_1 (dynamic d, DynamicObjectMock mock)
1204         {
1205                 mock.UnaryOperation = (binder) => {
1206                         Assert (binder.Operation, ExpressionType.OnesComplement, "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_1 (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 null;
1226                 };
1227
1228                 d = --d;
1229         }
1230
1231         void UnaryDecrement_2 (dynamic d, DynamicObjectMock mock)
1232         {
1233                 mock.UnaryOperation = (binder) => {
1234                         Assert (binder.Operation, ExpressionType.Decrement, "Operation");
1235                         AssertArgument (binder, new[] {
1236                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null)
1237                         }, "ArgumentInfo");
1238
1239                         return new object ();
1240                 };
1241
1242                 d = d--;
1243         }
1244
1245         void UnaryIncrement_1 (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 null;
1254                 };
1255
1256                 d = ++d;
1257         }
1258
1259         void UnaryIncrement_2 (dynamic d, DynamicObjectMock mock)
1260         {
1261                 mock.UnaryOperation = (binder) => {
1262                         Assert (binder.Operation, ExpressionType.Increment, "Operation");
1263                         AssertArgument (binder, new[] {
1264                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null)
1265                         }, "ArgumentInfo");
1266
1267                         return new object ();
1268                 };
1269
1270                 d = d++;
1271         }
1272
1273         void UnaryIsFalse_1 (dynamic d, DynamicObjectMock mock)
1274         {
1275                 mock.UnaryOperation = (binder) => {
1276                         Assert (binder.Operation, ExpressionType.IsFalse, "Operation");
1277                         AssertArgument (binder, new[] {
1278                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null)
1279                         }, "ArgumentInfo");
1280
1281                         return true;
1282                 };
1283
1284                 mock.BinaryOperation = (binder, arg) => {
1285                         Assert (binder.Operation, ExpressionType.Equal, "Operation");
1286                         AssertArgument (binder, new[] {
1287                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
1288                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant, null) },
1289                                 "ArgumentInfo");
1290
1291                         Assert (arg, null, "arg");
1292                 };
1293
1294                 object x = d == null;
1295         }
1296
1297         void UnaryIsFalse_2 (dynamic d, DynamicObjectMock mock)
1298         {
1299                 mock.UnaryOperation = (binder) => {
1300                         Assert (binder.Operation, ExpressionType.IsFalse, "Operation");
1301                         AssertArgument (binder, new[] {
1302                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null)
1303                         }, "ArgumentInfo");
1304
1305                         return true;
1306                 };
1307
1308                 mock.BinaryOperation = (binder, arg) => {
1309                         Assert (binder.Operation, ExpressionType.NotEqual, "Operation");
1310                         AssertArgument (binder, new[] {
1311                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
1312                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant, null) },
1313                                 "ArgumentInfo");
1314
1315                         Assert (arg, null, "arg");
1316                 };
1317
1318                 object x = d != null;
1319         }
1320
1321         void UnaryIsFalse_3 (dynamic d, DynamicObjectMock mock)
1322         {
1323                 mock.UnaryOperation = (binder) => {
1324                         Assert (binder.Operation, ExpressionType.IsFalse, "Operation");
1325                         AssertArgument (binder, new[] {
1326                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null)
1327                         }, "ArgumentInfo");
1328
1329                         return true;
1330                 };
1331
1332                 mock.BinaryOperation = (binder, arg) => {
1333                         Assert (binder.Operation, ExpressionType.And, "Operation");
1334                         AssertArgument (binder, new[] {
1335                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
1336                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant, null) },
1337                                 "ArgumentInfo");
1338
1339                         Assert (arg, null, "arg");
1340                 };
1341
1342                 object x = d && null;
1343         }
1344
1345         void UnaryIsTrue_1 (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 true;
1354                 };
1355
1356                 object g = d ? 1 : 4;
1357         }
1358
1359         void UnaryIsTrue_2 (dynamic d, DynamicObjectMock mock)
1360         {
1361                 mock.UnaryOperation = (binder) => {
1362                         Assert (binder.Operation, ExpressionType.IsTrue, "Operation");
1363                         AssertArgument (binder, new[] {
1364                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null)
1365                         }, "ArgumentInfo");
1366
1367                         return false;
1368                 };
1369
1370                 mock.BinaryOperation = (binder, arg) => {
1371                         Assert (binder.Operation, ExpressionType.Or, "Operation");
1372                         AssertArgument (binder, new[] {
1373                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
1374                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.Constant, null) },
1375                                 "ArgumentInfo");
1376
1377                         Assert (arg, null, "arg");
1378                 };
1379
1380                 object x = d || null;
1381         }
1382
1383         void UnaryIsTrue_3 (dynamic d, DynamicObjectMock mock)
1384         {
1385                 mock.UnaryOperation = (binder) => {
1386                         Assert (binder.Operation, ExpressionType.IsTrue, "Operation");
1387                         AssertArgument (binder, new[] {
1388                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null)
1389                         }, "ArgumentInfo");
1390
1391                         return false;
1392                 };
1393
1394                 mock.BinaryOperation = (binder, arg) => {
1395                         Assert (binder.Operation, ExpressionType.Or, "Operation");
1396                         AssertArgument (binder, new[] {
1397                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.None, null),
1398                                 CSharpArgumentInfo.Create (CSharpArgumentInfoFlags.UseCompileTimeType, null) },
1399                                 "ArgumentInfo");
1400
1401                         Assert (arg, false, "arg");
1402                 };
1403
1404                 bool b = false;
1405                 object x = d || b;
1406         }
1407
1408 #pragma warning restore 168, 169, 219
1409
1410         static bool RunTest (MethodInfo test)
1411         {
1412                 Console.Write ("Running test {0, -25}", test.Name);
1413                 try {
1414                         var d = new DynamicObjectMock ();
1415                         test.Invoke (new Tester (), new[] { d, d });
1416                         if (d.HitCounter < 1)
1417                                 Assert (true, false, "HitCounter");
1418
1419                         Console.WriteLine ("OK");
1420                         return true;
1421                 } catch (Exception e) {
1422                         Console.WriteLine ("FAILED");
1423                         Console.WriteLine (e.ToString ());
1424                         return false;
1425                 }
1426         }
1427
1428         public static int Main ()
1429         {
1430                 var tests = from test in typeof (Tester).GetMethods (BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.DeclaredOnly)
1431                                         where test.GetParameters ().Length == 2
1432                                         orderby test.Name
1433                                         select RunTest (test);
1434
1435                 int failures = tests.Count (a => !a);
1436                 Console.WriteLine (failures + " tests failed");
1437                 return failures;
1438         }
1439 }