/// <summary>
        /// Examine package settings to see if they are valid. An
        /// <see cref="NUnitEngineException"> is thrown if errors
        /// are found.
        /// </summary>
        /// <param name="package">The package whose settings are to be validated</param>
        public void ValidatePackageSettings(TestPackage package)
        {
            var sb = new StringBuilder();

            var frameworkSetting = package.GetSetting(EnginePackageSettings.RequestedRuntimeFramework, "");
            var runAsX86         = package.GetSetting(EnginePackageSettings.RunAsX86, false);

            if (frameworkSetting.Length > 0)
            {
                // Check requested framework is actually available
                if (!_runtimeService.IsAvailable(frameworkSetting))
                {
                    sb.Append($"\n* The requested framework {frameworkSetting} is unknown or not available.\n");
                }
            }

            // At this point, any unsupported settings in the TestPackage were
            // put there by the user, so we consider the package invalid. This
            // will be checked again as each project package is expanded and
            // treated as a warning in that case.
            foreach (string setting in package.Settings.Keys)
            {
                if (EnginePackageSettings.IsObsoleteSetting(setting))
                {
                    sb.Append($"\n* The {setting} setting is no longer supported.\n");
                }
            }

            if (sb.Length > 0)
            {
                throw new NUnitEngineException($"The following errors were detected in the TestPackage:\n{sb}");
            }
        }
        /// <summary>
        /// Expands a TestPackage based on a known project format, populating it
        /// with the project contents and any settings the project provides.
        /// Note that the package file path must be checked to ensure that it is
        /// a known project format before calling this method.
        /// </summary>
        /// <param name="package">The TestPackage to be expanded</param>
        public void ExpandProjectPackage(TestPackage package)
        {
            Guard.ArgumentNotNull(package, "package");
            Guard.ArgumentValid(package.SubPackages.Count == 0, "Package is already expanded", "package");

            string path = package.FullName;

            if (!File.Exists(path))
            {
                return;
            }

            IProject project = LoadFrom(path);

            Guard.ArgumentValid(project != null, "Unable to load project " + path, "package");

            string activeConfig = package.GetSetting(EnginePackageSettings.ActiveConfig, (string)null); // Need RunnerSetting

            if (activeConfig == null)
            {
                activeConfig = project.ActiveConfigName;
            }
            else
            {
                Guard.ArgumentValid(project.ConfigNames.Contains(activeConfig), $"Requested configuration {activeConfig} was not found", "package");
            }

            TestPackage tempPackage = project.GetTestPackage(activeConfig);

            // Add info about the configurations to the project package
            tempPackage.Settings[EnginePackageSettings.ActiveConfig] = activeConfig;
            tempPackage.Settings[EnginePackageSettings.ConfigNames]  = new List <string>(project.ConfigNames).ToArray();

            // The original package held overrides, so don't change them, but
            // do apply any settings specified within the project itself.
            foreach (string key in tempPackage.Settings.Keys)
            {
                // If an obsolete setting is returned from an older version of
                // a project loader extension, we ignore it entirely.
                // TODO: Give a warning message
                if (EnginePackageSettings.IsObsoleteSetting(key))
                {
                    continue;
                }

                if (package.Settings.ContainsKey(key)) // Don't override settings from command line
                {
                    continue;
                }

                package.Settings[key] = tempPackage.Settings[key];
            }

            foreach (var subPackage in tempPackage.SubPackages)
            {
                package.AddSubPackage(subPackage);
            }

            // If no config file is specified (by user or by the project loader) check
            // to see if one exists in same directory as the package. If so, we
            // use it. If not, each assembly will use its own config, if present.
            if (!package.Settings.ContainsKey(EnginePackageSettings.ConfigurationFile))
            {
                var packageConfig = Path.ChangeExtension(path, ".config");
                if (File.Exists(packageConfig))
                {
                    package.Settings[EnginePackageSettings.ConfigurationFile] = packageConfig;
                }
            }
        }