/// <summary> /// Executes the given test by replacing the userAnswer with its reference implementation. /// It is expected that the test will succeed with no warnings. /// </summary> public virtual bool Simulate(OperationInfo test, string userAnswer, IChannel channel) { // The skeleton answer used to compile the workspace var skeletonAnswer = FindSkeletonAnswer(test, userAnswer); if (skeletonAnswer == null) { channel.Stderr($"Invalid task name: {userAnswer}"); return(false); } // The reference implementation var referenceAnswer = FindReferenceImplementation(test, userAnswer); if (referenceAnswer == null) { channel.Stderr($"Reference answer not found: {userAnswer}"); return(false); } try { var qsim = CreateSimulator(); var hasWarnings = false; qsim.DisableLogToConsole(); qsim.Register(skeletonAnswer.RoslynType, referenceAnswer.RoslynType, typeof(ICallable)); qsim.OnLog += (msg) => { hasWarnings = msg?.StartsWith("[WARNING]") ?? hasWarnings; channel.Stdout(msg); }; var value = test.RunAsync(qsim, null).Result; if (qsim is IDisposable dis) { dis.Dispose(); } return(!hasWarnings); } catch (AggregateException agg) { foreach (var e in agg.InnerExceptions) { channel.Stderr(e.Message); } channel.Stderr($"Try again!"); return(false); } catch (Exception e) { channel.Stderr(e.Message); channel.Stderr($"Try again!"); return(false); } }
/// <summary> /// Executes the given kata using the provided <c>userAnswer</c> as the actual answer. /// To do this, it finds another operation with the same name but in the Kata's namespace /// (by calling `FindSkeltonAnswer`) and replace its implementation with the userAnswer /// in the simulator. /// </summary> public virtual bool Simulate(OperationInfo test, OperationInfo userAnswer, IChannel channel) { var skeletonAnswer = FindSkeletonAnswer(test, userAnswer); if (skeletonAnswer == null) { channel.Stderr($"Invalid task: {userAnswer.FullName}"); return(false); } try { var qsim = CreateSimulator(); qsim.DisableExceptionPrinting(); qsim.DisableLogToConsole(); qsim.OnLog += channel.Stdout; qsim.OnDisplayableDiagnostic += channel.Display; // Register all solutions to previously executed tasks (including the current one) foreach (KeyValuePair <OperationInfo, OperationInfo> answer in AllAnswers) { Logger.LogDebug($"Registering {answer.Key.FullName}"); qsim.Register(answer.Key.RoslynType, answer.Value.RoslynType, typeof(ICallable)); } var value = test.RunAsync(qsim, null).Result; if (qsim is IDisposable dis) { dis.Dispose(); } return(true); } catch (AggregateException agg) { foreach (var e in agg.InnerExceptions) { channel.Stderr(e.Message); } channel.Stderr($"Try again!"); return(false); } catch (Exception e) { channel.Stderr(e.Message); channel.Stderr($"Try again!"); return(false); } }
/// <summary> /// Executes the given kata using the provided <c>userAnswer</c> as the actual answer. /// To do this, it finds another operation with the same name but in the Kata's namespace /// (by calling `FindRawAnswer`) and replace its implementation with the userAnswer /// in the simulator. /// </summary> public virtual bool Simulate(OperationInfo kata, OperationInfo userAnswer, IChannel channel) { var rawAnswer = FindRawAnswer(kata, userAnswer); if (rawAnswer == null) { channel.Stderr($"Invalid task: {userAnswer.FullName}"); return(false); } try { var qsim = CreateSimulator(); qsim.DisableLogToConsole(); qsim.Register(rawAnswer.RoslynType, userAnswer.RoslynType, typeof(ICallable)); qsim.OnLog += channel.Stdout; var value = kata.RunAsync(qsim, null).Result; if (qsim is IDisposable dis) { dis.Dispose(); } return(true); } catch (AggregateException agg) { foreach (var e in agg.InnerExceptions) { channel.Stderr(e.Message); } channel.Stderr($"Try again!"); return(false); } catch (Exception e) { channel.Stderr(e.Message); channel.Stderr($"Try again!"); return(false); } }