示例#1
0
        /// <summary>
        /// Gathers the exploration strategy statistics for
        /// the latest testing iteration.
        /// </summary>
        /// <param name="runtime">BugFindingRuntime</param>
        private void GatherIterationStatistics(BugFindingRuntime runtime)
        {
            TestReport report = runtime.Scheduler.GetReport();

            report.CoverageInfo.Merge(runtime.CoverageInfo);
            this.TestReport.Merge(report);
        }
示例#2
0
        /// <summary>
        /// Emits race instrumentation traces.
        /// </summary>
        /// <param name="runtime">BugFindingRuntime</param>
        /// <param name="iteration">Iteration</param>
        private void EmitRaceInstrumentationTraces(BugFindingRuntime runtime, int iteration)
        {
            string name = Path.GetFileNameWithoutExtension(this.Assembly.Location);

            name += "_" + base.Configuration.TestingProcessId;

            string directoryPath = base.GetRuntimeTracesDirectory();

            foreach (var kvp in runtime.MachineActionTraceMap)
            {
                Debug.WriteLine($"<RaceTracing> Machine id '{kvp.Key}'");

                foreach (var actionTrace in kvp.Value)
                {
                    if (actionTrace.Type == MachineActionType.InvocationAction)
                    {
                        Debug.WriteLine($"<RaceTracing> Action '{actionTrace.ActionName}' " +
                                        $"'{actionTrace.ActionId}'");
                    }
                }

                if (kvp.Value.Count > 0)
                {
                    string path = directoryPath + name + "_iteration_" + iteration +
                                  "_machine_" + kvp.Key.GetHashCode() + ".osl";
                    using (FileStream stream = File.Open(path, FileMode.Create))
                    {
                        DataContractSerializer serializer = new DataContractSerializer(kvp.Value.GetType());
                        serializer.WriteObject(stream, kvp.Value);
                        Debug.WriteLine($"..... Writing {path}");
                    }
                }
            }
        }
示例#3
0
        /// <summary>
        /// Constructs a reproducable trace.
        /// </summary>
        /// <param name="runtime">BugFindingRuntime</param>
        /// <param name="logger">InMemoryLogger</param>
        private void ConstructReproducableTrace(BugFindingRuntime runtime, InMemoryLogger logger)
        {
            this.ReadableTrace  = logger.ToString();
            this.ReadableTrace += this.TestReport.GetText(base.Configuration, "<StrategyLog>");
            this.BugTrace       = runtime.BugTrace;

            StringBuilder stringBuilder = new StringBuilder();

            if (this.Strategy.IsFair())
            {
                stringBuilder.Append("--fair-scheduling").Append(Environment.NewLine);
            }

            if (base.Configuration.CacheProgramState)
            {
                stringBuilder.Append("--state-caching").Append(Environment.NewLine);
                stringBuilder.Append("--liveness-temperature-threshold:" +
                                     base.Configuration.LivenessTemperatureThreshold).
                Append(Environment.NewLine);
            }
            else
            {
                stringBuilder.Append("--liveness-temperature-threshold:" +
                                     base.Configuration.LivenessTemperatureThreshold).
                Append(Environment.NewLine);
            }

            if (!base.Configuration.TestMethodName.Equals(""))
            {
                stringBuilder.Append("--test-method:" +
                                     base.Configuration.TestMethodName).
                Append(Environment.NewLine);
            }

            for (int idx = 0; idx < runtime.ScheduleTrace.Count; idx++)
            {
                ScheduleStep step = runtime.ScheduleTrace[idx];
                if (step.Type == ScheduleStepType.SchedulingChoice)
                {
                    stringBuilder.Append($"{step.ScheduledMachineId.Type}" +
                                         $"({step.ScheduledMachineId.Value})");
                }
                else if (step.BooleanChoice != null)
                {
                    stringBuilder.Append(step.BooleanChoice.Value);
                }
                else
                {
                    stringBuilder.Append(step.IntegerChoice.Value);
                }

                if (idx < runtime.ScheduleTrace.Count - 1)
                {
                    stringBuilder.Append(Environment.NewLine);
                }
            }

            this.ReproducableTrace = stringBuilder.ToString();
        }
示例#4
0
 /// <summary>
 /// Constructor.
 /// </summary>
 /// <param name="runtime">BugFindingRuntime</param>
 /// <param name="strategy">SchedulingStrategy</param>
 internal BugFindingScheduler(BugFindingRuntime runtime, ISchedulingStrategy strategy)
 {
     this.Runtime                  = runtime;
     this.Strategy                 = strategy;
     this.TaskMap                  = new ConcurrentDictionary <int, MachineInfo>();
     this.CompletionSource         = new TaskCompletionSource <bool>();
     this.IsSchedulerRunning       = true;
     this.BugFound                 = false;
     this.HasFullyExploredSchedule = false;
 }
示例#5
0
 /// <summary>
 /// Constructor.
 /// </summary>
 /// <param name="runtime">BugFindingRuntime</param>
 /// <param name="strategy">SchedulingStrategy</param>
 internal BugFindingScheduler(BugFindingRuntime runtime, ISchedulingStrategy strategy)
 {
     this.Runtime                  = runtime;
     this.Strategy                 = strategy;
     this.SchedulableInfoMap       = new Dictionary <ulong, SchedulableInfo>();
     this.CompletionSource         = new TaskCompletionSource <bool>();
     this.IsSchedulerRunning       = true;
     this.BugFound                 = false;
     this.HasFullyExploredSchedule = false;
 }
示例#6
0
        /// <summary>
        /// Initializes the shared counter.
        /// </summary>
        /// <param name="value">Initial value</param>
        /// <param name="Runtime">BugFindingRuntime</param>
        public MockSharedCounter(int value, BugFindingRuntime Runtime)
        {
            this.Runtime   = Runtime;
            CounterMachine = Runtime.CreateMachine(typeof(SharedCounterMachine));

            var currentMachine = Runtime.GetCurrentMachine();

            Runtime.SendEvent(CounterMachine, SharedCounterEvent.SetEvent(currentMachine.Id, value));
            currentMachine.Receive(typeof(SharedCounterResponseEvent)).Wait();
        }
示例#7
0
        /// <summary>
        /// Constructs a reproducable trace.
        /// </summary>
        /// <param name="runtime">BugFindingRuntime</param>
        private void ConstructReproducableTrace(BugFindingRuntime runtime)
        {
            StringBuilder stringBuilder = new StringBuilder();

            if (this.Strategy.IsFair())
            {
                stringBuilder.Append("--fair-scheduling").Append(Environment.NewLine);
            }

            if (base.Configuration.EnableCycleDetection)
            {
                stringBuilder.Append("--cycle-detection").Append(Environment.NewLine);
                stringBuilder.Append("--liveness-temperature-threshold:" +
                                     base.Configuration.LivenessTemperatureThreshold).
                Append(Environment.NewLine);
            }
            else
            {
                stringBuilder.Append("--liveness-temperature-threshold:" +
                                     base.Configuration.LivenessTemperatureThreshold).
                Append(Environment.NewLine);
            }

            if (!base.Configuration.TestMethodName.Equals(""))
            {
                stringBuilder.Append("--test-method:" +
                                     base.Configuration.TestMethodName).
                Append(Environment.NewLine);
            }

            for (int idx = 0; idx < runtime.ScheduleTrace.Count; idx++)
            {
                ScheduleStep step = runtime.ScheduleTrace[idx];
                if (step.Type == ScheduleStepType.SchedulingChoice)
                {
                    stringBuilder.Append($"({step.ScheduledMachineId})");
                }
                else if (step.BooleanChoice != null)
                {
                    stringBuilder.Append(step.BooleanChoice.Value);
                }
                else
                {
                    stringBuilder.Append(step.IntegerChoice.Value);
                }

                if (idx < runtime.ScheduleTrace.Count - 1)
                {
                    stringBuilder.Append(Environment.NewLine);
                }
            }

            this.ReproducableTrace = stringBuilder.ToString();
        }
示例#8
0
 /// <summary>
 /// Initializes the shared dictionary.
 /// </summary>
 /// <param name="comparer">Comparre for keys</param>
 /// <param name="Runtime">BugFindingRuntime</param>
 public MockSharedDictionary(IEqualityComparer <TKey> comparer, BugFindingRuntime Runtime)
 {
     this.Runtime = Runtime;
     if (comparer != null)
     {
         DictionaryMachine = Runtime.CreateMachine(typeof(SharedDictionaryMachine <TKey, TValue>),
                                                   SharedDictionaryEvent.InitEvent(comparer));
     }
     else
     {
         DictionaryMachine = Runtime.CreateMachine(typeof(SharedDictionaryMachine <TKey, TValue>));
     }
 }
示例#9
0
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="runtime">BugFindingRuntime</param>
        /// <param name="schedulingStrategy">ISchedulingStrategy</param>
        internal LivenessChecker(BugFindingRuntime runtime, ISchedulingStrategy schedulingStrategy)
        {
            this.Runtime = runtime;

            this.Monitors       = new List <Monitor>();
            this.PotentialCycle = new List <Tuple <ScheduleStep, State> >();
            this.HotMonitors    = new HashSet <Monitor>();

            this.LivenessTemperature = 0;
            this.EndOfCycleIndex     = 0;
            this.CurrentCycleIndex   = 0;
            this.SchedulingStrategy  = schedulingStrategy;

            this.Seed   = this.Runtime.Configuration.RandomSchedulingSeed ?? DateTime.Now.Millisecond;
            this.Random = new DefaultRandomNumberGenerator(this.Seed);
        }
示例#10
0
        /// <summary>
        /// Runs the next testing iteration.
        /// </summary>
        /// <param name="iteration">Iteration</param>
        private void RunNextIteration(int iteration)
        {
            if (this.ShouldPrintIteration(iteration + 1))
            {
                base.Logger.WriteLine($"..... Iteration #{iteration + 1}");
            }

            // Runtime used to serialize and test the program in this iteration.
            BugFindingRuntime runtime = null;

            // Logger used to intercept the program output if no custom logger
            // is installed and if verbosity is turned off.
            InMemoryLogger runtimeLogger = null;

            // Gets a handle to the standard output and error streams.
            var stdOut = Console.Out;
            var stdErr = Console.Error;

            try
            {
                // Creates a new instance of the bug-finding runtime.
                runtime = new BugFindingRuntime(base.Configuration, base.Strategy, base.Reporter);

                if (base.Configuration.EnableDataRaceDetection)
                {
                    // Create a reporter to monitor interesting operations for race detection
                    this.Reporter.SetRuntime(runtime);
                }

                // If verbosity is turned off, then intercept the program log, and also dispose
                // the standard output and error streams.
                if (base.Configuration.Verbose < 2)
                {
                    runtimeLogger = new InMemoryLogger();
                    runtime.SetLogger(runtimeLogger);

                    // Sets the scheduling strategy logger to the in-memory logger.
                    base.SchedulingStrategyLogger.SetLogger(runtimeLogger);

                    var writer = new LogWriter(new DisposingLogger());
                    Console.SetOut(writer);
                    Console.SetError(writer);
                }

                // Runs the test inside the P# test-harness machine.
                runtime.RunTestHarness(base.TestMethod, base.TestAction);

                // Wait for the test to terminate.
                runtime.Wait();

                if (runtime.Scheduler.BugFound)
                {
                    base.ErrorReporter.WriteErrorLine(runtime.Scheduler.BugReport);
                }

                // Invokes user-provided cleanup for this iteration.
                if (base.TestIterationDisposeMethod != null)
                {
                    // Disposes the test state.
                    base.TestIterationDisposeMethod.Invoke(null, null);
                }

                // Invoke the per iteration callbacks, if any.
                foreach (var callback in base.PerIterationCallbacks)
                {
                    callback(iteration);
                }

                if (base.Configuration.RaceFound)
                {
                    string message = IO.Utilities.Format("Found a race");
                    runtime.Scheduler.NotifyAssertionFailure(message, false);
                    foreach (var report in this.TestReport.BugReports)
                    {
                        runtime.Logger.WriteLine(report);
                    }
                }

                // Checks that no monitor is in a hot state at termination. Only
                // checked if no safety property violations have been found.
                if (!runtime.Scheduler.BugFound)
                {
                    runtime.AssertNoMonitorInHotStateAtTermination();
                }

                this.GatherIterationStatistics(runtime);

                if (base.TestReport.NumOfFoundBugs > 0)
                {
                    if (runtimeLogger != null)
                    {
                        this.ReadableTrace  = runtimeLogger.ToString();
                        this.ReadableTrace += this.TestReport.GetText(base.Configuration, "<StrategyLog>");
                    }

                    this.BugTrace = runtime.BugTrace;
                    this.ConstructReproducableTrace(runtime);
                }
            }
            finally
            {
                if (base.Configuration.Verbose < 2)
                {
                    // Restores the standard output and error streams.
                    Console.SetOut(stdOut);
                    Console.SetError(stdErr);
                }

                if (base.Configuration.PerformFullExploration && runtime.Scheduler.BugFound)
                {
                    base.Logger.WriteLine($"..... Iteration #{iteration + 1} " +
                                          $"triggered bug #{base.TestReport.NumOfFoundBugs} " +
                                          $"[task-{this.Configuration.TestingProcessId}]");
                }

                // Resets the scheduling strategy logger to the default logger.
                base.SchedulingStrategyLogger.ResetToDefaultLogger();

                // Cleans up the runtime before the next iteration starts.
                runtimeLogger?.Dispose();
                runtime?.Dispose();
            }
        }
示例#11
0
 /// <summary>
 /// Constructor.
 /// </summary>
 /// <param name="runtime">BugFindingRuntime</param>
 internal StateCache(BugFindingRuntime runtime)
 {
     this.Runtime      = runtime;
     this.StateMap     = new Dictionary <ScheduleStep, State>();
     this.Fingerprints = new HashSet <Fingerprint>();
 }
示例#12
0
        /// <summary>
        /// Creates a bug-reproducing task.
        /// </summary>
        /// <returns>Task</returns>
        private Task CreateBugReproducingTask()
        {
            Task task = new Task(() =>
            {
                // Runtime used to serialize and test the program.
                BugFindingRuntime runtime = null;

                // Logger used to intercept the program output if no custom logger
                // is installed and if verbosity is turned off.
                InMemoryLogger runtimeLogger = null;

                // Gets a handle to the standard output and error streams.
                var stdOut = Console.Out;
                var stdErr = Console.Error;

                try
                {
                    if (base.TestInitMethod != null)
                    {
                        // Initializes the test state.
                        base.TestInitMethod.Invoke(null, new object[] { });
                    }

                    // Creates a new instance of the bug-finding runtime.
                    if (base.TestRuntimeFactoryMethod != null)
                    {
                        runtime = (BugFindingRuntime)base.TestRuntimeFactoryMethod.Invoke(null,
                                                                                          new object[] { base.Configuration, base.Strategy, base.Reporter });
                    }
                    else
                    {
                        runtime = new BugFindingRuntime(base.Configuration, base.Strategy, base.Reporter);
                    }


                    // If verbosity is turned off, then intercept the program log, and also redirect
                    // the standard output and error streams into the runtime logger.
                    if (base.Configuration.Verbose < 2)
                    {
                        runtimeLogger = new InMemoryLogger();
                        runtime.SetLogger(runtimeLogger);

                        var writer = new LogWriter(new DisposingLogger());
                        Console.SetOut(writer);
                        Console.SetError(writer);
                    }

                    // Runs the test inside the P# test-harness machine.
                    runtime.RunTestHarness(base.TestMethod, base.TestAction);

                    // Wait for the test to terminate.
                    runtime.Wait();

                    // Invokes user-provided cleanup for this iteration.
                    if (base.TestIterationDisposeMethod != null)
                    {
                        // Disposes the test state.
                        base.TestIterationDisposeMethod.Invoke(null, new object[] { });
                    }

                    // Invokes user-provided cleanup for all iterations.
                    if (base.TestDisposeMethod != null)
                    {
                        // Disposes the test state.
                        base.TestDisposeMethod.Invoke(null, new object[] { });
                    }

                    this.InternalError = (base.Strategy as ReplayStrategy).ErrorText;

                    // Checks that no monitor is in a hot state at termination. Only
                    // checked if no safety property violations have been found.
                    if (!runtime.Scheduler.BugFound && this.InternalError.Length == 0)
                    {
                        runtime.AssertNoMonitorInHotStateAtTermination();
                    }

                    if (runtime.Scheduler.BugFound && this.InternalError.Length == 0)
                    {
                        base.ErrorReporter.WriteErrorLine(runtime.Scheduler.BugReport);
                    }

                    TestReport report = runtime.Scheduler.GetReport();
                    report.CoverageInfo.Merge(runtime.CoverageInfo);
                    this.TestReport.Merge(report);
                }
                catch (TargetInvocationException ex)
                {
                    if (!(ex.InnerException is TaskCanceledException))
                    {
                        ExceptionDispatchInfo.Capture(ex.InnerException).Throw();
                    }
                }
                finally
                {
                    if (base.Configuration.Verbose < 2)
                    {
                        // Restores the standard output and error streams.
                        Console.SetOut(stdOut);
                        Console.SetError(stdErr);
                    }

                    // Cleans up the runtime.
                    runtimeLogger?.Dispose();
                    runtime?.Dispose();
                }
            }, base.CancellationTokenSource.Token);

            return(task);
        }
示例#13
0
        /// <summary>
        /// Runs the next testing iteration.
        /// </summary>
        /// <param name="iteration">Iteration</param>
        private void RunNextIteration(int iteration)
        {
            if (this.ShouldPrintIteration(iteration + 1))
            {
                base.Logger.WriteLine($"..... Iteration #{iteration + 1}");
            }

            // Runtime used to serialize and test the program in this iteration.
            BugFindingRuntime runtime = null;

            // Logger used to intercept the program output if no custom logger
            // is installed and if verbosity is turned off.
            InMemoryLogger runtimeLogger = null;

            // Gets a handle to the standard output and error streams.
            var stdOut = Console.Out;
            var stdErr = Console.Error;

            try
            {
                // Creates a new instance of the bug-finding runtime.
                runtime = new BugFindingRuntime(base.Configuration, base.Strategy);

                // If verbosity is turned off, then intercept the program log, and also dispose
                // the standard output and error streams.
                if (base.Configuration.Verbose < 2)
                {
                    runtimeLogger = new InMemoryLogger();
                    runtime.SetLogger(runtimeLogger);

                    var writer = new LogWriter(new DisposingLogger());
                    Console.SetOut(writer);
                    Console.SetError(writer);
                }

                // Runs the test inside the P# test-harness machine.
                runtime.RunTestHarness(base.TestMethod, base.TestAction);

                // Wait for the test to terminate.
                runtime.Wait();

                if (runtime.Scheduler.BugFound)
                {
                    base.ErrorReporter.WriteErrorLine(runtime.Scheduler.BugReport);
                }

                if (this.Configuration.EnableDataRaceDetection)
                {
                    this.EmitRaceInstrumentationTraces(runtime, iteration);
                }

                // Invokes user-provided cleanup for this iteration.
                if (base.TestIterationDisposeMethod != null)
                {
                    // Disposes the test state.
                    base.TestIterationDisposeMethod.Invoke(null, null);
                }

                // Invoke the per iteration callbacks, if any.
                foreach (var callback in base.PerIterationCallbacks)
                {
                    callback(iteration);
                }

                // TODO: Clean this up.
                base.Configuration.RaceDetectionCallback?.Invoke();
                if (base.Configuration.RaceFound)
                {
                    string message = IO.Utilities.Format("Found a race");
                    runtime.Scheduler.NotifyAssertionFailure(message, false);
                }

                // Checks for any liveness property violations. Requires
                // that the program has terminated and no safety property
                // violations have been found.
                if (!runtime.Scheduler.BugFound)
                {
                    runtime.LivenessChecker.CheckLivenessAtTermination();
                }

                this.GatherIterationStatistics(runtime);

                if (runtimeLogger != null && base.TestReport.NumOfFoundBugs > 0 &&
                    !base.Configuration.PerformFullExploration && !base.Configuration.SuppressTrace)
                {
                    this.ConstructReproducableTrace(runtime, runtimeLogger);
                }
                else if (runtimeLogger != null && base.Configuration.PrintTrace)
                {
                    this.ConstructReproducableTrace(runtime, runtimeLogger);
                }
            }
            finally
            {
                if (base.Configuration.Verbose < 2)
                {
                    // Restores the standard output and error streams.
                    Console.SetOut(stdOut);
                    Console.SetError(stdErr);
                }

                if (base.Configuration.PerformFullExploration && runtime.Scheduler.BugFound)
                {
                    base.Logger.WriteLine($"..... Iteration #{iteration + 1} " +
                                          $"triggered bug #{base.TestReport.NumOfFoundBugs} " +
                                          $"[task-{this.Configuration.TestingProcessId}]");
                }

                // Cleans up the runtime before the next iteration starts.
                runtimeLogger?.Dispose();
                runtime?.Dispose();
            }
        }
示例#14
0
 /// <summary>
 /// Initializes the shared counter.
 /// </summary>
 /// <param name="value">Initial value</param>
 /// <param name="Runtime">BugFindingRuntime</param>
 public MockSharedCounter(int value, BugFindingRuntime Runtime)
 {
     this.Runtime   = Runtime;
     CounterMachine = Runtime.CreateMachine(typeof(SharedCounterMachine));
     Runtime.SendEvent(CounterMachine, SharedCounterEvent.SetEvent(value));
 }
示例#15
0
 public void SetRuntime(PSharpRuntime runtime)
 {
     runtime.Assert((runtime as BugFindingRuntime) != null,
                    "Requires passed runtime to support method GetCurrentMachineId");
     this.Runtime = runtime as BugFindingRuntime;
 }
 /// <summary>
 /// Constructor.
 /// </summary>
 /// <param name="runtime">PSharpBugFindingRuntime</param>
 /// <param name="taskMap">Task map</param>
 internal AsynchronousTaskScheduler(BugFindingRuntime runtime, ConcurrentDictionary <int, Machine> taskMap)
 {
     this.Runtime = runtime;
     this.TaskMap = taskMap;
 }
示例#17
0
 /// <summary>
 /// Constructor.
 /// </summary>
 /// <param name="runtime">BugFindingRuntime</param>
 internal StateCache(BugFindingRuntime runtime)
 {
     Runtime      = runtime;
     Fingerprints = new HashSet <Fingerprint>();
 }
示例#18
0
 /// <summary>
 /// Initializes the shared register.
 /// </summary>
 /// <param name="value">Initial value</param>
 /// <param name="Runtime">Runtime</param>
 public MockSharedRegister(T value, BugFindingRuntime Runtime)
 {
     this.Runtime    = Runtime;
     registerMachine = Runtime.CreateMachine(typeof(SharedRegisterMachine <T>));
     Runtime.SendEvent(registerMachine, SharedRegisterEvent.SetEvent(value));
 }