public void When_a_download_is_failing_error_condition_shall_be_shown_instead_if_status()
        {
            TestPrerequisite[] TestPrerequisites = { new TestPrerequisite("Name1", false, false, "Down1"), new TestPrerequisite("Name2", false, false, "Down2") };

            InstallWindowModel Model = new InstallWindowModel(TestPrerequisites, (downloadId, progressCallback, downloadedCallback) => this.DownloadFunc(downloadId, progressCallback, downloadedCallback, TestPrerequisites.First(_ => _.DownloadId == downloadId)));

            Assert.That(Model.Status, Is.TypeOf <InstallWindowModel.PreperationStatus>());
            ((InstallWindowModel.PreperationStatus)Model.Status).SetUpSystemCommand.Execute(null);
            InstallWindowModelTest.WaitForStateChange <InstallWindowModel.InstallationStatus>(Model);
            ManualResetEvent StatusChangeEvent = new ManualResetEvent(false);

            Model.PropertyChanged += (s, e) =>
            {
                if (e.PropertyName == nameof(InstallWindowModel.Status))
                {
                    StatusChangeEvent.Set();
                }
            };


            Assert.That(((InstallWindowModel.InstallationStatus)Model.Status).Installation, Is.TypeOf <InstallWindowModel.InstallationStatus.InstallationWaitingForDownloadStatus>());
            Assert.That(((InstallWindowModel.InstallationStatus)Model.Status).Download, Is.TypeOf <InstallWindowModel.InstallationStatus.DownloadingStatus>());

            TestPrerequisites[1].MarkDownloaded(false);

            InstallWindowModelTest.WaitForStateChange <InstallWindowModel.InstallationErrorStatus>(Model);

            InstallWindowModel.StatusBase Status = Model.Status;
            //Shall not throw exception, but leave the status a-is
            TestPrerequisites[0].UpdateProgress(.5);
            TestPrerequisites[0].MarkDownloaded(true);

            Assert.That(Model.Status, Is.SameAs(Status));
        }
        public void When_install_of_a_prerequisite_fails_the_state_shall_move_into_error_status()
        {
            TestPrerequisite[] TestPrerequisites = { new TestPrerequisite("Name1", false, false, null) };
            InstallWindowModel Model             = new InstallWindowModel(TestPrerequisites, (downloadId, progressCallback, downloadedCallback) => this.DownloadFunc(downloadId, progressCallback, downloadedCallback, TestPrerequisites.First(_ => _.DownloadId == downloadId)));

            Assert.That(Model.Status, Is.TypeOf <InstallWindowModel.PreperationStatus>());
            ((InstallWindowModel.PreperationStatus)Model.Status).SetUpSystemCommand.Execute(null);

            InstallWindowModelTest.WaitForStateChange <InstallWindowModel.InstallationStatus>(Model);

            TestPrerequisites[0].MarkInstalled(false);

            InstallWindowModelTest.WaitForStateChange <InstallWindowModel.InstallationErrorStatus>(Model);
            Assert.That(((InstallWindowModel.InstallationErrorStatus)Model.Status).Message, Is.EqualTo("Install FAIL!"));
        }
        public void When_administrative_rights_are_needded_those_prerequisites_shall_be_delegated_to_child_process_with_admin_rights()
        {
            TestPrerequisite[] TestPrerequisites = { new TestPrerequisite("Name1", true, false, null), new TestPrerequisite("Name2", false, false, null) };
            AdminProcess       AdminProcess      = new AdminProcess();
            InstallWindowModel Model             = new InstallWindowModel(TestPrerequisites, (downloadId, progressCallback, downloadedCallback) => this.DownloadFunc(downloadId, progressCallback, downloadedCallback, TestPrerequisites.First(_ => _.DownloadId == downloadId)), AdminProcess);

            Assert.That(Model.Status, Is.TypeOf <InstallWindowModel.PreperationStatus>());
            Assert.That(((InstallWindowModel.PreperationStatus)Model.Status).IsAdminRequired, Is.True);
            ((InstallWindowModel.PreperationStatus)Model.Status).SetUpSystemCommand.Execute(null);
            InstallWindowModelTest.WaitForStateChange <InstallWindowModel.InstallationStatus>(Model);

            AdminProcess.WaitInstallStarted();
            AdminProcess.MarkInstalled(true);

            TestPrerequisites[1].MarkInstalled(true);

            InstallWindowModelTest.WaitForStateChange <InstallWindowModel.InstallationSuccessStatus>(Model);
        }
        public void When_download_is_needed_installation_shall_wait_but_if_download_is_finished_while_installation_happens_it_shall_continue_immediately()
        {
            TestPrerequisite[] TestPrerequisites = { new TestPrerequisite("Name1", false, false, "Down1"), new TestPrerequisite("Name2", false, false, "Down2") };

            InstallWindowModel Model = new InstallWindowModel(TestPrerequisites, (downloadId, progressCallback, downloadedCallback) => this.DownloadFunc(downloadId, progressCallback, downloadedCallback, TestPrerequisites.First(_ => _.DownloadId == downloadId)));

            Assert.That(Model.Status, Is.TypeOf <InstallWindowModel.PreperationStatus>());
            ((InstallWindowModel.PreperationStatus)Model.Status).SetUpSystemCommand.Execute(null);
            InstallWindowModelTest.WaitForStateChange <InstallWindowModel.InstallationStatus>(Model);
            ManualResetEvent StatusChangeEvent = new ManualResetEvent(false);

            Model.PropertyChanged += (s, e) =>
            {
                if (e.PropertyName == nameof(InstallWindowModel.Status))
                {
                    StatusChangeEvent.Set();
                }
            };


            Assert.That(((InstallWindowModel.InstallationStatus)Model.Status).Installation, Is.TypeOf <InstallWindowModel.InstallationStatus.InstallationWaitingForDownloadStatus>());
            Assert.That(((InstallWindowModel.InstallationStatus)Model.Status).Download, Is.TypeOf <InstallWindowModel.InstallationStatus.DownloadingStatus>());

            TestPrerequisites[1].MarkDownloaded(true);

            InstallWindowModelTest.WaitForStateChange <InstallWindowModel.InstallationStatus.InstallingStatus>(Model);

            Assert.That(((InstallWindowModel.InstallationStatus.InstallingStatus)((InstallWindowModel.InstallationStatus)Model.Status).Installation).InstallationStatus, Is.EqualTo("Name2"));
            Assert.That(((InstallWindowModel.InstallationStatus)Model.Status).Download, Is.TypeOf <InstallWindowModel.InstallationStatus.DownloadingStatus>());

            TestPrerequisites[0].MarkDownloaded(true);
            InstallWindowModelTest.WaitForStateChange <InstallWindowModel.InstallationStatus.DownloadFinishedStatus>(Model);

            StatusChangeEvent.Reset();
            TestPrerequisites[1].MarkInstalled(true);
            StatusChangeEvent.WaitOne(TimeSpan.FromSeconds(10));

            Assert.That(((InstallWindowModel.InstallationStatus.InstallingStatus)((InstallWindowModel.InstallationStatus)Model.Status).Installation).InstallationStatus, Is.EqualTo("Name1"));
            Assert.That(((InstallWindowModel.InstallationStatus)Model.Status).Download, Is.TypeOf <InstallWindowModel.InstallationStatus.DownloadFinishedStatus>());

            TestPrerequisites[0].MarkInstalled(true);

            InstallWindowModelTest.WaitForStateChange <InstallWindowModel.InstallationSuccessStatus>(Model);
        }
        public void When_download_is_needed_installation_shall_wait_but_first_downloaded_shall_be_installed_first()
        {
            TestPrerequisite[] TestPrerequisites = { new TestPrerequisite("Name1", false, false, "Down1"), new TestPrerequisite("Name2", false, false, "Down2") };

            InstallWindowModel Model = new InstallWindowModel(TestPrerequisites, (downloadId, progressCallback, downloadedCallback) => this.DownloadFunc(downloadId, progressCallback, downloadedCallback, TestPrerequisites.First(_ => _.DownloadId == downloadId)));

            Assert.That(Model.Status, Is.TypeOf <InstallWindowModel.PreperationStatus>());
            ((InstallWindowModel.PreperationStatus)Model.Status).SetUpSystemCommand.Execute(null);
            InstallWindowModelTest.WaitForStateChange <InstallWindowModel.InstallationStatus>(Model);

            Assert.That(((InstallWindowModel.InstallationStatus)Model.Status).Installation, Is.TypeOf <InstallWindowModel.InstallationStatus.InstallationWaitingForDownloadStatus>());
            Assert.That(((InstallWindowModel.InstallationStatus)Model.Status).Download, Is.TypeOf <InstallWindowModel.InstallationStatus.DownloadingStatus>());

            TestPrerequisites[1].MarkDownloaded(true);

            InstallWindowModelTest.WaitForStateChange <InstallWindowModel.InstallationStatus.InstallingStatus>(Model);

            Assert.That(((InstallWindowModel.InstallationStatus.InstallingStatus)((InstallWindowModel.InstallationStatus)Model.Status).Installation).InstallationStatus, Is.EqualTo("Name2"));
            Assert.That(((InstallWindowModel.InstallationStatus)Model.Status).Download, Is.TypeOf <InstallWindowModel.InstallationStatus.DownloadingStatus>());
            Assert.That(((InstallWindowModel.InstallationStatus.DownloadingStatus)((InstallWindowModel.InstallationStatus)Model.Status).Download).AcquiredPackages, Is.EqualTo(1));

            TestPrerequisites[1].MarkInstalled(true);

            InstallWindowModelTest.WaitForStateChange <InstallWindowModel.InstallationStatus.InstallationWaitingForDownloadStatus>(Model);

            TestPrerequisites[0].MarkDownloaded(true);

            InstallWindowModelTest.WaitForStateChange <InstallWindowModel.InstallationStatus.InstallingStatus>(Model);

            Assert.That(((InstallWindowModel.InstallationStatus.InstallingStatus)((InstallWindowModel.InstallationStatus)Model.Status).Installation).InstallationStatus, Is.EqualTo("Name1"));
            Assert.That(((InstallWindowModel.InstallationStatus)Model.Status).Download, Is.TypeOf <InstallWindowModel.InstallationStatus.DownloadFinishedStatus>());

            TestPrerequisites[0].MarkInstalled(true);

            InstallWindowModelTest.WaitForStateChange <InstallWindowModel.InstallationSuccessStatus>(Model);
        }
        public void When_Install_needed_without_download_installation_shall_begin_immediately_after_start()
        {
            TestPrerequisite[] TestPrerequisites = { new TestPrerequisite("Name1", false, false, null) };
            InstallWindowModel Model             = new InstallWindowModel(TestPrerequisites, (downloadId, progressCallback, downloadedCallback) => this.DownloadFunc(downloadId, progressCallback, downloadedCallback, TestPrerequisites.First(_ => _.DownloadId == downloadId)));

            Assert.That(Model.Status, Is.TypeOf <InstallWindowModel.PreperationStatus>());
            Assert.That(((InstallWindowModel.PreperationStatus)Model.Status).IsAdminRequired, Is.False);
            Assert.That(((InstallWindowModel.PreperationStatus)Model.Status).MissingSoftware.Length, Is.EqualTo(1));
            Assert.That(((InstallWindowModel.PreperationStatus)Model.Status).MissingSoftware[0], Is.EqualTo("Name1"));

            ((InstallWindowModel.PreperationStatus)Model.Status).SetUpSystemCommand.Execute(null);

            InstallWindowModelTest.WaitForStateChange <InstallWindowModel.InstallationStatus>(Model);

            Assert.That(((InstallWindowModel.InstallationStatus)Model.Status).Download, Is.Null);
            Assert.That(((InstallWindowModel.InstallationStatus)Model.Status).Installation, Is.TypeOf <InstallWindowModel.InstallationStatus.InstallingStatus>());
            Assert.That(((InstallWindowModel.InstallationStatus.InstallingStatus)((InstallWindowModel.InstallationStatus)Model.Status).Installation).NumberOfPackagesToInstall, Is.EqualTo(1));
            Assert.That(((InstallWindowModel.InstallationStatus.InstallingStatus)((InstallWindowModel.InstallationStatus)Model.Status).Installation).InstalledPackages, Is.EqualTo(0));
            Assert.That(((InstallWindowModel.InstallationStatus.InstallingStatus)((InstallWindowModel.InstallationStatus)Model.Status).Installation).InstallationStatus, Is.EqualTo("Name1"));

            TestPrerequisites[0].MarkInstalled(true);

            InstallWindowModelTest.WaitForStateChange <InstallWindowModel.InstallationSuccessStatus>(Model);
        }
        private static void WaitForStateChange <T>(InstallWindowModel model)
        {
            TimeSpan Timeout = Debugger.IsAttached ? TimeSpan.FromDays(1) : TimeSpan.FromSeconds(10);

            if (typeof(InstallWindowModel.StatusBase).IsAssignableFrom(typeof(T)))
            {
                while (model.Status.GetType() != typeof(T) && Timeout.Ticks > 0)
                {
                    Thread.Sleep(100);
                    Timeout = Timeout - TimeSpan.FromMilliseconds(100);
                }
                Assert.That(model.Status, Is.TypeOf <T>());
            }
            else if (typeof(InstallWindowModel.InstallationStatus.InstallationStatusBase).IsAssignableFrom(typeof(T)))
            {
                while ((model.Status.GetType() != typeof(InstallWindowModel.InstallationStatus) || ((InstallWindowModel.InstallationStatus)model.Status).Installation.GetType() != typeof(T)) && Timeout.Ticks > 0)
                {
                    Thread.Sleep(100);
                    Timeout = Timeout - TimeSpan.FromMilliseconds(100);
                }
                Assert.That(((InstallWindowModel.InstallationStatus)model.Status).Installation, Is.TypeOf <T>());
            }
            else if (typeof(InstallWindowModel.InstallationStatus.DownloadStatusBase).IsAssignableFrom(typeof(T)))
            {
                while ((model.Status.GetType() != typeof(InstallWindowModel.InstallationStatus) || ((InstallWindowModel.InstallationStatus)model.Status).Download.GetType() != typeof(T)) && Timeout.Ticks > 0)
                {
                    Thread.Sleep(100);
                    Timeout = Timeout - TimeSpan.FromMilliseconds(100);
                }
                Assert.That(((InstallWindowModel.InstallationStatus)model.Status).Download, Is.TypeOf <T>());
            }
            else
            {
                throw new ArgumentException();
            }
        }