1
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
2
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
5
using System.Collections.Generic;
7
namespace Debugger.Tests
9
public class ExpressionEvaluator_Tests
11
public class BaseClass
13
string name = "base name";
19
public static string StaticField = "base static field";
21
public string Foo(int i)
23
return "base Foo - int";
26
public string Foo(double d)
28
return "base Foo - double";
31
public string this[long i] {
33
return "base indexer - long";
38
public class DerivedClass: BaseClass
40
string name = "derived name";
42
new public string Name {
46
public char SetterOnlyProperty { set { ; } }
48
new public static string StaticField = "derived static field";
49
public const int ConstInt = 42;
50
public const string ConstString = "const string";
51
public const object ConstNull = null;
52
public const MyEnum ConstEnum = MyEnum.B;
54
public static string StaticProperty {
56
return "static property";
60
public static string StaticMethod()
62
return "static method";
65
public string Foo(object o)
67
return "derived Foo - object";
70
new public string Foo(int i)
72
return "derived Foo - int";
75
public string Foo(string s)
77
return "derived Foo - string";
80
public string this[double d] {
82
return "derived indexer - double";
86
public string this[string s] {
88
return "derived indexer - string";
92
public string Convert(string s, double d)
94
return "converted to " + s + " and " + d;
98
public enum MyEnum { A = 3, B = 6 };
100
string instanceField = "instance field value";
101
static string staticField = "static field value";
111
public static void Main()
113
new ExpressionEvaluator_Tests().Fun("function argument");
116
static bool WorkerThreadMoved = false;
118
public unsafe void Fun(string arg)
126
string emptyString = "";
128
char[] array = "Hello".ToCharArray();
129
char[] array2 = "world".ToCharArray();
130
char[][] arrays = new char[][] {array, array2};
131
List<char> list = new List<char>(array);
133
DerivedClass myClass = new DerivedClass();
134
BaseClass myClass2 = myClass;
136
int*[][,] complexType1 = new int*[][,] { new int*[,] { { (int*)0xDA1D } } };
137
A<int>.B.C<char>[][,] complexType2 = new A<int>.B.C<char>[0][,];
139
System.Threading.Thread bgWork = new System.Threading.Thread(
140
delegate() { WorkerThreadMoved = true; }
143
System.Diagnostics.Debugger.Break();
145
System.Threading.Thread.Sleep(100);
146
System.Diagnostics.Debugger.Break();
152
namespace Debugger.Tests {
153
using Debugger.MetaData;
154
using System.Reflection;
155
using ICSharpCode.NRefactory;
156
using ICSharpCode.NRefactory.Ast;
157
using ICSharpCode.NRefactory.Visitors;
158
using NUnit.Framework;
160
public partial class DebuggerTests
162
string expressionsInput = @"
164
pi - 3; pi + b; i + b; (uint)2 - 3; ((uint)2 - 3).GetType() ; (ulong)2 - 3 ; (b + b).GetType()
165
1 << 4; 7 << -1; 1 << (uint)2; 1.0 & 2.0; System.Int32.MaxValue + 1; (uint)2 - (uint)3; 1 / 0
166
hi + hi; hi + ''#''; hi + pi; hi + null; emptyString; ''''
167
hi + ''#'' == ''hi#''; hi + ''#'' == (object) ''hi#''; hi == (string)null; hi == null; hi == 1; null == null
169
(5 + 6) % (1 + 2); 3 % 2 == 1
170
15 & 255; 15 && 255; (ulong)1 + (long)1 /* invalid */
171
b + 3 == i; b + 4 == i
172
true == true; true == false
174
i = 10; -i; ++i; i++; +i; i += 1; ~i; i = 4
175
-(byte)1; (-(byte)1).GetType(); -(uint)1; (-(uint)1).GetType(); -(ulong)1 /* invalid */
176
-2147483648 /* int.MinValue */; (-2147483648).GetType(); -(-2147483648)
177
-9223372036854775808 /* long.MinValue */; (-9223372036854775808).GetType(); -(-9223372036854775808)
178
-1.0; ~1.0; !1; flag; !flag
180
arg; instanceField; staticField
182
array; arrays; array[1]; array[i]; array[i - 1]
185
new char[3] {'a', 'b', 'c'}
186
new char[] {'a', 'b', 'c'}
187
new char[][] { new char[] { 'a', 'b' }, new char[] { 'c', 'd' } }
188
new char[5] {'a', 'b', 'c'}
191
list; list[1]; list[i]; hi[1]; ''abcd''[2]
193
list.Add((char)42); list.Add((char)52); list
194
list = new System.Collections.Generic.List<char>(array2); list
196
(Debugger.Tests.ExpressionEvaluator_Tests.BaseClass)myClass
197
(Debugger.Tests.ExpressionEvaluator_Tests.DerivedClass)myClass2
203
[NUnit.Framework.Test]
204
[NUnit.Framework.Ignore("Test fails randomly (race condition)")]
205
public void ExpressionEvaluator_Tests()
208
process.SelectedStackFrame.StepOver();
209
process.SelectedStackFrame.StepOver(); // Start worker thread
211
EvalAll(expressionsInput);
213
// Test member hiding / overloading
215
Value myClass = SelectedStackFrame.GetLocalVariableValue("myClass").GetPermanentReference();
216
Expression myClassExpr = SelectedStackFrame.MethodInfo.GetLocalVariable(SelectedStackFrame.IP, "myClass").GetExpression();
218
List<Expression> expressions = new List<Expression>();
219
foreach(MemberInfo memberInfo in myClass.Type.GetFieldsAndNonIndexedProperties(DebugType.BindingFlagsAll)) {
220
expressions.Add(myClassExpr.AppendMemberReference((IDebugMemberInfo)memberInfo));
222
expressions.Add(myClassExpr.AppendMemberReference((DebugMethodInfo)myClass.Type.GetMethod("StaticMethod")));
223
expressions.Add(myClassExpr.AppendMemberReference((DebugMethodInfo)((DebugType)myClass.Type.BaseType).GetMethod("Foo", new string[] { "i" }), new PrimitiveExpression(1)));
224
expressions.Add(myClassExpr.AppendMemberReference((DebugMethodInfo)myClass.Type.GetMethod("Foo", new string[] { "i" }), new PrimitiveExpression(1)));
225
expressions.Add(myClassExpr.AppendMemberReference((DebugMethodInfo)myClass.Type.GetMethod("Foo", new string[] { "s" }), new PrimitiveExpression("a")));
227
foreach(Expression expr in expressions) {
228
Eval(expr.PrettyPrint());
240
myClass.Convert(1, 2)
241
myClass.Convert(''abc'', 2)
246
// Test type round tripping
248
foreach(DebugLocalVariableInfo locVar in process.SelectedStackFrame.MethodInfo.GetLocalVariables()) {
249
if (locVar.Name.StartsWith("complexType")) {
250
TypeReference complexTypeRef = locVar.LocalType.GetTypeReference();
251
string code = "typeof(" + complexTypeRef.PrettyPrint() + ")";
252
TypeOfExpression complexTypeRefRT = (TypeOfExpression)ExpressionEvaluator.Parse(code, SupportedLanguage.CSharp);
253
DebugType type = complexTypeRefRT.TypeReference.ResolveType(process.SelectedStackFrame.AppDomain);
254
string status = locVar.LocalType.FullName == type.FullName ? "ok" : "fail";
255
ObjectDumpToString("TypeResulution", string.Format(" {0} = {1} ({2})", code, type.FullName, status));
261
DebugLocalVariableInfo loc = SelectedStackFrame.MethodInfo.GetLocalVariable(SelectedStackFrame.IP, "list");
262
Type locType = loc.LocalType;
263
Type valType = loc.GetValue(SelectedStackFrame).Type;
264
ObjectDump("TypesIdentitcal", object.ReferenceEquals(locType, valType));
265
ObjectDump("TypesEqual", locType == valType);
267
ObjectDump("WorkerThreadMoved", process.SelectedStackFrame.GetThisValue().GetMemberValue("WorkerThreadMoved").AsString());
269
ObjectDump("WorkerThreadMoved", process.SelectedStackFrame.GetThisValue().GetMemberValue("WorkerThreadMoved").AsString());
274
void EvalAll(string exprs)
276
exprs = exprs.Replace("''", "\"");
277
foreach(string line in exprs.Split('\n', ';')) {
282
void Eval(string expr)
285
if (string.IsNullOrEmpty(expr)) {
289
Value result = ICSharpCode.NRefactory.Visitors.ExpressionEvaluator.Evaluate(expr, SupportedLanguage.CSharp, process.SelectedStackFrame);
290
restultFmted = ICSharpCode.NRefactory.Visitors.ExpressionEvaluator.FormatValue(result);
291
} catch (GetValueException e) {
292
restultFmted = e.Message;
295
if (restultFmted != null) {
296
restultFmted = restultFmted.Replace("\0", "\\0");
297
ObjectDump("Eval", " " + expr + " = " + restultFmted + " ");
299
ObjectDump("Eval", " " + expr);
307
<?xml version="1.0" encoding="utf-8"?>
310
name="ExpressionEvaluator_Tests.cs">
312
<ModuleLoaded>mscorlib.dll (No symbols)</ModuleLoaded>
313
<ModuleLoaded>ExpressionEvaluator_Tests.exe (Has symbols)</ModuleLoaded>
314
<DebuggingPaused>Break ExpressionEvaluator_Tests.cs:143,4-143,40</DebuggingPaused>
315
<DebuggingPaused>StepComplete ExpressionEvaluator_Tests.cs:144,4-144,19</DebuggingPaused>
316
<DebuggingPaused>StepComplete ExpressionEvaluator_Tests.cs:145,4-145,39</DebuggingPaused>
320
<Eval> *i = Target object is not a pointer </Eval>
321
<Eval> *iPtr = 4 </Eval>
322
<Eval> pi = 3.14 </Eval>
323
<Eval> pi - 3 = 0.1400001 </Eval>
324
<Eval> pi + b = 4.14 </Eval>
325
<Eval> i + b = 5 </Eval>
326
<Eval> (uint)2 - 3 = -1 </Eval>
327
<Eval> ((uint)2 - 3).GetType() = System.Int64 </Eval>
328
<Eval> (ulong)2 - 3 = Can not use the binary operator Subtract on types System.UInt64 and System.Int32 </Eval>
329
<Eval> (b + b).GetType() = System.Int32 </Eval>
330
<Eval> 1 << 4 = 16 </Eval>
331
<Eval> 7 << -1 = -2147483648 </Eval>
332
<Eval> 1 << (uint)2 = Can not use the binary operator ShiftLeft on types System.Int32 and System.UInt32 </Eval>
333
<Eval> 1.0 & 2.0 = Can not use the binary operator BitwiseAnd on types System.Double and System.Double </Eval>
334
<Eval> System.Int32.MaxValue + 1 = Arithmetic operation resulted in an overflow. </Eval>
335
<Eval> (uint)2 - (uint)3 = Arithmetic operation resulted in an overflow. </Eval>
336
<Eval> 1 / 0 = Attempted to divide by zero. </Eval>
337
<Eval> hi + hi = "hihi" </Eval>
338
<Eval> hi + "#" = "hi#" </Eval>
339
<Eval> hi + pi = "hi3.14" </Eval>
340
<Eval> hi + null = "hi" </Eval>
341
<Eval> emptyString = "" </Eval>
342
<Eval> "" = "" </Eval>
343
<Eval> hi + "#" == "hi#" = True </Eval>
344
<Eval> hi + "#" == (object) "hi#" = False </Eval>
345
<Eval> hi == (string)null = False </Eval>
346
<Eval> hi == null = False </Eval>
347
<Eval> hi == 1 = Can not use the binary operator Equality on types System.String and System.Int32 </Eval>
348
<Eval> null == null = True </Eval>
350
<Eval> (5 + 6) % (1 + 2) = 2 </Eval>
351
<Eval> 3 % 2 == 1 = True </Eval>
352
<Eval> 15 & 255 = 15 </Eval>
353
<Eval> 15 && 255 = Can not use the binary operator LogicalAnd on types System.Int32 and System.Int32 </Eval>
354
<Eval> (ulong)1 + (long)1 /* invalid */ = Can not use the binary operator Add on types System.UInt64 and System.Int64 </Eval>
355
<Eval> b + 3 == i = True </Eval>
356
<Eval> b + 4 == i = False </Eval>
357
<Eval> true == true = True </Eval>
358
<Eval> true == false = False </Eval>
360
<Eval> i = 10 = 10 </Eval>
361
<Eval> -i = -10 </Eval>
362
<Eval> ++i = 11 </Eval>
363
<Eval> i++ = 11 </Eval>
364
<Eval> +i = 12 </Eval>
365
<Eval> i += 1 = 13 </Eval>
366
<Eval> ~i = -14 </Eval>
367
<Eval> i = 4 = 4 </Eval>
368
<Eval> -(byte)1 = -1 </Eval>
369
<Eval> (-(byte)1).GetType() = System.Int32 </Eval>
370
<Eval> -(uint)1 = -1 </Eval>
371
<Eval> (-(uint)1).GetType() = System.Int64 </Eval>
372
<Eval> -(ulong)1 /* invalid */ = Can not use the unary operator Minus on type System.UInt64 </Eval>
373
<Eval> -2147483648 /* int.MinValue */ = -2147483648 </Eval>
374
<Eval> (-2147483648).GetType() = System.Int32 </Eval>
375
<Eval> -(-2147483648) = Arithmetic operation resulted in an overflow. </Eval>
376
<Eval> -9223372036854775808 /* long.MinValue */ = -9223372036854775808 </Eval>
377
<Eval> (-9223372036854775808).GetType() = System.Int64 </Eval>
378
<Eval> -(-9223372036854775808) = Arithmetic operation resulted in an overflow. </Eval>
379
<Eval> -1.0 = -1 </Eval>
380
<Eval> ~1.0 = Can not use the unary operator BitNot on type System.Double </Eval>
381
<Eval> !1 = Can not use the unary operator Not on type System.Int32 </Eval>
382
<Eval> flag = True </Eval>
383
<Eval> !flag = False </Eval>
385
<Eval> arg = "function argument" </Eval>
386
<Eval> instanceField = "instance field value" </Eval>
387
<Eval> staticField = "static field value" </Eval>
389
<Eval> array = Char[] {'H', 'e', 'l', 'l', 'o'} </Eval>
390
<Eval> arrays = Char[][] {Char[] {'H', 'e', 'l', 'l', 'o'}, Char[] {'w', 'o', 'r', 'l', 'd'}} </Eval>
391
<Eval> array[1] = 'e' </Eval>
392
<Eval> array[i] = 'o' </Eval>
393
<Eval> array[i - 1] = 'l' </Eval>
394
<Eval> new char[3] = Char[] {'\0', '\0', '\0'} </Eval>
395
<Eval> new char[b] {'a'} = Char[] {'a'} </Eval>
396
<Eval> new char[3] {'a', 'b', 'c'} = Char[] {'a', 'b', 'c'} </Eval>
397
<Eval> new char[] {'a', 'b', 'c'} = Char[] {'a', 'b', 'c'} </Eval>
398
<Eval> new char[][] { new char[] { 'a', 'b' }, new char[] { 'c', 'd' } } = Char[][] {Char[] {'a', 'b'}, Char[] {'c', 'd'}} </Eval>
399
<Eval> new char[5] {'a', 'b', 'c'} = Incorrect initializer length </Eval>
400
<Eval> new char[1,2] = Multi-dimensional arrays are not suppored </Eval>
401
<Eval> new char[pi] = Integer expected </Eval>
402
<Eval> list = List`1 {'H', 'e', 'l', 'l', 'o'} </Eval>
403
<Eval> list[1] = 'e' </Eval>
404
<Eval> list[i] = 'o' </Eval>
405
<Eval> hi[1] = 'i' </Eval>
406
<Eval> "abcd"[2] = 'c' </Eval>
408
<Eval> list.Add((char)42)</Eval>
409
<Eval> list.Add((char)52)</Eval>
410
<Eval> list = List`1 {'H', 'e', 'l', 'l', 'o', '*', '4'} </Eval>
411
<Eval> list = new System.Collections.Generic.List<char>(array2) = List`1 {'w', 'o', 'r', 'l', 'd'} </Eval>
412
<Eval> list = List`1 {'w', 'o', 'r', 'l', 'd'} </Eval>
414
<Eval> (Debugger.Tests.ExpressionEvaluator_Tests.BaseClass)myClass = Debugger.Tests.ExpressionEvaluator_Tests+DerivedClass </Eval>
415
<Eval> (Debugger.Tests.ExpressionEvaluator_Tests.DerivedClass)myClass2 = Debugger.Tests.ExpressionEvaluator_Tests+DerivedClass </Eval>
416
<Eval> (string)i = Can not cast System.Int32 to System.String </Eval>
417
<Eval> (string)hi = "hi" </Eval>
418
<Eval> (int)hi = Can not cast System.String to System.Int32 </Eval>
420
<Eval> Debugger.Tests.ExpressionEvaluator_Tests.DerivedClass.ConstInt = 42 </Eval>
421
<Eval> Debugger.Tests.ExpressionEvaluator_Tests.DerivedClass.ConstString = "const string" </Eval>
422
<Eval> Debugger.Tests.ExpressionEvaluator_Tests.DerivedClass.ConstNull = null </Eval>
423
<Eval> Debugger.Tests.ExpressionEvaluator_Tests.DerivedClass.ConstEnum = B </Eval>
424
<Eval> myClass.name = "derived name" </Eval>
425
<Eval> Debugger.Tests.ExpressionEvaluator_Tests.DerivedClass.StaticField = "derived static field" </Eval>
426
<Eval> myClass.Name = "derived name" </Eval>
427
<Eval> Debugger.Tests.ExpressionEvaluator_Tests.DerivedClass.StaticProperty = "static property" </Eval>
428
<Eval> ((Debugger.Tests.ExpressionEvaluator_Tests.BaseClass)myClass).name = "base name" </Eval>
429
<Eval> Debugger.Tests.ExpressionEvaluator_Tests.BaseClass.StaticField = "base static field" </Eval>
430
<Eval> ((Debugger.Tests.ExpressionEvaluator_Tests.BaseClass)myClass).Name = "base name" </Eval>
431
<Eval> Debugger.Tests.ExpressionEvaluator_Tests.DerivedClass.StaticMethod() = "static method" </Eval>
432
<Eval> ((Debugger.Tests.ExpressionEvaluator_Tests.BaseClass)myClass).Foo(1) = "base Foo - int" </Eval>
433
<Eval> myClass.Foo(1) = "derived Foo - int" </Eval>
434
<Eval> myClass.Foo("a") = "derived Foo - string" </Eval>
436
<Eval> myClass.Foo(1.0) = "base Foo - double" </Eval>
437
<Eval> myClass.Foo(myClass) = "derived Foo - object" </Eval>
438
<Eval> myClass.Foo(1) = "derived Foo - int" </Eval>
439
<Eval> myClass.Foo("abc") = "derived Foo - string" </Eval>
440
<Eval> myClass[1] = More then one applicable overload found:
441
String Debugger.Tests.ExpressionEvaluator_Tests+DerivedClass.Item[Double d]
442
String Debugger.Tests.ExpressionEvaluator_Tests+BaseClass.Item[Int64 i] </Eval>
443
<Eval> myClass[(long)1] = "base indexer - long" </Eval>
444
<Eval> myClass[1.0] = "derived indexer - double" </Eval>
445
<Eval> myClass["abc"] = "derived indexer - string" </Eval>
446
<Eval> myClass.Convert(1, 2) = Incorrect parameter type for 's'. Excpeted System.String, seen System.Int32 </Eval>
447
<Eval> myClass.Convert("abc", 2) = "converted to abc and 2" </Eval>
449
<TypeResulution> typeof(System.Int32*[][,]) = System.Int32*[,][] (ok)</TypeResulution>
450
<TypeResulution> typeof(Debugger.Tests.ExpressionEvaluator_Tests.A<System.Int32>.B.C<System.Char>[][,]) = Debugger.Tests.ExpressionEvaluator_Tests+A`1+B+C`1[System.Int32,System.Char][,][] (ok)</TypeResulution>
451
<TypesIdentitcal>True</TypesIdentitcal>
452
<TypesEqual>True</TypesEqual>
453
<WorkerThreadMoved>False</WorkerThreadMoved>
454
<DebuggingPaused>Break ExpressionEvaluator_Tests.cs:146,4-146,40</DebuggingPaused>
455
<WorkerThreadMoved>True</WorkerThreadMoved>
459
#endif // EXPECTED_OUTPUT