Beispiel #1
0
        /// <summary>
        /// Rewrites the assemblies specified in the configuration.
        /// </summary>
        private static void RewriteAssemblies(Configuration configuration, RewritingOptions options)
        {
            try
            {
                if (options.AssemblyPaths.Count is 1)
                {
                    Console.WriteLine($". Rewriting {options.AssemblyPaths.First()}");
                }
                else
                {
                    Console.WriteLine($". Rewriting the assemblies specified in {options.AssembliesDirectory}");
                }

                var profiler = new Profiler();
                RewritingEngine.Run(options, configuration, profiler);
                Console.WriteLine($". Done rewriting in {profiler.Results()} sec");
            }
            catch (Exception ex)
            {
                if (ex is AggregateException aex)
                {
                    ex = aex.Flatten().InnerException;
                }

                Error.ReportAndExit(configuration.IsDebugVerbosityEnabled ? ex.ToString() : ex.Message);
            }
        }
Beispiel #2
0
        /// <summary>
        /// Rewrites the assemblies specified in the configuration.
        /// </summary>
        private static void RewriteAssemblies(Configuration configuration, RewritingOptions options)
        {
            try
            {
                string assemblyDir = null;
                var    fileList    = new HashSet <string>();
                if (!string.IsNullOrEmpty(configuration.AssemblyToBeAnalyzed))
                {
                    var fullPath = Path.GetFullPath(configuration.AssemblyToBeAnalyzed);
                    Console.WriteLine($". Rewriting {fullPath}");
                    assemblyDir = Path.GetDirectoryName(fullPath);
                    fileList.Add(fullPath);
                }
                else if (Directory.Exists(configuration.RewritingOptionsPath))
                {
                    assemblyDir = Path.GetFullPath(configuration.RewritingOptionsPath);
                    Console.WriteLine($". Rewriting the assemblies specified in {assemblyDir}");
                }

                RewritingOptions config = options;

                if (!string.IsNullOrEmpty(assemblyDir))
                {
                    // Create a new RewritingOptions object from command line args only.
                    config.AssembliesDirectory = assemblyDir;
                    config.OutputDirectory     = assemblyDir;
                    config.AssemblyPaths       = fileList;
                }
                else
                {
                    // Load options from JSON file.
                    config = RewritingOptions.ParseFromJSON(configuration.RewritingOptionsPath);
                    Console.WriteLine($". Rewriting the assemblies specified in {configuration.RewritingOptionsPath}");
                    config.PlatformVersion = configuration.PlatformVersion;

                    // Allow command line options to override the JSON configuration file options.
                    config.Merge(options);
                }

                RewritingEngine.Run(configuration, config);
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.StackTrace);
                Error.ReportAndExit(ex.Message);
            }
        }
        /// <summary>
        /// Write the rewriting options in a JSON file.
        /// </summary>
        private static void ProduceRewritingOptions(string path, IDictionary <int, HashSet <string> > assemblyFrequencies)
        {
            foreach (var(info, file) in GetTestProjectInfos(path))
            {
                var supportedAssemblies = new HashSet <string>();
                foreach (var assembly in info.Assemblies)
                {
                    if (!info.UnsupportedAssemblies.Contains(assembly))
                    {
                        supportedAssemblies.Add(assembly);
                    }
                }

                bool skip = false;
                foreach (var assembly in info.TestAssemblies)
                {
                    if (!supportedAssemblies.Contains(assembly))
                    {
                        skip = true;
                        break;
                    }
                }

                if (skip)
                {
                    continue;
                }

                var directoryPath = Path.GetDirectoryName(file);
                var options       = new RewritingOptions
                {
                    AssembliesPath       = ".",
                    OutputPath           = Path.Combine(".", "rewritten"),
                    IsRewritingUnitTests = true
                };

                foreach (var assembly in supportedAssemblies)
                {
                    options.Assemblies.Add(assembly);
                }

                string reportFile = $"{Path.Combine(directoryPath, RewritingOptions.FileName)}";
                Console.WriteLine($"... Writing rewriting options to '{reportFile}'");
                string report = JsonSerializer.Serialize(options, GetJsonSerializerOptions());
                File.WriteAllText(reportFile, report);
            }
        }
        public void TestJsonConfigurationDifferentOutputDirectory()
        {
            string configDirectory = GetJsonConfigurationDirectory("Configurations");
            string configPath      = Path.Combine(configDirectory, "test1.coyote.json");

            Assert.True(File.Exists(configPath));

            var options = RewritingOptions.ParseFromJSON(configPath);

            Assert.NotNull(options);
            options.PlatformVersion = GetPlatformVersion();

            Assert.Equal(Path.Combine(configDirectory, "Input"), options.AssembliesDirectory);
            Assert.Equal(Path.Combine(configDirectory, "Input", "Output"), options.OutputDirectory);
            Assert.False(options.IsReplacingAssemblies);

            Assert.Single(options.AssemblyPaths);
            Assert.Equal(Path.Combine(options.AssembliesDirectory, "Test.dll"), options.AssemblyPaths.First());
        }
        public void TestJsonConfigurationReplacingBinaries()
        {
            string configDirectory = GetJsonConfigurationDirectory("Configurations");
            string configPath      = Path.Combine(configDirectory, "test2.coyote.json");

            Assert.True(File.Exists(configPath), "File not found: " + configPath);

            var options = RewritingOptions.ParseFromJSON(configPath);

            Assert.NotNull(options);
            options.PlatformVersion = GetPlatformVersion();

            Assert.Equal(configDirectory, options.AssembliesDirectory);
            Assert.Equal(configDirectory, options.OutputDirectory);
            Assert.True(options.IsReplacingAssemblies);

            Assert.Equal(2, options.AssemblyPaths.Count());
            Assert.Equal(Path.Combine(options.AssembliesDirectory, "Test1.dll"),
                         options.AssemblyPaths.First());
        }
        public void TestJsonConfigurationDifferentOutputDirectory()
        {
            string configDirectory = GetJsonConfigurationDirectory("Configurations");
            string configPath      = Path.Combine(configDirectory, "test1.coyote.json");

            Assert.True(File.Exists(configPath));

            var options = RewritingOptions.ParseFromJSON(configPath);

            Assert.NotNull(options);
            options = options.Sanitize();

            Assert.Equal(Path.Combine(configDirectory, "Input"), options.AssembliesDirectory);
            Assert.Equal(Path.Combine(configDirectory, "Input", "Output"), options.OutputDirectory);
            Assert.False(options.IsReplacingAssemblies());

            Assert.Single(options.AssemblyPaths);
            Assert.Equal(Path.Combine(options.AssembliesDirectory, "Test.dll"), options.AssemblyPaths.First());

            // Ensure this option defaults to true.
            Assert.True(options.IsRewritingConcurrentCollections);
        }
        public void TestJsonConfigurationReplacingBinaries()
        {
            string configDirectory = GetJsonConfigurationDirectory("Configurations");
            string configPath      = Path.Combine(configDirectory, "test2.coyote.json");

            Assert.True(File.Exists(configPath), "File not found: " + configPath);

            var options = RewritingOptions.ParseFromJSON(configPath);

            Assert.NotNull(options);
            options = options.Sanitize();

            Assert.Equal(configDirectory, options.AssembliesDirectory);
            Assert.Equal(configDirectory, options.OutputDirectory);
            Assert.True(options.IsReplacingAssemblies());

            Assert.Equal(2, options.AssemblyPaths.Count());
            Assert.Equal(Path.Combine(options.AssembliesDirectory, "Test1.dll"),
                         options.AssemblyPaths.First());

            // Ensure this option can be set to false.
            Assert.False(options.IsRewritingConcurrentCollections);
        }
        /// <summary>
        /// Parses the command line options and returns a configuration.
        /// </summary>
        /// <param name="args">The command line arguments to parse.</param>
        /// <param name="configuration">The Configuration object populated with the parsed command line options.</param>
        /// <param name="options">The optional rewriting options.</param>
        internal bool Parse(string[] args, Configuration configuration, RewritingOptions options)
        {
            try
            {
                var result = this.Parser.ParseArguments(args);
                if (result != null)
                {
                    foreach (var arg in result)
                    {
                        UpdateConfigurationWithParsedArgument(configuration, options, arg);
                    }

                    SanitizeConfiguration(configuration);
                    return(true);
                }
            }
            catch (CommandLineException ex)
            {
                if ((from arg in ex.Result where arg.LongName == "version" select arg).Any())
                {
                    WriteVersion();
                    Environment.Exit(1);
                }
                else
                {
                    this.Parser.PrintHelp(Console.Out);
                    Error.ReportAndExit(ex.Message);
                }
            }
            catch (Exception ex)
            {
                this.Parser.PrintHelp(Console.Out);
                Error.ReportAndExit(ex.Message);
            }

            return(false);
        }
Beispiel #9
0
        private static void Main(string[] args)
        {
            // Save these so we can force output to happen even if TestingProcess has re-routed it.
            StdOut   = Console.Out;
            StdError = Console.Error;
            AppDomain.CurrentDomain.ProcessExit        += OnProcessExit;
            AppDomain.CurrentDomain.UnhandledException += OnUnhandledException;
            Console.CancelKeyPress += OnProcessCanceled;

            // Parses the command line options to get the configuration and rewriting options.
            var configuration = Configuration.Create();

            configuration.TelemetryServerPath = typeof(Program).Assembly.Location;
            var rewritingOptions = RewritingOptions.Create();

            var  result    = CoyoteTelemetryClient.GetOrCreateMachineId().Result;
            bool firstTime = result.Item2;

            var options = new CommandLineOptions();

            if (!options.Parse(args, configuration, rewritingOptions))
            {
                options.PrintHelp(Console.Out);
                if (!firstTime && configuration.EnableTelemetry)
                {
                    CoyoteTelemetryClient.PrintTelemetryMessage(Console.Out);
                }

                Environment.Exit(1);
            }

            if (!configuration.RunAsParallelBugFindingTask)
            {
                if (firstTime)
                {
                    string version = typeof(Runtime.CoyoteRuntime).Assembly.GetName().Version.ToString();
                    Console.WriteLine("Welcome to Microsoft Coyote {0}", version);
                    Console.WriteLine("----------------------------{0}", new string('-', version.Length));
                    if (configuration.EnableTelemetry)
                    {
                        CoyoteTelemetryClient.PrintTelemetryMessage(Console.Out);
                    }

                    TelemetryClient = new CoyoteTelemetryClient(configuration);
                    TelemetryClient.TrackEventAsync("welcome").Wait();
                }

                Console.WriteLine("Microsoft (R) Coyote version {0} for .NET{1}",
                                  typeof(CommandLineOptions).Assembly.GetName().Version,
                                  GetDotNetVersion());
                Console.WriteLine("Copyright (C) Microsoft Corporation. All rights reserved.\n");
            }

            SetEnvironment(configuration);

            switch (configuration.ToolCommand.ToLower())
            {
            case "test":
                RunTest(configuration);
                break;

            case "replay":
                ReplayTest(configuration);
                break;

            case "rewrite":
                RewriteAssemblies(configuration, rewritingOptions);
                break;

            case "telemetry":
                RunServer(configuration);
                break;
            }
        }
        /// <summary>
        /// Updates the configuration with the specified parsed argument.
        /// </summary>
        private static void UpdateConfigurationWithParsedArgument(Configuration configuration, RewritingOptions options, CommandLineArgument option)
        {
            switch (option.LongName)
            {
            case "command":
                configuration.ToolCommand = (string)option.Value;
                break;

            case "outdir":
                configuration.OutputFilePath = (string)option.Value;
                break;

            case "debug":
                configuration.IsDebugVerbosityEnabled = true;
                Debug.IsEnabled = true;
                break;

            case "verbosity":
                configuration.IsVerbose = true;
                string verbosity = (string)option.Value;
                switch (verbosity)
                {
                case "quiet":
                    configuration.IsVerbose = false;
                    break;

                case "detailed":
                    configuration.LogLevel = options.LogLevel = LogSeverity.Informational;
                    break;

                case "normal":
                    configuration.LogLevel = options.LogLevel = LogSeverity.Warning;
                    break;

                case "minimal":
                    configuration.LogLevel = options.LogLevel = LogSeverity.Error;
                    break;

                default:
                    Error.ReportAndExit($"Please give a valid value for 'verbosity' must be one of 'errors', 'warnings', or 'info', but found {verbosity}.");
                    break;
                }

                break;

            case "path":
                if (configuration.ToolCommand is "test" || configuration.ToolCommand is "replay")
                {
                    // In the case of 'coyote test' or 'replay', the path is the assembly to be tested.
                    configuration.AssemblyToBeAnalyzed = (string)option.Value;
                }
                else if (configuration.ToolCommand is "rewrite")
                {
                    // In the case of 'coyote rewrite', the path is the JSON configuration file
                    // with the binary rewriting options.
                    string filename = (string)option.Value;
                    if (Directory.Exists(filename))
                    {
                        // then we want to rewrite a whole folder full of dll's.
                        configuration.RewritingOptionsPath = filename;
                    }
                    else
                    {
                        string extension = Path.GetExtension(filename);
                        if (string.Compare(extension, ".json", StringComparison.OrdinalIgnoreCase) is 0)
                        {
                            configuration.RewritingOptionsPath = filename;
                        }
                        else if (string.Compare(extension, ".dll", StringComparison.OrdinalIgnoreCase) is 0 ||
                                 string.Compare(extension, ".exe", StringComparison.OrdinalIgnoreCase) is 0)
                        {
                            configuration.AssemblyToBeAnalyzed = filename;
                        }
                        else
                        {
                            Error.ReportAndExit("Please give a valid .dll or JSON configuration file for binary rewriting.");
                        }
                    }
Beispiel #11
0
        /// <summary>
        /// Initializes a new instance of the <see cref="CommandLineParser"/> class.
        /// </summary>
        internal CommandLineParser(string[] args)
        {
            this.Configuration    = Configuration.Create();
            this.RewritingOptions = RewritingOptions.Create();
            this.Arguments        = new Dictionary <string, Argument>();
            this.Options          = new Dictionary <string, Option>();

            var allowedVerbosityLevels = new HashSet <string>
            {
                "quiet",
                "minimal",
                "normal",
                "detailed"
            };

            var verbosityOption = new Option <string>(
                aliases: new[] { "-v", "--verbosity" },
                getDefaultValue: () => "quiet",
                description: "Enable verbosity with an optional verbosity level. " +
                $"Allowed values are {string.Join(", ", allowedVerbosityLevels)}. " +
                "Skipping the argument sets the verbosity level to 'detailed'.")
            {
                ArgumentHelpName = "LEVEL",
                Arity            = ArgumentArity.ZeroOrOne
            };

            var debugOption = new Option <bool>(aliases: new[] { "-d", "--debug" })
            {
                Arity = ArgumentArity.Zero
            };

            // Add validators.
            verbosityOption.AddValidator(result => ValidateOptionValueIsAllowed(result, allowedVerbosityLevels));

            // Create the commands.
            this.TestCommand    = this.CreateTestCommand(this.Configuration);
            this.ReplayCommand  = this.CreateReplayCommand();
            this.RewriteCommand = this.CreateRewriteCommand();

            // Create the root command.
            var rootCommand = new RootCommand("The Coyote systematic testing tool.\n\n" +
                                              $"Learn how to use Coyote at {LearnAboutCoyoteUrl}.\nLearn what is new at {LearnWhatIsNewUrl}.");

            this.AddGlobalOption(rootCommand, verbosityOption);
            this.AddGlobalOption(rootCommand, debugOption);
            rootCommand.AddCommand(this.TestCommand);
            rootCommand.AddCommand(this.ReplayCommand);
            rootCommand.AddCommand(this.RewriteCommand);
            rootCommand.TreatUnmatchedTokensAsErrors = true;

            var commandLineBuilder = new CommandLineBuilder(rootCommand);

            commandLineBuilder.UseDefaults();

            var parser = commandLineBuilder.Build();

            this.Results = parser.Parse(args);
            if (this.Results.Errors.Any() || IsHelpRequested(this.Results))
            {
                // There are parsing errors, so invoke the result to print the errors and help message.
                this.Results.Invoke();
                this.IsSuccessful = false;
            }
            else
            {
                // There were no errors, so use the parsed results to update the default configurations.
                this.UpdateConfigurations(this.Results);
                this.IsSuccessful = true;
            }
        }