/// <summary>
        /// Executes all relevant patches in all known components. A patch is relevant only
        /// if its min and max versions encompass the currently installed version and the
        /// supported component version in the assembly is higher than the one in the database.
        /// </summary>
        /// <returns>Package execution results grouped by component id. It may contain multiple
        /// results for a single component if there are multiple patches in the assembly for
        /// subsequent component versions.</returns>
        internal static Dictionary <string, Dictionary <Version, PackagingResult> > ExecuteAssemblyPatches(
            RepositoryStartSettings settings = null)
        {
            //TODO: make sure that patches are executed exclusively
            // No other app domain should be able to start executing patches.

            return(ExecuteAssemblyPatches(RepositoryVersionInfo.GetAssemblyComponents(), settings));
        }
        private static void PatchAndCheck(string componentId,
                                          Version[] packageVersions,
                                          Version[] successfulPatchVersions,
                                          Version[] failedPatchVersions,
                                          Version expectedVersion)
        {
            Version initialVersion = null;

            // install mock packages
            if (packageVersions?.Any() ?? false)
            {
                // the first should be an install package, Patch packages will follow
                var install = true;

                foreach (var packageVersion in packageVersions)
                {
                    PackageManager.Storage.SavePackage(new Package
                    {
                        ComponentId      = componentId,
                        ComponentVersion = packageVersion,
                        ExecutionResult  = ExecutionResult.Successful,
                        PackageType      = install ? PackageType.Install : PackageType.Patch
                    });

                    install = false;
                }

                RepositoryVersionInfo.Reset();

                initialVersion = packageVersions.Last();
            }

            var installedComponent = RepositoryVersionInfo.Instance.Components.Single(c => c.ComponentId == componentId);

            if (installedComponent != null)
            {
                Assert.AreEqual(initialVersion, installedComponent.Version);
            }

            var assemblyComponent = RepositoryVersionInfo.GetAssemblyComponents()
                                    .Single(c => c.ComponentId == componentId);

            // ACTION
            var results = PackageManager.ExecuteAssemblyPatches(assemblyComponent);

            // reload version info
            installedComponent = RepositoryVersionInfo.Instance.Components.Single(c => c.ComponentId == componentId);

            if (successfulPatchVersions?.Any() ?? false)
            {
                // the component was successfully upgraded
                foreach (var patchVersion in successfulPatchVersions)
                {
                    Assert.IsTrue(results[patchVersion].Successful);
                }
            }
            if (failedPatchVersions?.Any() ?? false)
            {
                // there should be failed patch results
                foreach (var patchVersion in failedPatchVersions)
                {
                    Assert.IsFalse(results[patchVersion].Successful);
                }
            }

            if (!(successfulPatchVersions?.Any() ?? false) && !(failedPatchVersions?.Any() ?? false))
            {
                // no patch is expected
                Assert.IsFalse(results?.Keys.Any() ?? false);
            }

            if (installedComponent != null)
            {
                Assert.AreEqual(expectedVersion, installedComponent.Version);
            }
        }