static string Run(string className, System.Reflection.Assembly koanAssembly, ExecutorWrapper wrapper) { Type classToRun = koanAssembly.GetType(className); if (classToRun == null) { return("(0/0)"); } string[] queue = new string[classToRun.GetMethods().Length + 1]; int highestKoanNumber = 0; foreach (MethodInfo method in classToRun.GetMethods()) { if (method.Name == null) { continue; } DotNetKoans.KoanAttribute custAttr = method.GetCustomAttributes(typeof(DotNetKoans.KoanAttribute), false).FirstOrDefault() as DotNetKoans.KoanAttribute; if (custAttr == null) { continue; } queue[custAttr.Position] = method.Name; if (custAttr.Position > highestKoanNumber) { highestKoanNumber = custAttr.Position; } } int numberOfTestsActuallyRun = 0; int numberOfTestsPassed = 0; foreach (string test in queue) { if (String.IsNullOrEmpty(test)) { continue; } numberOfTestsActuallyRun++; if (TEST_FAILED != 0) { continue; } wrapper.RunTest(className, test, callback); if (TEST_FAILED == 0) { numberOfTestsPassed++; } } if (numberOfTestsActuallyRun != highestKoanNumber) { Console.WriteLine("!!!!WARNING - Some Koans appear disabled. The highest koan found was {0} but we ran {1} koan(s)", highestKoanNumber, numberOfTestsActuallyRun); } return(string.Format("({0}/{1})", numberOfTestsPassed, numberOfTestsActuallyRun)); }
static void Run(string className, System.Reflection.Assembly koanAssembly, ExecutorWrapper wrapper) { Type classToRun = koanAssembly.GetType(className); if (classToRun == null) { Console.WriteLine("Class {0} not found", className); } object koans = Activator.CreateInstance(classToRun); MethodInfo[] queue = new MethodInfo[classToRun.GetMethods().Length + 1]; int highestKoanNumber = 0; foreach (MethodInfo method in classToRun.GetMethods()) { if (method.Name == null) { continue; } DotNetKoans.KoanAttribute custAttr = method.GetCustomAttributes(typeof(DotNetKoans.KoanAttribute), false).FirstOrDefault() as DotNetKoans.KoanAttribute; if (custAttr == null) { continue; } if (queue[custAttr.Position] != null) { Console.WriteLine("More than one koan in {0} has the position {1}", className, custAttr.Position); } queue[custAttr.Position] = method; if (custAttr.Position > highestKoanNumber) { highestKoanNumber = custAttr.Position; } } int numberOfKoansRunInThisCollection = 0; int numberOfKoansPassedInThisCollection = 0; BindingFlags flags = BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.Public; foreach (MethodInfo test in queue) { if (test == null) { continue; } ++numberKoansProcessed; numberOfKoansRunInThisCollection++; if (aKoanHasFailed) { continue; } try { Type attType = typeof(AsyncStateMachineAttribute); // Obtain the custom attribute for the method. // The value returned contains the StateMachineType property. // Null is returned if the attribute isn't present for the method. var attrib = (AsyncStateMachineAttribute)test.GetCustomAttribute(attType); if (attrib != null) { Task t = (classToRun.InvokeMember(test.Name, flags, null, koans, new Object[] { }) as Task); t.Wait(); } else { classToRun.InvokeMember(test.Name, flags, null, koans, new Object[] { }); } } catch (Exception e) { aKoanHasFailed = true; firstFailingKoan = numberKoansProcessed - 1; Exception ie = e.InnerException; if (ie == null) { ie = e; } string st = ie.StackTrace; string[] stLines = st.Split(new char[] { '\n' }); // uncomment if there are problems parsing the stack trace: /*foreach (string line in stLines) * Console.WriteLine(line);*/ string filenameAndLine = ""; foreach (string s in stLines) { filenameAndLine = GetFilenameAndLine(s); if (filenameAndLine != null) { break; } } // make the message a single line, so that it is completely seen if the Error List pane is selected instead of the Output pane: string message = ie.Message.Replace("\n", " \\ ").Replace("\r", ""); Console.WriteLine("The test {0} has damaged your karma.", test); // Use this format: "file(linenr): warning: " followed by anything, so it shows up as a warning in the Error List pane. // In both the Error List pane and Output pane clicking it jumps to the line where a fix is needed. // Replacing 'warning' by 'error' would work too, but also give a distracting extra error message. Console.WriteLine(filenameAndLine + ": warning: {0}", message); } if (!aKoanHasFailed) { numberOfKoansPassedInThisCollection++; } } if (numberOfKoansRunInThisCollection != highestKoanNumber) { Console.WriteLine("!!!!WARNING - Some Koans in {0} appear disabled. The highest koan found was {1} but we ran {2} koan(s)", className, highestKoanNumber, numberOfKoansRunInThisCollection); } }