]> rtime.felk.cvut.cz Git - wvtest.git/blob - dotnet/wvtest.cs
wvtestrunner: catch segfaults in the subprogram.
[wvtest.git] / dotnet / wvtest.cs
1 /*
2  * Versaplex:
3  *   Copyright (C)2007-2008 Versabanq Innovations Inc. and contributors.
4  *       See the included file named LICENSE for license information.
5  */
6 using System;
7 using System.Collections.Generic;
8 using System.Reflection;
9 using System.Runtime.Serialization;
10 using Wv;
11
12 // We put this in wvtest.cs since wvtest.cs should be able to compile all
13 // by itself, without relying on any other parts of wvdotnet.  On the other
14 // hand, it's perfectly fine for wvdotnet to have wvtest.cs in it.
15 namespace Wv
16 {
17     public static class WvReflection
18     {
19         public static IEnumerable<Type> find_types(Type attrtype)
20         {
21             foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies())
22             {
23                 foreach (Type t in a.GetTypes())
24                 {
25                     if (!t.IsDefined(attrtype, false))
26                         continue;
27                     
28                     yield return t;
29                 }
30             }
31         }
32         
33         public static IEnumerable<MethodInfo> find_methods(this Type t,
34                                                            Type attrtype)
35         {
36             foreach (MethodInfo m in t.GetMethods())
37             {
38                 if (!m.IsDefined(attrtype, false))
39                     continue;
40                 
41                 yield return m;
42             }
43         }
44     }
45 }
46
47 namespace Wv.Test
48 {
49     public class WvTest
50     {
51         struct TestInfo
52         {
53             public string name;
54             public Action cb;
55             
56             public TestInfo(string name, Action cb)
57                 { this.name = name; this.cb = cb; }
58         }
59         List<TestInfo> tests = new List<TestInfo>();
60
61         public int failures { get; private set; }
62         
63         public WvTest()
64         {
65             foreach (Type t in 
66                      WvReflection.find_types(typeof(TestFixtureAttribute)))
67             {
68                 foreach (MethodInfo m in 
69                          t.find_methods(typeof(TestAttribute)))
70                 {
71                     // The new t2, m2 are needed so that each delegate gets
72                     // its own copy of the variable.
73                     Type t2 = t;
74                     MethodInfo m2 = m;
75                     RegisterTest(String.Format("{0}/{1}",
76                                                t.Name, m.Name),
77                                  delegate() {
78                                      try {
79                                          m2.Invoke(Activator.CreateInstance(t2),
80                                                    null); 
81                                      } catch (TargetInvocationException e) {
82                                          throw e.InnerException;
83                                      }
84                                  });
85                 }
86             }
87         }
88
89         public void RegisterTest(string name, Action tc)
90         {
91             tests.Add(new TestInfo(name, tc));
92         }
93
94         public static void DoMain()
95         {
96             // Enough to run an entire test
97             Environment.Exit(new WvTest().Run());
98         }
99
100         public int Run()
101         {
102             string[] args = Environment.GetCommandLineArgs();
103             
104             if (args.Length <= 1)
105                 Console.WriteLine("WvTest: Running all tests");
106             else
107                 Console.WriteLine("WvTest: Running only selected tests");
108
109             foreach (TestInfo test in tests)
110             {
111                 string[] parts = test.name.Split(new char[] { '/' }, 2);
112                 
113                 bool runthis = (args.Length <= 1);
114                 foreach (string arg in args)
115                     if (parts[0].StartsWith(arg) || parts[1].StartsWith(arg))
116                         runthis = true;
117                 
118                 if (!runthis) continue;
119                 
120                 Console.WriteLine("\nTesting \"{0}\" in {1}:",
121                                   parts[1], parts[0]);
122
123                 try {
124                     test.cb();
125                 } catch (WvAssertionFailure) {
126                     failures++;
127                 } catch (Exception e) {
128                     Console.WriteLine(e.ToString());
129                     Console.WriteLine("! WvTest Exception received   FAILED");
130                     failures++;
131                 }
132             }
133             
134             Console.Out.WriteLine("Result: {0} failures.", failures);
135             
136             // Return a safe unix exit code
137             return failures > 0 ? 1 : 0;
138         }
139
140         public static bool booleanize(bool x)
141         {
142             return x;
143         }
144
145         public static bool booleanize(long x)
146         {
147             return x != 0;
148         }
149         
150         public static bool booleanize(ulong x)
151         {
152             return x != 0;
153         }
154         
155         public static bool booleanize(string s)
156         {
157             return s != null && s != "";
158         }
159         
160         public static bool booleanize(object o)
161         {
162             return o != null;
163         }
164         
165         static bool expect_fail = false;
166         public static void expect_next_failure()
167         {
168             expect_fail = true;
169         }
170         
171         public static bool test(bool ok, string file, int line, string s)
172         {
173             s = s.Replace("\n", "!");
174             s = s.Replace("\r", "!");
175             string suffix = "";
176             if (expect_fail)
177             {
178                 if (!ok)
179                     suffix = " (expected) ok";
180                 else
181                     suffix = " (expected fail!) FAILED";
182             }
183             Console.WriteLine("! {0}:{1,-5} {2,-40} {3}{4}",
184                               file, line, s,
185                               ok ? "ok" : "FAILED",
186                               suffix);
187             Console.Out.Flush();
188             expect_fail = false;
189
190             if (!ok)
191                 throw new WvAssertionFailure(String.Format("{0}:{1} {2}", file, line, s));
192
193             return ok;
194         }
195
196         public static void test_exception(string file, int line, string s)
197         {
198             Console.WriteLine("! {0}:{1,-5} {2,-40} {3}",
199                                          file, line, s, "EXCEPTION");
200             Console.Out.Flush();
201         }
202         
203         public static bool test_eq(bool cond1, bool cond2,
204                                    string file, int line,
205                                    string s1, string s2)
206         {
207             return test(cond1 == cond2, file, line,
208                 String.Format("[{0}] == [{1}] ({{{2}}} == {{{3}}})",
209                               cond1, cond2, s1, s2));
210         }
211         
212         public static bool test_eq(long cond1, long cond2,
213                                    string file, int line,
214                                    string s1, string s2)
215         {
216             return test(cond1 == cond2, file, line,
217                 String.Format("[{0}] == [{1}] ({{{2}}} == {{{3}}})",
218                               cond1, cond2, s1, s2));
219         }
220         
221         public static bool test_eq(ulong cond1, ulong cond2,
222                                    string file, int line,
223                                    string s1, string s2)
224         {
225             return test(cond1 == cond2, file, line,
226                 String.Format("[{0}] == [{1}] ({{{2}}} == {{{3}}})",
227                               cond1, cond2, s1, s2));
228         }
229         
230         public static bool test_eq(double cond1, double cond2,
231                                    string file, int line,
232                                    string s1, string s2)
233         {
234             return test(cond1 == cond2, file, line,
235                 String.Format("[{0}] == [{1}] ({{{2}}} == {{{3}}})",
236                               cond1, cond2, s1, s2));
237         }
238         
239         public static bool test_eq(decimal cond1, decimal cond2,
240                                    string file, int line,
241                                    string s1, string s2)
242         {
243             return test(cond1 == cond2, file, line,
244                 String.Format("[{0}] == [{1}] ({{{2}}} == {{{3}}})",
245                               cond1, cond2, s1, s2));
246         }
247         
248         public static bool test_eq(string cond1, string cond2,
249                                    string file, int line,
250                                    string s1, string s2)
251         {
252             return test(cond1 == cond2, file, line,
253                 String.Format("[{0}] == [{1}] ({{{2}}} == {{{3}}})",
254                               cond1, cond2, s1, s2));
255         }
256
257         // some objects can compare themselves to 'null', which is helpful.
258         // for example, DateTime.MinValue == null, but only through
259         // IComparable, not through IObject.
260         public static bool test_eq(IComparable cond1, IComparable cond2,
261                                    string file, int line,
262                                    string s1, string s2)
263         {
264             return test(cond1.CompareTo(cond2) == 0, file, line,
265                         String.Format("[{0}] == [{1}]", s1, s2));
266         }
267
268         public static bool test_eq(object cond1, object cond2,
269                                    string file, int line,
270                                    string s1, string s2)
271         {
272             return test(cond1 == cond2, file, line,
273                 String.Format("[{0}] == [{1}]", s1, s2));
274         }
275
276         public static bool test_ne(bool cond1, bool cond2,
277                                    string file, int line,
278                                    string s1, string s2)
279         {
280             return test(cond1 != cond2, file, line,
281                 String.Format("[{0}] != [{1}] ({{{2}}} != {{{3}}})",
282                               cond1, cond2, s1, s2));
283         }
284         
285         public static bool test_ne(long cond1, long cond2,
286                                    string file, int line,
287                                    string s1, string s2)
288         {
289             return test(cond1 != cond2, file, line,
290                 String.Format("[{0}] != [{1}] ({{{2}}} != {{{3}}})",
291                               cond1, cond2, s1, s2));
292         }
293         
294         public static bool test_ne(ulong cond1, ulong cond2,
295                                    string file, int line,
296                                    string s1, string s2)
297         {
298             return test(cond1 != cond2, file, line,
299                 String.Format("[{0}] != [{1}] ({{{2}}} != {{{3}}})",
300                               cond1, cond2, s1, s2));
301         }
302         
303         public static bool test_ne(double cond1, double cond2,
304                                    string file, int line,
305                                    string s1, string s2)
306         {
307             return test(cond1 != cond2, file, line,
308                 String.Format("[{0}] != [{1}] ({{{2}}} != {{{3}}})",
309                               cond1, cond2, s1, s2));
310         }
311         
312         public static bool test_ne(decimal cond1, decimal cond2,
313                                    string file, int line,
314                                    string s1, string s2)
315         {
316             return test(cond1 != cond2, file, line,
317                 String.Format("[{0}] != [{1}] ({{{2}}} != {{{3}}})",
318                               cond1, cond2, s1, s2));
319         }
320         
321         public static bool test_ne(string cond1, string cond2,
322                                    string file, int line,
323                                    string s1, string s2)
324         {
325             return test(cond1 != cond2, file, line,
326                 String.Format("[{0}] != [{1}] ({{{2}}} != {{{3}}})",
327                               cond1, cond2, s1, s2));
328         }
329         
330         // See notes for test_eq(IComparable,IComparable)
331         public static bool test_ne(IComparable cond1, IComparable cond2,
332                                    string file, int line,
333                                    string s1, string s2)
334         {
335             return test(cond1.CompareTo(cond2) != 0, file, line,
336                         String.Format("[{0}] != [{1}]", s1, s2));
337         }
338         
339         public static bool test_ne(object cond1, object cond2,
340                                    string file, int line,
341                                    string s1, string s2)
342         {
343             return test(cond1 != cond2, file, line,
344                 String.Format("[{0}] != [{1}]", s1, s2));
345         }
346     }
347
348     public class WvAssertionFailure : Exception
349     {
350         public WvAssertionFailure()
351             : base()
352         {
353         }
354
355         public WvAssertionFailure(string msg)
356             : base(msg)
357         {
358         }
359     }
360
361     // Placeholders for NUnit compatibility
362     public class TestFixtureAttribute : Attribute
363     {
364     }
365     public class TestAttribute : Attribute
366     {
367     }
368     [AttributeUsage(AttributeTargets.Method, AllowMultiple=true)]
369     public class CategoryAttribute : Attribute
370     {
371         public CategoryAttribute(string x)
372         {
373         }
374     }
375 }