2 using System.Reflection;
3 using System.Collections.Generic;
5 [AttributeUsageAttribute(AttributeTargets.All, Inherited = true, AllowMultiple = true)]
6 public class CategoryAttribute : Attribute
8 public CategoryAttribute (string category) {
12 public string Category {
17 public class TestDriver {
19 static public int RunTests (Type type, string[] args) {
20 int failed = 0, ran = 0;
25 bool do_timings = false;
29 DateTime start, end = DateTime.Now;
33 var exclude = new Dictionary<string, string> ();
34 List<string> run_only = new List<string> ();
35 List<string> exclude_test = new List<string> ();
36 if (args != null && args.Length > 0) {
37 for (j = 0; j < args.Length;) {
38 if (args [j] == "--time") {
41 } else if (args [j] == "--iter") {
42 iterations = Int32.Parse (args [j + 1]);
44 } else if ((args [j] == "-v") || (args [j] == "--verbose")) {
47 } else if ((args [j] == "-q") || (args [j] == "--quiet")) {
52 } else if (args [j] == "--exclude") {
53 exclude [args [j + 1]] = args [j + 1];
55 } else if (args [j] == "--exclude-test") {
56 exclude_test.Add (args [j + 1]);
58 } else if (args [j] == "--run-only") {
59 run_only.Add (args [j + 1]);
62 Console.WriteLine ("Unknown argument: " + args [j]);
68 methods = type.GetMethods (BindingFlags.Public|BindingFlags.NonPublic|BindingFlags.Static);
69 for (int iter = 0; iter < iterations; ++iter) {
70 for (i = 0; i < methods.Length; ++i) {
71 name = methods [i].Name;
72 if (!name.StartsWith ("test_", StringComparison.Ordinal))
74 if (run_only.Count > 0) {
76 for (j = 0; j < run_only.Count; j++) {
77 if (name.EndsWith (run_only [j])) {
85 if (exclude.Count > 0 || exclude_test.Count > 0) {
86 var attrs = methods [i].GetCustomAttributes (typeof (CategoryAttribute), false);
88 for (j = 0; j < exclude_test.Count; j++) {
89 if (name.EndsWith (exclude_test [j])) {
94 foreach (CategoryAttribute attr in attrs) {
95 if (exclude.ContainsKey (attr.Category))
100 Console.WriteLine ("Skipping '{0}'.", name);
105 for (j = 5; j < name.Length; ++j)
106 if (!Char.IsDigit (name [j]))
109 Console.WriteLine ("Running '{0}' ...", name);
110 expected = Int32.Parse (name.Substring (5, j - 5));
111 start = DateTime.Now;
112 result = (int)methods [i].Invoke (null, null);
115 long tdiff = end.Ticks - start.Ticks;
116 int mdiff = (int)tdiff/10000;
118 Console.WriteLine ("{0} took {1} ms", name, mdiff);
121 if (result != expected) {
123 Console.WriteLine ("{0} failed: got {1}, expected {2}", name, result, expected);
129 Console.WriteLine ("Total ms: {0}", tms);
132 Console.WriteLine ("Regression tests: {0} ran, {1} skipped, {2} failed in {3}", ran, nskipped, failed, type);
134 Console.WriteLine ("Regression tests: {0} ran, {1} failed in {2}", ran, failed, type);
138 //Console.WriteLine ("Regression tests: {0} ran, {1} failed in [{2}]{3}", ran, failed, type.Assembly.GetName().Name, type);
141 static public int RunTests (Type type) {
142 return RunTests (type, null);
146 /// Provide tests with the ability to find out how much time they have to run before being timed out.
147 public class TestTimeout {
148 const string ENV_TIMEOUT = "TEST_DRIVER_TIMEOUT_SEC";
149 private readonly TimeSpan availableTime;
150 private TimeSpan slack;
151 private DateTime startTime;
154 /// How much time the test runner provided for us or TimeSpan.Zero if there is no bound.
156 public TimeSpan AvailableTime { get { return availableTime; } }
158 public DateTime StartTime { get { return startTime; } }
160 /// <summary> Extra time to add when deciding if there
161 /// is still time to run. Bigger slack means less
164 public TimeSpan Slack {
165 get { return slack; }
166 set { slack = value; }
169 public TestTimeout () {
170 availableTime = initializeAvailableTime ();
171 slack = defaultSlack ();
175 /// Consider the test started.
179 startTime = DateTime.UtcNow;
182 public bool HaveTimeLeft ()
184 if (availableTime == TimeSpan.Zero)
186 var t = DateTime.UtcNow;
187 var finishTime = startTime + availableTime - slack;
188 return (t < finishTime);
191 private TimeSpan defaultSlack ()
193 return TimeSpan.FromSeconds (5);
196 private TimeSpan initializeAvailableTime ()
198 var e = System.Environment.GetEnvironmentVariable(ENV_TIMEOUT);
200 if (Double.TryParse(e, out d)) {
201 return TimeSpan.FromSeconds(d);
203 return TimeSpan.Zero;