/// <summary> /// Tries to create a new machine of the given type with an optional payload. /// </summary> /// <param name="type">Type of the machine</param> /// <param name="payload">Optional payload</param> /// <returns>Machine id</returns> internal static MachineId TryCreateMachine(Type type, params Object[] payload) { if (type.IsSubclassOf(typeof(Machine))) { Object machine = Activator.CreateInstance(type); var mid = (machine as Machine).Id; mid.IpAddress = PSharpRuntime.IpAddress; mid.Port = PSharpRuntime.Port; PSharpRuntime.MachineMap.Add(mid.Value, machine as Machine); Output.Debug(DebugType.Runtime, "<CreateLog> Machine {0}({1}) is created.", type.Name, mid.Value); Task task = new Task(() => { (machine as Machine).AssignInitialPayload(payload); (machine as Machine).GotoStartState(); (machine as Machine).RunEventHandler(); }); task.Start(); return(mid); } else { ErrorReporter.ReportAndExit("Type '{0}' is not a machine.", type.Name); return(null); } }
private void CheckForParsingErrors() { if (Configuration.ApplicationFilePath.Equals("")) { ErrorReporter.ReportAndExit("Please give a valid P# application path."); } }
/// <summary> /// Sends an asynchronous event to a machine. /// </summary> /// <param name="mid">Machine id</param> /// <param name="e">Event</param> internal static void Send(MachineId mid, Event e) { if (mid == null) { ErrorReporter.ReportAndExit("Cannot send to a null machine."); } else if (e == null) { ErrorReporter.ReportAndExit("Cannot send a null event."); } var machine = PSharpRuntime.MachineMap[mid.Value]; var runHandler = false; machine.Enqueue(e, ref runHandler); if (!runHandler) { return; } Task task = new Task(() => { machine.RunEventHandler(); }); task.Start(); }
/// <summary> /// Handler for unhandled exceptions. /// </summary> /// <param name="sender"></param> /// <param name="args"></param> static void UnhandledExceptionHandler(object sender, UnhandledExceptionEventArgs args) { var ex = (Exception)args.ExceptionObject; Output.Debug(ex.Message); Output.Debug(ex.StackTrace); ErrorReporter.ReportAndExit("internal failure: {0}.", ex.GetType().ToString()); }
protected override void CheckForParsingErrors() { var configuration = base.Configuration as RuntimeContainerConfiguration; if (configuration.ApplicationFilePath.Equals("")) { ErrorReporter.ReportAndExit("Please give a valid P# application path."); } }
/// <summary> /// Reports a parsing error. Only works if the parser is /// running internally. /// </summary> protected void ReportParsingError() { if (!this.IsRunningInternally || this.ParsingErrorLog.Length == 0) { return; } var errorIndex = this.TokenStream.Index; if (this.TokenStream.Index == this.TokenStream.Length && this.TokenStream.Index > 0) { errorIndex--; } var errorToken = this.TokenStream.GetAt(errorIndex); var errorLine = this.OriginalTokens.Where( val => val.TextUnit.Line == errorToken.TextUnit.Line).ToList(); this.ParsingErrorLog += "\nIn " + this.SyntaxTree.FilePath + " (line " + errorToken.TextUnit.Line + "):\n"; int nonWhiteIndex = 0; for (int idx = 0; idx < errorLine.Count; idx++) { if (errorLine[idx].Type != TokenType.WhiteSpace) { nonWhiteIndex = idx; break; } } for (int idx = nonWhiteIndex; idx < errorLine.Count; idx++) { this.ParsingErrorLog += errorLine[idx].TextUnit.Text; } for (int idx = nonWhiteIndex; idx < errorLine.Count; idx++) { if (errorLine[idx].Equals(errorToken) && errorIndex == this.TokenStream.Index) { this.ParsingErrorLog += new StringBuilder().Append('~', errorLine[idx].TextUnit.Text.Length); break; } else { this.ParsingErrorLog += new StringBuilder().Append(' ', errorLine[idx].TextUnit.Text.Length); } } if (errorIndex != this.TokenStream.Index) { this.ParsingErrorLog += "^"; } ErrorReporter.ReportAndExit(this.ParsingErrorLog); }
/// <summary> /// Compiles the given P# project. /// </summary> /// <param name="project">Project</param> private static void CompileProject(Project project) { var runtimeDllPath = typeof(Dispatcher).Assembly.Location; var bugFindingRuntimeDllPath = typeof(BugFindingDispatcher).Assembly.Location; var runtimeDll = project.MetadataReferences.FirstOrDefault(val => val.Display.EndsWith( Path.DirectorySeparatorChar + "Microsoft.PSharp.Runtime.dll")); if (runtimeDll != null && (Configuration.RunStaticAnalysis || Configuration.RunDynamicAnalysis)) { project = project.RemoveMetadataReference(runtimeDll); } if ((Configuration.RunStaticAnalysis || Configuration.RunDynamicAnalysis) && !project.MetadataReferences.Any(val => val.Display.EndsWith( Path.DirectorySeparatorChar + "Microsoft.PSharp.BugFindingRuntime.dll"))) { project = project.AddMetadataReference(MetadataReference.CreateFromFile( bugFindingRuntimeDllPath)); } var compilation = project.GetCompilationAsync().Result; try { if (Configuration.RunDynamicAnalysis) { var dll = CompilationEngine.ToFile(compilation, OutputKind.DynamicallyLinkedLibrary, project.OutputFilePath); if (Configuration.ProjectName.Equals(project.Name)) { Configuration.AssembliesToBeAnalyzed.Add(dll); } } else if (Configuration.CompileForDistribution) { CompilationEngine.ToFile(compilation, OutputKind.DynamicallyLinkedLibrary, project.OutputFilePath); } else { CompilationEngine.ToFile(compilation, project.CompilationOptions.OutputKind, project.OutputFilePath); } } catch (ApplicationException ex) { ErrorReporter.ReportAndExit(ex.Message); } }
private void CheckForParsingErrors() { if (Configuration.ApplicationFilePath.Equals("")) { ErrorReporter.ReportAndExit("Please give a valid P# application path."); } if (!Path.GetExtension(Configuration.ApplicationFilePath).Equals(".dll")) { ErrorReporter.ReportAndExit("The application must be a `dll` file compiled " + "using the P# compiler with the option `/distributed`."); } }
/// <summary> /// Create a new P# dynamic analysis context from the given assembly. /// </summary> /// <param name="assemblyName">Assembly name</param> public static void Create(string assemblyName) { try { AnalysisContext.Assembly = Assembly.LoadFrom(assemblyName); } catch (FileNotFoundException ex) { ErrorReporter.ReportAndExit(ex.Message); } AnalysisContext.Setup(); }
/// <summary> /// Create a new P# dynamic analysis context from the given assembly. /// </summary> /// <param name="assemblyName">Assembly name</param> public static void Create(Assembly assembly) { try { AnalysisContext.Assembly = assembly; } catch (FileNotFoundException ex) { ErrorReporter.ReportAndExit(ex.Message); } AnalysisContext.Setup(); }
/// <summary> /// Tries to create a new machine of the given type with an optional payload. /// </summary> /// <param name="type">Type of the machine</param> /// <param name="payload">Optional payload</param> /// <returns>Machine id</returns> internal static MachineId TryCreateMachine(Type type, params Object[] payload) { if (type.IsSubclassOf(typeof(Machine))) { Object machine = Activator.CreateInstance(type); MachineId mid = (machine as Machine).Id; PSharpRuntime.MachineMap.Add(mid.Value, machine as Machine); Output.Log("<CreateLog> Machine {0}({1}) is created.", type.Name, mid.MVal); Task task = new Task(() => { PSharpRuntime.BugFinder.NotifyTaskStarted(); (machine as Machine).AssignInitialPayload(payload); (machine as Machine).GotoStartState(); (machine as Machine).RunEventHandler(); PSharpRuntime.BugFinder.NotifyTaskCompleted(); }); lock (PSharpRuntime.Lock) { PSharpRuntime.MachineTasks.Add(task); PSharpRuntime.TaskMap.Add(task.Id, machine as Machine); } PSharpRuntime.BugFinder.NotifyNewTaskCreated(task.Id, machine as Machine); if (PSharpRuntime.Configuration.ScheduleIntraMachineConcurrency) { task.Start(PSharpRuntime.TaskScheduler); } else { task.Start(); } PSharpRuntime.BugFinder.WaitForTaskToStart(task.Id); PSharpRuntime.BugFinder.Schedule(); return(mid); } else { ErrorReporter.ReportAndExit("Type '{0}' is not a machine.", type.Name); return(null); } }
/// <summary> /// Finds the entry point to the P# program. /// </summary> private void FindEntryPoint() { List <MethodInfo> testMethods = null; try { testMethods = this.Assembly.GetTypes().SelectMany(t => t.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.InvokeMethod)). Where(m => m.GetCustomAttributes(typeof(Test), false).Length > 0).ToList(); } catch (ReflectionTypeLoadException ex) { foreach (var le in ex.LoaderExceptions) { ErrorReporter.Report(le.Message); } ErrorReporter.ReportAndExit("Failed to load assembly '{0}'", this.Assembly.FullName); } catch (Exception ex) { ErrorReporter.Report(ex.Message); ErrorReporter.ReportAndExit("Failed to load assembly '{0}'", this.Assembly.FullName); } if (testMethods.Count == 0) { ErrorReporter.ReportAndExit("Cannot detect a P# test method. " + "Use the attribute [Test] to declare a test method."); } else if (testMethods.Count > 1) { ErrorReporter.ReportAndExit("Only one test method to the P# program can be declared. " + "{0} test methods were found instead.", testMethods.Count); } if (testMethods[0].ReturnType != typeof(void) || testMethods[0].ContainsGenericParameters || testMethods[0].GetParameters().Length > 0 || testMethods[0].IsAbstract || testMethods[0].IsVirtual || testMethods[0].IsConstructor || !testMethods[0].IsPublic || !testMethods[0].IsStatic) { ErrorReporter.ReportAndExit("Incorrect test method declaration. Please " + "declare the test method as follows:\n" + " [Test] public static void Test() { ... }"); } this.TestMethod = testMethods[0]; }
/// <summary> /// Loads the application assembly. /// </summary> private static void LoadApplicationAssembly() { Assembly applicationAssembly = null; try { applicationAssembly = Assembly.LoadFrom(Configuration.ApplicationFilePath); } catch (FileNotFoundException ex) { ErrorReporter.ReportAndExit(ex.Message); } PSharpRuntime.AppAssembly = applicationAssembly; }
/// <summary> /// Constructor. /// </summary> /// <param name="configuration">Configuration</param> /// <param name="assemblyName">Assembly name</param> private AnalysisContext(DynamicAnalysisConfiguration configuration, string assemblyName) { this.Configuration = configuration; try { this.Assembly = Assembly.LoadFrom(assemblyName); } catch (FileNotFoundException ex) { ErrorReporter.ReportAndExit(ex.Message); } this.FindEntryPoint(); }
protected override void CheckForParsingErrors() { var configuration = base.Configuration as RemoteManagerConfiguration; if (configuration.ApplicationFilePath.Equals("")) { ErrorReporter.ReportAndExit("Please give a valid P# application path."); } if (!Path.GetExtension(configuration.ApplicationFilePath).Equals(".dll")) { ErrorReporter.ReportAndExit("The application must be a `dll` file compiled " + "using the P# compiler with the option `/distributed`."); } }
/// <summary> /// Finds the entry point to the P# program. /// </summary> /// <param name="assembly">Assembly</param> /// <returns>MethodInfo</returns> private static MethodInfo FindEntryPoint(Assembly assembly) { var entrypoints = assembly.GetTypes().SelectMany(t => t.GetMethods()). Where(m => m.GetCustomAttributes(typeof(Test), false).Length > 0).ToList(); if (entrypoints.Count == 0) { ErrorReporter.ReportAndExit("Cannot detect a P# test method. " + "Use the attribute [Test] to declare a test method."); } else if (entrypoints.Count > 1) { ErrorReporter.ReportAndExit("Only one test method to the P# program can be declared. " + "{0} test methods were found instead.", entrypoints.Count); } return(entrypoints[0]); }
/// <summary> /// Sends an asynchronous event to a machine. /// </summary> /// <param name="mid">Machine id</param> /// <param name="e">Event</param> internal static void Send(MachineId mid, Event e) { if (mid == null) { ErrorReporter.ReportAndExit("Cannot send to a null machine."); } else if (e == null) { ErrorReporter.ReportAndExit("Cannot send a null event."); } var machine = PSharpRuntime.MachineMap[mid.Value]; var runHandler = false; machine.Enqueue(e, ref runHandler); if (!runHandler) { PSharpRuntime.BugFinder.Schedule(Task.CurrentId); return; } Task task = new Task(() => { PSharpRuntime.BugFinder.NotifyTaskStarted(Task.CurrentId); machine.RunEventHandler(); PSharpRuntime.BugFinder.NotifyTaskCompleted(Task.CurrentId); }); lock (PSharpRuntime.Lock) { PSharpRuntime.MachineTasks.Add(task); } PSharpRuntime.BugFinder.NotifyNewTaskCreated(task.Id, machine); task.Start(); PSharpRuntime.BugFinder.WaitForTaskToStart(task.Id); PSharpRuntime.BugFinder.Schedule(Task.CurrentId); }
/// <summary> /// Tries to create a new machine of the given type with an optional payload. /// </summary> /// <param name="type">Type of the machine</param> /// <param name="payload">Optional payload</param> /// <returns>Machine id</returns> internal static MachineId TryCreateMachine(Type type, params Object[] payload) { if (type.IsSubclassOf(typeof(Machine))) { Machine machine = Activator.CreateInstance(type) as Machine; MachineId mid = machine.Id; mid.IpAddress = PSharpRuntime.IpAddress; mid.Port = PSharpRuntime.Port; if (!PSharpRuntime.MachineMap.TryAdd(mid.Value, machine)) { ErrorReporter.ReportAndExit("Machine {0}({1}) was already created.", type.Name, mid.Value); } Task task = new Task(() => { PSharpRuntime.TaskMap.TryAdd(Task.CurrentId.Value, machine); try { machine.AssignInitialPayload(payload); machine.GotoStartState(); machine.RunEventHandler(); } finally { PSharpRuntime.TaskMap.TryRemove(Task.CurrentId.Value, out machine); } }); task.Start(); return(mid); } else { ErrorReporter.ReportAndExit("Type '{0}' is not a machine.", type.Name); return(null); } }
/// <summary> /// Compiles the given P# project. /// </summary> /// <param name="project">Project</param> private void CompileProject(Project project) { var runtimeDllPath = typeof(Dispatcher).Assembly.Location; var bugFindingRuntimeDllPath = typeof(BugFindingDispatcher).Assembly.Location; var runtimeDll = project.MetadataReferences.FirstOrDefault(val => val.Display.EndsWith( Path.DirectorySeparatorChar + "Microsoft.PSharp.Runtime.dll")); if (runtimeDll != null && this.CompilationContext.ActiveCompilationTarget == CompilationTarget.Testing) { project = project.RemoveMetadataReference(runtimeDll); } if (this.CompilationContext.ActiveCompilationTarget == CompilationTarget.Testing && !project.MetadataReferences.Any(val => val.Display.EndsWith( Path.DirectorySeparatorChar + "Microsoft.PSharp.BugFindingRuntime.dll"))) { project = project.AddMetadataReference(MetadataReference.CreateFromFile( bugFindingRuntimeDllPath)); } var compilation = project.GetCompilationAsync().Result; try { if (this.CompilationContext.ActiveCompilationTarget == CompilationTarget.Testing || this.CompilationContext.ActiveCompilationTarget == CompilationTarget.Distribution) { this.ToFile(compilation, OutputKind.DynamicallyLinkedLibrary, project.OutputFilePath); } else { this.ToFile(compilation, project.CompilationOptions.OutputKind, project.OutputFilePath); } } catch (ApplicationException ex) { ErrorReporter.ReportAndExit(ex.Message); } }
/// <summary> /// Parses the command line options. /// </summary> public override void Parse() { for (int idx = 0; idx < base.Options.Length; idx++) { #region cluster manager options if (this.Options[idx].ToLower().StartsWith("/n:") && this.Options[idx].Length > 3) { int i = 0; if (!int.TryParse(this.Options[idx].Substring(3), out i) && i > 0) { ErrorReporter.ReportAndExit("Please give a valid number of containers " + "'/n:[x]', where [x] > 0."); } Configuration.NumberOfContainers = i; } else if (base.Options[idx].ToLower().StartsWith("/main:") && base.Options[idx].Length > 6) { Configuration.ApplicationFilePath = base.Options[idx].Substring(6); } #endregion #region error else { ErrorReporter.ReportAndExit("cannot recognise command line option '" + base.Options[idx] + "'."); } #endregion } this.CheckForParsingErrors(); }
/// <summary> /// Parses the command line options. /// </summary> public override void Parse() { for (int idx = 0; idx < base.Options.Length; idx++) { #region runtime container options if (this.Options[idx].ToLower().StartsWith("/id:") && this.Options[idx].Length > 4) { int i = 0; if (!int.TryParse(this.Options[idx].Substring(4), out i) && i >= 0) { ErrorReporter.ReportAndExit("Please give a valid container id"); } Configuration.ContainerId = i; } else if (base.Options[idx].ToLower().StartsWith("/main:") && base.Options[idx].Length > 6) { Configuration.ApplicationFilePath = base.Options[idx].Substring(6); } #endregion #region error else { ErrorReporter.ReportAndExit("cannot recognise command line option '" + base.Options[idx] + "'."); } #endregion } this.CheckForParsingErrors(); }
/// <summary> /// Sends an asynchronous event to a machine. /// </summary> /// <param name="mid">Machine id</param> /// <param name="e">Event</param> internal static void Send(MachineId mid, Event e) { if (mid == null) { ErrorReporter.ReportAndExit("Cannot send to a null machine."); } else if (e == null) { ErrorReporter.ReportAndExit("Cannot send a null event."); } Machine machine = PSharpRuntime.MachineMap[mid.Value]; bool runHandler = false; machine.Enqueue(e, ref runHandler); if (!runHandler) { return; } Task task = new Task(() => { PSharpRuntime.TaskMap.TryAdd(Task.CurrentId.Value, machine as Machine); try { machine.RunEventHandler(); } finally { PSharpRuntime.TaskMap.TryRemove(Task.CurrentId.Value, out machine); } }); task.Start(); }
/// <summary> /// Loads the solution. /// </summary> public CompilationContext LoadSolution() { // Create a new workspace. var workspace = MSBuildWorkspace.Create(); Solution solution = null; try { // Populate the workspace with the user defined solution. solution = (workspace as MSBuildWorkspace).OpenSolutionAsync( @"" + this.Configuration.SolutionFilePath + "").Result; } catch (AggregateException ex) { ErrorReporter.ReportAndExit(ex.InnerException.Message); } catch (Exception) { ErrorReporter.ReportAndExit("Please give a valid solution path."); } this.InstallCompilationTargets(solution); if (!this.Configuration.ProjectName.Equals("")) { // Find the project specified by the user. var project = this.GetProjectWithName(this.Configuration.ProjectName); if (project == null) { ErrorReporter.ReportAndExit("Please give a valid project name."); } } this.HasInitialized = true; return(this); }
/// <summary> /// Parse the given option. /// </summary> /// <param name="option">Option</param> protected override void ParseOption(string option) { var configuration = base.Configuration as RemoteManagerConfiguration; if (option.ToLower().StartsWith("/n:") && option.Length > 3) { int i = 0; if (!int.TryParse(option.Substring(3), out i) && i > 0) { ErrorReporter.ReportAndExit("Please give a valid number of containers " + "'/n:[x]', where [x] > 0."); } configuration.NumberOfContainers = i; } else if (option.ToLower().StartsWith("/main:") && option.Length > 6) { configuration.ApplicationFilePath = option.Substring(6); } else { base.ParseOption(option); } }
/// <summary> /// Parse the given option. /// </summary> /// <param name="option">Option</param> protected override void ParseOption(string option) { var configuration = base.Configuration as RuntimeContainerConfiguration; if (option.ToLower().StartsWith("/id:") && option.Length > 4) { int i = 0; if (!int.TryParse(option.Substring(4), out i) && i >= 0) { ErrorReporter.ReportAndExit("Please give a valid container id"); } configuration.ContainerId = i; } else if (option.ToLower().StartsWith("/main:") && option.Length > 6) { configuration.ApplicationFilePath = option.Substring(6); } else { base.ParseOption(option); } }
/// <summary> /// Creates a new container. /// </summary> /// <returns>Process</returns> private static void CreateContainer() { Output.PrettyPrintLine("... Creating container '{0}'", Manager.ContainerIdCounter); Process process = new Process(); process.StartInfo.FileName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "PSharpRuntimeContainer.exe"); process.StartInfo.Arguments = "/id:" + Manager.ContainerIdCounter; process.StartInfo.Arguments += " /main:" + Manager.Configuration.ApplicationFilePath; Manager.Containers.Add(Manager.ContainerIdCounter, process); Manager.ContainerIdCounter++; try { process.Start(); } catch (System.ComponentModel.Win32Exception ex) { ErrorReporter.ReportAndExit(ex.Message); } }
/// <summary> /// Handler for unhandled exceptions. /// </summary> /// <param name="sender"></param> /// <param name="args"></param> static void UnhandledExceptionHandler(object sender, UnhandledExceptionEventArgs args) { var ex = (Exception)args.ExceptionObject; ErrorReporter.ReportAndExit("internal failure: {0}", ex.ToString()); }
/// <summary> /// Explores the P# program for bugs. /// </summary> private static void FindBugs() { Output.Print("... Using '{0}' strategy", AnalysisContext.Strategy); Task task = new Task(() => { for (int i = 0; i < Configuration.SchedulingIterations; i++) { if (SCTEngine.ShouldPrintIteration(i + 1)) { Output.Print("..... Iteration #{0}", i + 1); } PSharpRuntime.BugFinder = new Scheduler(SCTEngine.Strategy); StringWriter sw = null; if (Configuration.Verbose < 2) { sw = SCTEngine.RedirectOutput(); SCTEngine.HasRedirectedOutput = true; } // Start the test and wait for it to terminate. AnalysisContext.TestMethod.Invoke(null, null); PSharpRuntime.WaitMachines(); // Runs the liveness checker to find any liveness property violations. // Requires that no bug has been found and the scheduler terminated // before reaching the depth bound. if (Configuration.CheckLiveness && !PSharpRuntime.BugFinder.BugFound) { PSharpRuntime.LivenessChecker.Run(); } if (SCTEngine.HasRedirectedOutput) { SCTEngine.ResetOutput(); } SCTEngine.ExploredSchedules++; SCTEngine.ExploredDepth = PSharpRuntime.BugFinder.SchedulingPoints; if (PSharpRuntime.BugFinder.BugFound) { SCTEngine.NumOfFoundBugs++; SCTEngine.BugReport = PSharpRuntime.BugFinder.BugReport; } else { SCTEngine.BugReport = ""; } if (SCTEngine.Strategy.HasFinished()) { break; } SCTEngine.Strategy.Reset(); if (!Configuration.FullExploration && (SCTEngine.NumOfFoundBugs > 0 || Configuration.PrintTrace)) { if (sw != null && !Configuration.SuppressTrace) { SCTEngine.PrintTrace(sw); } break; } } }); Profiler.StartMeasuringExecutionTime(); task.Start(); try { if (Configuration.AnalysisTimeout > 0) { task.Wait(Configuration.AnalysisTimeout * 1000); } else { task.Wait(); } } catch (AggregateException) { if (SCTEngine.HasRedirectedOutput) { SCTEngine.ResetOutput(); } ErrorReporter.ReportAndExit("Internal systematic testing exception. " + "Please send a bug report to the developers."); } finally { Profiler.StopMeasuringExecutionTime(); } }
/// <summary> /// Sends an asynchronous event to a machine. /// </summary> /// <param name="mid">Machine id</param> /// <param name="e">Event</param> internal static void Send(MachineId mid, Event e) { if (mid == null) { ErrorReporter.ReportAndExit("Cannot send to a null machine."); } else if (e == null) { ErrorReporter.ReportAndExit("Cannot send a null event."); } if (PSharpRuntime.TaskMap.ContainsKey((int)Task.CurrentId)) { Machine sender = PSharpRuntime.TaskMap[(int)Task.CurrentId]; Output.Log("<SendLog> Machine '{0}({1})' sent event '{2}' to '{3}({4})'.", sender, sender.Id.MVal, e.GetType(), mid.Type, mid.MVal); } else { Output.Log("<SendLog> Event '{0}' was sent to '{1}({2})'.", e.GetType(), mid.Type, mid.MVal); } Machine machine = PSharpRuntime.MachineMap[mid.Value]; bool runHandler = false; machine.Enqueue(e, ref runHandler); if (!runHandler) { PSharpRuntime.BugFinder.Schedule(); return; } Task task = new Task(() => { PSharpRuntime.BugFinder.NotifyTaskStarted(); machine.RunEventHandler(); PSharpRuntime.BugFinder.NotifyTaskCompleted(); }); lock (PSharpRuntime.Lock) { PSharpRuntime.MachineTasks.Add(task); PSharpRuntime.TaskMap.Add(task.Id, machine as Machine); } PSharpRuntime.BugFinder.NotifyNewTaskCreated(task.Id, machine); if (PSharpRuntime.Configuration.ScheduleIntraMachineConcurrency) { task.Start(PSharpRuntime.TaskScheduler); } else { task.Start(); } PSharpRuntime.BugFinder.WaitForTaskToStart(task.Id); PSharpRuntime.BugFinder.Schedule(); }
/// <summary> /// Explores the P# program for bugs. /// </summary> private void FindBugs() { Output.PrintLine("... Using '{0}' strategy", AnalysisContext.Configuration.SchedulingStrategy); Task task = new Task(() => { for (int i = 0; i < this.AnalysisContext.Configuration.SchedulingIterations; i++) { if (this.ShouldPrintIteration(i + 1)) { Output.PrintLine("..... Iteration #{0}", i + 1); } if (this.AnalysisContext.Configuration.ScheduleIntraMachineConcurrency) { PSharpRuntime.BugFinder = new TaskAwareBugFindingScheduler(this.Strategy); } else { PSharpRuntime.BugFinder = new BugFindingScheduler(this.Strategy); } StringWriter sw = null; if (this.AnalysisContext.Configuration.RedirectConsoleOutput && this.AnalysisContext.Configuration.Verbose < 2) { sw = this.RedirectConsoleOutput(); this.HasRedirectedConsoleOutput = true; } // Configure the test. PSharpRuntime.Configure(this.AnalysisContext.Configuration); // Start the test and wait for it to terminate. this.AnalysisContext.TestMethod.Invoke(null, null); PSharpRuntime.WaitMachines(); // Runs the liveness checker to find any liveness property violations. // Requires that no bug has been found, the scheduler terminated before // reaching the depth bound, and there is state caching is not active. if (this.AnalysisContext.Configuration.CheckLiveness && !this.AnalysisContext.Configuration.CacheProgramState && !PSharpRuntime.BugFinder.BugFound) { PSharpRuntime.LivenessChecker.Run(); } if (this.HasRedirectedConsoleOutput) { this.ResetOutput(); } this.ExploredSchedules++; this.ExploredDepth = PSharpRuntime.BugFinder.SchedulingPoints; if (PSharpRuntime.BugFinder.BugFound) { this.NumOfFoundBugs++; this.BugReport = PSharpRuntime.BugFinder.BugReport; } else { this.BugReport = ""; } if (this.Strategy.HasFinished()) { break; } this.Strategy.ConfigureNextIteration(); if (!this.AnalysisContext.Configuration.FullExploration && (this.NumOfFoundBugs > 0 || this.AnalysisContext.Configuration.PrintTrace)) { if (sw != null && !this.AnalysisContext.Configuration.SuppressTrace) { this.PrintTrace(sw); } break; } } }); Profiler.StartMeasuringExecutionTime(); task.Start(); try { if (this.AnalysisContext.Configuration.Timeout > 0) { task.Wait(this.AnalysisContext.Configuration.Timeout * 1000); } else { task.Wait(); } } catch (AggregateException ex) { if (this.HasRedirectedConsoleOutput) { this.ResetOutput(); } Output.Debug(ex.Message); Output.Debug(ex.StackTrace); ErrorReporter.ReportAndExit("Internal systematic testing exception. " + "Please send a bug report to the developers."); } finally { Profiler.StopMeasuringExecutionTime(); } }